Merge "Fix PowerStatsTestsRavenwood" into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index c768121..df4a3e5 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -100,6 +100,7 @@
         "framework-jobscheduler-job.flags-aconfig-java",
         "framework_graphics_flags_java_lib",
         "hwui_flags_java_lib",
+        "interaction_jank_monitor_flags_lib",
         "libcore_exported_aconfig_flags_lib",
         "libgui_flags_java_lib",
         "power_flags_lib",
@@ -1428,6 +1429,18 @@
     defaults: ["framework-minus-apex-aconfig-java-defaults"],
 }
 
+java_aconfig_library {
+    name: "android.app.appfunctions.exported-flags-aconfig-java",
+    aconfig_declarations: "android.app.appfunctions.flags-aconfig",
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+    mode: "exported",
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.permission",
+    ],
+    min_sdk_version: "30",
+}
+
 // Adaptive Auth
 aconfig_declarations {
     name: "android.adaptiveauth.flags-aconfig",
@@ -1578,3 +1591,17 @@
     aconfig_declarations: "dropbox_flags",
     defaults: ["framework-minus-apex-aconfig-java-defaults"],
 }
+
+// Zero Jank
+aconfig_declarations {
+    name: "interaction_jank_monitor_flags",
+    package: "com.android.internal.jank",
+    container: "system",
+    srcs: ["core/java/com/android/internal/jank/flags.aconfig"],
+}
+
+java_aconfig_library {
+    name: "interaction_jank_monitor_flags_lib",
+    aconfig_declarations: "interaction_jank_monitor_flags",
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
diff --git a/Ravenwood.bp b/Ravenwood.bp
index 5f32ba0..ec58210 100644
--- a/Ravenwood.bp
+++ b/Ravenwood.bp
@@ -50,7 +50,7 @@
 framework_minus_apex_cmd = "$(location hoststubgen) " +
     "@$(location :ravenwood-standard-options) " +
     "--debug-log $(location hoststubgen_framework-minus-apex.log) " +
-    "--out-impl-jar $(location ravenwood.jar) " +
+    "--out-jar $(location ravenwood.jar) " +
     "--in-jar $(location :framework-minus-apex-for-hoststubgen) " +
     "--policy-override-file $(location :ravenwood-framework-policies) " +
     "--annotation-allowed-classes-file $(location :ravenwood-annotation-allowed-classes) "
@@ -183,7 +183,7 @@
         "--stats-file $(location hoststubgen_services.core_stats.csv) " +
         "--supported-api-list-file $(location hoststubgen_services.core_apis.csv) " +
 
-        "--out-impl-jar $(location ravenwood.jar) " +
+        "--out-jar $(location ravenwood.jar) " +
 
         "--gen-keep-all-file $(location hoststubgen_services.core_keep_all.txt) " +
         "--gen-input-dump-file $(location hoststubgen_services.core_dump.txt) " +
diff --git a/core/api/current.txt b/core/api/current.txt
index ddfd364..5685221 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -43963,11 +43963,11 @@
     field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT = "satellite_connection_hysteresis_sec_int";
     field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_SATELLITE_ENTITLEMENT_STATUS_REFRESH_DAYS_INT = "satellite_entitlement_status_refresh_days_int";
     field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL = "satellite_entitlement_supported_bool";
-    field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ESOS_INACTIVITY_TIMEOUT_SEC_INT = "satellite_esos_inactivity_timeout_sec_int";
     field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ESOS_SUPPORTED_BOOL = "satellite_esos_supported_bool";
-    field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT = "satellite_p2p_sms_inactivity_timeout_sec_int";
+    field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT = "satellite_roaming_esos_inactivity_timeout_sec_int";
+    field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT = "satellite_roaming_p2p_sms_inactivity_timeout_sec_int";
     field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL = "satellite_roaming_p2p_sms_supported_bool";
-    field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT = "satellite_screen_off_inactivity_timeout_sec_int";
+    field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT = "satellite_roaming_screen_off_inactivity_timeout_sec_int";
     field public static final String KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL = "show_4g_for_3g_data_icon_bool";
     field public static final String KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL = "show_4g_for_lte_data_icon_bool";
     field public static final String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool";
diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java
index 62b5412..e0a9371 100644
--- a/core/java/android/app/AutomaticZenRule.java
+++ b/core/java/android/app/AutomaticZenRule.java
@@ -49,7 +49,7 @@
 
     /**
      * Rule is of an unknown type. This is the default value if not provided by the owning app,
-     * and the value returned if the true type was added in an API level lower than the calling
+     * and the value returned if the true type was added in an API level higher than the calling
      * app's targetSdk.
      */
     @FlaggedApi(Flags.FLAG_MODES_API)
@@ -315,7 +315,8 @@
     }
 
     /**
-     * Gets the zen policy.
+     * Gets the {@link ZenPolicy} applied if {@link #getInterruptionFilter()} is
+     * {@link NotificationManager#INTERRUPTION_FILTER_PRIORITY}.
      */
     @Nullable
     public ZenPolicy getZenPolicy() {
@@ -345,6 +346,17 @@
 
     /**
      * Sets the interruption filter that is applied when this rule is active.
+     *
+     * <ul>
+     *     <li>When {@link NotificationManager#INTERRUPTION_FILTER_PRIORITY}, the rule will use
+     *     the {@link ZenPolicy} supplied to {@link #setZenPolicy} (or a default one).
+     *     <li>When {@link NotificationManager#INTERRUPTION_FILTER_ALARMS} or
+     *     {@link NotificationManager#INTERRUPTION_FILTER_NONE}, the rule will use a fixed
+     *     {@link ZenPolicy} matching the filter.
+     *     <li>When {@link NotificationManager#INTERRUPTION_FILTER_ALL}, the rule will not block
+     *     notifications, but can still have {@link ZenDeviceEffects}.
+     * </ul>
+     *
      * @param interruptionFilter The do not disturb mode to enter when this rule is active.
      */
     public void setInterruptionFilter(@InterruptionFilter int interruptionFilter) {
@@ -374,7 +386,8 @@
     }
 
     /**
-     * Sets the zen policy.
+     * Sets the {@link ZenPolicy} applied if {@link #getInterruptionFilter()} is
+     * {@link NotificationManager#INTERRUPTION_FILTER_PRIORITY}.
      *
      * <p>When updating an existing rule via {@link NotificationManager#updateAutomaticZenRule},
      * a {@code null} value here means the previous policy is retained.
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index e99ba84..7a36fbb 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -2706,14 +2706,9 @@
         if (mAllowlistToken == null) {
             mAllowlistToken = processAllowlistToken;
         }
-        if (Flags.secureAllowlistToken()) {
-            // Propagate this token to all pending intents that are unmarshalled from the parcel,
-            // or keep the one we're already propagating, if that's the case.
-            if (!parcel.hasClassCookie(PendingIntent.class)) {
-                parcel.setClassCookie(PendingIntent.class, mAllowlistToken);
-            }
-        } else {
-            // Propagate this token to all pending intents that are unmarshalled from the parcel.
+        // Propagate this token to all pending intents that are unmarshalled from the parcel,
+        // or keep the one we're already propagating, if that's the case.
+        if (!parcel.hasClassCookie(PendingIntent.class)) {
             parcel.setClassCookie(PendingIntent.class, mAllowlistToken);
         }
 
@@ -3333,28 +3328,22 @@
             PendingIntent.addOnMarshaledListener(addedListener);
         }
         try {
-            if (Flags.secureAllowlistToken()) {
-                boolean mustClearCookie = false;
-                if (!parcel.hasClassCookie(Notification.class)) {
-                    // This is the "root" notification, and not an "inner" notification (including
-                    // publicVersion or anything else that might be embedded in extras). So we want
-                    // to use its token for every inner notification (might be null).
-                    parcel.setClassCookie(Notification.class, mAllowlistToken);
-                    mustClearCookie = true;
-                }
-                try {
-                    // IMPORTANT: Add marshaling code in writeToParcelImpl as we
-                    // want to intercept all pending events written to the parcel.
-                    writeToParcelImpl(parcel, flags);
-                } finally {
-                    if (mustClearCookie) {
-                        parcel.removeClassCookie(Notification.class, mAllowlistToken);
-                    }
-                }
-            } else {
+            boolean mustClearCookie = false;
+            if (!parcel.hasClassCookie(Notification.class)) {
+                // This is the "root" notification, and not an "inner" notification (including
+                // publicVersion or anything else that might be embedded in extras). So we want
+                // to use its token for every inner notification (might be null).
+                parcel.setClassCookie(Notification.class, mAllowlistToken);
+                mustClearCookie = true;
+            }
+            try {
                 // IMPORTANT: Add marshaling code in writeToParcelImpl as we
                 // want to intercept all pending events written to the parcel.
                 writeToParcelImpl(parcel, flags);
+            } finally {
+                if (mustClearCookie) {
+                    parcel.removeClassCookie(Notification.class, mAllowlistToken);
+                }
             }
 
             synchronized (this) {
@@ -3371,13 +3360,9 @@
     private void writeToParcelImpl(Parcel parcel, int flags) {
         parcel.writeInt(1);
 
-        if (Flags.secureAllowlistToken()) {
-            // Always use the same token as the root notification (might be null).
-            IBinder rootNotificationToken = (IBinder) parcel.getClassCookie(Notification.class);
-            parcel.writeStrongBinder(rootNotificationToken);
-        } else {
-            parcel.writeStrongBinder(mAllowlistToken);
-        }
+        // Always use the same token as the root notification (might be null).
+        IBinder rootNotificationToken = (IBinder) parcel.getClassCookie(Notification.class);
+        parcel.writeStrongBinder(rootNotificationToken);
 
         parcel.writeLong(when);
         parcel.writeLong(creationTime);
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 789c99d..1b29b7a 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -168,7 +168,11 @@
     /**
      * @hide
      */
-    public static final int MAX_VIBRATION_LENGTH = 1000;
+    public static final int MAX_VIBRATION_LENGTH = 500;
+    /**
+     * @hide
+     */
+    public static final int MAX_SERIALIZED_VIBRATION_LENGTH = 32_768;
 
     private static final String TAG_CHANNEL = "channel";
     private static final String ATT_NAME = "name";
@@ -368,6 +372,9 @@
         if (Flags.notificationChannelVibrationEffectApi()) {
             mVibrationEffect =
                     in.readInt() != 0 ? VibrationEffect.CREATOR.createFromParcel(in) : null;
+            if (Flags.notifChannelCropVibrationEffects() && mVibrationEffect != null) {
+                mVibrationEffect = getTrimmedVibrationEffect(mVibrationEffect);
+            }
         }
         mUserLockedFields = in.readInt();
         mUserVisibleTaskShown = in.readByte() != 0;
@@ -582,6 +589,23 @@
         return input;
     }
 
+    // Returns trimmed vibration effect or null if not trimmable.
+    private VibrationEffect getTrimmedVibrationEffect(VibrationEffect effect) {
+        if (effect == null) {
+            return null;
+        }
+        // trim if possible; check serialized length; reject if it is still too long
+        VibrationEffect result = effect;
+        VibrationEffect trimmed = effect.cropToLengthOrNull(MAX_VIBRATION_LENGTH);
+        if (trimmed != null) {
+            result = trimmed;
+        }
+        if (vibrationToString(result).length() > MAX_SERIALIZED_VIBRATION_LENGTH) {
+            return null;
+        }
+        return result;
+    }
+
     /**
      * @hide
      */
@@ -685,6 +709,11 @@
     public void setVibrationPattern(long[] vibrationPattern) {
         this.mVibrationEnabled = vibrationPattern != null && vibrationPattern.length > 0;
         this.mVibrationPattern = vibrationPattern;
+        if (Flags.notifChannelCropVibrationEffects()) {
+            if (vibrationPattern != null && vibrationPattern.length > MAX_VIBRATION_LENGTH) {
+                this.mVibrationPattern = Arrays.copyOf(vibrationPattern, MAX_VIBRATION_LENGTH);
+            }
+        }
         if (Flags.notificationChannelVibrationEffectApi()) {
             try {
                 this.mVibrationEffect =
@@ -731,9 +760,21 @@
     public void setVibrationEffect(@Nullable VibrationEffect effect) {
         this.mVibrationEnabled = effect != null;
         this.mVibrationEffect = effect;
-        this.mVibrationPattern =
-                effect == null
-                ? null : effect.computeCreateWaveformOffOnTimingsOrNull();
+        if (Flags.notifChannelCropVibrationEffects() && effect != null) {
+            // Try converting to a vibration pattern and trimming that array. If not convertible
+            // to a pattern directly, try trimming the vibration effect if possible and storing
+            // that version instead.
+            long[] pattern = effect.computeCreateWaveformOffOnTimingsOrNull();
+            if (pattern != null) {
+                setVibrationPattern(pattern);
+            } else {
+                this.mVibrationEffect = getTrimmedVibrationEffect(mVibrationEffect);
+            }
+        } else {
+            this.mVibrationPattern =
+                    mVibrationEffect == null
+                            ? null : mVibrationEffect.computeCreateWaveformOffOnTimingsOrNull();
+        }
     }
 
     /**
@@ -1172,7 +1213,9 @@
             if (vibrationEffect != null) {
                 // Restore the effect only if it is not null. This allows to avoid undoing a
                 // `setVibrationPattern` call above, if that was done with a non-null pattern
-                // (e.g. back up from a version that did not support `setVibrationEffect`).
+                // (e.g. back up from a version that did not support `setVibrationEffect`), or
+                // when notif_channel_crop_vibration_effects is true, if there is an equivalent
+                // vibration pattern available.
                 setVibrationEffect(vibrationEffect);
             }
         }
@@ -1365,7 +1408,11 @@
             out.attribute(null, ATT_VIBRATION, longArrayToString(getVibrationPattern()));
         }
         if (getVibrationEffect() != null) {
-            out.attribute(null, ATT_VIBRATION_EFFECT, vibrationToString(getVibrationEffect()));
+            if (!Flags.notifChannelCropVibrationEffects() || getVibrationPattern() == null) {
+                // When notif_channel_crop_vibration_effects is on, only serialize the vibration
+                // effect if we do not already have an equivalent vibration pattern.
+                out.attribute(null, ATT_VIBRATION_EFFECT, vibrationToString(getVibrationEffect()));
+            }
         }
         if (getUserLockedFields() != 0) {
             out.attributeInt(null, ATT_USER_LOCKED, getUserLockedFields());
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 1ddec17..0f54cb7 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -10476,10 +10476,6 @@
     @WorkerThread
     public void setApplicationRestrictions(@Nullable ComponentName admin, String packageName,
             Bundle settings) {
-        if (!Flags.dmrhSetAppRestrictions()) {
-            throwIfParentInstance("setApplicationRestrictions");
-        }
-
         if (mService != null) {
             try {
                 mService.setApplicationRestrictions(admin, mContext.getPackageName(), packageName,
@@ -11884,9 +11880,6 @@
     @WorkerThread
     public @NonNull Bundle getApplicationRestrictions(
             @Nullable ComponentName admin, String packageName) {
-        if (!Flags.dmrhSetAppRestrictions()) {
-            throwIfParentInstance("getApplicationRestrictions");
-        }
 
         if (mService != null) {
             try {
@@ -14231,21 +14224,11 @@
      */
     public @NonNull DevicePolicyManager getParentProfileInstance(@NonNull ComponentName admin) {
         throwIfParentInstance("getParentProfileInstance");
-        try {
-            if (Flags.dmrhSetAppRestrictions()) {
-                UserManager um = mContext.getSystemService(UserManager.class);
-                if (!um.isManagedProfile()) {
-                    throw new SecurityException("The current user does not have a parent profile.");
-                }
-            } else {
-                if (!mService.isManagedProfile(admin)) {
-                    throw new SecurityException("The current user does not have a parent profile.");
-                }
-            }
-            return new DevicePolicyManager(mContext, mService, true);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
+        UserManager um = mContext.getSystemService(UserManager.class);
+        if (!um.isManagedProfile()) {
+            throw new SecurityException("The current user does not have a parent profile.");
         }
+        return new DevicePolicyManager(mContext, mService, true);
     }
 
     /**
diff --git a/core/java/android/app/admin/flags/flags.aconfig b/core/java/android/app/admin/flags/flags.aconfig
index d9bd77f..540592f 100644
--- a/core/java/android/app/admin/flags/flags.aconfig
+++ b/core/java/android/app/admin/flags/flags.aconfig
@@ -210,16 +210,6 @@
 }
 
 flag {
-  name: "dmrh_set_app_restrictions"
-  namespace: "enterprise"
-  description: "Allow DMRH to set application restrictions (both on the profile and the parent)"
-  bug: "328758346"
-  metadata {
-    purpose: PURPOSE_BUGFIX
-  }
-}
-
-flag {
   name: "always_persist_do"
   namespace: "enterprise"
   description: "Always write device_owners2.xml so that migration flags aren't lost"
diff --git a/core/java/android/app/notification.aconfig b/core/java/android/app/notification.aconfig
index 606ca33..9891e89 100644
--- a/core/java/android/app/notification.aconfig
+++ b/core/java/android/app/notification.aconfig
@@ -128,6 +128,16 @@
 }
 
 flag {
+  name: "notif_channel_crop_vibration_effects"
+  namespace: "systemui"
+  description: "Limits the size of vibration effects that can be stored in a NotificationChannel"
+  bug: "345881518"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
+
+flag {
   name: "evenly_divided_call_style_action_layout"
   namespace: "systemui"
   description: "Evenly divides horizontal space for action buttons in CallStyle notifications."
diff --git a/core/java/android/companion/virtual/flags/flags.aconfig b/core/java/android/companion/virtual/flags/flags.aconfig
index 22a9ccf..297fe8a 100644
--- a/core/java/android/companion/virtual/flags/flags.aconfig
+++ b/core/java/android/companion/virtual/flags/flags.aconfig
@@ -111,3 +111,10 @@
     description: "Device awareness in power and display APIs"
     bug: "285020111"
 }
+
+flag {
+  name: "status_bar_and_insets"
+  namespace: "virtual_devices"
+  description: "Allow for status bar and insets on virtual devices"
+  bug: "350007866"
+}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 3bf0f032..12c5d07 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -33,6 +33,7 @@
 import android.annotation.Nullable;
 import android.annotation.PermissionMethod;
 import android.annotation.PermissionName;
+import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
 import android.annotation.StringDef;
 import android.annotation.StringRes;
@@ -6678,6 +6679,8 @@
      * Use with {@link #getSystemService(String)} to retrieve a {@link
      * android.webkit.WebViewUpdateManager} for accessing the WebView update service.
      *
+     * <p>This can only be used on devices with {@link PackageManager#FEATURE_WEBVIEW}.
+     *
      * @see #getSystemService(String)
      * @see android.webkit.WebViewUpdateManager
      * @hide
@@ -6685,6 +6688,7 @@
     @FlaggedApi(android.webkit.Flags.FLAG_UPDATE_SERVICE_IPC_WRAPPER)
     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
     @SuppressLint("ServiceName")
+    @RequiresFeature(PackageManager.FEATURE_WEBVIEW)
     public static final String WEBVIEW_UPDATE_SERVICE = "webviewupdate";
 
     /**
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index abb0d8d..da3cc1b 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -7650,13 +7650,6 @@
             | FLAG_GRANT_PREFIX_URI_PERMISSION;
 
     /**
-     * Flags that are not normally set by application code, but set for you by the system.
-     */
-    private static final int SYSTEM_ONLY_FLAGS = FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
-            | FLAG_ACTIVITY_BROUGHT_TO_FRONT
-            | FLAG_RECEIVER_FROM_SHELL;
-
-    /**
      * Local flag indicating this instance was created by copy constructor.
      */
     private static final int LOCAL_FLAG_FROM_COPY = 1 << 0;
@@ -7709,11 +7702,6 @@
     @TestApi
     public static final int EXTENDED_FLAG_FILTER_MISMATCH = 1 << 0;
 
-    /**
-     * Extended flags that are not normally set by application code, but set for you by the system.
-     */
-    private static final int SYSTEM_ONLY_EXTENDED_FLAGS = EXTENDED_FLAG_FILTER_MISMATCH;
-
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // toUri() and parseUri() options.
@@ -12657,28 +12645,6 @@
         }
     }
 
-    /**
-     * Prepare this {@link Intent} to enter system_server.
-     *
-     * @hide
-     */
-    public void prepareToEnterSystemServer() {
-        // Refuse possible leaked file descriptors
-        if (hasFileDescriptors()) {
-            throw new IllegalArgumentException("File descriptors passed in Intent");
-        }
-        // These flags are set only by the system, and should be stripped out as soon as the intent
-        // is received by system_server from the caller so it can be properly updated later.
-        removeFlags(SYSTEM_ONLY_FLAGS);
-        removeExtendedFlags(SYSTEM_ONLY_EXTENDED_FLAGS);
-        if (mOriginalIntent != null) {
-            mOriginalIntent.prepareToEnterSystemServer();
-        }
-        if (mSelector != null) {
-            mSelector.prepareToEnterSystemServer();
-        }
-    }
-
     /** @hide */
     public boolean hasWebURI() {
         if (getData() == null) {
diff --git a/core/java/android/content/pm/multiuser.aconfig b/core/java/android/content/pm/multiuser.aconfig
index 3a33ef9..28534ad 100644
--- a/core/java/android/content/pm/multiuser.aconfig
+++ b/core/java/android/content/pm/multiuser.aconfig
@@ -161,6 +161,16 @@
 }
 
 flag {
+    name: "fix_avatar_content_provider_null_authority"
+    namespace: "multiuser"
+    description: "Fix crash when content provider authority is null."
+    bug: "362880068"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+  }
+}
+
+flag {
     name: "fix_avatar_picker_not_responding_for_new_user"
     namespace: "multiuser"
     description: "Avatar picker is not responding after selecting photo for new user."
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index fbed50a..ac72116 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1537,9 +1537,14 @@
      * be made, and for firing pre-capture flash pulses to estimate
      * scene brightness and required final capture flash power, when
      * the flash is enabled.</p>
-     * <p>Normally, this entry should be set to START for only a
-     * single request, and the application should wait until the
-     * sequence completes before starting a new one.</p>
+     * <p>Flash is enabled during precapture sequence when:</p>
+     * <ul>
+     * <li>AE mode is ON_ALWAYS_FLASH</li>
+     * <li>AE mode is ON_AUTO_FLASH and the scene is deemed too dark without flash, or</li>
+     * <li>AE mode is ON and flash mode is TORCH or SINGLE</li>
+     * </ul>
+     * <p>Normally, this entry should be set to START for only single request, and the
+     * application should wait until the sequence completes before starting a new one.</p>
      * <p>When a precapture metering sequence is finished, the camera device
      * may lock the auto-exposure routine internally to be able to accurately expose the
      * subsequent still capture image (<code>{@link CaptureRequest#CONTROL_CAPTURE_INTENT android.control.captureIntent} == STILL_CAPTURE</code>).
@@ -2705,6 +2710,13 @@
      * in {@link CameraCharacteristics#FLASH_SINGLE_STRENGTH_DEFAULT_LEVEL android.flash.singleStrengthDefaultLevel}.
      * If {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is set to any of <code>ON_AUTO_FLASH</code>, <code>ON_ALWAYS_FLASH</code>,
      * <code>ON_AUTO_FLASH_REDEYE</code>, <code>ON_EXTERNAL_FLASH</code> values, then the strengthLevel will be ignored.</p>
+     * <p>When AE mode is ON and flash mode is TORCH or SINGLE, the application should make sure
+     * the AE mode, flash mode, and flash strength level remain the same between precapture
+     * trigger request and final capture request. The flash strength level being set during
+     * precapture sequence is used by the camera device as a reference. The actual strength
+     * may be less, and the auto-exposure routine makes sure proper conversions of sensor
+     * exposure time and sensitivities between precapture and final capture for the specified
+     * strength level.</p>
      * <p><b>Range of valid values:</b><br>
      * <code>[1-{@link CameraCharacteristics#FLASH_TORCH_STRENGTH_MAX_LEVEL android.flash.torchStrengthMaxLevel}]</code> when the {@link CaptureRequest#FLASH_MODE android.flash.mode} is
      * set to TORCH;
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index d652b4c..34ce92c 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -935,9 +935,14 @@
      * be made, and for firing pre-capture flash pulses to estimate
      * scene brightness and required final capture flash power, when
      * the flash is enabled.</p>
-     * <p>Normally, this entry should be set to START for only a
-     * single request, and the application should wait until the
-     * sequence completes before starting a new one.</p>
+     * <p>Flash is enabled during precapture sequence when:</p>
+     * <ul>
+     * <li>AE mode is ON_ALWAYS_FLASH</li>
+     * <li>AE mode is ON_AUTO_FLASH and the scene is deemed too dark without flash, or</li>
+     * <li>AE mode is ON and flash mode is TORCH or SINGLE</li>
+     * </ul>
+     * <p>Normally, this entry should be set to START for only single request, and the
+     * application should wait until the sequence completes before starting a new one.</p>
      * <p>When a precapture metering sequence is finished, the camera device
      * may lock the auto-exposure routine internally to be able to accurately expose the
      * subsequent still capture image (<code>{@link CaptureRequest#CONTROL_CAPTURE_INTENT android.control.captureIntent} == STILL_CAPTURE</code>).
@@ -2821,8 +2826,6 @@
      * boost when the light level threshold is exceeded.</p>
      * <p>This state indicates when low light boost is 'ACTIVE' and applied. Similarly, it can
      * indicate when it is not being applied by returning 'INACTIVE'.</p>
-     * <p>This key will be absent from the CaptureResult if AE mode is not set to
-     * 'ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY.</p>
      * <p>The default value will always be 'INACTIVE'.</p>
      * <p><b>Possible values:</b></p>
      * <ul>
@@ -2996,6 +2999,13 @@
      * in {@link CameraCharacteristics#FLASH_SINGLE_STRENGTH_DEFAULT_LEVEL android.flash.singleStrengthDefaultLevel}.
      * If {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is set to any of <code>ON_AUTO_FLASH</code>, <code>ON_ALWAYS_FLASH</code>,
      * <code>ON_AUTO_FLASH_REDEYE</code>, <code>ON_EXTERNAL_FLASH</code> values, then the strengthLevel will be ignored.</p>
+     * <p>When AE mode is ON and flash mode is TORCH or SINGLE, the application should make sure
+     * the AE mode, flash mode, and flash strength level remain the same between precapture
+     * trigger request and final capture request. The flash strength level being set during
+     * precapture sequence is used by the camera device as a reference. The actual strength
+     * may be less, and the auto-exposure routine makes sure proper conversions of sensor
+     * exposure time and sensitivities between precapture and final capture for the specified
+     * strength level.</p>
      * <p><b>Range of valid values:</b><br>
      * <code>[1-{@link CameraCharacteristics#FLASH_TORCH_STRENGTH_MAX_LEVEL android.flash.torchStrengthMaxLevel}]</code> when the {@link CaptureRequest#FLASH_MODE android.flash.mode} is
      * set to TORCH;
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index a60c48e..c7dba6c 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -80,6 +80,7 @@
 import java.util.concurrent.Executor;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
@@ -90,6 +91,17 @@
     private final String TAG;
     private final boolean DEBUG = false;
 
+    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
+        private static final ThreadFactory mFactory = Executors.defaultThreadFactory();
+
+        @Override
+        public Thread newThread(Runnable r) {
+            Thread thread = mFactory.newThread(r);
+            thread.setName("CameraDeviceExecutor");
+            return thread;
+        }
+    };
+
     private static final int REQUEST_ID_NONE = -1;
 
     /**
@@ -354,7 +366,11 @@
         mCameraId = cameraId;
         if (Flags.singleThreadExecutor()) {
             mDeviceCallback = new ClientStateCallback(executor, callback);
-            mDeviceExecutor = Executors.newSingleThreadExecutor();
+            if (Flags.singleThreadExecutorNaming()) {
+                mDeviceExecutor = Executors.newSingleThreadExecutor(sThreadFactory);
+            } else {
+                mDeviceExecutor = Executors.newSingleThreadExecutor();
+            }
         } else {
             mDeviceCallback = callback;
             mDeviceExecutor = executor;
diff --git a/core/java/android/os/ArtModuleServiceManager.java b/core/java/android/os/ArtModuleServiceManager.java
index e0b631d..995094b 100644
--- a/core/java/android/os/ArtModuleServiceManager.java
+++ b/core/java/android/os/ArtModuleServiceManager.java
@@ -37,10 +37,12 @@
     /** A class that exposes the method to obtain each system service. */
     public static final class ServiceRegisterer {
         @NonNull private final String mServiceName;
+        private final boolean mRetry;
 
         /** @hide */
-        public ServiceRegisterer(@NonNull String serviceName) {
+        public ServiceRegisterer(@NonNull String serviceName, boolean retry) {
             mServiceName = serviceName;
+            mRetry = retry;
         }
 
         /**
@@ -53,27 +55,47 @@
          */
         @Nullable
         public IBinder waitForService() {
-            return ServiceManager.waitForService(mServiceName);
+            if (mRetry) {
+                return ServiceManager.waitForService(mServiceName);
+            }
+            IBinder binder = ServiceManager.getService(mServiceName);
+            for (int remainingTimeMs = 5000; binder == null && remainingTimeMs > 0;
+                    remainingTimeMs -= 100) {
+                // There can be a race:
+                // 1. Client A invokes "ctl.start", which starts the service.
+                // 2. Client A gets a service handle from `ServiceManager.getService`.
+                // 3. Client B invokes "ctl.start", which does nothing because the service is
+                //    already running.
+                // 4. Client A drops the service handle. The service is notified that there is no
+                //    more client at that point, so it shuts down itself.
+                // 5. Client B cannot get a service handle from `ServiceManager.getService` because
+                //    the service is shut down.
+                // To address this problem, we invoke "ctl.start" repeatedly.
+                SystemProperties.set("ctl.start", mServiceName);
+                SystemClock.sleep(100);
+                binder = ServiceManager.getService(mServiceName);
+            }
+            return binder;
         }
     }
 
     /** Returns {@link ServiceRegisterer} for the "artd" service. */
     @NonNull
     public ServiceRegisterer getArtdServiceRegisterer() {
-        return new ServiceRegisterer("artd");
+        return new ServiceRegisterer("artd", true /* retry */);
     }
 
     /** Returns {@link ServiceRegisterer} for the "artd_pre_reboot" service. */
     @NonNull
     @FlaggedApi(Flags.FLAG_USE_ART_SERVICE_V2)
     public ServiceRegisterer getArtdPreRebootServiceRegisterer() {
-        return new ServiceRegisterer("artd_pre_reboot");
+        return new ServiceRegisterer("artd_pre_reboot", false /* retry */);
     }
 
     /** Returns {@link ServiceRegisterer} for the "dexopt_chroot_setup" service. */
     @NonNull
     @FlaggedApi(Flags.FLAG_USE_ART_SERVICE_V2)
     public ServiceRegisterer getDexoptChrootSetupServiceRegisterer() {
-        return new ServiceRegisterer("dexopt_chroot_setup");
+        return new ServiceRegisterer("dexopt_chroot_setup", true /* retry */);
     }
 }
diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java
index 1100731..c22f46c 100644
--- a/core/java/android/os/BinderProxy.java
+++ b/core/java/android/os/BinderProxy.java
@@ -646,6 +646,37 @@
     private native boolean unlinkToDeathNative(DeathRecipient recipient, int flags);
 
     /**
+     * This list is to hold strong reference to the frozen state callbacks. The callbacks are only
+     * weakly referenced by JNI so the strong references here are needed to keep the callbacks
+     * around until the proxy is GC'ed.
+     */
+    private List<IFrozenStateChangeCallback> mFrozenStateChangeCallbacks =
+            Collections.synchronizedList(new ArrayList<>());
+
+    /**
+     * See {@link IBinder#addFrozenStateChangeCallback(IFrozenStateChangeCallback)}
+     */
+    public void addFrozenStateChangeCallback(IFrozenStateChangeCallback callback)
+            throws RemoteException {
+        addFrozenStateChangeCallbackNative(callback);
+        mFrozenStateChangeCallbacks.add(callback);
+    }
+
+    /**
+     * See {@link IBinder#removeFrozenStateChangeCallback}
+     */
+    public boolean removeFrozenStateChangeCallback(IFrozenStateChangeCallback callback) {
+        mFrozenStateChangeCallbacks.remove(callback);
+        return removeFrozenStateChangeCallbackNative(callback);
+    }
+
+    private native void addFrozenStateChangeCallbackNative(IFrozenStateChangeCallback callback)
+            throws RemoteException;
+
+    private native boolean removeFrozenStateChangeCallbackNative(
+            IFrozenStateChangeCallback callback);
+
+    /**
      * Perform a dump on the remote object
      *
      * @param fd The raw file descriptor that the dump is being sent to.
@@ -730,6 +761,17 @@
         }
     }
 
+    private static void invokeFrozenStateChangeCallback(
+            IFrozenStateChangeCallback callback, IBinder binderProxy, int stateIndex) {
+        try {
+            callback.onFrozenStateChanged(binderProxy,
+                    IFrozenStateChangeCallback.State.values()[stateIndex]);
+        } catch (RuntimeException exc) {
+            Log.w("BinderNative", "Uncaught exception from frozen state change callback",
+                    exc);
+        }
+    }
+
     /**
      * C++ pointer to BinderProxyNativeData. That consists of strong pointers to the
      * native IBinder object, and a DeathRecipientList.
diff --git a/core/java/android/os/IBinder.java b/core/java/android/os/IBinder.java
index 50242ba..8185e8e 100644
--- a/core/java/android/os/IBinder.java
+++ b/core/java/android/os/IBinder.java
@@ -376,4 +376,53 @@
      * return value instead.
      */
     public boolean unlinkToDeath(@NonNull DeathRecipient recipient, int flags);
+
+    /** @hide */
+    interface IFrozenStateChangeCallback {
+        enum State {FROZEN, UNFROZEN};
+
+        /**
+         * Interface for receiving a callback when the process hosting an IBinder
+         * has changed its frozen state.
+         * @param who The IBinder whose hosting process has changed state.
+         * @param state The latest state.
+         */
+        void onFrozenStateChanged(@NonNull IBinder who, State state);
+    }
+
+    /**
+     * {@link addFrozenStateChangeCallback} provides a callback mechanism to notify about process
+     * frozen/unfrozen events. Upon registration and any subsequent state changes, the callback is
+     * invoked with the latest process frozen state.
+     *
+     * <p>If the listener process (the one using this API) is itself frozen, state change events
+     * might be combined into a single one with the latest frozen state. This single event would
+     * then be delivered when the listener process becomes unfrozen. Similarly, if an event happens
+     * before the previous event is consumed, they might be combined. This means the callback might
+     * not be called for every single state change, so don't rely on this API to count how many
+     * times the state has changed.</p>
+     *
+     * <p>The callback is automatically removed when all references to the binder proxy are
+     * dropped.</p>
+     *
+     * <p>You will only receive state change notifications for remote binders, as local binders by
+     * definition can't be frozen without you being frozen too.</p>
+     *
+     * <p>@throws {@link UnsupportedOperationException} if the kernel binder driver does not support
+     * this feature.
+     * @hide
+     */
+    default void addFrozenStateChangeCallback(@NonNull IFrozenStateChangeCallback callback)
+            throws RemoteException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Unregister a {@link IFrozenStateChangeCallback}. The callback will no longer be invoked when
+     * the hosting process changes its frozen state.
+     * @hide
+     */
+    default boolean removeFrozenStateChangeCallback(@NonNull IFrozenStateChangeCallback callback) {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index f02d4a9..64a2dbc 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -540,6 +540,17 @@
     /** @hide */
     public abstract void validate();
 
+
+    /**
+     * If supported, truncate the length of this vibration effect to the provided length and return
+     * the result. Will always return null for repeating effects.
+     *
+     * @return The desired effect, or {@code null} if truncation is not applicable.
+     * @hide
+     */
+    @Nullable
+    public abstract VibrationEffect cropToLengthOrNull(int length);
+
     /**
      * Gets the estimated duration of the vibration in milliseconds.
      *
@@ -866,6 +877,30 @@
             }
         }
 
+        /** @hide */
+        @Override
+        @Nullable
+        public VibrationEffect cropToLengthOrNull(int length) {
+            // drop repeating effects
+            if (mRepeatIndex >= 0) {
+                return null;
+            }
+
+            int segmentCount = mSegments.size();
+            if (segmentCount <= length) {
+                return this;
+            }
+
+            ArrayList truncated = new ArrayList(mSegments.subList(0, length));
+            Composed updated = new Composed(truncated, mRepeatIndex);
+            try {
+                updated.validate();
+            } catch (IllegalArgumentException e) {
+                return null;
+            }
+            return updated;
+        }
+
         @Override
         public long getDuration() {
             if (mRepeatIndex >= 0) {
@@ -1150,6 +1185,13 @@
                     "Vendor effect bundle must be non-empty");
         }
 
+        /** @hide */
+        @Override
+        @Nullable
+        public VibrationEffect cropToLengthOrNull(int length) {
+            return null;
+        }
+
         @Override
         public long getDuration() {
             return -1; // UNKNOWN
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 24f52d0..98904fe 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1974,7 +1974,7 @@
     /**
      * Activity Action: Show Notification Policy access settings.
      * <p>
-     * Users can grant and deny access to Notification Policy (DND / Priority Modes) configuration
+     * Users can grant and deny access to Notification Policy (DND / Modes) configuration
      * from here. Managed profiles cannot grant Notification Policy access.
      * See {@link android.app.NotificationManager#isNotificationPolicyAccessGranted()} for more
      * details.
diff --git a/core/java/android/service/chooser/flags.aconfig b/core/java/android/service/chooser/flags.aconfig
index 1f1a351..2b75493 100644
--- a/core/java/android/service/chooser/flags.aconfig
+++ b/core/java/android/service/chooser/flags.aconfig
@@ -2,6 +2,22 @@
 container: "system"
 
 flag {
+  name: "chooser_album_text"
+  is_exported: true
+  namespace: "intentresolver"
+  description: "Flag controlling the album text subtype hint for sharesheet"
+  bug: "323380224"
+}
+
+flag {
+  name: "enable_sharesheet_metadata_extra"
+  is_exported: true
+  namespace: "intentresolver"
+  description: "This flag enables sharesheet metadata to be displayed to users."
+  bug: "318942069"
+}
+
+flag {
   name: "chooser_payload_toggling"
   is_exported: true
   namespace: "intentresolver"
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index ba64786..3d8d933 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -2932,7 +2932,7 @@
             }
         }
 
-        // TODO: b/333527800 - Rename to isActive()
+        // TODO: b/363193376 - Rename to isActive()
         public boolean isAutomaticActive() {
             if (Flags.modesApi() && Flags.modesUi()) {
                 if (!enabled || getPkg() == null) {
diff --git a/core/java/android/service/notification/ZenPolicy.java b/core/java/android/service/notification/ZenPolicy.java
index 2669391..be0d7b3 100644
--- a/core/java/android/service/notification/ZenPolicy.java
+++ b/core/java/android/service/notification/ZenPolicy.java
@@ -393,6 +393,46 @@
     }
 
     /**
+     * Base Zen Policy used when {@link android.app.NotificationManager#setInterruptionFilter} is
+     * called with {@link android.app.NotificationManager#INTERRUPTION_FILTER_ALARMS} or an
+     * {@link android.app.AutomaticZenRule} specifies said filter.
+     *
+     * <p>Note that <em>visual effects</em> for filtered notifications are unset in this base
+     * policy, so should be merged on top of the default policy's visual effects (see
+     * {@link #overwrittenWith(ZenPolicy)}).
+     *
+     * @hide
+     */
+    @FlaggedApi(Flags.FLAG_MODES_API)
+    public static ZenPolicy getBasePolicyInterruptionFilterAlarms() {
+        return new ZenPolicy.Builder()
+                .disallowAllSounds()
+                .allowAlarms(true)
+                .allowMedia(true)
+                .allowPriorityChannels(false)
+                .build();
+    }
+
+    /**
+     * Base Zen Policy used when {@link android.app.NotificationManager#setInterruptionFilter} is
+     * called with {@link android.app.NotificationManager#INTERRUPTION_FILTER_NONE} or an
+     * {@link android.app.AutomaticZenRule} specifies said filter.
+     *
+     * <p>Note that <em>visual effects</em> for filtered notifications are unset in this base
+     * policy, so it should be merged on top of the device default policy's visual effects (see
+     * {@link #overwrittenWith(ZenPolicy)}).
+     *
+     * @hide
+     */
+    @FlaggedApi(Flags.FLAG_MODES_API)
+    public static ZenPolicy getBasePolicyInterruptionFilterNone() {
+        return new ZenPolicy.Builder()
+                .disallowAllSounds()
+                .allowPriorityChannels(false)
+                .build();
+    }
+
+    /**
      * Conversation type that can bypass DND.
      * @return {@link #CONVERSATION_SENDERS_UNSET}, {@link #CONVERSATION_SENDERS_ANYONE},
      * {@link #CONVERSATION_SENDERS_IMPORTANT}, {@link #CONVERSATION_SENDERS_NONE}.
diff --git a/core/java/android/util/LocalLog.java b/core/java/android/util/LocalLog.java
index feb80cc..ca5798a 100644
--- a/core/java/android/util/LocalLog.java
+++ b/core/java/android/util/LocalLog.java
@@ -112,6 +112,11 @@
         }
     }
 
+    // @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+    public synchronized void clear() {
+        mLog.clear();
+    }
+
     public static class ReadOnlyLocalLog {
         private final LocalLog mLog;
         ReadOnlyLocalLog(LocalLog log) {
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 9e4b27d..2dda835 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -445,16 +445,20 @@
         // Jank due to unknown reasons.
         public static final int UNKNOWN = 0x80;
 
-        public JankData(long frameVsyncId, @JankType int jankType, long frameIntervalNs) {
+        public JankData(long frameVsyncId, @JankType int jankType, long frameIntervalNs,
+                long scheduledAppFrameTimeNs, long actualAppFrameTimeNs) {
             this.frameVsyncId = frameVsyncId;
             this.jankType = jankType;
             this.frameIntervalNs = frameIntervalNs;
-
+            this.scheduledAppFrameTimeNs = scheduledAppFrameTimeNs;
+            this.actualAppFrameTimeNs = actualAppFrameTimeNs;
         }
 
         public final long frameVsyncId;
         public final @JankType int jankType;
         public final long frameIntervalNs;
+        public final long scheduledAppFrameTimeNs;
+        public final long actualAppFrameTimeNs;
     }
 
     /**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 523ff38..7b4ea41 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -27377,6 +27377,29 @@
     }
 
     /**
+     * Modifiers the input matrix such that it maps root view's coordinates to view-local
+     * coordinates.
+     *
+     * @param matrix input matrix to modify
+     * @hide
+     */
+    public void transformMatrixRootToLocal(@NonNull Matrix matrix) {
+        final ViewParent parent = mParent;
+        if (parent instanceof final View vp) {
+            vp.transformMatrixRootToLocal(matrix);
+            matrix.postTranslate(vp.mScrollX, vp.mScrollY);
+        }
+        // This method is different from transformMatrixToLocal that it doesn't perform any
+        // transformation for ViewRootImpl
+
+        matrix.postTranslate(-mLeft, -mTop);
+
+        if (!hasIdentityMatrix()) {
+            matrix.postConcat(getInverseMatrix());
+        }
+    }
+
+    /**
      * @hide
      */
     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index fb2b8b9..63bf392 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -373,6 +373,7 @@
     private final int mMaximumDrawingCacheSize;
     private final int mOverscrollDistance;
     private final int mOverflingDistance;
+    private final boolean mViewTouchScreenHapticScrollFeedbackEnabled;
     @UnsupportedAppUsage
     private final boolean mFadingMarqueeEnabled;
     private final long mGlobalActionsKeyTimeout;
@@ -437,6 +438,7 @@
         mSmartSelectionInitializedTimeout = SMART_SELECTION_INITIALIZED_TIMEOUT_IN_MILLISECOND;
         mSmartSelectionInitializingTimeout = SMART_SELECTION_INITIALIZING_TIMEOUT_IN_MILLISECOND;
         mPreferKeepClearForFocusEnabled = false;
+        mViewTouchScreenHapticScrollFeedbackEnabled = false;
     }
 
     /**
@@ -588,6 +590,12 @@
         mViewBasedRotaryEncoderScrollHapticsEnabledConfig =
                 res.getBoolean(
                         com.android.internal.R.bool.config_viewBasedRotaryEncoderHapticsEnabled);
+        mViewTouchScreenHapticScrollFeedbackEnabled =
+                Flags.enableTouchScrollFeedback()
+                        ? res.getBoolean(
+                        com.android.internal.R.bool
+                                .config_viewTouchScreenHapticScrollFeedbackEnabled)
+                        : false;
     }
 
     /**
@@ -1285,6 +1293,10 @@
             return mRotaryEncoderHapticScrollFeedbackEnabled;
         }
 
+        if ((source & InputDevice.SOURCE_TOUCHSCREEN) != 0) {
+            return mViewTouchScreenHapticScrollFeedbackEnabled;
+        }
+
         return false;
     }
 
diff --git a/core/java/android/view/flags/scroll_feedback_flags.aconfig b/core/java/android/view/flags/scroll_feedback_flags.aconfig
index 338037f..e9c85684 100644
--- a/core/java/android/view/flags/scroll_feedback_flags.aconfig
+++ b/core/java/android/view/flags/scroll_feedback_flags.aconfig
@@ -14,4 +14,11 @@
     name: "use_view_based_rotary_encoder_scroll_haptics"
     description: "If enabled, the rotary encoder scroll haptic implementation in the View class will be used, and the HapticScrollFeedbackProvider logic for rotary encoder haptic will be muted."
     bug: "299587011"
-}
\ No newline at end of file
+}
+
+flag {
+    namespace: "toolkit"
+    name: "enable_touch_scroll_feedback"
+    description: "Enables touchscreen haptic scroll feedback"
+    bug: "331830899"
+}
diff --git a/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java b/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java
index 2f515fe..3a008aa 100644
--- a/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java
+++ b/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java
@@ -323,14 +323,14 @@
     static boolean showSoftInput(@NonNull IInputMethodClient client, @Nullable IBinder windowToken,
             @NonNull ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
             int lastClickToolType, @Nullable ResultReceiver resultReceiver,
-            @SoftInputShowHideReason int reason) {
+            @SoftInputShowHideReason int reason, boolean async) {
         final IInputMethodManager service = getService();
         if (service == null) {
             return false;
         }
         try {
             return service.showSoftInput(client, windowToken, statsToken, flags, lastClickToolType,
-                    resultReceiver, reason);
+                    resultReceiver, reason, async);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -339,14 +339,15 @@
     @AnyThread
     static boolean hideSoftInput(@NonNull IInputMethodClient client, @Nullable IBinder windowToken,
             @NonNull ImeTracker.Token statsToken, @InputMethodManager.HideFlags int flags,
-            @Nullable ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
+            @Nullable ResultReceiver resultReceiver, @SoftInputShowHideReason int reason,
+            boolean async) {
         final IInputMethodManager service = getService();
         if (service == null) {
             return false;
         }
         try {
             return service.hideSoftInput(client, windowToken, statsToken, flags, resultReceiver,
-                    reason);
+                    reason, async);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -407,7 +408,7 @@
             @Nullable IRemoteInputConnection remoteInputConnection,
             @Nullable IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
             int unverifiedTargetSdkVersion, @UserIdInt int userId,
-            @NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
+            @NonNull ImeOnBackInvokedDispatcher imeDispatcher, boolean useAsyncShowHideMethod) {
         final IInputMethodManager service = getService();
         if (service == null) {
             return -1;
@@ -416,7 +417,7 @@
             service.startInputOrWindowGainedFocusAsync(startInputReason, client, windowToken,
                     startInputFlags, softInputMode, windowFlags, editorInfo, remoteInputConnection,
                     remoteAccessibilityInputConnection, unverifiedTargetSdkVersion, userId,
-                    imeDispatcher, advanceAngGetStartInputSequenceNumber());
+                    imeDispatcher, advanceAngGetStartInputSequenceNumber(), useAsyncShowHideMethod);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 23d7732..2f649c2 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -56,6 +56,7 @@
 import android.annotation.UserIdInt;
 import android.app.ActivityThread;
 import android.app.PropertyInvalidatedCache;
+import android.app.compat.CompatChanges;
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledSince;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -441,6 +442,36 @@
     public static final long CLEAR_SHOW_FORCED_FLAG_WHEN_LEAVING = 214016041L; // This is a bug id.
 
     /**
+     * Use async method for {@link InputMethodManager#showSoftInput(View, int, ResultReceiver)},
+     * {@link InputMethodManager#showSoftInput(View, int)} and
+     * {@link InputMethodManager#hideSoftInputFromWindow(IBinder, int, ResultReceiver)},
+     * {@link InputMethodManager#hideSoftInputFromWindow(IBinder, int)} for apps targeting V+.
+     * <p>
+     * Apps can incorrectly rely on {@link InputMethodManager#showSoftInput(View, int)} and
+     * {@link InputMethodManager#hideSoftInputFromWindow(IBinder, int)} method return type
+     * to interpret result of a request rather than relying on {@link ResultReceiver}. The return
+     * type of the method was never documented to have accurate info of visibility but few apps
+     * incorrectly rely on it.
+     * <p>
+     * Starting Android V, we use async calls into system_server which returns {@code true} if
+     * method call was made but return type doesn't guarantee execution.
+     * Apps targeting older versions will fallback to existing behavior of calling synchronous
+     * methods which had undocumented result in return type.
+     *
+     * @hide
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM)
+    private static final long USE_ASYNC_SHOW_HIDE_METHOD = 352594277L; // This is a bug id.
+
+    /**
+     * Version-gating is guarded by bug-fix flag.
+     */
+    private static final boolean ASYNC_SHOW_HIDE_METHOD_ENABLED =
+            !Flags.compatchangeForZerojankproxy()
+                || CompatChanges.isChangeEnabled(USE_ASYNC_SHOW_HIDE_METHOD);
+
+    /**
      * If {@code true}, avoid calling the
      * {@link com.android.server.inputmethod.InputMethodManagerService InputMethodManagerService}
      * by skipping the call to {@link IInputMethodManager#startInputOrWindowGainedFocus}
@@ -2246,6 +2277,8 @@
      *             {@link View#isFocused view focus}, and its containing window has
      *             {@link View#hasWindowFocus window focus}. Otherwise the call fails and
      *             returns {@code false}.
+     * @return {@code true} if a request was sent to system_server, {@code false} otherwise. Note:
+     * this does not return result of the request. For result use {@param resultReceiver} instead.
      */
     public boolean showSoftInput(View view, @ShowFlags int flags) {
         // Re-dispatch if there is a context mismatch.
@@ -2315,6 +2348,8 @@
      * code you receive may be either {@link #RESULT_UNCHANGED_SHOWN},
      * {@link #RESULT_UNCHANGED_HIDDEN}, {@link #RESULT_SHOWN}, or
      * {@link #RESULT_HIDDEN}.
+     * @return {@code true} if a request was sent to system_server, {@code false} otherwise. Note:
+     * this does not return result of the request. For result use {@param resultReceiver} instead.
      */
     public boolean showSoftInput(View view, @ShowFlags int flags, ResultReceiver resultReceiver) {
         return showSoftInput(view, flags, resultReceiver, SoftInputShowHideReason.SHOW_SOFT_INPUT);
@@ -2383,7 +2418,8 @@
                         flags,
                         mCurRootView.getLastClickToolType(),
                         resultReceiver,
-                        reason);
+                        reason,
+                        ASYNC_SHOW_HIDE_METHOD_ENABLED);
             }
         }
     }
@@ -2426,7 +2462,8 @@
                     flags,
                     mCurRootView.getLastClickToolType(),
                     resultReceiver,
-                    reason);
+                    reason,
+                    ASYNC_SHOW_HIDE_METHOD_ENABLED);
         }
     }
 
@@ -2459,6 +2496,9 @@
      *
      * @param windowToken The token of the window that is making the request,
      * as returned by {@link View#getWindowToken() View.getWindowToken()}.
+     * @return {@code true} if a request was sent to system_server, {@code false} otherwise. Note:
+     * this does not return result of the request. For result use {@link ResultReceiver} in
+     * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)} instead.
      */
     public boolean hideSoftInputFromWindow(IBinder windowToken, @HideFlags int flags) {
         return hideSoftInputFromWindow(windowToken, flags, null);
@@ -2487,6 +2527,8 @@
      * code you receive may be either {@link #RESULT_UNCHANGED_SHOWN},
      * {@link #RESULT_UNCHANGED_HIDDEN}, {@link #RESULT_SHOWN}, or
      * {@link #RESULT_HIDDEN}.
+     * @return {@code true} if a request was sent to system_server, {@code false} otherwise. Note:
+     * this does not return result of the request. For result use {@param resultReceiver} instead.
      */
     public boolean hideSoftInputFromWindow(IBinder windowToken, @HideFlags int flags,
             ResultReceiver resultReceiver) {
@@ -2530,7 +2572,7 @@
                 return true;
             } else {
                 return IInputMethodManagerGlobalInvoker.hideSoftInput(mClient, windowToken,
-                        statsToken, flags, resultReceiver, reason);
+                        statsToken, flags, resultReceiver, reason, ASYNC_SHOW_HIDE_METHOD_ENABLED);
             }
         }
     }
@@ -2573,7 +2615,7 @@
             ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
 
             return IInputMethodManagerGlobalInvoker.hideSoftInput(mClient, view.getWindowToken(),
-                    statsToken, flags, null, reason);
+                    statsToken, flags, null, reason, ASYNC_SHOW_HIDE_METHOD_ENABLED);
         }
     }
 
@@ -3350,7 +3392,7 @@
                         servedInputConnection == null ? null
                                 : servedInputConnection.asIRemoteAccessibilityInputConnection(),
                         view.getContext().getApplicationInfo().targetSdkVersion, targetUserId,
-                        mImeDispatcher);
+                        mImeDispatcher, ASYNC_SHOW_HIDE_METHOD_ENABLED);
             } else {
                 res = IInputMethodManagerGlobalInvoker.startInputOrWindowGainedFocus(
                         startInputReason, mClient, windowGainingFocus, startInputFlags,
@@ -3653,7 +3695,8 @@
                     statsToken,
                     HIDE_NOT_ALWAYS,
                     null,
-                    reason);
+                    reason,
+                    true /*async */);
         }
     }
 
@@ -3745,7 +3788,7 @@
 
             IInputMethodManagerGlobalInvoker.hideSoftInput(mClient, windowToken, statsToken,
                     0 /* flags */, null /* resultReceiver */,
-                    SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API);
+                    SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API, true /* async */);
         }
     }
 
diff --git a/core/java/android/view/inputmethod/flags.aconfig b/core/java/android/view/inputmethod/flags.aconfig
index e294ee2..bae8aff 100644
--- a/core/java/android/view/inputmethod/flags.aconfig
+++ b/core/java/android/view/inputmethod/flags.aconfig
@@ -136,3 +136,14 @@
     purpose: PURPOSE_BUGFIX
   }
 }
+
+flag {
+  name: "compatchange_for_zerojankproxy"
+  namespace: "input_method"
+  description: "Version-gate the sync/async nature of IMM#show/hideSoftInput() when using zeroJankProxy."
+  bug: "352594277"
+  is_fixed_read_only: true
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index f336b5d..ffe8c80 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -3088,11 +3088,11 @@
         }
 
         if (Flags.updateServiceIpcWrapper()) {
-            WebViewUpdateManager manager = WebViewUpdateManager.getInstance();
-            if (manager == null) {
+            if (WebViewFactory.isWebViewSupported()) {
+                return WebViewUpdateManager.getInstance().getCurrentWebViewPackage();
+            } else {
                 return null;
             }
-            return manager.getCurrentWebViewPackage();
         } else {
             IWebViewUpdateService service = WebViewFactory.getUpdateService();
             if (service == null) {
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index f532934..e10a398 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -208,7 +208,7 @@
         public MissingWebViewPackageException(Exception e) { super(e); }
     }
 
-    private static boolean isWebViewSupported() {
+    static boolean isWebViewSupported() {
         // No lock; this is a benign race as Boolean's state is final and the PackageManager call
         // will always return the same value.
         if (sWebViewSupported == null) {
diff --git a/core/java/android/webkit/WebViewUpdateManager.java b/core/java/android/webkit/WebViewUpdateManager.java
index dd48df9..0eb71001 100644
--- a/core/java/android/webkit/WebViewUpdateManager.java
+++ b/core/java/android/webkit/WebViewUpdateManager.java
@@ -19,12 +19,14 @@
 import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.app.SystemServiceRegistry;
 import android.content.Context;
 import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
 import android.os.RemoteException;
 
 /** @hide */
@@ -43,8 +45,11 @@
      *
      * This exists for the benefit of callsites without a {@link Context}; prefer
      * {@link Context#getSystemService(Class)} otherwise.
+     *
+     * This can only be used on devices with {@link PackageManager#FEATURE_WEBVIEW}.
      */
     @SuppressLint("ManagerLookup") // service opts in to getSystemServiceWithNoContext()
+    @RequiresFeature(PackageManager.FEATURE_WEBVIEW)
     public static @Nullable WebViewUpdateManager getInstance() {
         return (WebViewUpdateManager) SystemServiceRegistry.getSystemServiceWithNoContext(
                 Context.WEBVIEW_UPDATE_SERVICE);
diff --git a/core/java/android/webkit/WebViewUpdateService.java b/core/java/android/webkit/WebViewUpdateService.java
index 6f53dde..01af182 100644
--- a/core/java/android/webkit/WebViewUpdateService.java
+++ b/core/java/android/webkit/WebViewUpdateService.java
@@ -34,11 +34,11 @@
      */
     public static WebViewProviderInfo[] getAllWebViewPackages() {
         if (Flags.updateServiceIpcWrapper()) {
-            WebViewUpdateManager manager = WebViewUpdateManager.getInstance();
-            if (manager == null) {
+            if (WebViewFactory.isWebViewSupported()) {
+                return WebViewUpdateManager.getInstance().getAllWebViewPackages();
+            } else {
                 return new WebViewProviderInfo[0];
             }
-            return manager.getAllWebViewPackages();
         } else {
             IWebViewUpdateService service = getUpdateService();
             if (service == null) {
@@ -57,11 +57,11 @@
      */
     public static WebViewProviderInfo[] getValidWebViewPackages() {
         if (Flags.updateServiceIpcWrapper()) {
-            WebViewUpdateManager manager = WebViewUpdateManager.getInstance();
-            if (manager == null) {
+            if (WebViewFactory.isWebViewSupported()) {
+                return WebViewUpdateManager.getInstance().getValidWebViewPackages();
+            } else {
                 return new WebViewProviderInfo[0];
             }
-            return manager.getValidWebViewPackages();
         } else {
             IWebViewUpdateService service = getUpdateService();
             if (service == null) {
@@ -80,11 +80,11 @@
      */
     public static String getCurrentWebViewPackageName() {
         if (Flags.updateServiceIpcWrapper()) {
-            WebViewUpdateManager manager = WebViewUpdateManager.getInstance();
-            if (manager == null) {
+            if (WebViewFactory.isWebViewSupported()) {
+                return WebViewUpdateManager.getInstance().getCurrentWebViewPackageName();
+            } else {
                 return null;
             }
-            return manager.getCurrentWebViewPackageName();
         } else {
             IWebViewUpdateService service = getUpdateService();
             if (service == null) {
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index ab6b512..3c854ea 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -16,6 +16,8 @@
 
 package android.widget;
 
+import static android.view.flags.Flags.enableTouchScrollFeedback;
+import static android.view.flags.Flags.scrollFeedbackApi;
 import static android.view.flags.Flags.viewVelocityApi;
 
 import android.annotation.ColorInt;
@@ -82,7 +84,6 @@
 import android.view.autofill.AutofillId;
 import android.view.contentcapture.ContentCaptureManager;
 import android.view.contentcapture.ContentCaptureSession;
-import android.view.flags.Flags;
 import android.view.inputmethod.BaseInputConnection;
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.CorrectionInfo;
@@ -3703,7 +3704,6 @@
                 // If it's non-null, we're already in a scroll.
                 mScrollStrictSpan = StrictMode.enterCriticalSpan("AbsListView-scroll");
             }
-
             if (y != mLastY) {
                 // We may be here after stopping a fling and continuing to scroll.
                 // If so, we haven't disallowed intercepting touch events yet.
@@ -3735,8 +3735,15 @@
                 boolean atEdge = false;
                 if (incrementalDeltaY != 0) {
                     atEdge = trackMotionScroll(deltaY, incrementalDeltaY);
-                }
 
+                    // TODO: b/360198915 - Add unit testing for using ScrollFeedbackProvider
+                    if (enableTouchScrollFeedback()) {
+                        initHapticScrollFeedbackProviderIfNotExists();
+                        mHapticScrollFeedbackProvider.onScrollProgress(
+                                vtev.getDeviceId(), vtev.getSource(), MotionEvent.AXIS_Y,
+                                incrementalDeltaY);
+                    }
+                }
                 // Check to see if we have bumped into the scroll limit
                 motionView = this.getChildAt(motionIndex);
                 if (motionView != null) {
@@ -3745,7 +3752,6 @@
                     final int motionViewRealTop = motionView.getTop();
                     if (atEdge) {
                         // Apply overscroll
-
                         int overscroll = -incrementalDeltaY -
                                 (motionViewRealTop - motionViewPrevTop);
                         if (dispatchNestedScroll(0, overscroll - incrementalDeltaY, 0, overscroll,
@@ -3772,6 +3778,15 @@
                                     mDirection = 0; // Reset when entering overscroll.
                                     mTouchMode = TOUCH_MODE_OVERSCROLL;
                                 }
+
+                                if (enableTouchScrollFeedback()) {
+                                    initHapticScrollFeedbackProviderIfNotExists();
+                                    mHapticScrollFeedbackProvider.onScrollLimit(
+                                            vtev.getDeviceId(), vtev.getSource(),
+                                            MotionEvent.AXIS_Y,
+                                            /* isStart= */ incrementalDeltaY > 0);
+                                }
+
                                 if (incrementalDeltaY > 0) {
                                     mEdgeGlowTop.onPullDistance((float) -overscroll / getHeight(),
                                             (float) x / getWidth());
@@ -3981,7 +3996,6 @@
         if (mFastScroll != null && mFastScroll.onTouchEvent(ev)) {
             return true;
         }
-
         initVelocityTrackerIfNotExists();
         final MotionEvent vtev = MotionEvent.obtain(ev);
 
@@ -4520,7 +4534,7 @@
                     final int overscrollMode = getOverScrollMode();
 
                     if (!trackMotionScroll(delta, delta)) {
-                        if (Flags.scrollFeedbackApi()) {
+                        if (scrollFeedbackApi()) {
                             initHapticScrollFeedbackProviderIfNotExists();
                             mHapticScrollFeedbackProvider.onScrollProgress(
                                     event.getDeviceId(), event.getSource(), axis, delta);
@@ -4536,7 +4550,7 @@
                         float overscroll = (delta - (motionViewRealTop - motionViewPrevTop))
                                 / ((float) getHeight());
                         boolean hitTopLimit = delta > 0;
-                        if (Flags.scrollFeedbackApi()) {
+                        if (scrollFeedbackApi()) {
                             initHapticScrollFeedbackProviderIfNotExists();
                             mHapticScrollFeedbackProvider.onScrollLimit(
                                     event.getDeviceId(), event.getSource(), axis,
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index a346a67..a4b28ad 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -14375,7 +14375,7 @@
 
         Matrix matrix = mTempMatrix;
         matrix.reset();
-        transformMatrixToLocal(matrix);
+        transformMatrixRootToLocal(matrix);
         editorBounds.set(rect);
         // When the view has transformations like scaleX/scaleY computing the global visible
         // rectangle will already apply the transformations. The getLocalVisibleRect only offsets
diff --git a/core/java/android/window/SnapshotDrawerUtils.java b/core/java/android/window/SnapshotDrawerUtils.java
index 2f595d1..9a7bce0 100644
--- a/core/java/android/window/SnapshotDrawerUtils.java
+++ b/core/java/android/window/SnapshotDrawerUtils.java
@@ -151,9 +151,11 @@
         @VisibleForTesting
         public void setFrames(Rect frame, Rect systemBarInsets) {
             mFrame.set(frame);
-            mSystemBarInsets.set(systemBarInsets);
             mSizeMismatch = (mFrame.width() != mSnapshotW || mFrame.height() != mSnapshotH);
-            mSystemBarBackgroundPainter.setInsets(systemBarInsets);
+            if (!Flags.drawSnapshotAspectRatioMatch() && systemBarInsets != null) {
+                mSystemBarInsets.set(systemBarInsets);
+                mSystemBarBackgroundPainter.setInsets(systemBarInsets);
+            }
         }
 
         private void drawSnapshot(boolean releaseAfterDraw) {
@@ -394,9 +396,12 @@
         final ActivityManager.RunningTaskInfo runningTaskInfo = info.taskInfo;
         final ActivityManager.TaskDescription taskDescription =
                 getOrCreateTaskDescription(runningTaskInfo);
-        drawSurface.initiateSystemBarPainter(lp.flags, lp.privateFlags,
-                attrs.insetsFlags.appearance, taskDescription, info.requestedVisibleTypes);
-        final Rect systemBarInsets = getSystemBarInsets(windowBounds, topWindowInsetsState);
+        Rect systemBarInsets = null;
+        if (!Flags.drawSnapshotAspectRatioMatch()) {
+            drawSurface.initiateSystemBarPainter(lp.flags, lp.privateFlags,
+                    attrs.insetsFlags.appearance, taskDescription, info.requestedVisibleTypes);
+            systemBarInsets = getSystemBarInsets(windowBounds, topWindowInsetsState);
+        }
         drawSurface.setFrames(windowBounds, systemBarInsets);
         drawSurface.drawSnapshot(releaseAfterDraw);
     }
diff --git a/core/java/android/window/TaskFragmentParentInfo.java b/core/java/android/window/TaskFragmentParentInfo.java
index 1555416..efd74c3 100644
--- a/core/java/android/window/TaskFragmentParentInfo.java
+++ b/core/java/android/window/TaskFragmentParentInfo.java
@@ -41,6 +41,8 @@
 
     private final int mDisplayId;
 
+    private final int mTaskId;
+
     private final boolean mVisible;
 
     private final boolean mHasDirectActivity;
@@ -49,9 +51,11 @@
 
     /** @hide */
     public TaskFragmentParentInfo(@NonNull Configuration configuration, int displayId,
-            boolean visible, boolean hasDirectActivity, @Nullable SurfaceControl decorSurface) {
+            int taskId, boolean visible, boolean hasDirectActivity,
+            @Nullable SurfaceControl decorSurface) {
         mConfiguration.setTo(configuration);
         mDisplayId = displayId;
+        mTaskId = taskId;
         mVisible = visible;
         mHasDirectActivity = hasDirectActivity;
         mDecorSurface = decorSurface;
@@ -61,6 +65,7 @@
     public TaskFragmentParentInfo(@NonNull TaskFragmentParentInfo info) {
         mConfiguration.setTo(info.getConfiguration());
         mDisplayId = info.mDisplayId;
+        mTaskId = info.mTaskId;
         mVisible = info.mVisible;
         mHasDirectActivity = info.mHasDirectActivity;
         mDecorSurface = info.mDecorSurface;
@@ -87,6 +92,15 @@
     }
 
     /**
+     * The id of the parent Task.
+     *
+     * @hide
+     */
+    public int getTaskId() {
+        return mTaskId;
+    }
+
+    /**
      * Whether the parent Task is visible or not
      *
      * @hide
@@ -120,7 +134,8 @@
             return false;
         }
         return getWindowingMode() == that.getWindowingMode() && mDisplayId == that.mDisplayId
-                && mVisible == that.mVisible && mHasDirectActivity == that.mHasDirectActivity
+                && mTaskId == that.mTaskId && mVisible == that.mVisible
+                && mHasDirectActivity == that.mHasDirectActivity
                 && mDecorSurface == that.mDecorSurface;
     }
 
@@ -140,6 +155,7 @@
         return TaskFragmentParentInfo.class.getSimpleName() + ":{"
                 + "config=" + mConfiguration
                 + ", displayId=" + mDisplayId
+                + ", taskId=" + mTaskId
                 + ", visible=" + mVisible
                 + ", hasDirectActivity=" + mHasDirectActivity
                 + ", decorSurface=" + mDecorSurface
@@ -163,6 +179,7 @@
         final TaskFragmentParentInfo that = (TaskFragmentParentInfo) obj;
         return mConfiguration.equals(that.mConfiguration)
                 && mDisplayId == that.mDisplayId
+                && mTaskId == that.mTaskId
                 && mVisible == that.mVisible
                 && mHasDirectActivity == that.mHasDirectActivity
                 && mDecorSurface == that.mDecorSurface;
@@ -172,6 +189,7 @@
     public int hashCode() {
         int result = mConfiguration.hashCode();
         result = 31 * result + mDisplayId;
+        result = 31 * result + mTaskId;
         result = 31 * result + (mVisible ? 1 : 0);
         result = 31 * result + (mHasDirectActivity ? 1 : 0);
         result = 31 * result + Objects.hashCode(mDecorSurface);
@@ -183,6 +201,7 @@
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         mConfiguration.writeToParcel(dest, flags);
         dest.writeInt(mDisplayId);
+        dest.writeInt(mTaskId);
         dest.writeBoolean(mVisible);
         dest.writeBoolean(mHasDirectActivity);
         dest.writeTypedObject(mDecorSurface, flags);
@@ -191,6 +210,7 @@
     private TaskFragmentParentInfo(Parcel in) {
         mConfiguration.readFromParcel(in);
         mDisplayId = in.readInt();
+        mTaskId = in.readInt();
         mVisible = in.readBoolean();
         mHasDirectActivity = in.readBoolean();
         mDecorSurface = in.readTypedObject(SurfaceControl.CREATOR);
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index ebf87f1..cab6d8e 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -245,3 +245,10 @@
       purpose: PURPOSE_BUGFIX
     }
 }
+
+flag {
+    name: "enable_desktop_windowing_persistence"
+    namespace: "lse_desktop_experience"
+    description: "Persists the desktop windowing session across reboots."
+    bug: "350456942"
+}
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index 53ef49b..d474c6d 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -127,7 +127,7 @@
     private Runnable mWaitForFinishTimedOut;
 
     private static class JankInfo {
-        long frameVsyncId;
+        final long frameVsyncId;
         long totalDurationNanos;
         boolean isFirstFrame;
         boolean hwuiCallbackFired;
@@ -135,29 +135,42 @@
         @JankType int jankType;
         @RefreshRate int refreshRate;
 
-        static JankInfo createFromHwuiCallback(long frameVsyncId, long totalDurationNanos,
-                boolean isFirstFrame) {
-            return new JankInfo(frameVsyncId, true, false, JANK_NONE, UNKNOWN_REFRESH_RATE,
-                    totalDurationNanos, isFirstFrame);
+        static JankInfo createFromHwuiCallback(
+                long frameVsyncId, long totalDurationNanos, boolean isFirstFrame) {
+            return new JankInfo(frameVsyncId).update(totalDurationNanos, isFirstFrame);
         }
 
-        static JankInfo createFromSurfaceControlCallback(long frameVsyncId,
-                @JankType int jankType, @RefreshRate int refreshRate) {
-            return new JankInfo(
-                    frameVsyncId, false, true, jankType, refreshRate, 0, false /* isFirstFrame */);
+        static JankInfo createFromSurfaceControlCallback(SurfaceControl.JankData jankStat) {
+            return new JankInfo(jankStat.frameVsyncId).update(jankStat);
         }
 
-        private JankInfo(long frameVsyncId, boolean hwuiCallbackFired,
-                boolean surfaceControlCallbackFired, @JankType int jankType,
-                @RefreshRate int refreshRate,
-                long totalDurationNanos, boolean isFirstFrame) {
+        private JankInfo(long frameVsyncId) {
             this.frameVsyncId = frameVsyncId;
-            this.hwuiCallbackFired = hwuiCallbackFired;
-            this.surfaceControlCallbackFired = surfaceControlCallbackFired;
-            this.jankType = jankType;
-            this.refreshRate = refreshRate;
-            this.totalDurationNanos = totalDurationNanos;
+            this.hwuiCallbackFired = false;
+            this.surfaceControlCallbackFired = false;
+            this.jankType = JANK_NONE;
+            this.refreshRate = UNKNOWN_REFRESH_RATE;
+            this.totalDurationNanos = 0;
+            this.isFirstFrame = false;
+        }
+
+        private JankInfo update(SurfaceControl.JankData jankStat) {
+            this.surfaceControlCallbackFired = true;
+            this.jankType = jankStat.jankType;
+            this.refreshRate = DisplayRefreshRate.getRefreshRate(jankStat.frameIntervalNs);
+            if (Flags.useSfFrameDuration()) {
+                this.totalDurationNanos = jankStat.actualAppFrameTimeNs;
+            }
+            return this;
+        }
+
+        private JankInfo update(long totalDurationNanos, boolean isFirstFrame) {
+            this.hwuiCallbackFired = true;
+            if (!Flags.useSfFrameDuration()) {
+                this.totalDurationNanos = totalDurationNanos;
+            }
             this.isFirstFrame = isFirstFrame;
+            return this;
         }
 
         @Override
@@ -457,16 +470,12 @@
                 if (!isInRange(jankStat.frameVsyncId)) {
                     continue;
                 }
-                int refreshRate = DisplayRefreshRate.getRefreshRate(jankStat.frameIntervalNs);
                 JankInfo info = findJankInfo(jankStat.frameVsyncId);
                 if (info != null) {
-                    info.surfaceControlCallbackFired = true;
-                    info.jankType = jankStat.jankType;
-                    info.refreshRate = refreshRate;
+                    info.update(jankStat);
                 } else {
                     mJankInfos.put((int) jankStat.frameVsyncId,
-                            JankInfo.createFromSurfaceControlCallback(
-                                    jankStat.frameVsyncId, jankStat.jankType, refreshRate));
+                            JankInfo.createFromSurfaceControlCallback(jankStat));
                 }
             }
             processJankInfos();
@@ -513,9 +522,7 @@
             }
             JankInfo info = findJankInfo(frameVsyncId);
             if (info != null) {
-                info.hwuiCallbackFired = true;
-                info.totalDurationNanos = totalDurationNanos;
-                info.isFirstFrame = isFirstFrame;
+                info.update(totalDurationNanos, isFirstFrame);
             } else {
                 mJankInfos.put((int) frameVsyncId, JankInfo.createFromHwuiCallback(
                         frameVsyncId, totalDurationNanos, isFirstFrame));
diff --git a/core/java/com/android/internal/jank/flags.aconfig b/core/java/com/android/internal/jank/flags.aconfig
new file mode 100644
index 0000000..b6b8bc5
--- /dev/null
+++ b/core/java/com/android/internal/jank/flags.aconfig
@@ -0,0 +1,10 @@
+package: "com.android.internal.jank"
+container: "system"
+
+flag {
+  name: "use_sf_frame_duration"
+  namespace: "android_platform_window_surfaces"
+  description: "Whether to get the frame duration from SurfaceFlinger, or HWUI"
+  bug: "354763298"
+  is_fixed_read_only: true
+}
diff --git a/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java b/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java
index ee3a3c2..319efe0 100644
--- a/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java
+++ b/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java
@@ -60,7 +60,9 @@
     public static void ensureRavenwoodInitialized() {
     }
 
-    private static native void ensureRavenwoodInitialized$ravenwood();
+    private static void ensureRavenwoodInitialized$ravenwood() {
+        nativeEnsureRavenwoodInitialized();
+    }
 
     /**
      * USE IT SPARINGLY! Returns true if it's running on Ravenwood, hostside test environment.
@@ -92,7 +94,9 @@
         throw notSupportedOnDevice();
     }
 
-    private native <T> T fromAddress$ravenwood(long address);
+    private <T> T fromAddress$ravenwood(long address) {
+        return nativeFromAddress(address);
+    }
 
     /**
      * See {@link Workaround}. It's only usable on Ravenwood.
@@ -114,7 +118,14 @@
         throw notSupportedOnDevice();
     }
 
-    private native String getRavenwoodRuntimePath$ravenwood();
+    private String getRavenwoodRuntimePath$ravenwood() {
+        return nativeGetRavenwoodRuntimePath();
+    }
+
+    // Private native methods that are actually substituted on Ravenwood
+    private native <T> T nativeFromAddress(long address);
+    private native String nativeGetRavenwoodRuntimePath();
+    private static native void nativeEnsureRavenwoodInitialized();
 
     /**
      * A set of APIs used to work around missing features on Ravenwood. Ideally, this class should
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index b51678e..efbf887 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -76,10 +76,10 @@
 
     boolean showSoftInput(in IInputMethodClient client, @nullable IBinder windowToken,
             in ImeTracker.Token statsToken, int flags, int lastClickToolType,
-            in @nullable ResultReceiver resultReceiver, int reason);
+            in @nullable ResultReceiver resultReceiver, int reason, boolean async);
     boolean hideSoftInput(in IInputMethodClient client, @nullable IBinder windowToken,
             in ImeTracker.Token statsToken, int flags,
-            in @nullable ResultReceiver resultReceiver, int reason);
+            in @nullable ResultReceiver resultReceiver, int reason, boolean async);
 
     /**
      * A test API for CTS to request hiding the current soft input window, with the request origin
@@ -120,7 +120,8 @@
             in @nullable EditorInfo editorInfo, in @nullable IRemoteInputConnection inputConnection,
             in @nullable IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
             int unverifiedTargetSdkVersion, int userId,
-            in ImeOnBackInvokedDispatcher imeDispatcher, int startInputSeq);
+            in ImeOnBackInvokedDispatcher imeDispatcher, int startInputSeq,
+            boolean useAsyncShowHideMethod);
 
     void showInputMethodPickerFromClient(in IInputMethodClient client,
             int auxiliarySubtypeMode);
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 46710b5..9bccf5a 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -3379,44 +3379,39 @@
   public:
     JavaSystemPropertyListener(JNIEnv* env, jobject javaCallback, std::string sysPropName) :
             mCallback {javaCallback, env},
-            mPi {__system_property_find(sysPropName.c_str())},
+            mSysPropName(sysPropName),
+            mCachedProperty(android::base::CachedProperty{std::move(sysPropName)}),
             mListenerThread([this](mediautils::stop_token stok) mutable {
-                static const struct timespec close_delay = { .tv_sec = 1 };
                 while (!stok.stop_requested()) {
-                    uint32_t old_serial = mSerial.load();
-                    uint32_t new_serial;
-                    if (__system_property_wait(mPi, old_serial, &new_serial, &close_delay)) {
-                        while (new_serial > old_serial) {
-                            if (mSerial.compare_exchange_weak(old_serial, new_serial)) {
-                                fireUpdate();
-                                break;
-                            }
-                        }
-                    }
+                    using namespace std::chrono_literals;
+                    // 1s timeout so this thread can eventually respond to the stop token
+                    std::string newVal = mCachedProperty.WaitForChange(1000ms) ?: "";
+                    updateValue(newVal);
                 }
             }) {}
 
     void triggerUpdateIfChanged() {
-        uint32_t old_serial = mSerial.load();
-        uint32_t new_serial = __system_property_serial(mPi);
-        while (new_serial > old_serial) {
-            if (mSerial.compare_exchange_weak(old_serial, new_serial)) {
-                fireUpdate();
-                break;
-            }
-        }
+        // We must check the property without using the cached property due to thread safety issues
+        std::string newVal = base::GetProperty(mSysPropName, "");
+        updateValue(newVal);
     }
 
   private:
-    void fireUpdate() {
+    void updateValue(std::string newVal) {
+        if (newVal == "") return;
+        std::lock_guard l{mLock};
+        if (mLastVal == newVal) return;
         const auto threadEnv = GetOrAttachJNIEnvironment(gVm);
         threadEnv->CallVoidMethod(mCallback.get(), gRunnableClassInfo.run);
+        mLastVal = std::move(newVal);
     }
 
     // Should outlive thread object
     const GlobalRef mCallback;
-    const prop_info * const mPi;
-    std::atomic<uint32_t> mSerial = 0;
+    const std::string mSysPropName;
+    android::base::CachedProperty mCachedProperty;
+    std::string mLastVal = "";
+    std::mutex mLock;
     const mediautils::jthread mListenerThread;
 };
 
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 46b4695..921b77d 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -56,11 +56,11 @@
 //#undef ALOGV
 //#define ALOGV(...) fprintf(stderr, __VA_ARGS__)
 
-#define DEBUG_DEATH 0
-#if DEBUG_DEATH
-#define LOGDEATH ALOGD
+#define DEBUG_DEATH_FREEZE 0
+#if DEBUG_DEATH_FREEZE
+#define LOG_DEATH_FREEZE ALOGD
 #else
-#define LOGDEATH ALOGV
+#define LOG_DEATH_FREEZE ALOGV
 #endif
 
 using namespace android;
@@ -116,6 +116,7 @@
     jclass mClass;
     jmethodID mGetInstance;
     jmethodID mSendDeathNotice;
+    jmethodID mInvokeFrozenStateChangeCallback;
 
     // Object state.
     jfieldID mNativeData;  // Field holds native pointer to BinderProxyNativeData.
@@ -547,23 +548,59 @@
 
 // ----------------------------------------------------------------------------
 
-// Per-IBinder death recipient bookkeeping.  This is how we reconcile local jobject
-// death recipient references passed in through JNI with the permanent corresponding
-// JavaDeathRecipient objects.
+// A JavaRecipient receives either death notifications or frozen state change
+// callbacks from natve code (IBinder) and dispatch the notifications to its
+// corresponding Java listener object.
+//
+// A RecipientList keeps tracks of all JavaRecipients for an IBinder. This way
+// we can find a JavaRecipient given a Java listener object.
+//
+// The implementation is shared between death recipients and frozen state change
+// callbacks via template. For death recipients the template is instantiated as
+// follows:
+//
+//                   IBinder::DeathRecipient
+//                            ^
+//                            |
+//                        (inherits)
+//                            |
+//            JavaRecipient<IBinder::DeathRecipient> <----> RecipientList<IBinder::DeathRecipient>
+//                            ^
+//                            |
+//                        (inherits)
+//                            |
+//                    JavaDeathRecipient
+//
+//
+// The instantiation for frozen state change callbacks are:
+//
+//             IBinder::FrozenStateChangeCallback
+//                           ^
+//                           |
+//                       (inherits)
+//                           |
+//     JavaRecipient<IBinder::FrozenStateChangeCallback>
+//                           ^                ^
+//                           |                |
+//                       (inherits)           +--> RecipientList<IBinder::FrozenStateChangeCallback>
+//                           |
+//              JavaFrozenStateChangeCallback
 
-class JavaDeathRecipient;
+template <typename T>
+class JavaRecipient;
 
-class DeathRecipientList : public RefBase {
-    List< sp<JavaDeathRecipient> > mList;
+template <typename T>
+class RecipientList : public RefBase {
+    List<sp<JavaRecipient<T> > > mList;
     Mutex mLock;
 
 public:
-    DeathRecipientList();
-    ~DeathRecipientList();
+    RecipientList();
+    ~RecipientList();
 
-    void add(const sp<JavaDeathRecipient>& recipient);
-    void remove(const sp<JavaDeathRecipient>& recipient);
-    sp<JavaDeathRecipient> find(jobject recipient);
+    void add(const sp<JavaRecipient<T> >& recipient);
+    void remove(const sp<JavaRecipient<T> >& recipient);
+    sp<JavaRecipient<T> > find(jobject recipient);
 
     Mutex& lock();  // Use with care; specifically for mutual exclusion during binder death
 };
@@ -584,11 +621,113 @@
 #endif // __BIONIC__
 #endif // BINDER_DEATH_RECIPIENT_WEAK_FROM_JNI
 
-class JavaDeathRecipient : public IBinder::DeathRecipient
-{
+template <typename T>
+constexpr const char* logPrefix();
+
+template <>
+constexpr const char* logPrefix<IBinder::DeathRecipient>() {
+    return "[DEATH]";
+}
+
+template <>
+constexpr const char* logPrefix<IBinder::FrozenStateChangeCallback>() {
+    return "[FREEZE]";
+}
+
+template <typename T>
+class JavaRecipient : public T {
 public:
-    JavaDeathRecipient(JNIEnv* env, jobject object, const sp<DeathRecipientList>& list)
+    JavaRecipient(JNIEnv* env, jobject object, const sp<RecipientList<T> >& list,
+                  bool useWeakReference)
           : mVM(jnienv_to_javavm(env)), mObject(NULL), mObjectWeak(NULL), mList(list) {
+        if (useWeakReference) {
+            mObjectWeak = env->NewWeakGlobalRef(object);
+        } else {
+            mObject = env->NewGlobalRef(object);
+        }
+        // These objects manage their own lifetimes so are responsible for final bookkeeping.
+        // The list holds a strong reference to this object.
+        LOG_DEATH_FREEZE("%s Adding JavaRecipient %p to RecipientList %p", logPrefix<T>(), this,
+                         list.get());
+        list->add(this);
+    }
+
+    void clearReference() {
+        sp<RecipientList<T> > list = mList.promote();
+        if (list != NULL) {
+            LOG_DEATH_FREEZE("%s Removing JavaRecipient %p from RecipientList %p", logPrefix<T>(),
+                             this, list.get());
+            list->remove(this);
+        } else {
+            LOG_DEATH_FREEZE("%s clearReference() on JavaRecipient %p but RecipientList wp purged",
+                             logPrefix<T>(), this);
+        }
+    }
+
+    bool matches(jobject obj) {
+        bool result;
+        JNIEnv* env = javavm_to_jnienv(mVM);
+
+        if (mObject != NULL) {
+            result = env->IsSameObject(obj, mObject);
+        } else {
+            ScopedLocalRef<jobject> me(env, env->NewLocalRef(mObjectWeak));
+            result = env->IsSameObject(obj, me.get());
+        }
+        return result;
+    }
+
+    void warnIfStillLive() {
+        if (mObject != NULL) {
+            // Okay, something is wrong -- we have a hard reference to a live death
+            // recipient on the VM side, but the list is being torn down.
+            JNIEnv* env = javavm_to_jnienv(mVM);
+            ScopedLocalRef<jclass> objClassRef(env, env->GetObjectClass(mObject));
+            ScopedLocalRef<jstring> nameRef(env,
+                                            (jstring)env->CallObjectMethod(objClassRef.get(),
+                                                                           gClassOffsets.mGetName));
+            ScopedUtfChars nameUtf(env, nameRef.get());
+            if (nameUtf.c_str() != NULL) {
+                ALOGW("BinderProxy is being destroyed but the application did not call "
+                      "unlinkToDeath to unlink all of its death recipients beforehand.  "
+                      "Releasing leaked death recipient: %s",
+                      nameUtf.c_str());
+            } else {
+                ALOGW("BinderProxy being destroyed; unable to get DR object name");
+                env->ExceptionClear();
+            }
+        }
+    }
+
+protected:
+    virtual ~JavaRecipient() {
+        // ALOGI("Removing death ref: recipient=%p\n", mObject);
+        JNIEnv* env = javavm_to_jnienv(mVM);
+        if (mObject != NULL) {
+            env->DeleteGlobalRef(mObject);
+        } else {
+            env->DeleteWeakGlobalRef(mObjectWeak);
+        }
+    }
+
+    JavaVM* const mVM;
+
+    // If useWeakReference is false (e.g. JavaDeathRecipient when target sdk version < 35), the
+    // Java-side Recipient is strongly referenced from mObject initially, and may later be demoted
+    // to a weak reference (mObjectWeak), e.g. upon linkToDeath() and then after binderDied() is
+    // called.
+    // If useWeakReference is true, the strong reference is never made here (i.e. mObject == NULL
+    // always). Instead, the strong reference to the Java-side Recipient is made in
+    // BinderProxy.{mDeathRecipients,mFrozenStateChangeCallbacks}. In the native world, only the
+    // weak reference is kept.
+    jobject mObject;
+    jweak mObjectWeak;
+    wp<RecipientList<T> > mList;
+};
+
+class JavaDeathRecipient : public JavaRecipient<IBinder::DeathRecipient> {
+public:
+    static bool useWeakReference() {
         // b/298374304: For apps targeting Android V or beyond, we no longer hold the global JNI ref
         // to the death recipient objects. This is to prevent the memory leak which can happen when
         // the death recipient object internally has a strong reference to the proxy object. Under
@@ -604,25 +743,26 @@
         // reference to. If however you want to get binderDied() regardless of the proxy object's
         // lifecycle, keep a strong reference to the death recipient object by yourself.
 #ifdef BINDER_DEATH_RECIPIENT_WEAK_FROM_JNI
-        if (target_sdk_is_at_least_vic()) {
-            mObjectWeak = env->NewWeakGlobalRef(object);
-        } else
+        return target_sdk_is_at_least_vic();
+#else
+        return false;
 #endif
-        {
-            mObject = env->NewGlobalRef(object);
-        }
-        // These objects manage their own lifetimes so are responsible for final bookkeeping.
-        // The list holds a strong reference to this object.
-        LOGDEATH("Adding JDR %p to DRL %p", this, list.get());
-        list->add(this);
+    }
 
+    JavaDeathRecipient(JNIEnv* env, jobject object,
+                       const sp<RecipientList<IBinder::DeathRecipient> >& list)
+          : JavaRecipient(env, object, list, useWeakReference()) {
         gNumDeathRefsCreated.fetch_add(1, std::memory_order_relaxed);
         gcIfManyNewRefs(env);
     }
 
+    ~JavaDeathRecipient() {
+        gNumDeathRefsDeleted.fetch_add(1, std::memory_order_relaxed);
+    }
+
     void binderDied(const wp<IBinder>& who)
     {
-        LOGDEATH("Receiving binderDied() on JavaDeathRecipient %p\n", this);
+        LOG_DEATH_FREEZE("Receiving binderDied() on JavaDeathRecipient %p\n", this);
         if (mObject == NULL && mObjectWeak == NULL) {
             return;
         }
@@ -662,7 +802,7 @@
         // with our containing DeathRecipientList so that we can't delete the global ref on mObject
         // while the list is being iterated.
         if (mObject != NULL) {
-            sp<DeathRecipientList> list = mList.promote();
+            auto list = mList.promote();
             if (list != NULL) {
                 AutoMutex _l(list->lock());
 
@@ -673,126 +813,96 @@
         }
     }
 
-    void clearReference()
-    {
-        sp<DeathRecipientList> list = mList.promote();
-        if (list != NULL) {
-            LOGDEATH("Removing JDR %p from DRL %p", this, list.get());
-            list->remove(this);
-        } else {
-            LOGDEATH("clearReference() on JDR %p but DRL wp purged", this);
-        }
-    }
-
-    bool matches(jobject obj) {
-        bool result;
-        JNIEnv* env = javavm_to_jnienv(mVM);
-
-        if (mObject != NULL) {
-            result = env->IsSameObject(obj, mObject);
-        } else {
-            ScopedLocalRef<jobject> me(env, env->NewLocalRef(mObjectWeak));
-            result = env->IsSameObject(obj, me.get());
-        }
-        return result;
-    }
-
-    void warnIfStillLive() {
-        if (mObject != NULL) {
-            // Okay, something is wrong -- we have a hard reference to a live death
-            // recipient on the VM side, but the list is being torn down.
-            JNIEnv* env = javavm_to_jnienv(mVM);
-            ScopedLocalRef<jclass> objClassRef(env, env->GetObjectClass(mObject));
-            ScopedLocalRef<jstring> nameRef(env,
-                    (jstring) env->CallObjectMethod(objClassRef.get(), gClassOffsets.mGetName));
-            ScopedUtfChars nameUtf(env, nameRef.get());
-            if (nameUtf.c_str() != NULL) {
-                ALOGW("BinderProxy is being destroyed but the application did not call "
-                        "unlinkToDeath to unlink all of its death recipients beforehand.  "
-                        "Releasing leaked death recipient: %s", nameUtf.c_str());
-            } else {
-                ALOGW("BinderProxy being destroyed; unable to get DR object name");
-                env->ExceptionClear();
-            }
-        }
-    }
-
-protected:
-    virtual ~JavaDeathRecipient()
-    {
-        //ALOGI("Removing death ref: recipient=%p\n", mObject);
-        gNumDeathRefsDeleted.fetch_add(1, std::memory_order_relaxed);
-        JNIEnv* env = javavm_to_jnienv(mVM);
-        if (mObject != NULL) {
-            env->DeleteGlobalRef(mObject);
-        } else {
-            env->DeleteWeakGlobalRef(mObjectWeak);
-        }
-    }
-
 private:
-    JavaVM* const mVM;
-
-    // If target sdk version < 35, the Java-side DeathRecipient is strongly referenced from mObject
-    // upon linkToDeath() and then after binderDied() is called, the strong reference is demoted to
-    // a weak reference (mObjectWeak).
-    // If target sdk version >= 35, the strong reference is never made here (i.e. mObject == NULL
-    // always). Instead, the strong reference to the Java-side DeathRecipient is made in
-    // BinderProxy.mDeathRecipients. In the native world, only the weak reference is kept.
-    jobject mObject;
-    jweak mObjectWeak;
-    wp<DeathRecipientList> mList;
-
     // Whether binderDied was called or not.
     bool mFired = false;
 };
 
+class JavaFrozenStateChangeCallback : public JavaRecipient<IBinder::FrozenStateChangeCallback> {
+public:
+    JavaFrozenStateChangeCallback(
+            JNIEnv* env, jobject object,
+            const sp<RecipientList<IBinder::FrozenStateChangeCallback> >& list)
+          : JavaRecipient(env, object, list, /*useWeakReference=*/true) {}
+
+    void onStateChanged(const wp<IBinder>& who, State state) {
+        LOG_DEATH_FREEZE("Receiving onStateChanged() on JavaFrozenStateChangeCallback %p. state: "
+                         "%s\n",
+                         this, state == State::FROZEN ? "FROZEN" : "UNFROZEN");
+        if (mObjectWeak == NULL) {
+            return;
+        }
+        JNIEnv* env = javavm_to_jnienv(mVM);
+        ScopedLocalRef<jobject> jBinderProxy(env, javaObjectForIBinder(env, who.promote()));
+
+        // Hold a local reference to the recipient. This may fail if the recipient is weakly
+        // referenced, in which case we can't deliver the notification.
+        ScopedLocalRef<jobject> jCallback(env, env->NewLocalRef(mObjectWeak));
+        if (jCallback.get() == NULL) {
+            return;
+        }
+        env->CallStaticVoidMethod(gBinderProxyOffsets.mClass,
+                                  gBinderProxyOffsets.mInvokeFrozenStateChangeCallback,
+                                  jCallback.get(), jBinderProxy.get(), state);
+        if (env->ExceptionCheck()) {
+            jthrowable excep = env->ExceptionOccurred();
+            binder_report_exception(env, excep,
+                                    "*** Uncaught exception returned from frozen state change "
+                                    "notification!");
+        }
+    }
+};
+
 // ----------------------------------------------------------------------------
 
-DeathRecipientList::DeathRecipientList() {
-    LOGDEATH("New DRL @ %p", this);
+template <typename T>
+RecipientList<T>::RecipientList() {
+    LOG_DEATH_FREEZE("%s New RecipientList @ %p", logPrefix<T>(), this);
 }
 
-DeathRecipientList::~DeathRecipientList() {
-    LOGDEATH("Destroy DRL @ %p", this);
+template <typename T>
+RecipientList<T>::~RecipientList() {
+    LOG_DEATH_FREEZE("%s Destroy RecipientList @ %p", logPrefix<T>(), this);
     AutoMutex _l(mLock);
 
-    // Should never happen -- the JavaDeathRecipient objects that have added themselves
+    // Should never happen -- the JavaRecipientList objects that have added themselves
     // to the list are holding references on the list object.  Only when they are torn
     // down can the list header be destroyed.
     if (mList.size() > 0) {
-        List< sp<JavaDeathRecipient> >::iterator iter;
-        for (iter = mList.begin(); iter != mList.end(); iter++) {
+        for (auto iter = mList.begin(); iter != mList.end(); iter++) {
             (*iter)->warnIfStillLive();
         }
     }
 }
 
-void DeathRecipientList::add(const sp<JavaDeathRecipient>& recipient) {
+template <typename T>
+void RecipientList<T>::add(const sp<JavaRecipient<T> >& recipient) {
     AutoMutex _l(mLock);
 
-    LOGDEATH("DRL @ %p : add JDR %p", this, recipient.get());
+    LOG_DEATH_FREEZE("%s RecipientList @ %p : add JavaRecipient %p", logPrefix<T>(), this,
+                     recipient.get());
     mList.push_back(recipient);
 }
 
-void DeathRecipientList::remove(const sp<JavaDeathRecipient>& recipient) {
+template <typename T>
+void RecipientList<T>::remove(const sp<JavaRecipient<T> >& recipient) {
     AutoMutex _l(mLock);
 
-    List< sp<JavaDeathRecipient> >::iterator iter;
-    for (iter = mList.begin(); iter != mList.end(); iter++) {
+    for (auto iter = mList.begin(); iter != mList.end(); iter++) {
         if (*iter == recipient) {
-            LOGDEATH("DRL @ %p : remove JDR %p", this, recipient.get());
+            LOG_DEATH_FREEZE("%s RecipientList @ %p : remove JavaRecipient %p", logPrefix<T>(),
+                             this, recipient.get());
             mList.erase(iter);
             return;
         }
     }
 }
 
-sp<JavaDeathRecipient> DeathRecipientList::find(jobject recipient) {
+template <typename T>
+sp<JavaRecipient<T> > RecipientList<T>::find(jobject recipient) {
     AutoMutex _l(mLock);
 
-    List< sp<JavaDeathRecipient> >::iterator iter;
-    for (iter = mList.begin(); iter != mList.end(); iter++) {
+    for (auto iter = mList.begin(); iter != mList.end(); iter++) {
         if ((*iter)->matches(recipient)) {
             return *iter;
         }
@@ -800,10 +910,14 @@
     return NULL;
 }
 
-Mutex& DeathRecipientList::lock() {
+template <typename T>
+Mutex& RecipientList<T>::lock() {
     return mLock;
 }
 
+using DeathRecipientList = RecipientList<IBinder::DeathRecipient>;
+using FrozenStateChangeCallbackList = RecipientList<IBinder::FrozenStateChangeCallback>;
+
 // ----------------------------------------------------------------------------
 
 namespace android {
@@ -821,6 +935,11 @@
     // Death recipients for mObject. Reference counted only because DeathRecipients
     // hold a weak reference that can be temporarily promoted.
     sp<DeathRecipientList> mOrgue;  // Death recipients for mObject.
+
+    // Frozen state change callbacks for mObject. Reference counted only because
+    // JavaFrozenStateChangeCallback hold a weak reference that can be
+    // temporarily promoted.
+    sp<FrozenStateChangeCallbackList> mFrozenStateChangCallbackList;
 };
 
 BinderProxyNativeData* getBPNativeData(JNIEnv* env, jobject obj) {
@@ -840,12 +959,13 @@
     if (val->checkSubclass(&gBinderOffsets)) {
         // It's a JavaBBinder created by ibinderForJavaObject. Already has Java object.
         jobject object = static_cast<JavaBBinder*>(val.get())->object();
-        LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
+        LOG_DEATH_FREEZE("objectForBinder %p: it's our own %p!\n", val.get(), object);
         return object;
     }
 
     BinderProxyNativeData* nativeData = new BinderProxyNativeData();
     nativeData->mOrgue = new DeathRecipientList;
+    nativeData->mFrozenStateChangCallbackList = new FrozenStateChangeCallbackList;
     nativeData->mObject = val;
 
     jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
@@ -1448,7 +1568,7 @@
     BinderProxyNativeData *nd = getBPNativeData(env, obj);
     IBinder* target = nd->mObject.get();
 
-    LOGDEATH("linkToDeath: binder=%p recipient=%p\n", target, recipient);
+    LOG_DEATH_FREEZE("linkToDeath: binder=%p recipient=%p\n", target, recipient);
 
     if (!target->localBinder()) {
         DeathRecipientList* list = nd->mOrgue.get();
@@ -1479,15 +1599,15 @@
         return JNI_FALSE;
     }
 
-    LOGDEATH("unlinkToDeath: binder=%p recipient=%p\n", target, recipient);
+    LOG_DEATH_FREEZE("unlinkToDeath: binder=%p recipient=%p\n", target, recipient);
 
     if (!target->localBinder()) {
         status_t err = NAME_NOT_FOUND;
 
         // If we find the matching recipient, proceed to unlink using that
         DeathRecipientList* list = nd->mOrgue.get();
-        sp<JavaDeathRecipient> origJDR = list->find(recipient);
-        LOGDEATH("   unlink found list %p and JDR %p", list, origJDR.get());
+        sp<JavaRecipient<IBinder::DeathRecipient> > origJDR = list->find(recipient);
+        LOG_DEATH_FREEZE("   unlink found list %p and JDR %p", list, origJDR.get());
         if (origJDR != NULL) {
             wp<IBinder::DeathRecipient> dr;
             err = target->unlinkToDeath(origJDR, NULL, flags, &dr);
@@ -1513,11 +1633,85 @@
     return res;
 }
 
+static void android_os_BinderProxy_addFrozenStateChangeCallback(
+        JNIEnv* env, jobject obj,
+        jobject callback) // throws RemoteException
+{
+    if (callback == NULL) {
+        jniThrowNullPointerException(env, NULL);
+        return;
+    }
+
+    BinderProxyNativeData* nd = getBPNativeData(env, obj);
+    IBinder* target = nd->mObject.get();
+
+    LOG_DEATH_FREEZE("addFrozenStateChangeCallback: binder=%p callback=%p\n", target, callback);
+
+    if (!target->localBinder()) {
+        FrozenStateChangeCallbackList* list = nd->mFrozenStateChangCallbackList.get();
+        auto jfscc = sp<JavaFrozenStateChangeCallback>::make(env, callback, list);
+        status_t err = target->addFrozenStateChangeCallback(jfscc);
+        if (err != NO_ERROR) {
+            // Failure adding the callback, so clear its reference now.
+            jfscc->clearReference();
+            signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/);
+        }
+    }
+}
+
+static jboolean android_os_BinderProxy_removeFrozenStateChangeCallback(JNIEnv* env, jobject obj,
+                                                                       jobject callback) {
+    jboolean res = JNI_FALSE;
+    if (callback == NULL) {
+        jniThrowNullPointerException(env, NULL);
+        return res;
+    }
+
+    BinderProxyNativeData* nd = getBPNativeData(env, obj);
+    IBinder* target = nd->mObject.get();
+    if (target == NULL) {
+        ALOGW("Binder has been finalized when calling removeFrozenStateChangeCallback() with "
+              "callback=%p)\n",
+              callback);
+        return JNI_FALSE;
+    }
+
+    LOG_DEATH_FREEZE("removeFrozenStateChangeCallback: binder=%p callback=%p\n", target, callback);
+
+    if (!target->localBinder()) {
+        status_t err = NAME_NOT_FOUND;
+
+        // If we find the matching callback, proceed to unlink using that
+        FrozenStateChangeCallbackList* list = nd->mFrozenStateChangCallbackList.get();
+        sp<JavaRecipient<IBinder::FrozenStateChangeCallback> > origJFSCC = list->find(callback);
+        LOG_DEATH_FREEZE("   removeFrozenStateChangeCallback found list %p and JFSCC %p", list,
+                         origJFSCC.get());
+        if (origJFSCC != NULL) {
+            err = target->removeFrozenStateChangeCallback(origJFSCC);
+            if (err == NO_ERROR) {
+                origJFSCC->clearReference();
+            }
+        }
+
+        if (err == NO_ERROR || err == DEAD_OBJECT) {
+            res = JNI_TRUE;
+        } else {
+            jniThrowException(env, "java/util/NoSuchElementException",
+                              base::StringPrintf("Frozen state change callback does not exist (%s)",
+                                                 statusToString(err).c_str())
+                                      .c_str());
+        }
+    }
+
+    return res;
+}
+
 static void BinderProxy_destroy(void* rawNativeData)
 {
     BinderProxyNativeData * nativeData = (BinderProxyNativeData *) rawNativeData;
-    LOGDEATH("Destroying BinderProxy: binder=%p drl=%p\n",
-            nativeData->mObject.get(), nativeData->mOrgue.get());
+    LOG_DEATH_FREEZE("Destroying BinderProxy: binder=%p drl=%p fsccl=%p\n",
+                     nativeData->mObject.get(), nativeData->mOrgue.get(),
+                     nativeData->mFrozenStateChangCallbackList.get());
     delete nativeData;
     IPCThreadState::self()->flushCommands();
 }
@@ -1552,6 +1746,10 @@
     {"transactNative",      "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
     {"linkToDeathNative",   "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath},
     {"unlinkToDeathNative", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath},
+    {"addFrozenStateChangeCallbackNative",
+        "(Landroid/os/IBinder$IFrozenStateChangeCallback;)V", (void*)android_os_BinderProxy_addFrozenStateChangeCallback},
+    {"removeFrozenStateChangeCallbackNative",
+        "(Landroid/os/IBinder$IFrozenStateChangeCallback;)Z", (void*)android_os_BinderProxy_removeFrozenStateChangeCallback},
     {"getNativeFinalizer",  "()J", (void*)android_os_BinderProxy_getNativeFinalizer},
     {"getExtension",        "()Landroid/os/IBinder;", (void*)android_os_BinderProxy_getExtension},
 };
@@ -1574,6 +1772,10 @@
     gBinderProxyOffsets.mSendDeathNotice =
             GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",
                                    "(Landroid/os/IBinder$DeathRecipient;Landroid/os/IBinder;)V");
+    gBinderProxyOffsets.mInvokeFrozenStateChangeCallback =
+            GetStaticMethodIDOrDie(env, clazz, "invokeFrozenStateChangeCallback",
+                                   "(Landroid/os/IBinder$IFrozenStateChangeCallback;Landroid/os/"
+                                   "IBinder;I)V");
     gBinderProxyOffsets.mNativeData = GetFieldIDOrDie(env, clazz, "mNativeData", "J");
 
     clazz = FindClassOrDie(env, "java/lang/Class");
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 0f53164..17c89f8 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -2089,9 +2089,11 @@
         jobjectArray jJankDataArray = env->NewObjectArray(jankData.size(),
                 gJankDataClassInfo.clazz, nullptr);
         for (size_t i = 0; i < jankData.size(); i++) {
-            jobject jJankData = env->NewObject(gJankDataClassInfo.clazz, gJankDataClassInfo.ctor,
-                                               jankData[i].frameVsyncId, jankData[i].jankType,
-                                               jankData[i].frameIntervalNs);
+            jobject jJankData =
+                    env->NewObject(gJankDataClassInfo.clazz, gJankDataClassInfo.ctor,
+                                   jankData[i].frameVsyncId, jankData[i].jankType,
+                                   jankData[i].frameIntervalNs, jankData[i].scheduledAppFrameTimeNs,
+                                   jankData[i].actualAppFrameTimeNs);
             env->SetObjectArrayElement(jJankDataArray, i, jJankData);
             env->DeleteLocalRef(jJankData);
         }
@@ -2727,7 +2729,7 @@
     jclass jankDataClazz =
                 FindClassOrDie(env, "android/view/SurfaceControl$JankData");
     gJankDataClassInfo.clazz = MakeGlobalRefOrDie(env, jankDataClazz);
-    gJankDataClassInfo.ctor = GetMethodIDOrDie(env, gJankDataClassInfo.clazz, "<init>", "(JIJ)V");
+    gJankDataClassInfo.ctor = GetMethodIDOrDie(env, gJankDataClassInfo.clazz, "<init>", "(JIJJJ)V");
     jclass onJankDataListenerClazz =
             FindClassOrDie(env, "android/view/SurfaceControl$OnJankDataListener");
     gJankDataListenerClassInfo.clazz = MakeGlobalRefOrDie(env, onJankDataListenerClazz);
diff --git a/core/jni/platform/host/HostRuntime.cpp b/core/jni/platform/host/HostRuntime.cpp
index 020b27e..19f8299 100644
--- a/core/jni/platform/host/HostRuntime.cpp
+++ b/core/jni/platform/host/HostRuntime.cpp
@@ -391,6 +391,7 @@
 
 } // namespace android
 
+#ifndef _WIN32
 using namespace android;
 
 JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
@@ -407,3 +408,4 @@
 
     return JNI_VERSION_1_6;
 }
+#endif
diff --git a/core/res/res/layout/autofill_dataset_picker_header_footer.xml b/core/res/res/layout/autofill_dataset_picker_header_footer.xml
index 4d5f4f0..027f530 100644
--- a/core/res/res/layout/autofill_dataset_picker_header_footer.xml
+++ b/core/res/res/layout/autofill_dataset_picker_header_footer.xml
@@ -37,6 +37,7 @@
       <ListView
           android:id="@+id/autofill_dataset_list"
           android:layout_weight="1"
+          android:fadeScrollbars="false"
           android:layout_width="fill_parent"
           android:layout_height="0dp"
           android:drawSelectorOnTop="true"
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b6468ee..4beeb17 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -7030,6 +7030,10 @@
          {@link InputDevice#SOURCE_ROTARY_ENCODER}s. -->
     <bool name="config_viewBasedRotaryEncoderHapticsEnabled">false</bool>
 
+    <!-- Whether the scroll haptic feedback implementation is enabled for
+    {@link InputDevice#SOURCE_TOUCHSCREEN}s. -->
+    <bool name="config_viewTouchScreenHapticScrollFeedbackEnabled">false</bool>
+
     <!-- Whether the media player is shown on the quick settings -->
     <bool name="config_quickSettingsShowMediaPlayer">true</bool>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 74922ac..80ec67a 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -5490,8 +5490,11 @@
   <java-symbol type="bool" name="config_tvExternalInputLoggingDisplayNameFilterEnabled" />
   <java-symbol type="array" name="config_tvExternalInputLoggingDeviceOnScreenDisplayNames" />
   <java-symbol type="array" name="config_tvExternalInputLoggingDeviceBrandNames" />
+
+  <!-- Scroll Feedback Configs -->
   <java-symbol type="bool" name="config_viewRotaryEncoderHapticScrollFedbackEnabled" />
   <java-symbol type="bool" name="config_viewBasedRotaryEncoderHapticsEnabled" />
+  <java-symbol type="bool" name="config_viewTouchScreenHapticScrollFeedbackEnabled" />
 
   <java-symbol type="bool" name="config_quickSettingsShowMediaPlayer" />
 
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 452ae04..d35bfb7 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -131,7 +131,7 @@
         <item name="progressBarStyleSmallInverse">@style/Widget.DeviceDefault.ProgressBar.Small.Inverse</item>
         <item name="progressBarStyleLargeInverse">@style/Widget.DeviceDefault.ProgressBar.Large.Inverse</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="seekBarStyle">@style/Widget.DeviceDefault.SeekBar</item>
         <item name="ratingBarStyle">@style/Widget.DeviceDefault.RatingBar</item>
         <item name="ratingBarStyleIndicator">@style/Widget.DeviceDefault.RatingBar.Indicator</item>
@@ -351,7 +351,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -468,7 +468,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -587,7 +587,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -705,7 +705,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -831,7 +831,7 @@
         <item name="alertDialogTheme">@style/Theme.DeviceDefault.Dialog.Alert</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -948,7 +948,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -1064,7 +1064,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -1181,7 +1181,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -1314,7 +1314,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -1432,7 +1432,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -1548,7 +1548,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -1666,7 +1666,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -1783,7 +1783,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -1900,7 +1900,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -2017,7 +2017,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -2134,7 +2134,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -2251,7 +2251,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -2373,7 +2373,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -2488,7 +2488,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -2642,7 +2642,7 @@
         <item name="progressBarStyleSmallInverse">@style/Widget.DeviceDefault.Light.ProgressBar.Small.Inverse</item>
         <item name="progressBarStyleLargeInverse">@style/Widget.DeviceDefault.Light.ProgressBar.Large.Inverse</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="seekBarStyle">@style/Widget.DeviceDefault.Light.SeekBar</item>
         <item name="ratingBarStyle">@style/Widget.DeviceDefault.Light.RatingBar</item>
         <item name="ratingBarStyleIndicator">@style/Widget.DeviceDefault.Light.RatingBar.Indicator</item>
@@ -2858,7 +2858,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -2974,7 +2974,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -3091,7 +3091,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -3210,7 +3210,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -3328,7 +3328,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -3452,7 +3452,7 @@
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -3572,7 +3572,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -3691,7 +3691,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -3811,7 +3811,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -4133,7 +4133,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -4254,7 +4254,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -4373,7 +4373,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -4491,7 +4491,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -4608,7 +4608,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -4725,7 +4725,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -4840,7 +4840,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -5066,7 +5066,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -5162,7 +5162,7 @@
         <item name="alertDialogTheme">@style/Theme.DeviceDefault.Light.Dialog.Alert</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -5280,7 +5280,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -5471,7 +5471,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -5522,7 +5522,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
@@ -5641,7 +5641,7 @@
         <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
 
         <!-- Progress bar attributes -->
-        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
         <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
 
         <!-- Toolbar attributes -->
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index b0e48f1..99cbf05 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -21,6 +21,7 @@
     srcs: [
         "DisabledTestApp/src/**/*.java",
         "EnabledTestApp/src/**/*.java",
+        "BinderFrozenStateChangeCallbackTestApp/src/**/*.java",
         "BinderProxyCountingTestApp/src/**/*.java",
         "BinderProxyCountingTestService/src/**/*.java",
         "BinderDeathRecipientHelperApp/src/**/*.java",
@@ -138,6 +139,7 @@
         ":BinderDeathRecipientHelperApp1",
         ":BinderDeathRecipientHelperApp2",
         ":com.android.cts.helpers.aosp",
+        ":BinderFrozenStateChangeCallbackTestApp",
         ":BinderProxyCountingTestApp",
         ":BinderProxyCountingTestService",
         ":AppThatUsesAppOps",
diff --git a/core/tests/coretests/AndroidTest.xml b/core/tests/coretests/AndroidTest.xml
index 99b73a4..b1f1e2c 100644
--- a/core/tests/coretests/AndroidTest.xml
+++ b/core/tests/coretests/AndroidTest.xml
@@ -22,6 +22,7 @@
         <option name="test-file-name" value="FrameworksCoreTests.apk" />
         <option name="test-file-name" value="BinderDeathRecipientHelperApp1.apk" />
         <option name="test-file-name" value="BinderDeathRecipientHelperApp2.apk" />
+        <option name="test-file-name" value="BinderFrozenStateChangeCallbackTestApp.apk" />
         <option name="test-file-name" value="BinderProxyCountingTestApp.apk" />
         <option name="test-file-name" value="BinderProxyCountingTestService.apk" />
         <option name="test-file-name" value="AppThatUsesAppOps.apk" />
diff --git a/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/Android.bp b/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/Android.bp
new file mode 100644
index 0000000..de97dda
--- /dev/null
+++ b/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/Android.bp
@@ -0,0 +1,34 @@
+// Copyright (C) 2024 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 {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test_helper_app {
+    name: "BinderFrozenStateChangeCallbackTestApp",
+
+    static_libs: ["coretests-aidl"],
+    srcs: ["**/*.java"],
+
+    platform_apis: true,
+    certificate: "platform",
+
+    test_suites: ["device-tests"],
+}
diff --git a/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/AndroidManifest.xml b/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/AndroidManifest.xml
new file mode 100644
index 0000000..29c8f55
--- /dev/null
+++ b/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.frameworks.coretests.bfscctestapp">
+
+    <application>
+        <service android:name=".BfsccTestAppCmdService"
+                 android:exported="true"/>
+    </application>
+</manifest>
diff --git a/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/src/com/android/frameworks/coretests/bfscctestapp/BfsccTestAppCmdService.java b/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/src/com/android/frameworks/coretests/bfscctestapp/BfsccTestAppCmdService.java
new file mode 100644
index 0000000..77e8a40
--- /dev/null
+++ b/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/src/com/android/frameworks/coretests/bfscctestapp/BfsccTestAppCmdService.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2024 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.frameworks.coretests.bfscctestapp;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import com.android.frameworks.coretests.aidl.IBfsccTestAppCmdService;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+public class BfsccTestAppCmdService extends Service {
+    private IBfsccTestAppCmdService.Stub mBinder = new IBfsccTestAppCmdService.Stub() {
+        private final LinkedBlockingQueue<IBinder.IFrozenStateChangeCallback.State> mNotifications =
+                new LinkedBlockingQueue<>();
+
+        @Override
+        public void listenTo(IBinder binder) throws RemoteException {
+            binder.addFrozenStateChangeCallback(
+                    (IBinder who, IBinder.IFrozenStateChangeCallback.State state)
+                            -> mNotifications.offer(state));
+        }
+
+        @Override
+        public boolean[] waitAndConsumeNotifications() {
+            List<Boolean> results = new ArrayList<>();
+            try {
+                IBinder.IFrozenStateChangeCallback.State state =
+                        mNotifications.poll(5, TimeUnit.SECONDS);
+                if (state != null) {
+                    results.add(state == IBinder.IFrozenStateChangeCallback.State.FROZEN);
+                }
+            } catch (InterruptedException e) {
+                return null;
+            }
+            while (mNotifications.size() > 0) {
+                results.add(mNotifications.poll()
+                        == IBinder.IFrozenStateChangeCallback.State.FROZEN);
+            }
+            boolean[] convertedResults = new boolean[results.size()];
+            for (int i = 0; i < results.size(); i++) {
+                convertedResults[i] = results.get(i).booleanValue();
+            }
+            return convertedResults;
+        }
+    };
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mBinder;
+    }
+}
diff --git a/core/tests/coretests/BinderProxyCountingTestService/src/com/android/frameworks/coretests/binderproxycountingtestservice/BinderProxyCountingService.java b/core/tests/coretests/BinderProxyCountingTestService/src/com/android/frameworks/coretests/binderproxycountingtestservice/BinderProxyCountingService.java
index 41b4c69..09d79a6 100644
--- a/core/tests/coretests/BinderProxyCountingTestService/src/com/android/frameworks/coretests/binderproxycountingtestservice/BinderProxyCountingService.java
+++ b/core/tests/coretests/BinderProxyCountingTestService/src/com/android/frameworks/coretests/binderproxycountingtestservice/BinderProxyCountingService.java
@@ -50,4 +50,4 @@
     public IBinder onBind(Intent intent) {
         return mBinder;
     }
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java b/core/tests/coretests/aidl/com/android/frameworks/coretests/aidl/IBfsccTestAppCmdService.aidl
similarity index 71%
copy from services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java
copy to core/tests/coretests/aidl/com/android/frameworks/coretests/aidl/IBfsccTestAppCmdService.aidl
index 502337c..d8d7dc4 100644
--- a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java
+++ b/core/tests/coretests/aidl/com/android/frameworks/coretests/aidl/IBfsccTestAppCmdService.aidl
@@ -14,11 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.frameworks.coretests.aidl;
 
-class BinaryStatePowerStatsLayout extends EnergyConsumerPowerStatsLayout {
-    BinaryStatePowerStatsLayout() {
-        addDeviceSectionUsageDuration();
-        addUidSectionUsageDuration();
-    }
+interface IBfsccTestAppCmdService {
+   void listenTo(IBinder binder);
+   boolean[] waitAndConsumeNotifications();
 }
diff --git a/core/tests/coretests/src/android/app/NotificationChannelTest.java b/core/tests/coretests/src/android/app/NotificationChannelTest.java
index c08e42b..e47ef2d 100644
--- a/core/tests/coretests/src/android/app/NotificationChannelTest.java
+++ b/core/tests/coretests/src/android/app/NotificationChannelTest.java
@@ -233,6 +233,33 @@
     }
 
     @Test
+    @EnableFlags({Flags.FLAG_NOTIFICATION_CHANNEL_VIBRATION_EFFECT_API,
+            Flags.FLAG_NOTIF_CHANNEL_CROP_VIBRATION_EFFECTS})
+    public void testLongVibrationFields_canWriteToXml() throws Exception {
+        NotificationChannel channel = new NotificationChannel("id", "name", 3);
+        // populate pattern with contents
+        long[] pattern = new long[65550 / 2];
+        for (int i = 0; i < pattern.length; i++) {
+            pattern[i] = 100;
+        }
+        channel.setVibrationPattern(pattern);  // with flag on, also sets effect
+
+        // Send it through parceling & unparceling to simulate being passed through a binder call
+        NotificationChannel fromParcel = writeToAndReadFromParcel(channel);
+        assertThat(fromParcel.getVibrationPattern().length).isEqualTo(
+                NotificationChannel.MAX_VIBRATION_LENGTH);
+
+        // Confirm that this also survives writing to & restoring from XML
+        NotificationChannel result = backUpAndRestore(fromParcel);
+        assertThat(result.getVibrationPattern().length).isEqualTo(
+                NotificationChannel.MAX_VIBRATION_LENGTH);
+        assertThat(result.getVibrationEffect()).isNotNull();
+        assertThat(result.getVibrationEffect()
+                .computeCreateWaveformOffOnTimingsOrNull())
+                .isEqualTo(result.getVibrationPattern());
+    }
+
+    @Test
     public void testRestoreSoundUri_customLookup() throws Exception {
         Uri uriToBeRestoredUncanonicalized = Uri.parse("content://media/1");
         Uri uriToBeRestoredCanonicalized = Uri.parse("content://media/1?title=Song&canonical=1");
diff --git a/core/tests/coretests/src/android/os/BinderFrozenStateChangeNotificationTest.java b/core/tests/coretests/src/android/os/BinderFrozenStateChangeNotificationTest.java
new file mode 100644
index 0000000..ee2e7e0
--- /dev/null
+++ b/core/tests/coretests/src/android/os/BinderFrozenStateChangeNotificationTest.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.UiDevice;
+
+import com.android.frameworks.coretests.aidl.IBfsccTestAppCmdService;
+import com.android.frameworks.coretests.bdr_helper_app.TestCommsReceiver;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Queue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Tests functionality of {@link android.os.IBinder.IFrozenStateChangeCallback}.
+ */
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = ActivityManager.class)
+public class BinderFrozenStateChangeNotificationTest {
+    private static final String TAG = BinderFrozenStateChangeNotificationTest.class.getSimpleName();
+
+    private static final String TEST_PACKAGE_NAME_1 =
+            "com.android.frameworks.coretests.bfscctestapp";
+    private static final String TEST_PACKAGE_NAME_2 =
+            "com.android.frameworks.coretests.bdr_helper_app1";
+    private static final String TEST_APP_CMD_SERVICE =
+            TEST_PACKAGE_NAME_1 + ".BfsccTestAppCmdService";
+
+    private static final int CALLBACK_WAIT_TIMEOUT_SECS = 5;
+
+    private IBfsccTestAppCmdService mBfsccTestAppCmdService;
+    private ServiceConnection mTestAppConnection;
+    private Context mContext;
+    private Handler mHandler;
+
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getTargetContext();
+        mHandler = new Handler(Looper.getMainLooper());
+        ((ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE)).killUid(
+                mContext.getPackageManager().getPackageUid(TEST_PACKAGE_NAME_1, 0),
+                "Wiping Test Package");
+        mTestAppConnection = bindService();
+    }
+
+    private IBinder getNewRemoteBinder(String testPackage) throws InterruptedException {
+        final CountDownLatch resultLatch = new CountDownLatch(1);
+        final AtomicInteger resultCode = new AtomicInteger(Activity.RESULT_CANCELED);
+        final AtomicReference<Bundle> resultExtras = new AtomicReference<>();
+
+        final Intent intent = new Intent(TestCommsReceiver.ACTION_GET_BINDER)
+                .setClassName(testPackage, TestCommsReceiver.class.getName());
+        mContext.sendOrderedBroadcast(intent, null, new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                resultCode.set(getResultCode());
+                resultExtras.set(getResultExtras(true));
+                resultLatch.countDown();
+            }
+        }, mHandler, Activity.RESULT_CANCELED, null, null);
+
+        assertTrue("Request for binder timed out", resultLatch.await(5, TimeUnit.SECONDS));
+        assertEquals(Activity.RESULT_OK, resultCode.get());
+        return resultExtras.get().getBinder(TestCommsReceiver.EXTRA_KEY_BINDER);
+    }
+
+    private ServiceConnection bindService()
+            throws Exception {
+        final CountDownLatch bindLatch = new CountDownLatch(1);
+        ServiceConnection connection = new ServiceConnection() {
+            @Override
+            public void onServiceConnected(ComponentName name, IBinder service) {
+                Log.i(TAG, "Service connected");
+                mBfsccTestAppCmdService = IBfsccTestAppCmdService.Stub.asInterface(service);
+                bindLatch.countDown();
+            }
+
+            @Override
+            public void onServiceDisconnected(ComponentName name) {
+                Log.i(TAG, "Service disconnected");
+            }
+        };
+        mContext.bindService(
+                new Intent().setComponent(
+                        new ComponentName(TEST_PACKAGE_NAME_1, TEST_APP_CMD_SERVICE)),
+                connection,
+                Context.BIND_AUTO_CREATE
+                        | Context.BIND_NOT_FOREGROUND);
+        if (!bindLatch.await(5, TimeUnit.SECONDS)) {
+            fail("Timed out waiting for the service to bind");
+        }
+        return connection;
+    }
+
+    private void unbindService(ServiceConnection service) {
+        if (service != null) {
+            mContext.unbindService(service);
+        }
+    }
+
+    @Test
+    public void onStateChangeCalled() throws Exception {
+        final LinkedBlockingQueue<Boolean> results = new LinkedBlockingQueue<>();
+        if (createCallback(mBfsccTestAppCmdService.asBinder(), results) == null) {
+            return;
+        }
+        ensureUnfrozenCallback(results);
+        freezeApp1();
+        ensureFrozenCallback(results);
+        unfreezeApp1();
+        ensureUnfrozenCallback(results);
+    }
+
+    @Test
+    public void onStateChangeNotCalledAfterCallbackRemoved() throws Exception {
+        final LinkedBlockingQueue<Boolean> results = new LinkedBlockingQueue<>();
+        IBinder.IFrozenStateChangeCallback callback;
+        if ((callback = createCallback(mBfsccTestAppCmdService.asBinder(), results)) == null) {
+            return;
+        }
+        ensureUnfrozenCallback(results);
+        mBfsccTestAppCmdService.asBinder().removeFrozenStateChangeCallback(callback);
+        freezeApp1();
+        assertEquals("No more callbacks should be invoked.", 0, results.size());
+    }
+
+    @Test
+    public void multipleCallbacks() throws Exception {
+        final LinkedBlockingQueue<Boolean> results1 = new LinkedBlockingQueue<>();
+        final LinkedBlockingQueue<Boolean> results2 = new LinkedBlockingQueue<>();
+        IBinder.IFrozenStateChangeCallback callback1;
+        if ((callback1 = createCallback(mBfsccTestAppCmdService.asBinder(), results1)) == null) {
+            return;
+        }
+        ensureUnfrozenCallback(results1);
+        freezeApp1();
+        ensureFrozenCallback(results1);
+        if (createCallback(mBfsccTestAppCmdService.asBinder(), results2) == null) {
+            return;
+        }
+        ensureFrozenCallback(results2);
+
+        unfreezeApp1();
+        ensureUnfrozenCallback(results1);
+        ensureUnfrozenCallback(results2);
+
+        mBfsccTestAppCmdService.asBinder().removeFrozenStateChangeCallback(callback1);
+        freezeApp1();
+        assertEquals("No more callbacks should be invoked.", 0, results1.size());
+        ensureFrozenCallback(results2);
+    }
+
+    @Test
+    public void onStateChangeCalledWithTheRightBinder() throws Exception {
+        final IBinder binder = mBfsccTestAppCmdService.asBinder();
+        final LinkedBlockingQueue<IBinder> results = new LinkedBlockingQueue<>();
+        IBinder.IFrozenStateChangeCallback callback =
+                (IBinder who, IBinder.IFrozenStateChangeCallback.State state) -> results.offer(who);
+        try {
+            binder.addFrozenStateChangeCallback(callback);
+        } catch (UnsupportedOperationException e) {
+            return;
+        }
+        assertEquals("Callback received the wrong Binder object.",
+                binder, results.poll(CALLBACK_WAIT_TIMEOUT_SECS, TimeUnit.SECONDS));
+        freezeApp1();
+        assertEquals("Callback received the wrong Binder object.",
+                binder, results.poll(CALLBACK_WAIT_TIMEOUT_SECS, TimeUnit.SECONDS));
+        unfreezeApp1();
+        assertEquals("Callback received the wrong Binder object.",
+                binder, results.poll(CALLBACK_WAIT_TIMEOUT_SECS, TimeUnit.SECONDS));
+    }
+
+    @After
+    public void tearDown() {
+        if (mTestAppConnection != null) {
+            mContext.unbindService(mTestAppConnection);
+        }
+    }
+
+    private IBinder.IFrozenStateChangeCallback createCallback(IBinder binder, Queue<Boolean> queue)
+            throws RemoteException {
+        try {
+            final IBinder.IFrozenStateChangeCallback callback =
+                    (IBinder who, IBinder.IFrozenStateChangeCallback.State state) ->
+                            queue.offer(state == IBinder.IFrozenStateChangeCallback.State.FROZEN);
+            binder.addFrozenStateChangeCallback(callback);
+            return callback;
+        } catch (UnsupportedOperationException e) {
+            return null;
+        }
+    }
+
+    private void ensureFrozenCallback(LinkedBlockingQueue<Boolean> queue)
+            throws InterruptedException {
+        assertEquals(Boolean.TRUE, queue.poll(CALLBACK_WAIT_TIMEOUT_SECS, TimeUnit.SECONDS));
+    }
+
+    private void ensureUnfrozenCallback(LinkedBlockingQueue<Boolean> queue)
+            throws InterruptedException {
+        assertEquals(Boolean.FALSE, queue.poll(CALLBACK_WAIT_TIMEOUT_SECS, TimeUnit.SECONDS));
+    }
+
+    private String executeShellCommand(String cmd) throws Exception {
+        return UiDevice.getInstance(
+                InstrumentationRegistry.getInstrumentation()).executeShellCommand(cmd);
+    }
+
+    private void freezeApp1() throws Exception {
+        executeShellCommand("am freeze " + TEST_PACKAGE_NAME_1);
+    }
+
+    private void freezeApp2() throws Exception {
+        executeShellCommand("am freeze " + TEST_PACKAGE_NAME_2);
+    }
+
+    private void unfreezeApp1() throws Exception {
+        executeShellCommand("am unfreeze " + TEST_PACKAGE_NAME_1);
+    }
+
+    private void unfreezeApp2() throws Exception {
+        executeShellCommand("am unfreeze " + TEST_PACKAGE_NAME_2);
+    }
+}
diff --git a/core/tests/coretests/src/android/os/storage/StorageManagerIntegrationTest.java b/core/tests/coretests/src/android/os/storage/StorageManagerIntegrationTest.java
index ecd2f76..b157c95 100644
--- a/core/tests/coretests/src/android/os/storage/StorageManagerIntegrationTest.java
+++ b/core/tests/coretests/src/android/os/storage/StorageManagerIntegrationTest.java
@@ -16,8 +16,11 @@
 
 package android.os.storage;
 
+import android.content.res.ObbInfo;
+import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.ProxyFileDescriptorCallback;
+import android.os.ServiceManager;
 import android.system.ErrnoException;
 
 import androidx.test.filters.LargeTest;
@@ -104,7 +107,14 @@
     public void testMountBadPackageNameObb() throws Exception {
         final File file = createObbFile(OBB_FILE_3_BAD_PACKAGENAME, R.raw.obb_file3_bad_packagename);
         String filePath = file.getAbsolutePath();
-        mountObb(filePath, OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
+        try {
+            mountObb(filePath, OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
+            fail("mountObb should throw an exception as package name is incorrect");
+        } catch (Exception ex) {
+            assertEquals("Path " + filePath
+                            + " does not contain package name " + mContext.getPackageName(),
+                    ex.getMessage());
+        }
     }
 
     /**
@@ -154,6 +164,48 @@
         }
     }
 
+    @LargeTest
+    public void testObbInfo_withValidObbInfo_success() throws Exception {
+        final File file = createObbFile(OBB_FILE_1, R.raw.obb_file1);
+        String filePath = file.getAbsolutePath();
+        try {
+            mountObb(filePath);
+            unmountObb(filePath, DONT_FORCE);
+        } catch (Exception ex) {
+            fail("No exception expected, got " + ex.getMessage());
+        }
+    }
+
+    @LargeTest
+    public void testObbInfo_withInvalidObbInfo_exception() throws Exception {
+        final File file = createObbFile(OBB_FILE_1, R.raw.obb_file1);
+        String rawPath = file.getAbsolutePath();
+        String canonicalPath = file.getCanonicalPath();
+
+        ObbInfo obbInfo = ObbInfo.CREATOR.createFromParcel(Parcel.obtain());
+        obbInfo.packageName = "com.android.obbcrash";
+        obbInfo.version = 1;
+        obbInfo.filename = canonicalPath;
+
+        try {
+            IStorageManager.Stub.asInterface(ServiceManager.getServiceOrThrow("mount")).mountObb(
+                    rawPath, canonicalPath, new ObbActionListener(), 0, obbInfo);
+            fail("mountObb should throw an exception as package name is incorrect");
+        } catch (SecurityException ex) {
+            assertEquals("Path " + canonicalPath
+                            + " does not contain package name " + mContext.getPackageName(),
+                    ex.getMessage());
+        }
+    }
+
+    private static class ObbActionListener extends IObbActionListener.Stub {
+        @SuppressWarnings("hiding")
+        @Override
+        public void onObbResult(String filename, int nonce, int status) {
+
+        }
+    }
+
     private static class MyThreadFactory implements ThreadFactory {
         Thread thread = null;
 
diff --git a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
index 499caf5..c3a5b19c94 100644
--- a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
+++ b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
@@ -359,7 +359,7 @@
         tracker.end(FrameTracker.REASON_END_NORMAL);
 
         // Send incomplete callback for 102L
-        sendSfFrame(tracker, 102L, JANK_NONE);
+        sendSfFrame(tracker, 4, 102L, JANK_NONE);
 
         // Send janky but complete callbck fo 103L
         sendFrame(tracker, 50, JANK_APP_DEADLINE_MISSED, 103L);
@@ -629,7 +629,7 @@
         if (!tracker.mSurfaceOnly) {
             sendHwuiFrame(tracker, durationMillis, vsyncId, firstWindowFrame);
         }
-        sendSfFrame(tracker, vsyncId, jankType);
+        sendSfFrame(tracker, durationMillis, vsyncId, jankType);
     }
 
     private void sendHwuiFrame(FrameTracker tracker, long durationMillis, long vsyncId,
@@ -645,11 +645,13 @@
         captor.getValue().run();
     }
 
-    private void sendSfFrame(FrameTracker tracker, long vsyncId, @JankType int jankType) {
+    private void sendSfFrame(
+            FrameTracker tracker, long durationMillis, long vsyncId, @JankType int jankType) {
         final ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
         doNothing().when(tracker).postCallback(captor.capture());
         mListenerCapture.getValue().onJankDataAvailable(new JankData[] {
-                new JankData(vsyncId, jankType, FRAME_TIME_60Hz)
+                new JankData(vsyncId, jankType, FRAME_TIME_60Hz, FRAME_TIME_60Hz,
+                TimeUnit.MILLISECONDS.toNanos(durationMillis))
         });
         captor.getValue().run();
     }
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java b/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java
index 66de3d7..397cdcf 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java
@@ -124,6 +124,16 @@
             return this;
         }
 
+        @Override
+        public void addFrozenStateChangeCallback(IFrozenStateChangeCallback callback)
+                throws RemoteException {
+        }
+
+        @Override
+        public boolean removeFrozenStateChangeCallback(IFrozenStateChangeCallback callback) {
+            return false;
+        }
+
         public void die() {
             isAlive = false;
             if (mRecipient != null) {
diff --git a/core/tests/vibrator/src/android/os/VibrationEffectTest.java b/core/tests/vibrator/src/android/os/VibrationEffectTest.java
index 4f76dd6..f5b04ee 100644
--- a/core/tests/vibrator/src/android/os/VibrationEffectTest.java
+++ b/core/tests/vibrator/src/android/os/VibrationEffectTest.java
@@ -430,6 +430,86 @@
     }
 
     @Test
+    public void cropToLength_waveform_underLength() {
+        VibrationEffect effect = VibrationEffect.createWaveform(
+                /* timings= */ new long[]{0, 1, 2},
+                /* repeatIndex= */ -1);
+        VibrationEffect result = effect.cropToLengthOrNull(5);
+
+        assertThat(result).isEqualTo(effect); // unchanged
+    }
+
+    @Test
+    public void cropToLength_waveform_overLength() {
+        VibrationEffect effect = VibrationEffect.createWaveform(
+                /* timings= */ new long[]{0, 1, 2, 3, 4, 5, 6},
+                /* repeatIndex= */ -1);
+        VibrationEffect result = effect.cropToLengthOrNull(4);
+
+        assertThat(result).isEqualTo(VibrationEffect.createWaveform(
+                new long[]{0, 1, 2, 3},
+                -1));
+    }
+
+    @Test
+    public void cropToLength_waveform_repeating() {
+        // repeating waveforms cannot be truncated
+        VibrationEffect effect = VibrationEffect.createWaveform(
+                /* timings= */ new long[]{0, 1, 2, 3, 4, 5, 6},
+                /* repeatIndex= */ 2);
+        VibrationEffect result = effect.cropToLengthOrNull(3);
+
+        assertThat(result).isNull();
+    }
+
+    @Test
+    public void cropToLength_waveform_withAmplitudes() {
+        VibrationEffect effect = VibrationEffect.createWaveform(
+                /* timings= */ new long[]{0, 1, 2, 3, 4, 5, 6},
+                /* amplitudes= */ new int[]{10, 20, 40, 10, 20, 40, 10},
+                /* repeatIndex= */ -1);
+        VibrationEffect result = effect.cropToLengthOrNull(3);
+
+        assertThat(result).isEqualTo(VibrationEffect.createWaveform(
+                new long[]{0, 1, 2},
+                new int[]{10, 20, 40},
+                -1));
+    }
+
+    @Test
+    public void cropToLength_composed() {
+        VibrationEffect effect = VibrationEffect.startComposition()
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK)
+                .compose();
+        VibrationEffect result = effect.cropToLengthOrNull(1);
+
+        assertThat(result).isNotNull();
+        assertThat(result).isEqualTo(VibrationEffect.startComposition()
+                        .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+                        .compose());
+    }
+
+    @Test
+    public void cropToLength_composed_repeating() {
+        VibrationEffect effect = VibrationEffect.startComposition()
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+                .repeatEffectIndefinitely(TEST_ONE_SHOT)
+                .compose();
+        assertThat(effect.cropToLengthOrNull(1)).isNull();
+    }
+
+    @Test
+    @RequiresFlagsEnabled(android.os.vibrator.Flags.FLAG_VENDOR_VIBRATION_EFFECTS)
+    public void cropToLength_vendorEffect() {
+        PersistableBundle vendorData = new PersistableBundle();
+        vendorData.putInt("key", 1);
+        VibrationEffect effect = VibrationEffect.createVendorEffect(vendorData);
+
+        assertThat(effect.cropToLengthOrNull(2)).isNull();
+    }
+
+    @Test
     public void getRingtones_noPrebakedRingtones() {
         Resources r = mockRingtoneResources(new String[0]);
         Context context = mockContext(r);
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java
index 0726624..4ce2942 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java
@@ -58,7 +58,7 @@
     void scheduleBackup() {
         if (!mBackupIdlerScheduled) {
             mBackupIdlerScheduled = true;
-            Looper.myQueue().addIdleHandler(mBackupIdler);
+            Looper.getMainLooper().getQueue().addIdleHandler(mBackupIdler);
         }
     }
 
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
index 82dfda5..608a3be 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -136,6 +136,7 @@
         mInfo = new TaskFragmentParentInfo(
                 taskProperties.getConfiguration(),
                 taskProperties.getDisplayId(),
+                taskId,
                 // Note that it is always called when there's a new Activity is started, which
                 // implies the host task is visible and has an activity in the task.
                 true /* visible */,
@@ -194,7 +195,8 @@
 
     void setInvisible() {
         mInfo = new TaskFragmentParentInfo(mInfo.getConfiguration(), mInfo.getDisplayId(),
-                false /* visible */, mInfo.hasDirectActivity(), mInfo.getDecorSurface());
+                mInfo.getTaskId(), false /* visible */, mInfo.hasDirectActivity(),
+                mInfo.getDecorSurface());
     }
 
     boolean hasDirectActivity() {
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
index 90eeb58..5b97e7e 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
@@ -549,7 +549,7 @@
         assertThat(taskContainer.getTaskFragmentContainers()).containsExactly(overlayContainer);
 
         taskContainer.updateTaskFragmentParentInfo(new TaskFragmentParentInfo(Configuration.EMPTY,
-                DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */,
+                DEFAULT_DISPLAY, TASK_ID, true /* visible */, false /* hasDirectActivity */,
                 null /* decorSurface */));
 
         mSplitController.updateOverlayContainer(mTransaction, overlayContainer);
@@ -618,7 +618,8 @@
         final TaskContainer.TaskProperties taskProperties = taskContainer.getTaskProperties();
         final TaskFragmentParentInfo parentInfo = new TaskFragmentParentInfo(
                 new Configuration(taskProperties.getConfiguration()), taskProperties.getDisplayId(),
-                true /* visible */, false /* hasDirectActivity */, null /* decorSurface */);
+                TASK_ID, true /* visible */, false /* hasDirectActivity */,
+                null /* decorSurface */);
         parentInfo.getConfiguration().windowConfiguration.getBounds().offset(10, 10);
 
         mSplitController.onTaskFragmentParentInfoChanged(mTransaction, TASK_ID, parentInfo);
@@ -642,7 +643,8 @@
         final TaskContainer.TaskProperties taskProperties = taskContainer.getTaskProperties();
         final TaskFragmentParentInfo parentInfo = new TaskFragmentParentInfo(
                 new Configuration(taskProperties.getConfiguration()), taskProperties.getDisplayId(),
-                true /* visible */, false /* hasDirectActivity */, null /* decorSurface */);
+                TASK_ID, true /* visible */, false /* hasDirectActivity */,
+                null /* decorSurface */);
 
         mSplitController.onTaskFragmentParentInfoChanged(mTransaction, TASK_ID, parentInfo);
 
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
index d852204..0512412 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
@@ -1164,7 +1164,7 @@
     public void testOnTransactionReady_taskFragmentParentInfoChanged() {
         final TaskFragmentTransaction transaction = new TaskFragmentTransaction();
         final TaskFragmentParentInfo parentInfo = new TaskFragmentParentInfo(Configuration.EMPTY,
-                DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */,
+                DEFAULT_DISPLAY, TASK_ID, true /* visible */, false /* hasDirectActivity */,
                 null /* decorSurface */);
         transaction.addChange(new TaskFragmentTransaction.Change(
                 TYPE_TASK_FRAGMENT_PARENT_INFO_CHANGED)
@@ -1625,7 +1625,7 @@
         final TaskContainer taskContainer = mSplitController.getTaskContainer(TASK_ID);
         final Configuration configuration = new Configuration();
         final TaskFragmentParentInfo originalInfo = new TaskFragmentParentInfo(configuration,
-                DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */,
+                DEFAULT_DISPLAY, TASK_ID, true /* visible */, false /* hasDirectActivity */,
                 null /* decorSurface */);
         mSplitController.onTaskFragmentParentInfoChanged(mock(WindowContainerTransaction.class),
                 TASK_ID, originalInfo);
@@ -1634,7 +1634,7 @@
         // Making a public configuration change while the Task is invisible.
         configuration.densityDpi += 100;
         final TaskFragmentParentInfo invisibleInfo = new TaskFragmentParentInfo(configuration,
-                DEFAULT_DISPLAY, false /* visible */, false /* hasDirectActivity */,
+                DEFAULT_DISPLAY, TASK_ID, false /* visible */, false /* hasDirectActivity */,
                 null /* decorSurface */);
         mSplitController.onTaskFragmentParentInfoChanged(mock(WindowContainerTransaction.class),
                 TASK_ID, invisibleInfo);
@@ -1646,7 +1646,7 @@
 
         // Updates when Task to become visible
         final TaskFragmentParentInfo visibleInfo = new TaskFragmentParentInfo(configuration,
-                DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */,
+                DEFAULT_DISPLAY, TASK_ID, true /* visible */, false /* hasDirectActivity */,
                 null /* decorSurface */);
         mSplitController.onTaskFragmentParentInfoChanged(mock(WindowContainerTransaction.class),
                 TASK_ID, visibleInfo);
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
index 2847232..97f4d07 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
@@ -23,6 +23,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.view.Display.DEFAULT_DISPLAY;
 
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
 import static androidx.window.extensions.embedding.EmbeddingTestUtils.createTestTaskContainer;
 
 import static org.junit.Assert.assertEquals;
@@ -82,7 +83,7 @@
 
         configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
         taskContainer.updateTaskFragmentParentInfo(new TaskFragmentParentInfo(configuration,
-                DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */,
+                DEFAULT_DISPLAY, TASK_ID, true /* visible */, false /* hasDirectActivity */,
                 null /* decorSurface */));
 
         assertEquals(WINDOWING_MODE_MULTI_WINDOW,
@@ -90,7 +91,7 @@
 
         configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
         taskContainer.updateTaskFragmentParentInfo(new TaskFragmentParentInfo(configuration,
-                DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */,
+                DEFAULT_DISPLAY, TASK_ID, true /* visible */, false /* hasDirectActivity */,
                 null /* decorSurface */));
 
         assertEquals(WINDOWING_MODE_FREEFORM,
@@ -111,14 +112,14 @@
 
         configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
         taskContainer.updateTaskFragmentParentInfo(new TaskFragmentParentInfo(configuration,
-                DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */,
+                DEFAULT_DISPLAY, TASK_ID, true /* visible */, false /* hasDirectActivity */,
                 null /* decorSurface */));
 
         assertFalse(taskContainer.isInPictureInPicture());
 
         configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_PINNED);
         taskContainer.updateTaskFragmentParentInfo(new TaskFragmentParentInfo(configuration,
-                DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */,
+                DEFAULT_DISPLAY, TASK_ID, true /* visible */, false /* hasDirectActivity */,
                 null /* decorSurface */));
 
         assertTrue(taskContainer.isInPictureInPicture());
diff --git a/libs/WindowManager/Shell/aconfig/multitasking.aconfig b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
index 9de10c0..df1a98c 100644
--- a/libs/WindowManager/Shell/aconfig/multitasking.aconfig
+++ b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
@@ -138,3 +138,17 @@
         purpose: PURPOSE_BUGFIX
     }
 }
+
+flag {
+   name: "enable_bubble_to_fullscreen"
+   namespace: "multitasking"
+   description: "Enable an option to move bubbles to fullscreen"
+   bug: "363326492"
+}
+
+flag {
+    name: "enable_flexible_split"
+    namespace: "multitasking"
+    description: "Enables flexibile split feature for split screen"
+    bug: "349828130"
+}
diff --git a/libs/WindowManager/Shell/res/values/strings.xml b/libs/WindowManager/Shell/res/values/strings.xml
index 36d0a3c..a353db7 100644
--- a/libs/WindowManager/Shell/res/values/strings.xml
+++ b/libs/WindowManager/Shell/res/values/strings.xml
@@ -155,6 +155,8 @@
     <string name="bubbles_app_settings"><xliff:g id="notification_title" example="Android Messages">%1$s</xliff:g> settings</string>
     <!-- Text used for the bubble dismiss area. Bubbles dragged to, or flung towards, this area will go away. [CHAR LIMIT=30] -->
     <string name="bubble_dismiss_text">Dismiss bubble</string>
+    <!-- Text used to move the bubble to fullscreen. [CHAR LIMIT=30] -->
+    <string name="bubble_fullscreen_text">Move to fullscreen</string>
     <!-- Button text to stop a conversation from bubbling [CHAR LIMIT=60]-->
     <string name="bubbles_dont_bubble_conversation">Don\u2019t bubble conversation</string>
     <!-- Title text for the bubbles feature education cling shown when a bubble is on screen for the first time. [CHAR LIMIT=60]-->
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
index 694b1b0..f90b2aa 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
@@ -228,6 +228,13 @@
             public void onDismissBubble(Bubble bubble) {
                 mManager.dismissBubble(bubble, Bubbles.DISMISS_USER_GESTURE);
             }
+
+            @Override
+            public void onMoveToFullscreen(Bubble bubble) {
+                if (mTaskView != null) {
+                    mTaskView.moveToFullscreen();
+                }
+            }
         });
         mHandleView.setOnClickListener(view -> {
             mMenuViewController.showMenu(true /* animated */);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuViewController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuViewController.java
index 0d72998..5148107 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuViewController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuViewController.java
@@ -29,6 +29,7 @@
 import androidx.dynamicanimation.animation.DynamicAnimation;
 import androidx.dynamicanimation.animation.SpringForce;
 
+import com.android.wm.shell.Flags;
 import com.android.wm.shell.R;
 import com.android.wm.shell.bubbles.Bubble;
 import com.android.wm.shell.shared.animation.PhysicsAnimator;
@@ -219,6 +220,21 @@
                 }
         ));
 
+        if (Flags.enableBubbleAnything() || Flags.enableBubbleToFullscreen()) {
+            menuActions.add(new BubbleBarMenuView.MenuAction(
+                    Icon.createWithResource(resources,
+                            R.drawable.desktop_mode_ic_handle_menu_fullscreen),
+                    resources.getString(R.string.bubble_fullscreen_text),
+                    tintColor,
+                    view -> {
+                        hideMenu(true /* animated */);
+                        if (mListener != null) {
+                            mListener.onMoveToFullscreen(bubble);
+                        }
+                    }
+            ));
+        }
+
         return menuActions;
     }
 
@@ -249,5 +265,10 @@
          * Dismiss bubble and remove it from the bubble stack
          */
         void onDismissBubble(Bubble bubble);
+
+        /**
+         * Move the bubble to fullscreen.
+         */
+        void onMoveToFullscreen(Bubble bubble);
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
index 5b01a0d..f03daad 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
@@ -291,17 +291,11 @@
             if (hadImeSourceControl != hasImeSourceControl) {
                 dispatchImeControlTargetChanged(mDisplayId, hasImeSourceControl);
             }
+            final boolean hasImeLeash = hasImeSourceControl && imeSourceControl.getLeash() != null;
 
             boolean pendingImeStartAnimation = false;
-            boolean canAnimate;
-            if (android.view.inputmethod.Flags.refactorInsetsController()) {
-                canAnimate = hasImeSourceControl && imeSourceControl.getLeash() != null;
-            } else {
-                canAnimate = hasImeSourceControl;
-            }
-
             boolean positionChanged = false;
-            if (canAnimate) {
+            if (hasImeLeash) {
                 if (mAnimation != null) {
                     final Point lastSurfacePosition = hadImeSourceControl
                             ? mImeSourceControl.getSurfacePosition() : null;
@@ -325,6 +319,13 @@
                 // continue the bar to slide to the end (even without visible IME)
                 mAnimation.cancel();
             }
+
+            // Make mImeSourceControl point to the new control before starting the animation.
+            if (hadImeSourceControl && mImeSourceControl != imeSourceControl) {
+                mImeSourceControl.release(SurfaceControl::release);
+            }
+            mImeSourceControl = imeSourceControl;
+
             if (positionChanged) {
                 if (android.view.inputmethod.Flags.refactorInsetsController()) {
                     // For showing the IME, the leash has to be available first. Hiding
@@ -338,11 +339,6 @@
                 }
             }
 
-            if (hadImeSourceControl && mImeSourceControl != imeSourceControl) {
-                mImeSourceControl.release(SurfaceControl::release);
-            }
-            mImeSourceControl = imeSourceControl;
-
             if (android.view.inputmethod.Flags.refactorInsetsController()) {
                 if (pendingImeStartAnimation) {
                     startAnimation(true, true /* forceRestart */);
@@ -465,11 +461,12 @@
 
         private void startAnimation(final boolean show, final boolean forceRestart,
                 @NonNull final ImeTracker.Token statsToken) {
+            if (mImeSourceControl == null || mImeSourceControl.getLeash() == null) {
+                if (DEBUG) Slog.d(TAG, "No leash available, not starting the animation.");
+                return;
+            }
             if (android.view.inputmethod.Flags.refactorInsetsController()) {
-                if (mImeSourceControl == null || mImeSourceControl.getLeash() == null) {
-                    if (DEBUG) Slog.d(TAG, "No leash available, not starting the animation.");
-                    return;
-                } else if (!mImeRequestedVisible && show) {
+                if (!mImeRequestedVisible && show) {
                     // we have a control with leash, but the IME was not requested visible before,
                     // therefore aborting the show animation.
                     Slog.e(TAG, "IME was not requested visible, not starting the show animation.");
@@ -478,7 +475,7 @@
                 }
             }
             final InsetsSource imeSource = mInsetsState.peekSource(InsetsSource.ID_IME);
-            if (imeSource == null || mImeSourceControl == null) {
+            if (imeSource == null) {
                 ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE);
                 return;
             }
@@ -515,8 +512,10 @@
                 }
                 mAnimation.cancel();
             }
-            final float defaultY = mImeSourceControl.getSurfacePosition().y;
-            final float x = mImeSourceControl.getSurfacePosition().x;
+            final InsetsSourceControl animatingControl = new InsetsSourceControl(mImeSourceControl);
+            final SurfaceControl animatingLeash = animatingControl.getLeash();
+            final float defaultY = animatingControl.getSurfacePosition().y;
+            final float x = animatingControl.getSurfacePosition().x;
             final float hiddenY = defaultY + mImeFrame.height();
             final float shownY = defaultY;
             final float startY = show ? hiddenY : shownY;
@@ -538,13 +537,10 @@
             mAnimation.addUpdateListener(animation -> {
                 SurfaceControl.Transaction t = mTransactionPool.acquire();
                 float value = (float) animation.getAnimatedValue();
-                if (!android.view.inputmethod.Flags.refactorInsetsController() || (
-                        mImeSourceControl != null && mImeSourceControl.getLeash() != null)) {
-                    t.setPosition(mImeSourceControl.getLeash(), x, value);
-                    final float alpha = (mAnimateAlpha || isFloating)
-                            ? (value - hiddenY) / (shownY - hiddenY) : 1.f;
-                    t.setAlpha(mImeSourceControl.getLeash(), alpha);
-                }
+                t.setPosition(animatingLeash, x, value);
+                final float alpha = (mAnimateAlpha || isFloating)
+                        ? (value - hiddenY) / (shownY - hiddenY) : 1f;
+                t.setAlpha(animatingLeash, alpha);
                 dispatchPositionChanged(mDisplayId, imeTop(value), t);
                 t.apply();
                 mTransactionPool.release(t);
@@ -561,7 +557,7 @@
                     ValueAnimator valueAnimator = (ValueAnimator) animation;
                     float value = (float) valueAnimator.getAnimatedValue();
                     SurfaceControl.Transaction t = mTransactionPool.acquire();
-                    t.setPosition(mImeSourceControl.getLeash(), x, value);
+                    t.setPosition(animatingLeash, x, value);
                     if (DEBUG) {
                         Slog.d(TAG, "onAnimationStart d:" + mDisplayId + " top:"
                                 + imeTop(hiddenY) + "->" + imeTop(shownY)
@@ -573,19 +569,19 @@
                     final float alpha = (mAnimateAlpha || isFloating)
                             ? (value - hiddenY) / (shownY - hiddenY)
                             : 1.f;
-                    t.setAlpha(mImeSourceControl.getLeash(), alpha);
+                    t.setAlpha(animatingLeash, alpha);
                     if (mAnimationDirection == DIRECTION_SHOW) {
                         ImeTracker.forLogging().onProgress(mStatsToken,
                                 ImeTracker.PHASE_WM_ANIMATION_RUNNING);
-                        t.show(mImeSourceControl.getLeash());
+                        t.show(animatingLeash);
                     }
                     if (DEBUG_IME_VISIBILITY) {
                         EventLog.writeEvent(IMF_IME_REMOTE_ANIM_START,
                                 mStatsToken != null ? mStatsToken.getTag() : ImeTracker.TOKEN_NONE,
                                 mDisplayId, mAnimationDirection, alpha, value, endY,
-                                Objects.toString(mImeSourceControl.getLeash()),
-                                Objects.toString(mImeSourceControl.getInsetsHint()),
-                                Objects.toString(mImeSourceControl.getSurfacePosition()),
+                                Objects.toString(animatingLeash),
+                                Objects.toString(animatingControl.getInsetsHint()),
+                                Objects.toString(animatingControl.getSurfacePosition()),
                                 Objects.toString(mImeFrame));
                     }
                     t.apply();
@@ -599,31 +595,23 @@
                         EventLog.writeEvent(IMF_IME_REMOTE_ANIM_CANCEL,
                                 mStatsToken != null ? mStatsToken.getTag() : ImeTracker.TOKEN_NONE,
                                 mDisplayId,
-                                Objects.toString(mImeSourceControl.getInsetsHint()));
+                                Objects.toString(animatingControl.getInsetsHint()));
                     }
                 }
 
                 @Override
                 public void onAnimationEnd(Animator animation) {
-                    boolean hasLeash =
-                            mImeSourceControl != null && mImeSourceControl.getLeash() != null;
                     if (DEBUG) Slog.d(TAG, "onAnimationEnd " + mCancelled);
                     SurfaceControl.Transaction t = mTransactionPool.acquire();
                     if (!mCancelled) {
-                        if (!android.view.inputmethod.Flags.refactorInsetsController()
-                                || hasLeash) {
-                            t.setPosition(mImeSourceControl.getLeash(), x, endY);
-                            t.setAlpha(mImeSourceControl.getLeash(), 1.f);
-                        }
+                        t.setPosition(animatingLeash, x, endY);
+                        t.setAlpha(animatingLeash, 1.f);
                     }
                     dispatchEndPositioning(mDisplayId, mCancelled, t);
                     if (mAnimationDirection == DIRECTION_HIDE && !mCancelled) {
                         ImeTracker.forLogging().onProgress(mStatsToken,
                                 ImeTracker.PHASE_WM_ANIMATION_RUNNING);
-                        if (!android.view.inputmethod.Flags.refactorInsetsController()
-                                || hasLeash) {
-                            t.hide(mImeSourceControl.getLeash());
-                        }
+                        t.hide(animatingLeash);
                         removeImeSurface(mDisplayId);
                         ImeTracker.forLogging().onHidden(mStatsToken);
                     } else if (mAnimationDirection == DIRECTION_SHOW && !mCancelled) {
@@ -636,13 +624,9 @@
                         EventLog.writeEvent(IMF_IME_REMOTE_ANIM_END,
                                 mStatsToken != null ? mStatsToken.getTag() : ImeTracker.TOKEN_NONE,
                                 mDisplayId, mAnimationDirection, endY,
-                                Objects.toString(
-                                        mImeSourceControl != null ? mImeSourceControl.getLeash()
-                                                : "null"),
-                                Objects.toString(mImeSourceControl != null
-                                        ? mImeSourceControl.getInsetsHint() : "null"),
-                                Objects.toString(mImeSourceControl != null
-                                        ? mImeSourceControl.getSurfacePosition() : "null"),
+                                Objects.toString(animatingLeash),
+                                Objects.toString(animatingControl.getInsetsHint()),
+                                Objects.toString(animatingControl.getSurfacePosition()),
                                 Objects.toString(mImeFrame));
                     }
                     t.apply();
@@ -650,6 +634,7 @@
 
                     mAnimationDirection = DIRECTION_NONE;
                     mAnimation = null;
+                    animatingControl.release(SurfaceControl::release);
                 }
             });
             if (!show) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
index 972b78f..6146ecd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
@@ -831,7 +831,6 @@
      */
     static class CompatUIHintsState {
         boolean mHasShownSizeCompatHint;
-        boolean mHasShownCameraCompatHint;
         boolean mHasShownUserAspectRatioSettingsButtonHint;
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index e4cd10f..ab222c9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -99,6 +99,7 @@
 import java.lang.ref.WeakReference;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.StringJoiner;
 import java.util.function.Consumer;
 import java.util.function.IntConsumer;
 
@@ -831,6 +832,7 @@
                     mPictureInPictureParams.getTitle());
             mPipParamsChangedForwarder.notifySubtitleChanged(
                     mPictureInPictureParams.getSubtitle());
+            logRemoteActions(mPictureInPictureParams);
         }
 
         mPipUiEventLoggerLogger.setTaskInfo(mTaskInfo);
@@ -1112,6 +1114,7 @@
         }
         applyNewPictureInPictureParams(newParams);
         mPictureInPictureParams = newParams;
+        logRemoteActions(mPictureInPictureParams);
     }
 
     @Override
@@ -1420,6 +1423,16 @@
         }
     }
 
+    private void logRemoteActions(@NonNull PictureInPictureParams params) {
+        StringJoiner sj = new StringJoiner("|", "[", "]");
+        if (params.hasSetActions()) {
+            params.getActions().forEach((action) -> sj.add(action.getTitle()));
+        }
+
+        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                "%s: PIP remote actions=%s", TAG, sj.toString());
+    }
+
     /**
      * Animates resizing of the pinned stack given the duration.
      */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java
index 27ded57..cea995d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java
@@ -321,8 +321,10 @@
                 0 /* enterReason */,
                 0 /* exitReason */,
                 mLastSplitRatio,
-                0 /* mainStagePosition */, 0 /* mainStageUid */,
-                0 /* sideStagePosition */, 0 /* sideStageUid */,
+                mLastMainStagePosition,
+                mLastMainStageUid,
+                mLastSideStagePosition,
+                mLastSideStageUid,
                 0 /* dragInstanceId */,
                 mLoggerSessionId.getId());
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskView.java
index a85188a..82c0aaf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskView.java
@@ -118,6 +118,13 @@
         mTaskViewTaskController.startShortcutActivity(shortcut, options, launchBounds);
     }
 
+    /**
+     * Moves the current task in taskview out of the view and back to fullscreen.
+     */
+    public void moveToFullscreen() {
+        mTaskViewTaskController.moveToFullscreen();
+    }
+
     @Override
     public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
         if (mTaskViewTaskController.isUsingShellTransitions()) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
index 9750d3e..e74342e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
@@ -17,6 +17,7 @@
 package com.android.wm.shell.taskview;
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.view.WindowManager.TRANSIT_CHANGE;
 
 import android.annotation.NonNull;
@@ -256,6 +257,24 @@
         mTaskViewTransitions.startInstantTransition(TRANSIT_CHANGE, wct);
     }
 
+    /**
+     * Moves the current task in TaskView out of the view and back to fullscreen.
+     */
+    public void moveToFullscreen() {
+        if (mTaskToken == null) return;
+        mShellExecutor.execute(() -> {
+            WindowContainerTransaction wct = new WindowContainerTransaction();
+            wct.setWindowingMode(mTaskToken, WINDOWING_MODE_UNDEFINED);
+            wct.setAlwaysOnTop(mTaskToken, false);
+            mTaskOrganizer.setInterceptBackPressedOnTaskRoot(mTaskToken, false);
+            mTaskViewTransitions.moveTaskViewToFullscreen(wct, this);
+            if (mListener != null) {
+                // Task is being "removed" from the clients perspective
+                mListener.onTaskRemovalStarted(mTaskInfo.taskId);
+            }
+        });
+    }
+
     private void prepareActivityOptions(ActivityOptions options, Rect launchBounds) {
         final Binder launchCookie = new Binder();
         mShellExecutor.execute(() -> {
@@ -585,7 +604,6 @@
                 });
             }
             mTaskViewBase.onTaskVanished(taskInfo);
-            mTaskOrganizer.setInterceptBackPressedOnTaskRoot(taskInfo.token, false);
         }
     }
 
@@ -699,6 +717,9 @@
             mTaskViewBase.setResizeBgColor(startTransaction, backgroundColor);
         }
 
+        // After the embedded task has appeared, set it to non-trimmable. This is important
+        // to prevent recents from trimming and removing the embedded task.
+        wct.setTaskTrimmableFromRecents(taskInfo.token, false /* isTrimmableFromRecents */);
         mTaskViewBase.onTaskAppeared(mTaskInfo, mTaskLeash);
         if (mListener != null) {
             final int taskId = mTaskInfo.taskId;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java
index 15fe7ab..39648f6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java
@@ -236,6 +236,12 @@
         startNextTransition();
     }
 
+    void moveTaskViewToFullscreen(@NonNull WindowContainerTransaction wct,
+            @NonNull TaskViewTaskController taskView) {
+        mPending.add(new PendingTransition(TRANSIT_CHANGE, wct, taskView, null /* cookie */));
+        startNextTransition();
+    }
+
     /** Starts a new transition to make the given {@code taskView} visible. */
     public void setTaskViewVisible(TaskViewTaskController taskView, boolean visible) {
         setTaskViewVisible(taskView, visible, false /* reorder */);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java
index 0434742..1984885 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java
@@ -294,16 +294,6 @@
     }
 
     @Test
-    public void testUnsetOnBackPressedOnTaskRoot_legacyTransitions() {
-        assumeFalse(Transitions.ENABLE_SHELL_TRANSITIONS);
-        mTaskViewTaskController.onTaskAppeared(mTaskInfo, mLeash);
-        verify(mOrganizer).setInterceptBackPressedOnTaskRoot(eq(mTaskInfo.token), eq(true));
-
-        mTaskViewTaskController.onTaskVanished(mTaskInfo);
-        verify(mOrganizer).setInterceptBackPressedOnTaskRoot(eq(mTaskInfo.token), eq(false));
-    }
-
-    @Test
     public void testOnNewTask_noSurface() {
         assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
         WindowContainerTransaction wct = new WindowContainerTransaction();
@@ -443,19 +433,6 @@
     }
 
     @Test
-    public void testUnsetOnBackPressedOnTaskRoot() {
-        assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
-        WindowContainerTransaction wct = new WindowContainerTransaction();
-        mTaskViewTaskController.prepareOpenAnimation(true /* newTask */,
-                new SurfaceControl.Transaction(), new SurfaceControl.Transaction(), mTaskInfo,
-                mLeash, wct);
-        verify(mOrganizer).setInterceptBackPressedOnTaskRoot(eq(mTaskInfo.token), eq(true));
-
-        mTaskViewTaskController.prepareCloseAnimation();
-        verify(mOrganizer).setInterceptBackPressedOnTaskRoot(eq(mTaskInfo.token), eq(false));
-    }
-
-    @Test
     public void testSetObscuredTouchRect() {
         mTaskView.setObscuredTouchRect(
                 new Rect(/* left= */ 0, /* top= */ 10, /* right= */ 100, /* bottom= */ 120));
@@ -713,4 +690,26 @@
         verify(mViewHandler).post(any());
         verify(mTaskView).setResizeBackgroundColor(eq(Color.BLUE));
     }
+
+    @Test
+    public void testOnAppeared_setsTrimmableTask() {
+        WindowContainerTransaction wct = new WindowContainerTransaction();
+        mTaskViewTaskController.prepareOpenAnimation(true /* newTask */,
+                new SurfaceControl.Transaction(), new SurfaceControl.Transaction(), mTaskInfo,
+                mLeash, wct);
+
+        assertThat(wct.getHierarchyOps().get(0).isTrimmableFromRecents()).isFalse();
+    }
+
+    @Test
+    public void testMoveToFullscreen_callsTaskRemovalStarted() {
+        WindowContainerTransaction wct = new WindowContainerTransaction();
+        mTaskViewTaskController.prepareOpenAnimation(true /* newTask */,
+                new SurfaceControl.Transaction(), new SurfaceControl.Transaction(), mTaskInfo,
+                mLeash, wct);
+        mTaskView.surfaceCreated(mock(SurfaceHolder.class));
+        mTaskViewTaskController.moveToFullscreen();
+
+        verify(mViewListener).onTaskRemovalStarted(eq(mTaskInfo.taskId));
+    }
 }
diff --git a/libs/androidfw/Asset.cpp b/libs/androidfw/Asset.cpp
index 43a70c1..5a4cff0 100644
--- a/libs/androidfw/Asset.cpp
+++ b/libs/androidfw/Asset.cpp
@@ -309,9 +309,8 @@
         return NULL;
     }
 
-    // We succeeded, so relinquish control of dataMap
     pAsset->mAccessMode = mode;
-    return std::move(pAsset);
+    return pAsset;
 }
 
 /*
@@ -328,9 +327,8 @@
       return NULL;
   }
 
-  // We succeeded, so relinquish control of dataMap
   pAsset->mAccessMode = mode;
-  return std::move(pAsset);
+  return pAsset;
 }
 
 /*
diff --git a/location/api/system-current.txt b/location/api/system-current.txt
index f6e76a2..cf3f740 100644
--- a/location/api/system-current.txt
+++ b/location/api/system-current.txt
@@ -437,7 +437,7 @@
   }
 
   public class LocationManager {
-    method @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.INTERACT_ACROSS_USERS}) public void addProviderRequestChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.provider.ProviderRequest.ChangedListener);
+    method @Deprecated @FlaggedApi("android.location.flags.deprecate_provider_request_apis") @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.INTERACT_ACROSS_USERS}) public void addProviderRequestChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.provider.ProviderRequest.ChangedListener);
     method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void flushGnssBatch();
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
     method @Nullable public String getExtraLocationControllerPackage();
@@ -452,7 +452,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@Nullable String, @NonNull String, @Nullable String);
     method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.UPDATE_APP_OPS_STATS}) public boolean registerGnssBatchedLocationCallback(long, boolean, @NonNull android.location.BatchedLocationCallback, @Nullable android.os.Handler);
     method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
-    method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void removeProviderRequestChangedListener(@NonNull android.location.provider.ProviderRequest.ChangedListener);
+    method @Deprecated @FlaggedApi("android.location.flags.deprecate_provider_request_apis") @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void removeProviderRequestChangedListener(@NonNull android.location.provider.ProviderRequest.ChangedListener);
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.app.PendingIntent);
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index d921730..6342489 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -28,6 +28,7 @@
 
 import android.Manifest;
 import android.annotation.CallbackExecutor;
+import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresFeature;
@@ -47,6 +48,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.location.flags.Flags;
 import android.location.provider.IProviderRequestListener;
 import android.location.provider.ProviderProperties;
 import android.location.provider.ProviderRequest;
@@ -2957,8 +2959,13 @@
      *
      * @param executor the executor that the callback runs on
      * @param listener the listener to register
+     *
+     * @deprecated Do not use - this API was intended for testing only, and may not return any
+     * results in the future.
      * @hide
      */
+    @FlaggedApi(Flags.FLAG_DEPRECATE_PROVIDER_REQUEST_APIS)
+    @Deprecated
     @SystemApi
     @RequiresPermission(allOf = {Manifest.permission.LOCATION_HARDWARE,
             Manifest.permission.INTERACT_ACROSS_USERS})
@@ -2973,8 +2980,13 @@
      * Removes a {@link ProviderRequest.ChangedListener} that has been added.
      *
      * @param listener the listener to remove.
+     *
+     * @deprecated Do not use - this API was intended for testing only, and may not return any
+     * results in the future.
      * @hide
      */
+    @FlaggedApi(Flags.FLAG_DEPRECATE_PROVIDER_REQUEST_APIS)
+    @Deprecated
     @SystemApi
     @RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
     public void removeProviderRequestChangedListener(
diff --git a/location/java/android/location/flags/location.aconfig b/location/java/android/location/flags/location.aconfig
index 0edaaef..3c387d3 100644
--- a/location/java/android/location/flags/location.aconfig
+++ b/location/java/android/location/flags/location.aconfig
@@ -2,6 +2,13 @@
 container: "system"
 
 flag {
+    name: "deprecate_provider_request_apis"
+    namespace: "location"
+    description: "Deprecates LocationManager ProviderChanged APIs"
+    bug: "361811782"
+}
+
+flag {
     name: "keep_gnss_stationary_throttling"
     namespace: "location"
     description: "Keeps stationary throttling for the GNSS provider even if the disable_stationary_throttling flag is true."
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 1930c3d..b84990b 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -288,8 +288,7 @@
 
     /**
      * Returns a proxy MediaRouter2 instance that allows you to control the routing of an app
-     * specified by {@code clientPackageName}. Returns {@code null} if the specified package name
-     * does not exist.
+     * specified by {@code clientPackageName}.
      *
      * <p>Proxy MediaRouter2 instances operate differently than regular MediaRouter2 instances:
      *
diff --git a/media/native/midi/Android.bp b/media/native/midi/Android.bp
index a991a71f..7acb8c7 100644
--- a/media/native/midi/Android.bp
+++ b/media/native/midi/Android.bp
@@ -74,8 +74,4 @@
     symbol_file: "libamidi.map.txt",
 
     first_version: "29",
-    export_header_libs: [
-        "amidi",
-    ],
-
 }
diff --git a/native/android/Android.bp b/native/android/Android.bp
index c4c4102..3eb99c3 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -27,9 +27,6 @@
     symbol_file: "libandroid.map.txt",
     first_version: "9",
     unversioned_until: "current",
-    export_header_libs: [
-        "libandroid_headers",
-    ],
 }
 
 cc_defaults {
diff --git a/packages/SettingsLib/aconfig/settingslib.aconfig b/packages/SettingsLib/aconfig/settingslib.aconfig
index 2b3862f..34b597b 100644
--- a/packages/SettingsLib/aconfig/settingslib.aconfig
+++ b/packages/SettingsLib/aconfig/settingslib.aconfig
@@ -129,3 +129,13 @@
         purpose: PURPOSE_BUGFIX
     }
 }
+
+flag {
+    name: "member_device_lea_active_state_sync_fix"
+    namespace: "cross_device_experiences"
+    description: "Gates whether to enable fix for member device active state sync on lea profile"
+    bug: "364201289"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/packages/SettingsLib/res/values/config.xml b/packages/SettingsLib/res/values/config.xml
index 68b81db..3c3de04 100644
--- a/packages/SettingsLib/res/values/config.xml
+++ b/packages/SettingsLib/res/values/config.xml
@@ -31,4 +31,14 @@
     <!-- Control whether status bar should distinguish HSPA data icon form UMTS
     data icon on devices -->
     <bool name="config_hspa_data_distinguishable">false</bool>
+
+    <!-- Edit User avatar explicit package name -->
+    <string name="config_avatar_picker_package" translatable="false">
+        com.android.avatarpicker
+    </string>
+
+    <!-- Edit User avatar explicit activity class -->
+    <string name="config_avatar_picker_class" translatable="false">
+        com.android.avatarpicker.ui.AvatarPickerActivity
+    </string>
 </resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 687c728..4d771c0 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1364,6 +1364,9 @@
     <!-- Keywords for setting screen for controlling apps that can schedule alarms [CHAR LIMIT=100] -->
     <string name="keywords_alarms_and_reminders">schedule, alarm, reminder, clock</string>
 
+    <!-- Priority Modes: Name of the "manual" Do Not Disturb mode. [CHAR LIMIT=50] -->
+    <string name="zen_mode_do_not_disturb_name">Do Not Disturb</string>
+
     <!-- Sound: Title for the Do not Disturb option and associated settings page. [CHAR LIMIT=50]-->
     <string name="zen_mode_settings_title">Do Not Disturb</string>
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index b02b0c4..1e58335 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -495,7 +495,7 @@
                 || packageName.equals(sServicesSystemSharedLibPackageName)
                 || packageName.equals(sSharedSystemSharedLibPackageName)
                 || packageName.equals(PrintManager.PRINT_SPOOLER_PACKAGE_NAME)
-                || (updateServiceV2() && packageName.equals(getDefaultWebViewPackageName()))
+                || (updateServiceV2() && packageName.equals(getDefaultWebViewPackageName(pm)))
                 || isDeviceProvisioningPackage(resources, packageName);
     }
 
@@ -511,7 +511,7 @@
 
     /** Fetch the package name of the default WebView provider. */
     @Nullable
-    private static String getDefaultWebViewPackageName() {
+    private static String getDefaultWebViewPackageName(PackageManager pm) {
         if (sDefaultWebViewPackageName != null) {
             return sDefaultWebViewPackageName;
         }
@@ -519,9 +519,10 @@
         WebViewProviderInfo provider = null;
 
         if (android.webkit.Flags.updateServiceIpcWrapper()) {
-            WebViewUpdateManager manager = WebViewUpdateManager.getInstance();
-            if (manager != null) {
-                provider = manager.getDefaultWebViewPackage();
+            if (pm.hasSystemFeature(PackageManager.FEATURE_WEBVIEW)) {
+                // WebViewUpdateManager.getInstance() will not return null on devices with
+                // FEATURE_WEBVIEW.
+                provider = WebViewUpdateManager.getInstance().getDefaultWebViewPackage();
             }
         } else {
             try {
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/FakeZenModeRepository.kt b/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/FakeZenModeRepository.kt
index 4371f05..043219a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/FakeZenModeRepository.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/FakeZenModeRepository.kt
@@ -41,6 +41,8 @@
     override val modes: Flow<List<ZenMode>>
         get() = mutableModesFlow.asStateFlow()
 
+    override fun getModes(): List<ZenMode> = mutableModesFlow.value
+
     private val activeModesDurations = mutableMapOf<String, Duration?>()
 
     init {
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/ZenModeRepository.kt b/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/ZenModeRepository.kt
index 0ff7f84..7fdbcda 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/ZenModeRepository.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/ZenModeRepository.kt
@@ -59,6 +59,8 @@
     /** A list of all existing priority modes. */
     val modes: Flow<List<ZenMode>>
 
+    fun getModes(): List<ZenMode>
+
     fun activateMode(zenMode: ZenMode, duration: Duration? = null)
 
     fun deactivateMode(zenMode: ZenMode)
@@ -184,6 +186,15 @@
         }
     }
 
+    /**
+     * Gets the current list of [ZenMode] instances according to the backend.
+     *
+     * This is necessary, and cannot be supplanted by making [modes] a StateFlow, because it will be
+     * called whenever we know or suspect that [modes] may not have caught up to the latest data
+     * (such as right after a user switch).
+     */
+    override fun getModes(): List<ZenMode> = backend.modes
+
     override fun activateMode(zenMode: ZenMode, duration: Duration?) {
         backend.activateMode(zenMode, duration)
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/TestModeBuilder.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/TestModeBuilder.java
index f7492cf..8e0cdf8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/TestModeBuilder.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/TestModeBuilder.java
@@ -16,6 +16,7 @@
 
 package com.android.settingslib.notification.modes;
 
+import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
 import static android.service.notification.ZenModeConfig.ORIGIN_UNKNOWN;
 import static android.service.notification.ZenModeConfig.ORIGIN_USER_IN_SYSTEMUI;
 
@@ -24,11 +25,13 @@
 import android.content.ComponentName;
 import android.net.Uri;
 import android.service.notification.Condition;
+import android.service.notification.SystemZenRules;
 import android.service.notification.ZenDeviceEffects;
 import android.service.notification.ZenModeConfig;
 import android.service.notification.ZenPolicy;
 
 import androidx.annotation.DrawableRes;
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import java.util.Random;
@@ -40,13 +43,27 @@
     private ZenModeConfig.ZenRule mConfigZenRule;
 
     public static final ZenMode EXAMPLE = new TestModeBuilder().build();
-    public static final ZenMode MANUAL_DND_ACTIVE = manualDnd(Uri.EMPTY, true);
-    public static final ZenMode MANUAL_DND_INACTIVE = manualDnd(Uri.EMPTY, false);
 
-    public static ZenMode manualDnd(Uri conditionId, boolean isActive) {
+    public static final ZenMode MANUAL_DND_ACTIVE = manualDnd(Uri.EMPTY,
+            INTERRUPTION_FILTER_PRIORITY, true);
+
+    public static final ZenMode MANUAL_DND_INACTIVE = manualDnd(Uri.EMPTY,
+            INTERRUPTION_FILTER_PRIORITY, false);
+
+    @NonNull
+    public static ZenMode manualDnd(@NotificationManager.InterruptionFilter int filter,
+            boolean isActive) {
+        return manualDnd(Uri.EMPTY, filter, isActive);
+    }
+
+    private static ZenMode manualDnd(Uri conditionId,
+            @NotificationManager.InterruptionFilter int filter, boolean isActive) {
         return ZenMode.manualDndMode(
                 new AutomaticZenRule.Builder("Do Not Disturb", conditionId)
-                        .setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY)
+                        .setInterruptionFilter(filter)
+                        .setType(AutomaticZenRule.TYPE_OTHER)
+                        .setManualInvocationAllowed(true)
+                        .setPackage(SystemZenRules.PACKAGE_ANDROID)
                         .setZenPolicy(new ZenPolicy.Builder().disallowAllSounds().build())
                         .build(),
                 isActive);
@@ -58,7 +75,7 @@
         mId = "rule_" + id;
         mRule = new AutomaticZenRule.Builder("Test Rule #" + id, Uri.parse("rule://" + id))
                 .setPackage("some_package")
-                .setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY)
+                .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
                 .setZenPolicy(new ZenPolicy.Builder().disallowAllSounds().build())
                 .build();
         mConfigZenRule = new ZenModeConfig.ZenRule();
@@ -134,7 +151,7 @@
             @NotificationManager.InterruptionFilter int interruptionFilter) {
         mRule.setInterruptionFilter(interruptionFilter);
         mConfigZenRule.zenMode = NotificationManager.zenModeFromInterruptionFilter(
-                interruptionFilter, NotificationManager.INTERRUPTION_FILTER_PRIORITY);
+                interruptionFilter, INTERRUPTION_FILTER_PRIORITY);
         return this;
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java
index 36975c7..7b2a284 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java
@@ -18,9 +18,10 @@
 
 import static android.app.AutomaticZenRule.TYPE_SCHEDULE_CALENDAR;
 import static android.app.AutomaticZenRule.TYPE_SCHEDULE_TIME;
+import static android.app.NotificationManager.INTERRUPTION_FILTER_ALARMS;
 import static android.app.NotificationManager.INTERRUPTION_FILTER_ALL;
+import static android.app.NotificationManager.INTERRUPTION_FILTER_NONE;
 import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
-import static android.service.notification.SystemZenRules.PACKAGE_ANDROID;
 import static android.service.notification.SystemZenRules.getTriggerDescriptionForScheduleEvent;
 import static android.service.notification.SystemZenRules.getTriggerDescriptionForScheduleTime;
 import static android.service.notification.ZenModeConfig.tryParseCountdownConditionId;
@@ -68,23 +69,6 @@
     static final String MANUAL_DND_MODE_ID = ZenModeConfig.MANUAL_RULE_ID;
     static final String TEMP_NEW_MODE_ID = "temp_new_mode";
 
-    // Must match com.android.server.notification.ZenModeHelper#applyCustomPolicy.
-    private static final ZenPolicy POLICY_INTERRUPTION_FILTER_ALARMS =
-            new ZenPolicy.Builder()
-                    .disallowAllSounds()
-                    .allowAlarms(true)
-                    .allowMedia(true)
-                    .allowPriorityChannels(false)
-                    .build();
-
-    // Must match com.android.server.notification.ZenModeHelper#applyCustomPolicy.
-    private static final ZenPolicy POLICY_INTERRUPTION_FILTER_NONE =
-            new ZenPolicy.Builder()
-                    .disallowAllSounds()
-                    .hideAllVisualEffects()
-                    .allowPriorityChannels(false)
-                    .build();
-
     private static final Comparator<Integer> PRIORITIZED_TYPE_COMPARATOR = new Comparator<>() {
 
         private static final ImmutableList</* @AutomaticZenRule.Type */ Integer>
@@ -171,13 +155,9 @@
     }
 
     static ZenMode manualDndMode(AutomaticZenRule manualRule, boolean isActive) {
-        // Manual rule is owned by the system, so we set it here
-        AutomaticZenRule manualRuleWithPkg = new AutomaticZenRule.Builder(manualRule)
-                .setPackage(PACKAGE_ANDROID)
-                .build();
         return new ZenMode(
                 MANUAL_DND_MODE_ID,
-                manualRuleWithPkg,
+                manualRule,
                 Kind.MANUAL_DND,
                 isActive ? Status.ENABLED_AND_ACTIVE : Status.ENABLED);
     }
@@ -298,6 +278,23 @@
         }
     }
 
+    /** Returns the interruption filter of the mode. */
+    @NotificationManager.InterruptionFilter
+    public int getInterruptionFilter() {
+        return mRule.getInterruptionFilter();
+    }
+
+    /**
+     * Sets the interruption filter of the mode. This is valid for {@link AutomaticZenRule}-backed
+     * modes (and not manual DND).
+     */
+    public void setInterruptionFilter(@NotificationManager.InterruptionFilter int filter) {
+        if (isManualDnd() || !canEditPolicy()) {
+            throw new IllegalStateException("Cannot update interruption filter for mode " + this);
+        }
+        mRule.setInterruptionFilter(filter);
+    }
+
     @NonNull
     public ZenPolicy getPolicy() {
         switch (mRule.getInterruptionFilter()) {
@@ -306,10 +303,12 @@
                 return requireNonNull(mRule.getZenPolicy());
 
             case NotificationManager.INTERRUPTION_FILTER_ALARMS:
-                return POLICY_INTERRUPTION_FILTER_ALARMS;
+                return new ZenPolicy.Builder(ZenModeConfig.getDefaultZenPolicy()).build()
+                        .overwrittenWith(ZenPolicy.getBasePolicyInterruptionFilterAlarms());
 
             case NotificationManager.INTERRUPTION_FILTER_NONE:
-                return POLICY_INTERRUPTION_FILTER_NONE;
+                return new ZenPolicy.Builder(ZenModeConfig.getDefaultZenPolicy()).build()
+                        .overwrittenWith(ZenPolicy.getBasePolicyInterruptionFilterNone());
 
             case NotificationManager.INTERRUPTION_FILTER_UNKNOWN:
             default:
@@ -326,6 +325,10 @@
      */
     @SuppressLint("WrongConstant")
     public void setPolicy(@NonNull ZenPolicy policy) {
+        if (!canEditPolicy()) {
+            throw new IllegalStateException("Cannot update ZenPolicy for mode " + this);
+        }
+
         ZenPolicy currentPolicy = getPolicy();
         if (currentPolicy.equals(policy)) {
             return;
@@ -342,6 +345,12 @@
         mRule.setZenPolicy(policy);
     }
 
+    /**
+     * Returns the {@link ZenDeviceEffects} of the mode.
+     *
+     * <p>This is never {@code null}; if the backing AutomaticZenRule doesn't have effects set then
+     * a default (empty) effects set is returned.
+     */
     @NonNull
     public ZenDeviceEffects getDeviceEffects() {
         return mRule.getDeviceEffects() != null
@@ -349,6 +358,15 @@
                 : new ZenDeviceEffects.Builder().build();
     }
 
+    /** Sets the {@link ZenDeviceEffects} of the mode. */
+    public void setDeviceEffects(@NonNull ZenDeviceEffects effects) {
+        checkNotNull(effects);
+        if (!canEditPolicy()) {
+            throw new IllegalStateException("Cannot update device effects for mode " + this);
+        }
+        mRule.setDeviceEffects(effects);
+    }
+
     public void setCustomModeConditionId(Context context, Uri conditionId) {
         checkState(SystemZenRules.PACKAGE_ANDROID.equals(mRule.getPackageName()),
                 "Trying to change condition of non-system-owned rule %s (to %s)",
@@ -391,6 +409,18 @@
         return !isManualDnd();
     }
 
+    /**
+     * Whether the mode has an editable policy. Calling {@link #setPolicy},
+     * {@link #setDeviceEffects}, or {@link #setInterruptionFilter} is not valid for modes with a
+     * read-only policy.
+     */
+    public boolean canEditPolicy() {
+        // Cannot edit the policy of a temporarily active non-PRIORITY DND mode.
+        // Note that it's fine to edit the policy of an *AutomaticZenRule* with non-PRIORITY filter;
+        // the filter will we set to PRIORITY if you do.
+        return !isManualDndWithSpecialFilter();
+    }
+
     public boolean canBeDeleted() {
         return !isManualDnd();
     }
@@ -399,6 +429,12 @@
         return mKind == Kind.MANUAL_DND;
     }
 
+    private boolean isManualDndWithSpecialFilter() {
+        return isManualDnd()
+                && (mRule.getInterruptionFilter() == INTERRUPTION_FILTER_ALARMS
+                || mRule.getInterruptionFilter() == INTERRUPTION_FILTER_NONE);
+    }
+
     /**
      * A <em>custom manual</em> mode is a mode created by the user, and not yet assigned an
      * automatic trigger condition (neither time schedule nor a calendar).
@@ -414,6 +450,18 @@
         return mRule.isEnabled();
     }
 
+    /**
+     * Enables or disables the mode.
+     *
+     * <p>The DND mode cannot be disabled; trying to do so will fail.
+     */
+    public void setEnabled(boolean enabled) {
+        if (isManualDnd()) {
+            throw new IllegalStateException("Cannot update enabled for manual DND mode " + this);
+        }
+        mRule.setEnabled(enabled);
+    }
+
     public boolean isActive() {
         return mStatus == Status.ENABLED_AND_ACTIVE;
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java
index c8a12f4..71e03c1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java
@@ -16,6 +16,11 @@
 
 package com.android.settingslib.notification.modes;
 
+import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
+import static android.app.NotificationManager.zenModeToInterruptionFilter;
+import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+import static android.service.notification.SystemZenRules.PACKAGE_ANDROID;
+
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.AutomaticZenRule;
@@ -112,14 +117,22 @@
 
     private ZenMode getManualDndMode(ZenModeConfig config) {
         ZenModeConfig.ZenRule manualRule = config.manualRule;
+
+        // If DND is currently on with an interruption filter other than PRIORITY, construct the
+        // rule with that. DND will be *non-editable* while in this state.
+        int dndInterruptionFilter = config.isManualActive()
+                ? zenModeToInterruptionFilter(manualRule.zenMode)
+                : INTERRUPTION_FILTER_PRIORITY;
+
         AutomaticZenRule manualDndRule = new AutomaticZenRule.Builder(
-                mContext.getString(R.string.zen_mode_settings_title), manualRule.conditionId)
-                .setType(manualRule.type)
+                mContext.getString(R.string.zen_mode_do_not_disturb_name), manualRule.conditionId)
+                .setPackage(PACKAGE_ANDROID)
+                .setType(AutomaticZenRule.TYPE_OTHER)
                 .setZenPolicy(manualRule.zenPolicy)
                 .setDeviceEffects(manualRule.zenDeviceEffects)
-                .setManualInvocationAllowed(manualRule.allowManualInvocation)
+                .setManualInvocationAllowed(true)
                 .setConfigurationActivity(null) // No further settings
-                .setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY)
+                .setInterruptionFilter(dndInterruptionFilter)
                 .build();
 
         return ZenMode.manualDndMode(manualDndRule, config.isManualActive());
@@ -150,7 +163,7 @@
                 durationConditionId = ZenModeConfig.toTimeCondition(mContext,
                         (int) forDuration.toMinutes(), ActivityManager.getCurrentUser(), true).id;
             }
-            mNotificationManager.setZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+            mNotificationManager.setZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS,
                     durationConditionId, TAG, /* fromUser= */ true);
 
         } else {
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java b/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
index cdc3f12..f38e91a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
@@ -32,6 +32,7 @@
 
 import com.android.internal.util.UserIcons;
 import com.android.settingslib.drawable.CircleFramedDrawable;
+import com.android.settingslib.R;
 import com.android.settingslib.utils.ThreadUtils;
 
 import com.google.common.util.concurrent.FutureCallback;
@@ -132,6 +133,13 @@
         intent.addCategory(Intent.CATEGORY_DEFAULT);
         if (Flags.avatarSync()) {
             intent.putExtra(EXTRA_IS_USER_NEW, isUserNew);
+            // Fix vulnerability b/341688848 by explicitly set the class name of avatar picker.
+            if (Flags.fixAvatarCrossUserLeak()) {
+                final String packageName =
+                        mActivity.getString(R.string.config_avatar_picker_package);
+                final String className = mActivity.getString(R.string.config_avatar_picker_class);
+                intent.setClassName(packageName, className);
+            }
         } else {
             // SettingsLib is used by multiple apps therefore we need to know out of all apps
             // using settingsLib which one is the one we return value to.
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/data/repository/ZenModeRepositoryTest.kt b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/data/repository/ZenModeRepositoryTest.kt
index 67c73b1..c136644 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/data/repository/ZenModeRepositoryTest.kt
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/data/repository/ZenModeRepositoryTest.kt
@@ -199,6 +199,15 @@
         }
     }
 
+    @EnableFlags(android.app.Flags.FLAG_MODES_UI)
+    @Test
+    fun getModes_returnsModes() {
+        val modesList = listOf(TestModeBuilder().setId("One").build())
+        `when`(zenModesBackend.modes).thenReturn(modesList)
+
+        assertThat(underTest.getModes()).isEqualTo(modesList)
+    }
+
     private fun triggerIntent(action: String, extras: Map<String, Parcelable>? = null) {
         verify(context).registerReceiver(receiverCaptor.capture(), any(), any(), any())
         val intent = Intent(action)
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java
index 14b0c25..d08d91d 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java
@@ -24,6 +24,7 @@
 import static android.app.AutomaticZenRule.TYPE_THEATER;
 import static android.app.AutomaticZenRule.TYPE_UNKNOWN;
 import static android.app.NotificationManager.INTERRUPTION_FILTER_ALARMS;
+import static android.app.NotificationManager.INTERRUPTION_FILTER_ALL;
 import static android.app.NotificationManager.INTERRUPTION_FILTER_NONE;
 import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
 import static android.service.notification.SystemZenRules.PACKAGE_ANDROID;
@@ -31,11 +32,14 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import static org.junit.Assert.assertThrows;
+
 import android.app.AutomaticZenRule;
 import android.net.Uri;
 import android.os.Parcel;
 import android.service.notification.Condition;
 import android.service.notification.SystemZenRules;
+import android.service.notification.ZenDeviceEffects;
 import android.service.notification.ZenModeConfig;
 import android.service.notification.ZenPolicy;
 
@@ -69,20 +73,26 @@
                     .build();
 
     @Test
-    public void testBasicMethods() {
+    public void testBasicMethods_mode() {
         ZenMode zenMode = new ZenMode("id", ZEN_RULE, zenConfigRuleFor(ZEN_RULE, true));
 
         assertThat(zenMode.getId()).isEqualTo("id");
         assertThat(zenMode.getRule()).isEqualTo(ZEN_RULE);
         assertThat(zenMode.isManualDnd()).isFalse();
         assertThat(zenMode.canEditNameAndIcon()).isTrue();
+        assertThat(zenMode.canEditPolicy()).isTrue();
         assertThat(zenMode.canBeDeleted()).isTrue();
         assertThat(zenMode.isActive()).isTrue();
+    }
 
-        ZenMode manualMode = ZenMode.manualDndMode(ZEN_RULE, false);
+    @Test
+    public void testBasicMethods_manualDnd() {
+        ZenMode manualMode = TestModeBuilder.MANUAL_DND_INACTIVE;
+
         assertThat(manualMode.getId()).isEqualTo(ZenMode.MANUAL_DND_MODE_ID);
         assertThat(manualMode.isManualDnd()).isTrue();
         assertThat(manualMode.canEditNameAndIcon()).isFalse();
+        assertThat(manualMode.canEditPolicy()).isTrue();
         assertThat(manualMode.canBeDeleted()).isFalse();
         assertThat(manualMode.isActive()).isFalse();
         assertThat(manualMode.getRule().getPackageName()).isEqualTo(PACKAGE_ANDROID);
@@ -203,7 +213,7 @@
         ZenMode zenMode = new ZenMode("id", azr, zenConfigRuleFor(azr, false));
 
         assertThat(zenMode.getPolicy()).isEqualTo(
-                new ZenPolicy.Builder()
+                new ZenPolicy.Builder(ZenModeConfig.getDefaultZenPolicy())
                         .disallowAllSounds()
                         .allowAlarms(true)
                         .allowMedia(true)
@@ -220,9 +230,8 @@
         ZenMode zenMode = new ZenMode("id", azr, zenConfigRuleFor(azr, false));
 
         assertThat(zenMode.getPolicy()).isEqualTo(
-                new ZenPolicy.Builder()
+                new ZenPolicy.Builder(ZenModeConfig.getDefaultZenPolicy())
                         .disallowAllSounds()
-                        .hideAllVisualEffects()
                         .allowPriorityChannels(false)
                         .build());
     }
@@ -243,6 +252,77 @@
     }
 
     @Test
+    public void getInterruptionFilter_returnsFilter() {
+        ZenMode mode = new TestModeBuilder().setInterruptionFilter(
+                INTERRUPTION_FILTER_ALARMS).build();
+
+        assertThat(mode.getInterruptionFilter()).isEqualTo(INTERRUPTION_FILTER_ALARMS);
+    }
+
+    @Test
+    public void setInterruptionFilter_setsFilter() {
+        ZenMode mode = new TestModeBuilder().setInterruptionFilter(
+                INTERRUPTION_FILTER_ALARMS).build();
+
+        mode.setInterruptionFilter(INTERRUPTION_FILTER_ALL);
+
+        assertThat(mode.getInterruptionFilter()).isEqualTo(INTERRUPTION_FILTER_ALL);
+    }
+
+    @Test
+    public void setInterruptionFilter_manualDnd_throws() {
+        ZenMode manualDnd = TestModeBuilder.MANUAL_DND_INACTIVE;
+
+        assertThrows(IllegalStateException.class,
+                () -> manualDnd.setInterruptionFilter(INTERRUPTION_FILTER_ALL));
+    }
+
+    @Test
+    public void canEditPolicy_onlyFalseForSpecialDnd() {
+        assertThat(TestModeBuilder.EXAMPLE.canEditPolicy()).isTrue();
+        assertThat(TestModeBuilder.MANUAL_DND_ACTIVE.canEditPolicy()).isTrue();
+        assertThat(TestModeBuilder.MANUAL_DND_INACTIVE.canEditPolicy()).isTrue();
+
+        ZenMode dndWithAlarms = TestModeBuilder.manualDnd(INTERRUPTION_FILTER_ALARMS, true);
+        assertThat(dndWithAlarms.canEditPolicy()).isFalse();
+        ZenMode dndWithNone = TestModeBuilder.manualDnd(INTERRUPTION_FILTER_NONE, true);
+        assertThat(dndWithNone.canEditPolicy()).isFalse();
+
+        // Note: Backend will never return an inactive manual mode with custom filter.
+        ZenMode badDndWithAlarms = TestModeBuilder.manualDnd(INTERRUPTION_FILTER_ALARMS, false);
+        assertThat(badDndWithAlarms.canEditPolicy()).isFalse();
+        ZenMode badDndWithNone = TestModeBuilder.manualDnd(INTERRUPTION_FILTER_NONE, false);
+        assertThat(badDndWithNone.canEditPolicy()).isFalse();
+    }
+
+    @Test
+    public void canEditPolicy_whenTrue_allowsSettingPolicyAndEffects() {
+        ZenMode normalDnd = TestModeBuilder.manualDnd(INTERRUPTION_FILTER_PRIORITY, true);
+
+        assertThat(normalDnd.canEditPolicy()).isTrue();
+
+        ZenPolicy somePolicy = new ZenPolicy.Builder().showBadges(true).build();
+        normalDnd.setPolicy(somePolicy);
+        assertThat(normalDnd.getPolicy()).isEqualTo(somePolicy);
+
+        ZenDeviceEffects someEffects = new ZenDeviceEffects.Builder()
+                .setShouldUseNightMode(true).build();
+        normalDnd.setDeviceEffects(someEffects);
+        assertThat(normalDnd.getDeviceEffects()).isEqualTo(someEffects);
+    }
+
+    @Test
+    public void canEditPolicy_whenFalse_preventsSettingFilterPolicyOrEffects() {
+        ZenMode specialDnd = TestModeBuilder.manualDnd(INTERRUPTION_FILTER_ALARMS, true);
+
+        assertThat(specialDnd.canEditPolicy()).isFalse();
+        assertThrows(IllegalStateException.class,
+                () -> specialDnd.setPolicy(ZEN_POLICY));
+        assertThrows(IllegalStateException.class,
+                () -> specialDnd.setDeviceEffects(new ZenDeviceEffects.Builder().build()));
+    }
+
+    @Test
     public void comparator_prioritizes() {
         ZenMode manualDnd = TestModeBuilder.MANUAL_DND_INACTIVE;
         ZenMode driving1 = new TestModeBuilder().setName("b1").setType(TYPE_DRIVING).build();
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModesBackendTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModesBackendTest.java
index 539519b..aae72b3 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModesBackendTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModesBackendTest.java
@@ -16,12 +16,14 @@
 
 package com.android.settingslib.notification.modes;
 
+import static android.app.NotificationManager.INTERRUPTION_FILTER_ALARMS;
 import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
 import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
 import static android.provider.Settings.Global.ZEN_MODE_OFF;
 import static android.service.notification.Condition.SOURCE_UNKNOWN;
 import static android.service.notification.Condition.STATE_FALSE;
 import static android.service.notification.Condition.STATE_TRUE;
+import static android.service.notification.SystemZenRules.PACKAGE_ANDROID;
 import static android.service.notification.ZenAdapters.notificationPolicyToZenPolicy;
 import static android.service.notification.ZenPolicy.STATE_ALLOW;
 
@@ -47,8 +49,6 @@
 import android.service.notification.ZenModeConfig;
 import android.service.notification.ZenPolicy;
 
-import com.android.settingslib.R;
-
 import com.google.common.collect.ImmutableMap;
 
 import org.junit.Before;
@@ -172,9 +172,8 @@
         // all modes exist, but none of them are currently active
         assertThat(modes).containsExactly(
                         ZenMode.manualDndMode(
-                                new AutomaticZenRule.Builder(
-                                        mContext.getString(R.string.zen_mode_settings_title),
-                                        Uri.EMPTY)
+                                new AutomaticZenRule.Builder("Do Not Disturb", Uri.EMPTY)
+                                        .setPackage(PACKAGE_ANDROID)
                                         .setType(AutomaticZenRule.TYPE_OTHER)
                                         .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
                                         .setZenPolicy(notificationPolicyToZenPolicy(dndPolicy))
@@ -196,15 +195,59 @@
 
         ZenMode mode = mBackend.getMode(ZenMode.MANUAL_DND_MODE_ID);
 
+        assertThat(mode).isNotNull();
         assertThat(mode).isEqualTo(
                 ZenMode.manualDndMode(
-                        new AutomaticZenRule.Builder(
-                                mContext.getString(R.string.zen_mode_settings_title), Uri.EMPTY)
+                        new AutomaticZenRule.Builder("Do Not Disturb", Uri.EMPTY)
+                                .setPackage(PACKAGE_ANDROID)
                                 .setType(AutomaticZenRule.TYPE_OTHER)
                                 .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
                                 .setZenPolicy(notificationPolicyToZenPolicy(dndPolicy))
                                 .setManualInvocationAllowed(true)
                                 .build(), false));
+
+        assertThat(mode.isManualDnd()).isTrue();
+        assertThat(mode.isEnabled()).isTrue();
+        assertThat(mode.isActive()).isFalse();
+        assertThat(mode.canEditPolicy()).isTrue();
+        assertThat(mode.getPolicy()).isEqualTo(notificationPolicyToZenPolicy(dndPolicy));
+    }
+
+    @Test
+    public void getMode_dndWithOtherInterruptionFilter_returnsSpecialDndMode() {
+        ZenModeConfig config = configWithManualRule(new ZenModeConfig(), true);
+        config.manualRule.zenMode = Settings.Global.ZEN_MODE_ALARMS;
+        Policy dndPolicyForPriority = new Policy(Policy.PRIORITY_CATEGORY_ALARMS,
+                Policy.PRIORITY_SENDERS_CONTACTS, Policy.PRIORITY_SENDERS_CONTACTS);
+        config.applyNotificationPolicy(dndPolicyForPriority);
+        when(mNm.getZenModeConfig()).thenReturn(config);
+
+        ZenMode mode = mBackend.getMode(ZenMode.MANUAL_DND_MODE_ID);
+
+        assertThat(mode).isNotNull();
+        assertThat(mode).isEqualTo(
+                ZenMode.manualDndMode(
+                        new AutomaticZenRule.Builder("Do Not Disturb", Uri.EMPTY)
+                                .setPackage(PACKAGE_ANDROID)
+                                .setType(AutomaticZenRule.TYPE_OTHER)
+                                .setInterruptionFilter(INTERRUPTION_FILTER_ALARMS)
+                                .setZenPolicy(notificationPolicyToZenPolicy(dndPolicyForPriority))
+                                .setManualInvocationAllowed(true)
+                                .build(), true));
+
+        assertThat(mode.isManualDnd()).isTrue();
+        assertThat(mode.isEnabled()).isTrue();
+        assertThat(mode.isActive()).isTrue();
+
+        // Mode itself has a special fixed policy, different to the rule.
+        assertThat(mode.canEditPolicy()).isFalse();
+        assertThat(mode.getPolicy()).isEqualTo(
+                new ZenPolicy.Builder(ZenModeConfig.getDefaultZenPolicy())
+                        .disallowAllSounds()
+                        .allowAlarms(true)
+                        .allowMedia(true)
+                        .allowPriorityChannels(false)
+                        .build());
     }
 
     @Test
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
index 121bd3e..bfbf41d 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
@@ -99,6 +99,12 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.print("SyncDisabledForTests: ");
+        MyShellCommand.getSyncDisabledForTests(pw, pw);
+
+        pw.print("Is mainline: ");
+        pw.println(UpdatableDeviceConfigServiceReadiness.shouldStartUpdatableService());
+
         final IContentProvider iprovider = mProvider.getIContentProvider();
         pw.println("DeviceConfig flags:");
         for (String line : MyShellCommand.listAll(iprovider)) {
@@ -232,6 +238,17 @@
             return Binder.getCallingUid() == Process.ROOT_UID;
         }
 
+        private static int getSyncDisabledForTests(PrintWriter pOut, PrintWriter pErr) {
+            int syncDisabledModeInt = DeviceConfig.getSyncDisabledMode();
+            String syncDisabledModeString = formatSyncDisabledMode(syncDisabledModeInt);
+            if (syncDisabledModeString == null) {
+                pErr.println("Unknown mode: " + syncDisabledModeInt);
+                return -1;
+            }
+            pOut.println(syncDisabledModeString);
+            return 0;
+        }
+
       public static HashMap<String, String> getAllFlags(IContentProvider provider) {
         HashMap<String, String> allFlags = new HashMap<String, String>();
         for (DeviceConfig.Properties properties : DeviceConfig.getAllProperties()) {
@@ -597,14 +614,7 @@
                     DeviceConfig.setSyncDisabledMode(syncDisabledModeArg);
                     break;
                 case GET_SYNC_DISABLED_FOR_TESTS:
-                    int syncDisabledModeInt = DeviceConfig.getSyncDisabledMode();
-                    String syncDisabledModeString = formatSyncDisabledMode(syncDisabledModeInt);
-                    if (syncDisabledModeString == null) {
-                        perr.println("Unknown mode: " + syncDisabledModeInt);
-                        return -1;
-                    }
-                    pout.println(syncDisabledModeString);
-                    break;
+                    return getSyncDisabledForTests(pout, perr);
                 default:
                     perr.println("Unspecified command");
                     return -1;
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
index c60eb61..fb1f715 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
+++ b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
@@ -41,6 +41,7 @@
         "SettingsLibDisplayUtils",
         "SettingsLibSettingsTheme",
         "com_android_a11y_menu_flags_lib",
+        "//frameworks/libs/systemui:view_capture",
     ],
 
     optimize: {
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java
index c2cf6e1..c333a7a 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.accessibility.accessibilitymenu.view;
 
-import android.content.Context;
 import android.graphics.Rect;
 import android.view.LayoutInflater;
 import android.view.TouchDelegate;
@@ -43,16 +42,14 @@
     private final int mLargeTextSize;
 
     private final AccessibilityMenuService mService;
-    private final LayoutInflater mInflater;
     private final List<A11yMenuShortcut> mShortcutDataList;
     private final ShortcutDrawableUtils mShortcutDrawableUtils;
 
     public A11yMenuAdapter(
             AccessibilityMenuService service,
-            Context displayContext, List<A11yMenuShortcut> shortcutDataList) {
+            List<A11yMenuShortcut> shortcutDataList) {
         this.mService = service;
         this.mShortcutDataList = shortcutDataList;
-        mInflater = LayoutInflater.from(displayContext);
 
         mShortcutDrawableUtils = new ShortcutDrawableUtils(service);
 
@@ -78,7 +75,8 @@
     @Override
     public View getView(int position, View convertView, ViewGroup parent) {
         if (convertView == null) {
-            convertView = mInflater.inflate(R.layout.grid_item, parent, false);
+            convertView = LayoutInflater.from(parent.getContext())
+                    .inflate(R.layout.grid_item, parent, false);
 
             configureShortcutSize(convertView,
                     A11yMenuPreferenceFragment.isLargeButtonsEnabled(mService));
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java
index de3c472..3db61a5 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java
@@ -22,6 +22,8 @@
 import static android.view.View.ACCESSIBILITY_LIVE_REGION_POLITE;
 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
 
+import static com.android.app.viewcapture.ViewCaptureFactory.getViewCaptureAwareWindowManagerInstance;
+
 import static java.lang.Math.max;
 
 import android.animation.Animator;
@@ -51,7 +53,9 @@
 import android.widget.TextView;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.UiContext;
 
+import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
 import com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService;
 import com.android.systemui.accessibility.accessibilitymenu.Flags;
 import com.android.systemui.accessibility.accessibilitymenu.R;
@@ -101,7 +105,6 @@
     };
 
     private final AccessibilityMenuService mService;
-    private final WindowManager mWindowManager;
     private final DisplayManager mDisplayManager;
     private ViewGroup mLayout;
     private WindowManager.LayoutParams mLayoutParameter;
@@ -111,7 +114,6 @@
 
     public A11yMenuOverlayLayout(AccessibilityMenuService service) {
         mService = service;
-        mWindowManager = mService.getSystemService(WindowManager.class);
         mDisplayManager = mService.getSystemService(DisplayManager.class);
         configureLayout();
         mHandler = new Handler(Looper.getMainLooper());
@@ -134,8 +136,7 @@
         int lastVisibilityState = View.GONE;
         if (mLayout != null) {
             lastVisibilityState = mLayout.getVisibility();
-            mWindowManager.removeView(mLayout);
-            mLayout = null;
+            clearLayout();
         }
 
         if (mLayoutParameter == null) {
@@ -143,14 +144,17 @@
         }
 
         final Display display = mDisplayManager.getDisplay(DEFAULT_DISPLAY);
-        final Context context = mService.createDisplayContext(display).createWindowContext(
-                TYPE_ACCESSIBILITY_OVERLAY, null);
-        mLayout = new A11yMenuFrameLayout(context);
-        updateLayoutPosition();
-        inflateLayoutAndSetOnTouchListener(mLayout, context);
-        mA11yMenuViewPager = new A11yMenuViewPager(mService, context);
+        final Context uiContext = mService.createWindowContext(
+                display, TYPE_ACCESSIBILITY_OVERLAY, /* options= */null);
+        final ViewCaptureAwareWindowManager windowManager =
+                getViewCaptureAwareWindowManagerInstance(uiContext,
+                        com.android.systemui.Flags.enableViewCaptureTracing());
+        mLayout = new A11yMenuFrameLayout(uiContext);
+        updateLayoutPosition(uiContext);
+        inflateLayoutAndSetOnTouchListener(mLayout, uiContext);
+        mA11yMenuViewPager = new A11yMenuViewPager(mService);
         mA11yMenuViewPager.configureViewPagerAndFooter(mLayout, createShortcutList(), pageIndex);
-        mWindowManager.addView(mLayout, mLayoutParameter);
+        windowManager.addView(mLayout, mLayoutParameter);
         mLayout.setVisibility(lastVisibilityState);
         mA11yMenuViewPager.updateFooterState();
 
@@ -159,7 +163,11 @@
 
     public void clearLayout() {
         if (mLayout != null) {
-            mWindowManager.removeView(mLayout);
+            ViewCaptureAwareWindowManager windowManager = getViewCaptureAwareWindowManagerInstance(
+                    mLayout.getContext(), com.android.systemui.Flags.enableViewCaptureTracing());
+            if (windowManager != null) {
+                windowManager.removeView(mLayout);
+            }
             mLayout.setOnTouchListener(null);
             mLayout = null;
         }
@@ -170,8 +178,11 @@
         if (mLayout == null || mLayoutParameter == null) {
             return;
         }
-        updateLayoutPosition();
-        mWindowManager.updateViewLayout(mLayout, mLayoutParameter);
+        updateLayoutPosition(mLayout.getContext());
+        WindowManager windowManager = mLayout.getContext().getSystemService(WindowManager.class);
+        if (windowManager != null) {
+            windowManager.updateViewLayout(mLayout, mLayoutParameter);
+        }
     }
 
     private void initLayoutParams() {
@@ -183,8 +194,8 @@
         mLayoutParameter.setTitle(mService.getString(R.string.accessibility_menu_service_name));
     }
 
-    private void inflateLayoutAndSetOnTouchListener(ViewGroup view, Context displayContext) {
-        LayoutInflater inflater = LayoutInflater.from(displayContext);
+    private void inflateLayoutAndSetOnTouchListener(ViewGroup view, @UiContext Context uiContext) {
+        LayoutInflater inflater = LayoutInflater.from(uiContext);
         inflater.inflate(R.layout.paged_menu, view);
         view.setOnTouchListener(mService);
     }
@@ -238,7 +249,11 @@
     }
 
     /** Updates a11y menu layout position by configuring layout params. */
-    private void updateLayoutPosition() {
+    private void updateLayoutPosition(@UiContext @NonNull Context uiContext) {
+        WindowManager windowManager = uiContext.getSystemService(WindowManager.class);
+        if (windowManager == null) {
+            return;
+        }
         final Display display = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
         final Configuration configuration = mService.getResources().getConfiguration();
         final int orientation = configuration.orientation;
@@ -276,14 +291,13 @@
             mLayoutParameter.height = WindowManager.LayoutParams.WRAP_CONTENT;
             mLayout.setBackgroundResource(R.drawable.shadow_0deg);
         }
-
         // Adjusts the y position of a11y menu layout to make the layout not to overlap bottom
         // navigation bar window.
-        updateLayoutByWindowInsetsIfNeeded();
+        updateLayoutByWindowInsetsIfNeeded(windowManager);
         mLayout.setOnApplyWindowInsetsListener(
                 (view, insets) -> {
-                    if (updateLayoutByWindowInsetsIfNeeded()) {
-                        mWindowManager.updateViewLayout(mLayout, mLayoutParameter);
+                    if (updateLayoutByWindowInsetsIfNeeded(windowManager)) {
+                        windowManager.updateViewLayout(mLayout, mLayoutParameter);
                     }
                     return view.onApplyWindowInsets(insets);
                 });
@@ -295,9 +309,9 @@
      * This method adjusts the layout position and size to
      * make a11y menu not to overlap navigation bar window.
      */
-    private boolean updateLayoutByWindowInsetsIfNeeded() {
+    private boolean updateLayoutByWindowInsetsIfNeeded(@NonNull WindowManager windowManager) {
         boolean shouldUpdateLayout = false;
-        WindowMetrics windowMetrics = mWindowManager.getCurrentWindowMetrics();
+        WindowMetrics windowMetrics = windowManager.getCurrentWindowMetrics();
         Insets windowInsets = windowMetrics.getWindowInsets().getInsetsIgnoringVisibility(
                 WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout());
         int xOffset = max(windowInsets.left, windowInsets.right);
@@ -396,7 +410,7 @@
     }
 
     private class A11yMenuFrameLayout extends FrameLayout {
-        A11yMenuFrameLayout(@NonNull Context context) {
+        A11yMenuFrameLayout(@UiContext @NonNull Context context) {
             super(context);
         }
 
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java
index 08bbf19..a29ce82 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java
@@ -146,12 +146,8 @@
     /** The container layout for a11y menu. */
     private ViewGroup mA11yMenuLayout;
 
-    /** Display context for inflating views. */
-    private Context mDisplayContext;
-
-    public A11yMenuViewPager(AccessibilityMenuService service, Context displayContext) {
+    public A11yMenuViewPager(AccessibilityMenuService service) {
         this.mService = service;
-        this.mDisplayContext = displayContext;
     }
 
     /**
@@ -289,7 +285,8 @@
             footerLayout.getLayoutParams().height =
                     (int) (footerLayout.getLayoutParams().height / densityScale);
             // Adjust the view pager height for system bar and display cutout insets.
-            WindowManager windowManager = mService.getSystemService(WindowManager.class);
+            WindowManager windowManager = mA11yMenuLayout.getContext()
+                    .getSystemService(WindowManager.class);
             WindowMetrics windowMetric = windowManager.getCurrentWindowMetrics();
             Insets windowInsets = windowMetric.getWindowInsets().getInsetsIgnoringVisibility(
                     WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout());
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java
index 43ec956..152ff68 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java
@@ -57,7 +57,7 @@
     @Override
     public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
         A11yMenuAdapter adapter = new A11yMenuAdapter(
-                mService, holder.itemView.getContext(), mShortcutList.get(position));
+                mService, mShortcutList.get(position));
         GridView gridView = (GridView) holder.itemView;
         gridView.setNumColumns(A11yMenuViewPager.GridViewParams.getGridColumnCount(mService));
         gridView.setAdapter(adapter);
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 2e0c1ef..cf13621 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -1356,13 +1356,6 @@
 }
 
 flag {
-    name: "new_picker_ui"
-    namespace: "systemui"
-    description: "Enables the BC25 design of the customization picker UI."
-    bug: "339081035"
-}
-
-flag {
   namespace: "systemui"
   name: "settings_ext_register_content_observer_on_bg_thread"
   description: "Register content observer in callback flow APIs on background thread in SettingsProxyExt."
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
index c5bb33c..7fb88e8 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
@@ -27,8 +27,8 @@
 import com.android.compose.animation.scene.UserAction
 import com.android.compose.animation.scene.UserActionResult
 import com.android.systemui.bouncer.ui.BouncerDialogFactory
-import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneActionsViewModel
 import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel
+import com.android.systemui.bouncer.ui.viewmodel.BouncerUserActionsViewModel
 import com.android.systemui.compose.modifiers.sysuiResTag
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.lifecycle.ExclusiveActivatable
@@ -54,18 +54,17 @@
 class BouncerScene
 @Inject
 constructor(
-    private val actionsViewModelFactory: BouncerSceneActionsViewModel.Factory,
+    private val actionsViewModelFactory: BouncerUserActionsViewModel.Factory,
     private val contentViewModelFactory: BouncerSceneContentViewModel.Factory,
     private val dialogFactory: BouncerDialogFactory,
 ) : ExclusiveActivatable(), Scene {
     override val key = Scenes.Bouncer
 
-    private val actionsViewModel: BouncerSceneActionsViewModel by lazy {
+    private val actionsViewModel: BouncerUserActionsViewModel by lazy {
         actionsViewModelFactory.create()
     }
 
-    override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
-        actionsViewModel.actions
+    override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
 
     override suspend fun onActivated(): Nothing {
         actionsViewModel.activate()
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt
index f658169..8b6de6a 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt
@@ -49,10 +49,10 @@
 ) : ExclusiveActivatable(), Scene {
     override val key = Scenes.Communal
 
-    override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
-        MutableStateFlow<Map<UserAction, UserActionResult>>(
+    override val userActions: Flow<Map<UserAction, UserActionResult>> =
+        MutableStateFlow(
                 mapOf(
-                    Swipe(SwipeDirection.End) to UserActionResult(Scenes.Lockscreen),
+                    Swipe(SwipeDirection.End) to Scenes.Lockscreen,
                 )
             )
             .asStateFlow()
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt
index 5f600d3..c7c29f9 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt
@@ -24,7 +24,7 @@
 import com.android.compose.animation.scene.UserActionResult
 import com.android.compose.animation.scene.animateContentFloatAsState
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenSceneActionsViewModel
+import com.android.systemui.keyguard.ui.viewmodel.LockscreenUserActionsViewModel
 import com.android.systemui.lifecycle.ExclusiveActivatable
 import com.android.systemui.qs.ui.composable.QuickSettings
 import com.android.systemui.scene.shared.model.Scenes
@@ -38,17 +38,16 @@
 class LockscreenScene
 @Inject
 constructor(
-    actionsViewModelFactory: LockscreenSceneActionsViewModel.Factory,
+    actionsViewModelFactory: LockscreenUserActionsViewModel.Factory,
     private val lockscreenContent: Lazy<LockscreenContent>,
 ) : ExclusiveActivatable(), Scene {
     override val key = Scenes.Lockscreen
 
-    private val actionsViewModel: LockscreenSceneActionsViewModel by lazy {
+    private val actionsViewModel: LockscreenUserActionsViewModel by lazy {
         actionsViewModelFactory.create()
     }
 
-    override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
-        actionsViewModel.actions
+    override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
 
     override suspend fun onActivated(): Nothing {
         actionsViewModel.activate()
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt
index e4c611e..a22becc 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt
@@ -23,6 +23,8 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.unit.dp
 import com.android.compose.animation.scene.ContentScope
+import com.android.compose.animation.scene.UserAction
+import com.android.compose.animation.scene.UserActionResult
 import com.android.systemui.battery.BatteryMeterViewController
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.lifecycle.rememberViewModel
@@ -39,6 +41,7 @@
 import com.android.systemui.statusbar.phone.ui.TintedIconManager
 import dagger.Lazy
 import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
 
 @SysUISingleton
 class NotificationsShadeOverlay
@@ -59,6 +62,8 @@
         actionsViewModelFactory.create()
     }
 
+    override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
+
     override suspend fun activate(): Nothing {
         actionsViewModel.activate()
     }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt
index ea3f066..1f4cd04 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt
@@ -29,7 +29,7 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.lifecycle.ExclusiveActivatable
 import com.android.systemui.lifecycle.rememberViewModel
-import com.android.systemui.notifications.ui.viewmodel.NotificationsShadeSceneActionsViewModel
+import com.android.systemui.notifications.ui.viewmodel.NotificationsShadeUserActionsViewModel
 import com.android.systemui.scene.session.ui.composable.SaveableSession
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.ui.composable.Scene
@@ -49,7 +49,7 @@
 class NotificationsShadeScene
 @Inject
 constructor(
-    private val actionsViewModelFactory: NotificationsShadeSceneActionsViewModel.Factory,
+    private val actionsViewModelFactory: NotificationsShadeUserActionsViewModel.Factory,
     private val shadeHeaderViewModelFactory: ShadeHeaderViewModel.Factory,
     private val notificationsPlaceholderViewModelFactory: NotificationsPlaceholderViewModel.Factory,
     private val tintedIconManagerFactory: TintedIconManager.Factory,
@@ -61,12 +61,11 @@
 
     override val key = Scenes.NotificationsShade
 
-    private val actionsViewModel: NotificationsShadeSceneActionsViewModel by lazy {
+    private val actionsViewModel: NotificationsShadeUserActionsViewModel by lazy {
         actionsViewModelFactory.create()
     }
 
-    override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
-        actionsViewModel.actions
+    override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
 
     override suspend fun onActivated(): Nothing {
         actionsViewModel.activate()
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
index 373383f..d34295e 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
@@ -93,8 +93,8 @@
 import com.android.systemui.qs.footer.ui.compose.FooterActionsWithAnimatedVisibility
 import com.android.systemui.qs.ui.composable.QuickSettings.SharedValues.MediaLandscapeTopOffset
 import com.android.systemui.qs.ui.composable.QuickSettings.SharedValues.MediaOffset.InQS
-import com.android.systemui.qs.ui.viewmodel.QuickSettingsSceneActionsViewModel
 import com.android.systemui.qs.ui.viewmodel.QuickSettingsSceneContentViewModel
+import com.android.systemui.qs.ui.viewmodel.QuickSettingsUserActionsViewModel
 import com.android.systemui.res.R
 import com.android.systemui.scene.session.ui.composable.SaveableSession
 import com.android.systemui.scene.shared.model.Scenes
@@ -125,7 +125,7 @@
     private val shadeSession: SaveableSession,
     private val notificationStackScrollView: Lazy<NotificationScrollView>,
     private val notificationsPlaceholderViewModelFactory: NotificationsPlaceholderViewModel.Factory,
-    private val actionsViewModelFactory: QuickSettingsSceneActionsViewModel.Factory,
+    private val actionsViewModelFactory: QuickSettingsUserActionsViewModel.Factory,
     private val contentViewModelFactory: QuickSettingsSceneContentViewModel.Factory,
     private val tintedIconManagerFactory: TintedIconManager.Factory,
     private val batteryMeterViewControllerFactory: BatteryMeterViewController.Factory,
@@ -135,12 +135,11 @@
 ) : ExclusiveActivatable(), Scene {
     override val key = Scenes.QuickSettings
 
-    private val actionsViewModel: QuickSettingsSceneActionsViewModel by lazy {
+    private val actionsViewModel: QuickSettingsUserActionsViewModel by lazy {
         actionsViewModelFactory.create()
     }
 
-    override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
-        actionsViewModel.actions
+    override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
 
     override suspend fun onActivated(): Nothing {
         actionsViewModel.activate()
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt
index 988c712..f8d0588 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt
@@ -34,6 +34,8 @@
 import androidx.compose.ui.unit.dp
 import androidx.lifecycle.compose.collectAsStateWithLifecycle
 import com.android.compose.animation.scene.ContentScope
+import com.android.compose.animation.scene.UserAction
+import com.android.compose.animation.scene.UserActionResult
 import com.android.systemui.battery.BatteryMeterViewController
 import com.android.systemui.brightness.ui.compose.BrightnessSliderContainer
 import com.android.systemui.compose.modifiers.sysuiResTag
@@ -51,6 +53,7 @@
 import com.android.systemui.statusbar.phone.ui.StatusBarIconController
 import com.android.systemui.statusbar.phone.ui.TintedIconManager
 import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
 
 @SysUISingleton
 class QuickSettingsShadeOverlay
@@ -69,6 +72,8 @@
         actionsViewModelFactory.create()
     }
 
+    override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
+
     override suspend fun activate(): Nothing {
         actionsViewModel.activate()
     }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt
index 9316eb9..e27c7e2 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt
@@ -27,8 +27,8 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.lifecycle.ExclusiveActivatable
 import com.android.systemui.lifecycle.rememberViewModel
-import com.android.systemui.qs.ui.viewmodel.QuickSettingsShadeSceneActionsViewModel
 import com.android.systemui.qs.ui.viewmodel.QuickSettingsShadeSceneContentViewModel
+import com.android.systemui.qs.ui.viewmodel.QuickSettingsShadeUserActionsViewModel
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.ui.composable.Scene
 import com.android.systemui.shade.ui.composable.ExpandedShadeHeader
@@ -43,7 +43,7 @@
 class QuickSettingsShadeScene
 @Inject
 constructor(
-    private val actionsViewModelFactory: QuickSettingsShadeSceneActionsViewModel.Factory,
+    private val actionsViewModelFactory: QuickSettingsShadeUserActionsViewModel.Factory,
     private val contentViewModelFactory: QuickSettingsShadeSceneContentViewModel.Factory,
     private val shadeHeaderViewModelFactory: ShadeHeaderViewModel.Factory,
     private val tintedIconManagerFactory: TintedIconManager.Factory,
@@ -53,12 +53,11 @@
 
     override val key = Scenes.QuickSettingsShade
 
-    private val actionsViewModel: QuickSettingsShadeSceneActionsViewModel by lazy {
+    private val actionsViewModel: QuickSettingsShadeUserActionsViewModel by lazy {
         actionsViewModelFactory.create()
     }
 
-    override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
-        actionsViewModel.actions
+    override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
 
     override suspend fun onActivated(): Nothing {
         actionsViewModel.activate()
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/ActionableContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/ActionableContent.kt
new file mode 100644
index 0000000..8fe6893
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/ActionableContent.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 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.scene.ui.composable
+
+import com.android.compose.animation.scene.UserAction
+import com.android.compose.animation.scene.UserActionResult
+import kotlinx.coroutines.flow.Flow
+
+/** Defines interface for content that can respond to user-actions. */
+interface ActionableContent {
+    /**
+     * The mapping between [UserAction] and destination [UserActionResult]s.
+     *
+     * When the scene framework detects a user action, if the current scene has a map entry for that
+     * user action, the framework starts a transition to the content specified in the map.
+     *
+     * Once the content is shown, the scene framework will read this property and set up a collector
+     * to watch for new mapping values. For each map entry, the scene framework will set up user
+     * input handling for its [UserAction] and, if such a user action is detected, initiate a
+     * transition to the specified [UserActionResult].
+     *
+     * Note that reading from this method does _not_ mean that any user action has occurred.
+     * Instead, the property is read before any user action/gesture is detected so that the
+     * framework can decide whether to set up gesture/input detectors/listeners in case user actions
+     * of the given types ever occur.
+     *
+     * A missing value for a specific [UserAction] means that the user action of the given type is
+     * not currently active in the top-most content (in z-index order) and should be ignored by the
+     * framework until the top-most content changes.
+     */
+    val userActions: Flow<Map<UserAction, UserActionResult>>
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt
index 6fb4724..ae5dd8a 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt
@@ -33,7 +33,7 @@
 import com.android.systemui.qs.ui.composable.QuickSettings.SharedValues.MediaLandscapeTopOffset
 import com.android.systemui.qs.ui.composable.QuickSettings.SharedValues.MediaOffset.Default
 import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.scene.ui.viewmodel.GoneSceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.GoneUserActionsViewModel
 import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel
 import dagger.Lazy
@@ -50,14 +50,13 @@
 constructor(
     private val notificationStackScrolLView: Lazy<NotificationScrollView>,
     private val notificationsPlaceholderViewModelFactory: NotificationsPlaceholderViewModel.Factory,
-    private val viewModelFactory: GoneSceneActionsViewModel.Factory,
+    private val viewModelFactory: GoneUserActionsViewModel.Factory,
 ) : ExclusiveActivatable(), Scene {
     override val key = Scenes.Gone
 
-    private val actionsViewModel: GoneSceneActionsViewModel by lazy { viewModelFactory.create() }
+    private val actionsViewModel: GoneUserActionsViewModel by lazy { viewModelFactory.create() }
 
-    override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
-        actionsViewModel.actions
+    override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
 
     override suspend fun onActivated(): Nothing {
         actionsViewModel.activate()
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Overlay.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Overlay.kt
index d62befd..609ce90 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Overlay.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Overlay.kt
@@ -18,9 +18,14 @@
 
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
+import com.android.compose.animation.scene.Back
 import com.android.compose.animation.scene.ContentScope
 import com.android.compose.animation.scene.OverlayKey
+import com.android.compose.animation.scene.UserAction
+import com.android.compose.animation.scene.UserActionResult
 import com.android.systemui.lifecycle.Activatable
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flowOf
 
 /**
  * Defines interface for classes that can describe an "overlay".
@@ -29,9 +34,17 @@
  * container takes care of rendering any current overlays and allowing overlays to be shown, hidden,
  * or replaced based on a user action.
  */
-interface Overlay : Activatable {
+interface Overlay : Activatable, ActionableContent {
     /** Uniquely-identifying key for this overlay. The key must be unique within its container. */
     val key: OverlayKey
 
+    /**
+     * The user actions supported by this overlay.
+     *
+     * @see [ActionableContent.userActions]
+     */
+    override val userActions: Flow<Map<UserAction, UserActionResult>>
+        get() = flowOf(mapOf(Back to UserActionResult.HideOverlay(key)))
+
     @Composable fun ContentScope.Content(modifier: Modifier)
 }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Scene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Scene.kt
index 5319ec3..8d8ab8e 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Scene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Scene.kt
@@ -20,10 +20,7 @@
 import androidx.compose.ui.Modifier
 import com.android.compose.animation.scene.SceneKey
 import com.android.compose.animation.scene.SceneScope
-import com.android.compose.animation.scene.UserAction
-import com.android.compose.animation.scene.UserActionResult
 import com.android.systemui.lifecycle.Activatable
-import kotlinx.coroutines.flow.Flow
 
 /**
  * Defines interface for classes that can describe a "scene".
@@ -33,32 +30,10 @@
  * based on either user action (for example, swiping down while on the lock screen scene may switch
  * to the shade scene).
  */
-interface Scene : Activatable {
+interface Scene : Activatable, ActionableContent {
 
     /** Uniquely-identifying key for this scene. The key must be unique within its container. */
     val key: SceneKey
 
-    /**
-     * The mapping between [UserAction] and destination [UserActionResult]s.
-     *
-     * When the scene framework detects a user action, if the current scene has a map entry for that
-     * user action, the framework starts a transition to the scene in the map.
-     *
-     * Once the [Scene] becomes the current one, the scene framework will read this property and set
-     * up a collector to watch for new mapping values. If every map entry provided by the scene, the
-     * framework will set up user input handling for its [UserAction] and, if such a user action is
-     * detected, initiate a transition to the specified [UserActionResult].
-     *
-     * Note that reading from this method does _not_ mean that any user action has occurred.
-     * Instead, the property is read before any user action/gesture is detected so that the
-     * framework can decide whether to set up gesture/input detectors/listeners in case user actions
-     * of the given types ever occur.
-     *
-     * Note that a missing value for a specific [UserAction] means that the user action of the given
-     * type is not currently active in the scene and should be ignored by the framework, while the
-     * current scene is this one.
-     */
-    val destinationScenes: Flow<Map<UserAction, UserActionResult>>
-
     @Composable fun SceneScope.Content(modifier: Modifier)
 }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
index 851fa3f..a7e41ce 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
@@ -104,7 +104,7 @@
     // TODO(b/359173565): Add overlay user actions when the API is final.
     LaunchedEffect(currentSceneKey) {
         try {
-            sceneByKey[currentSceneKey]?.destinationScenes?.collectLatest { userActions ->
+            sceneByKey[currentSceneKey]?.userActions?.collectLatest { userActions ->
                 userActionsByContentKey[currentSceneKey] =
                     viewModel.resolveSceneFamilies(userActions)
             }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
index 5fcf522..a03bf43 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
@@ -108,8 +108,8 @@
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.ui.composable.Scene
 import com.android.systemui.shade.shared.model.ShadeMode
-import com.android.systemui.shade.ui.viewmodel.ShadeSceneActionsViewModel
 import com.android.systemui.shade.ui.viewmodel.ShadeSceneContentViewModel
+import com.android.systemui.shade.ui.viewmodel.ShadeUserActionsViewModel
 import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel
 import com.android.systemui.statusbar.phone.StatusBarLocation
@@ -154,7 +154,7 @@
 constructor(
     private val shadeSession: SaveableSession,
     private val notificationStackScrollView: Lazy<NotificationScrollView>,
-    private val actionsViewModelFactory: ShadeSceneActionsViewModel.Factory,
+    private val actionsViewModelFactory: ShadeUserActionsViewModel.Factory,
     private val contentViewModelFactory: ShadeSceneContentViewModel.Factory,
     private val notificationsPlaceholderViewModelFactory: NotificationsPlaceholderViewModel.Factory,
     private val tintedIconManagerFactory: TintedIconManager.Factory,
@@ -167,7 +167,7 @@
 
     override val key = Scenes.Shade
 
-    private val actionsViewModel: ShadeSceneActionsViewModel by lazy {
+    private val actionsViewModel: ShadeUserActionsViewModel by lazy {
         actionsViewModelFactory.create()
     }
 
@@ -175,8 +175,7 @@
         actionsViewModel.activate()
     }
 
-    override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
-        actionsViewModel.actions
+    override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
 
     @Composable
     override fun SceneScope.Content(
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt
index 4aa50b5..b30f2b7 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt
@@ -399,26 +399,53 @@
 
         val fromValue = sharedValue[transition.fromContent]
         val toValue = sharedValue[transition.toContent]
-        return if (fromValue != null && toValue != null) {
-            if (fromValue == toValue) {
-                // Optimization: avoid reading progress if the values are the same, so we don't
-                // relayout/redraw for nothing.
-                fromValue
-            } else {
-                val overscrollSpec = transition.currentOverscrollSpec
-                val progress =
-                    when {
-                        overscrollSpec == null -> {
-                            if (canOverflow) transition.progress
-                            else transition.progress.fastCoerceIn(0f, 1f)
-                        }
-                        overscrollSpec.content == transition.toContent -> 1f
-                        else -> 0f
-                    }
+        if (fromValue == null && toValue == null) {
+            return null
+        }
 
-                sharedValue.type.lerp(fromValue, toValue, progress)
+        if (fromValue != null && toValue != null) {
+            return interpolateSharedValue(fromValue, toValue, transition, sharedValue)
+        }
+
+        if (transition is TransitionState.Transition.ReplaceOverlay) {
+            val currentSceneValue = sharedValue[transition.currentScene]
+            if (currentSceneValue != null) {
+                return interpolateSharedValue(
+                    fromValue = fromValue ?: currentSceneValue,
+                    toValue = toValue ?: currentSceneValue,
+                    transition,
+                    sharedValue,
+                )
             }
-        } else fromValue ?: toValue
+        }
+
+        return fromValue ?: toValue
+    }
+
+    private fun interpolateSharedValue(
+        fromValue: T,
+        toValue: T,
+        transition: TransitionState.Transition,
+        sharedValue: SharedValue<T, *>,
+    ): T? {
+        if (fromValue == toValue) {
+            // Optimization: avoid reading progress if the values are the same, so we don't
+            // relayout/redraw for nothing.
+            return fromValue
+        }
+
+        val overscrollSpec = transition.currentOverscrollSpec
+        val progress =
+            when {
+                overscrollSpec == null -> {
+                    if (canOverflow) transition.progress
+                    else transition.progress.fastCoerceIn(0f, 1f)
+                }
+                overscrollSpec.content == transition.toContent -> 1f
+                else -> 0f
+            }
+
+        return sharedValue.type.lerp(fromValue, toValue, progress)
     }
 
     private fun transition(sharedValue: SharedValue<T, Delta>): TransitionState.Transition? {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
index 9b1740d..56c08b9 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
@@ -313,10 +313,27 @@
         // If this element is not supposed to be laid out now, either because it is not part of any
         // ongoing transition or the other content of its transition is overscrolling, then lay out
         // the element normally and don't place it.
-        val overscrollScene = transition?.currentOverscrollSpec?.content
-        val isOtherSceneOverscrolling = overscrollScene != null && overscrollScene != content.key
-        if (isOtherSceneOverscrolling) {
-            return doNotPlace(measurable, constraints)
+        val overscrollContent = transition?.currentOverscrollSpec?.content
+        if (overscrollContent != null && overscrollContent != content.key) {
+            when (transition) {
+                is TransitionState.Transition.ChangeScene ->
+                    return doNotPlace(measurable, constraints)
+
+                // If we are overscrolling an overlay that does not contain an element that is in
+                // the current scene, place it in that scene otherwise the element won't be placed
+                // at all.
+                is TransitionState.Transition.ShowOrHideOverlay,
+                is TransitionState.Transition.ReplaceOverlay -> {
+                    if (
+                        content.key == transition.currentScene &&
+                            overscrollContent !in element.stateByContent
+                    ) {
+                        return placeNormally(measurable, constraints)
+                    } else {
+                        return doNotPlace(measurable, constraints)
+                    }
+                }
+            }
         }
 
         val placeable =
@@ -836,19 +853,32 @@
         content,
         element.key,
         transition,
+        isInContent = { it in element.stateByContent },
     )
 }
 
-internal fun shouldPlaceOrComposeSharedElement(
+internal inline fun shouldPlaceOrComposeSharedElement(
     layoutImpl: SceneTransitionLayoutImpl,
     content: ContentKey,
     element: ElementKey,
     transition: TransitionState.Transition,
+    isInContent: (ContentKey) -> Boolean,
 ): Boolean {
-    // If we are overscrolling, only place/compose the element in the overscrolling scene.
-    val overscrollScene = transition.currentOverscrollSpec?.content
-    if (overscrollScene != null) {
-        return content == overscrollScene
+    val overscrollContent = transition.currentOverscrollSpec?.content
+    if (overscrollContent != null) {
+        return when (transition) {
+            // If we are overscrolling between scenes, only place/compose the element in the
+            // overscrolling scene.
+            is TransitionState.Transition.ChangeScene -> content == overscrollContent
+
+            // If we are overscrolling an overlay, place/compose the element if [content] is the
+            // overscrolling content or if [content] is the current scene and the overscrolling
+            // overlay does not contain the element.
+            is TransitionState.Transition.ReplaceOverlay,
+            is TransitionState.Transition.ShowOrHideOverlay ->
+                content == overscrollContent ||
+                    (content == transition.currentScene && !isInContent(overscrollContent))
+        }
     }
 
     val scenePicker = element.contentPicker
@@ -1230,17 +1260,30 @@
     // elements follow the finger direction.
     val isSharedElement = fromState != null && toState != null
     if (isSharedElement && isSharedElementEnabled(element.key, transition)) {
-        val start = contentValue(fromState!!)
-        val end = contentValue(toState!!)
+        return interpolateSharedElement(
+            transition = transition,
+            contentValue = contentValue,
+            fromState = fromState!!,
+            toState = toState!!,
+            isSpecified = isSpecified,
+            lerp = lerp,
+        )
+    }
 
-        // TODO(b/316901148): Remove checks to isSpecified() once the lookahead pass runs for all
-        // nodes before the intermediate layout pass.
-        if (!isSpecified(start)) return end
-        if (!isSpecified(end)) return start
-
-        // Make sure we don't read progress if values are the same and we don't need to interpolate,
-        // so we don't invalidate the phase where this is read.
-        return if (start == end) start else lerp(start, end, transition.progress)
+    // If we are replacing an overlay and the element is both in a single overlay and in the current
+    // scene, interpolate the state of the element using the current scene as the other scene.
+    if (!isSharedElement && transition is TransitionState.Transition.ReplaceOverlay) {
+        val currentSceneState = element.stateByContent[transition.currentScene]
+        if (currentSceneState != null) {
+            return interpolateSharedElement(
+                transition = transition,
+                contentValue = contentValue,
+                fromState = fromState ?: currentSceneState,
+                toState = toState ?: currentSceneState,
+                isSpecified = isSpecified,
+                lerp = lerp,
+            )
+        }
     }
 
     // Get the transformed value, i.e. the target value at the beginning (for entering elements) or
@@ -1383,3 +1426,24 @@
         lerp(idleValue, targetValue, rangeProgress)
     }
 }
+
+private inline fun <T> interpolateSharedElement(
+    transition: TransitionState.Transition,
+    contentValue: (Element.State) -> T,
+    fromState: Element.State,
+    toState: Element.State,
+    isSpecified: (T) -> Boolean,
+    lerp: (T, T, Float) -> T
+): T {
+    val start = contentValue(fromState)
+    val end = contentValue(toState)
+
+    // TODO(b/316901148): Remove checks to isSpecified() once the lookahead pass runs for all
+    // nodes before the intermediate layout pass.
+    if (!isSpecified(start)) return end
+    if (!isSpecified(end)) return start
+
+    // Make sure we don't read progress if values are the same and we don't need to interpolate,
+    // so we don't invalidate the phase where this is read.
+    return if (start == end) start else lerp(start, end, transition.progress)
+}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
index 715222c..471ad3f 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
@@ -194,11 +194,13 @@
         is TransitionState.Transition -> {
             // During transitions, always compose movable elements in the scene picked by their
             // content picker.
+            val contents = element.contentPicker.contents
             shouldPlaceOrComposeSharedElement(
                 layoutImpl,
                 content,
                 element,
                 elementState,
+                isInContent = { contents.contains(it) }
             )
         }
     }
@@ -208,8 +210,8 @@
     element: MovableElementKey,
     transitionStates: List<TransitionState>,
 ): TransitionState? {
-    val content = element.contentPicker.contents
-    return elementState(transitionStates, isInContent = { content.contains(it) })
+    val contents = element.contentPicker.contents
+    return elementState(transitionStates, isInContent = { contents.contains(it) })
 }
 
 private fun movableElementContentWhenIdle(
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt
index bec2bb2..471362b 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt
@@ -18,14 +18,17 @@
 
 import androidx.compose.animation.core.LinearEasing
 import androidx.compose.animation.core.tween
+import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.size
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.runtime.setValue
+import androidx.compose.runtime.snapshotFlow
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.testTag
@@ -42,7 +45,12 @@
 import com.android.compose.animation.scene.TestOverlays.OverlayB
 import com.android.compose.animation.scene.TestScenes.SceneA
 import com.android.compose.test.assertSizeIsEqualTo
+import com.android.compose.test.setContentAndCreateMainScope
+import com.android.compose.test.subjects.assertThat
+import com.android.compose.test.transition
+import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -524,4 +532,162 @@
             }
         }
     }
+
+    @Test
+    fun replaceAnimation_elementInCurrentSceneAndOneOverlay() {
+        val sharedIntKey = ValueKey("sharedInt")
+        val sharedIntValueByContent = mutableMapOf<ContentKey, Int>()
+
+        @Composable
+        fun SceneScope.animateContentInt(targetValue: Int) {
+            val animatedValue = animateContentIntAsState(targetValue, sharedIntKey)
+            LaunchedEffect(animatedValue) {
+                try {
+                    snapshotFlow { animatedValue.value }
+                        .collect { sharedIntValueByContent[contentKey] = it }
+                } finally {
+                    sharedIntValueByContent.remove(contentKey)
+                }
+            }
+        }
+
+        rule.testReplaceOverlayTransition(
+            currentSceneContent = {
+                Box(Modifier.size(width = 180.dp, height = 120.dp)) {
+                    animateContentInt(targetValue = 1_000)
+                    Foo(width = 60.dp, height = 40.dp)
+                }
+            },
+            fromContent = {},
+            fromAlignment = Alignment.TopStart,
+            toContent = {
+                animateContentInt(targetValue = 2_000)
+                Foo(width = 100.dp, height = 80.dp)
+            },
+            transition = {
+                // 4 frames of animation
+                spec = tween(4 * 16, easing = LinearEasing)
+            },
+        ) {
+            // Foo moves from (0,0) with a size of 60x40dp to centered (in a 180x120dp Box) with a
+            // size of 100x80dp, so at (40,20).
+            //
+            // The animated Int goes from 1_000 to 2_000.
+            before {
+                rule
+                    .onNode(isElement(TestElements.Foo, content = SceneA))
+                    .assertSizeIsEqualTo(60.dp, 40.dp)
+                    .assertPositionInRootIsEqualTo(0.dp, 0.dp)
+                rule.onNode(isElement(TestElements.Foo, content = OverlayA)).assertDoesNotExist()
+                rule.onNode(isElement(TestElements.Foo, content = OverlayB)).assertDoesNotExist()
+
+                assertThat(sharedIntValueByContent).containsEntry(SceneA, 1_000)
+                assertThat(sharedIntValueByContent).doesNotContainKey(OverlayA)
+                assertThat(sharedIntValueByContent).doesNotContainKey(OverlayB)
+            }
+
+            at(16) {
+                rule
+                    .onNode(isElement(TestElements.Foo, content = SceneA))
+                    .assertExists()
+                    .assertIsNotDisplayed()
+                rule.onNode(isElement(TestElements.Foo, content = OverlayA)).assertDoesNotExist()
+                rule
+                    .onNode(isElement(TestElements.Foo, content = OverlayB))
+                    .assertSizeIsEqualTo(70.dp, 50.dp)
+                    .assertPositionInRootIsEqualTo(10.dp, 5.dp)
+
+                assertThat(sharedIntValueByContent).containsEntry(SceneA, 1_250)
+                assertThat(sharedIntValueByContent).doesNotContainKey(OverlayA)
+                assertThat(sharedIntValueByContent).containsEntry(OverlayB, 1_250)
+            }
+
+            at(32) {
+                rule
+                    .onNode(isElement(TestElements.Foo, content = SceneA))
+                    .assertExists()
+                    .assertIsNotDisplayed()
+                rule.onNode(isElement(TestElements.Foo, content = OverlayA)).assertDoesNotExist()
+                rule
+                    .onNode(isElement(TestElements.Foo, content = OverlayB))
+                    .assertSizeIsEqualTo(80.dp, 60.dp)
+                    .assertPositionInRootIsEqualTo(20.dp, 10.dp)
+
+                assertThat(sharedIntValueByContent).containsEntry(SceneA, 1_500)
+                assertThat(sharedIntValueByContent).doesNotContainKey(OverlayA)
+                assertThat(sharedIntValueByContent).containsEntry(OverlayB, 1_500)
+            }
+
+            at(48) {
+                rule
+                    .onNode(isElement(TestElements.Foo, content = SceneA))
+                    .assertExists()
+                    .assertIsNotDisplayed()
+                rule.onNode(isElement(TestElements.Foo, content = OverlayA)).assertDoesNotExist()
+                rule
+                    .onNode(isElement(TestElements.Foo, content = OverlayB))
+                    .assertSizeIsEqualTo(90.dp, 70.dp)
+                    .assertPositionInRootIsEqualTo(30.dp, 15.dp)
+
+                assertThat(sharedIntValueByContent).containsEntry(SceneA, 1_750)
+                assertThat(sharedIntValueByContent).doesNotContainKey(OverlayA)
+                assertThat(sharedIntValueByContent).containsEntry(OverlayB, 1_750)
+            }
+
+            after {
+                rule
+                    .onNode(isElement(TestElements.Foo, content = SceneA))
+                    .assertExists()
+                    .assertIsNotDisplayed()
+                rule.onNode(isElement(TestElements.Foo, content = OverlayA)).assertDoesNotExist()
+                rule
+                    .onNode(isElement(TestElements.Foo, content = OverlayB))
+                    .assertSizeIsEqualTo(100.dp, 80.dp)
+                    .assertPositionInRootIsEqualTo(40.dp, 20.dp)
+
+                // Outside of transitions, the value is equal to the target value in each content.
+                assertThat(sharedIntValueByContent).containsEntry(SceneA, 1_000)
+                assertThat(sharedIntValueByContent).doesNotContainKey(OverlayA)
+                assertThat(sharedIntValueByContent).containsEntry(OverlayB, 2_000)
+            }
+        }
+    }
+
+    @Test
+    fun overscrollingOverlay_movableElementNotInOverlay() {
+        val state =
+            rule.runOnUiThread {
+                MutableSceneTransitionLayoutStateImpl(
+                    SceneA,
+                    transitions {
+                        // Make OverlayA overscrollable.
+                        overscroll(OverlayA, orientation = Orientation.Horizontal) {
+                            translate(ElementKey("elementThatDoesNotExist"), x = 10.dp)
+                        }
+                    }
+                )
+            }
+
+        val key = MovableElementKey("Foo", contents = setOf(SceneA))
+        val movableElementChildTag = "movableElementChildTag"
+        val scope =
+            rule.setContentAndCreateMainScope {
+                SceneTransitionLayout(state) {
+                    scene(SceneA) {
+                        MovableElement(key, Modifier) {
+                            content { Box(Modifier.testTag(movableElementChildTag).size(100.dp)) }
+                        }
+                    }
+                    overlay(OverlayA) { /* Does not contain the element. */ }
+                }
+            }
+
+        // Overscroll on Overlay A.
+        scope.launch { state.startTransition(transition(SceneA, OverlayA, progress = { 1.5f })) }
+        rule
+            .onNode(hasTestTag(movableElementChildTag) and inContent(SceneA))
+            .assertPositionInRootIsEqualTo(0.dp, 0.dp)
+            .assertSizeIsEqualTo(100.dp)
+            .assertIsDisplayed()
+    }
 }
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
index cd20a29a..d356c25 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
@@ -32,7 +32,7 @@
 import com.android.compose.animation.scene.transition.link.StateLink
 import com.android.compose.animation.scene.transition.seekToScene
 import com.android.compose.test.MonotonicClockTestScope
-import com.android.compose.test.TestTransition
+import com.android.compose.test.TestSceneTransition
 import com.android.compose.test.runMonotonicClockTest
 import com.android.compose.test.transition
 import com.google.common.truth.Truth.assertThat
@@ -556,8 +556,8 @@
 
     @Test
     fun multipleTransitions() = runTest {
-        val frozenTransitions = mutableSetOf<TestTransition>()
-        fun onFreezeAndAnimate(transition: TestTransition): () -> Unit {
+        val frozenTransitions = mutableSetOf<TestSceneTransition>()
+        fun onFreezeAndAnimate(transition: TestSceneTransition): () -> Unit {
             // Instead of letting the transition finish when it is frozen, we put the transition in
             // the frozenTransitions set so that we can verify that freezeAndAnimateToCurrentState()
             // is called when expected and then we call finish() ourselves to finish the
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestTransition.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestOverlayTransition.kt
similarity index 77%
copy from packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestTransition.kt
copy to packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestOverlayTransition.kt
index a6a83ee..646cff8 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestTransition.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestOverlayTransition.kt
@@ -18,18 +18,26 @@
 
 import androidx.compose.foundation.gestures.Orientation
 import com.android.compose.animation.scene.ContentKey
+import com.android.compose.animation.scene.OverlayKey
 import com.android.compose.animation.scene.SceneKey
 import com.android.compose.animation.scene.SceneTransitionLayoutImpl
 import com.android.compose.animation.scene.content.state.TransitionState
 import com.android.compose.animation.scene.content.state.TransitionState.Transition
 import kotlinx.coroutines.CompletableDeferred
 
-/** A transition for tests that will be finished once [finish] is called. */
-abstract class TestTransition(
+/** A [Transition.ShowOrHideOverlay] for tests that will be finished once [finish] is called. */
+abstract class TestOverlayTransition(
     fromScene: SceneKey,
-    toScene: SceneKey,
+    overlay: OverlayKey,
     replacedTransition: Transition?,
-) : Transition.ChangeScene(fromScene, toScene, replacedTransition) {
+) :
+    Transition.ShowOrHideOverlay(
+        overlay = overlay,
+        fromOrToScene = fromScene,
+        fromContent = fromScene,
+        toContent = overlay,
+        replacedTransition = replacedTransition,
+    ) {
     private val finishCompletable = CompletableDeferred<Unit>()
 
     override suspend fun run() {
@@ -42,11 +50,11 @@
     }
 }
 
-/** A utility to easily create a [TestTransition] in tests. */
+/** A utility to easily create a [TestOverlayTransition] in tests. */
 fun transition(
-    from: SceneKey,
-    to: SceneKey,
-    current: () -> SceneKey = { to },
+    fromScene: SceneKey,
+    overlay: OverlayKey,
+    isEffectivelyShown: () -> Boolean = { true },
     progress: () -> Float = { 0f },
     progressVelocity: () -> Float = { 0f },
     previewProgress: () -> Float = { 0f },
@@ -58,13 +66,14 @@
     isUpOrLeft: Boolean = false,
     bouncingContent: ContentKey? = null,
     orientation: Orientation = Orientation.Horizontal,
-    onFreezeAndAnimate: ((TestTransition) -> Unit)? = null,
+    onFreezeAndAnimate: ((TestOverlayTransition) -> Unit)? = null,
     replacedTransition: Transition? = null,
-): TestTransition {
+): TestOverlayTransition {
     return object :
-        TestTransition(from, to, replacedTransition), TransitionState.HasOverscrollProperties {
-        override val currentScene: SceneKey
-            get() = current()
+        TestOverlayTransition(fromScene, overlay, replacedTransition),
+        TransitionState.HasOverscrollProperties {
+        override val isEffectivelyShown: Boolean
+            get() = isEffectivelyShown()
 
         override val progress: Float
             get() = progress()
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestTransition.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestSceneTransition.kt
similarity index 89%
rename from packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestTransition.kt
rename to packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestSceneTransition.kt
index a6a83ee..d24b895 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestTransition.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestSceneTransition.kt
@@ -24,8 +24,8 @@
 import com.android.compose.animation.scene.content.state.TransitionState.Transition
 import kotlinx.coroutines.CompletableDeferred
 
-/** A transition for tests that will be finished once [finish] is called. */
-abstract class TestTransition(
+/** A [Transition.ChangeScene] for tests that will be finished once [finish] is called. */
+abstract class TestSceneTransition(
     fromScene: SceneKey,
     toScene: SceneKey,
     replacedTransition: Transition?,
@@ -42,7 +42,7 @@
     }
 }
 
-/** A utility to easily create a [TestTransition] in tests. */
+/** A utility to easily create a [TestSceneTransition] in tests. */
 fun transition(
     from: SceneKey,
     to: SceneKey,
@@ -58,11 +58,11 @@
     isUpOrLeft: Boolean = false,
     bouncingContent: ContentKey? = null,
     orientation: Orientation = Orientation.Horizontal,
-    onFreezeAndAnimate: ((TestTransition) -> Unit)? = null,
+    onFreezeAndAnimate: ((TestSceneTransition) -> Unit)? = null,
     replacedTransition: Transition? = null,
-): TestTransition {
+): TestSceneTransition {
     return object :
-        TestTransition(from, to, replacedTransition), TransitionState.HasOverscrollProperties {
+        TestSceneTransition(from, to, replacedTransition), TransitionState.HasOverscrollProperties {
         override val currentScene: SceneKey
             get() = current()
 
diff --git a/packages/SystemUI/docs/scene.md b/packages/SystemUI/docs/scene.md
index a7740c6..0ac15c5 100644
--- a/packages/SystemUI/docs/scene.md
+++ b/packages/SystemUI/docs/scene.md
@@ -124,8 +124,8 @@
 [`Scene`](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Scene.kt)
 interface, which has three parts: 1. The `key` property returns the
 [`SceneKey`](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneKey.kt)
-that uniquely identifies that scene 2. The `destinationScenes` `Flow` returns
-the (potentially ever-changing) set of navigation edges to other scenes, based
+that uniquely identifies that scene 2. The `userActions` `Flow` returns
+the (potentially ever-changing) set of navigation edges to other content, based
 on user-actions, which is how the navigation graph is defined (see
 [the Scene navigation](#Scene-navigation) section for more) 3. The `Content`
 function which uses
@@ -141,7 +141,7 @@
 @SysUISingleton class YourScene @Inject constructor( /* your dependencies here */ ) : Scene {
     override val key = SceneKey.YourScene
 
-    override val destinationScenes: StateFlow<Map<UserAction, SceneModel>> =
+    override val userActions: StateFlow<Map<UserAction, SceneModel>> =
         MutableStateFlow<Map<UserAction, SceneModel>>(
             mapOf(
                 // This is where scene navigation is defined, more on that below.
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
index 1cd9d76..72163e4 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
@@ -31,9 +31,7 @@
 import com.android.systemui.coroutines.collectValues
 import com.android.systemui.kosmos.testDispatcher
 import com.android.systemui.kosmos.testScope
-import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
-import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
 import com.android.systemui.testKosmos
 import com.android.systemui.user.data.repository.FakeUserRepository
 import com.android.systemui.util.mockito.whenever
@@ -58,14 +56,13 @@
 
     @Mock private lateinit var lockPatternUtils: LockPatternUtils
     @Mock private lateinit var getSecurityMode: Function<Int, KeyguardSecurityModel.SecurityMode>
-    @Mock private lateinit var tableLogger: TableLogBuffer
     @Mock private lateinit var devicePolicyManager: DevicePolicyManager
 
     private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
     private val clock = FakeSystemClock()
     private val userRepository = FakeUserRepository()
-    private lateinit var mobileConnectionsRepository: FakeMobileConnectionsRepository
+    private val mobileConnectionsRepository = kosmos.fakeMobileConnectionsRepository
 
     private lateinit var underTest: AuthenticationRepository
 
@@ -78,8 +75,6 @@
         userRepository.setUserInfos(USER_INFOS)
         runBlocking { userRepository.setSelectedUserInfo(USER_INFOS[0]) }
         whenever(getSecurityMode.apply(anyInt())).thenAnswer { currentSecurityMode }
-        mobileConnectionsRepository =
-            FakeMobileConnectionsRepository(FakeMobileMappingsProxy(), tableLogger)
 
         underTest =
             AuthenticationRepositoryImpl(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerUserActionsViewModelTest.kt
similarity index 93%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerUserActionsViewModelTest.kt
index a86a0c0..f58bbc3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerUserActionsViewModelTest.kt
@@ -44,17 +44,17 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 @EnableSceneContainer
-class BouncerSceneActionsViewModelTest : SysuiTestCase() {
+class BouncerUserActionsViewModelTest : SysuiTestCase() {
 
     private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
 
-    private lateinit var underTest: BouncerSceneActionsViewModel
+    private lateinit var underTest: BouncerUserActionsViewModel
 
     @Before
     fun setUp() {
         kosmos.sceneContainerStartable.start()
-        underTest = kosmos.bouncerSceneActionsViewModel
+        underTest = kosmos.bouncerUserActionsViewModel
         underTest.activateIn(testScope)
     }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
index ec8cc4d..53d82d7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
@@ -34,8 +34,6 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.testing.FakeMetricsLogger;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.flags.FakeFeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
@@ -83,7 +81,6 @@
     private final FalsingClassifier.Result mPassedResult = FalsingClassifier.Result.passed(1);
     private final FalsingClassifier.Result mFalsedResult =
             FalsingClassifier.Result.falsed(1, getClass().getSimpleName(), "");
-    private final FakeFeatureFlags mFakeFeatureFlags = new FakeFeatureFlags();
 
     @Before
     public void setup() {
@@ -101,8 +98,7 @@
         mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider,
                 mMetricsLogger, mClassifiers, mSingleTapClassifier, mLongTapClassifier,
                 mDoubleTapClassifier, mHistoryTracker, mKeyguardStateController,
-                mAccessibilityManager, false, mFakeFeatureFlags);
-        mFakeFeatureFlags.set(Flags.FALSING_OFF_FOR_UNFOLDED, true);
+                mAccessibilityManager, false);
     }
 
     @Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
index d4a7691..71abed7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
@@ -75,7 +75,7 @@
 import com.android.systemui.log.FaceAuthenticationLogger
 import com.android.systemui.log.SessionTracker
 import com.android.systemui.log.logcatLogBuffer
-import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logcatTableLogBuffer
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
 import com.android.systemui.power.domain.interactor.powerInteractor
@@ -90,7 +90,6 @@
 import com.android.systemui.util.mockito.captureMany
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
 import java.io.PrintWriter
 import java.io.StringWriter
@@ -199,25 +198,8 @@
         fmOverride: FaceManager? = faceManager,
         bypassControllerOverride: KeyguardBypassController? = bypassController
     ): DeviceEntryFaceAuthRepositoryImpl {
-        val systemClock = FakeSystemClock()
-        val faceAuthBuffer =
-            TableLogBuffer(
-                10,
-                "face auth",
-                systemClock,
-                mock(),
-                testDispatcher,
-                testScope.backgroundScope
-            )
-        val faceDetectBuffer =
-            TableLogBuffer(
-                10,
-                "face detect",
-                systemClock,
-                mock(),
-                testDispatcher,
-                testScope.backgroundScope
-            )
+        val faceAuthBuffer = logcatTableLogBuffer(kosmos, "face auth")
+        val faceDetectBuffer = logcatTableLogBuffer(kosmos, "face detect")
 
         return DeviceEntryFaceAuthRepositoryImpl(
             mContext,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt
index ca15eff..34d926a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt
@@ -24,6 +24,7 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.contextualeducation.GestureType
+import com.android.systemui.contextualeducation.GestureType.ALL_APPS
 import com.android.systemui.contextualeducation.GestureType.BACK
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.education.data.model.GestureEduModel
@@ -220,17 +221,19 @@
             verify(kosmos.mockEduInputManager)
                 .registerKeyGestureEventListener(any(), listenerCaptor.capture())
 
-            val backGestureEvent =
+            val allAppsKeyGestureEvent =
                 KeyGestureEvent(
                     /* deviceId= */ 1,
-                    intArrayOf(KeyEvent.KEYCODE_ESCAPE),
+                    IntArray(0),
                     KeyEvent.META_META_ON,
-                    KeyGestureEvent.KEY_GESTURE_TYPE_BACK
+                    KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS
                 )
-            listenerCaptor.value.onKeyGestureEvent(backGestureEvent)
+            listenerCaptor.value.onKeyGestureEvent(allAppsKeyGestureEvent)
 
             val model by
-                collectLastValue(kosmos.contextualEducationRepository.readGestureEduModelFlow(BACK))
+                collectLastValue(
+                    kosmos.contextualEducationRepository.readGestureEduModelFlow(ALL_APPS)
+                )
             assertThat(model?.lastShortcutTriggeredTime).isEqualTo(eduClock.instant())
         }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadStatsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadStatsInteractorTest.kt
index cd0c58f..8b5f594 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadStatsInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadStatsInteractorTest.kt
@@ -19,16 +19,23 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.contextualeducation.GestureType.ALL_APPS
 import com.android.systemui.contextualeducation.GestureType.BACK
+import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.education.data.repository.contextualEducationRepository
 import com.android.systemui.education.data.repository.fakeEduClock
+import com.android.systemui.inputdevice.data.model.UserDeviceConnectionStatus
+import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
+import kotlin.time.Duration.Companion.seconds
+import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.test.runTest
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.whenever
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
@@ -36,24 +43,190 @@
     private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
     private val underTest = kosmos.keyboardTouchpadEduStatsInteractor
+    private val repository = kosmos.contextualEducationRepository
+    private val fakeClock = kosmos.fakeEduClock
+    private val initialDelayElapsedDuration =
+        KeyboardTouchpadEduStatsInteractorImpl.initialDelayDuration + 1.seconds
 
     @Test
-    fun dataUpdatedOnIncrementSignalCount() =
+    fun dataUpdatedOnIncrementSignalCountWhenTouchpadConnected() =
         testScope.runTest {
-            val model by
-                collectLastValue(kosmos.contextualEducationRepository.readGestureEduModelFlow(BACK))
+            setUpForInitialDelayElapse()
+            whenever(mockUserInputDeviceRepository.isAnyTouchpadConnectedForUser)
+                .thenReturn(flowOf(UserDeviceConnectionStatus(isConnected = true, userId = 0)))
+
+            val model by collectLastValue(repository.readGestureEduModelFlow(BACK))
             val originalValue = model!!.signalCount
             underTest.incrementSignalCount(BACK)
+
             assertThat(model?.signalCount).isEqualTo(originalValue + 1)
         }
 
     @Test
+    fun dataUnchangedOnIncrementSignalCountWhenTouchpadDisconnected() =
+        testScope.runTest {
+            setUpForInitialDelayElapse()
+            whenever(mockUserInputDeviceRepository.isAnyTouchpadConnectedForUser)
+                .thenReturn(flowOf(UserDeviceConnectionStatus(isConnected = false, userId = 0)))
+
+            val model by collectLastValue(repository.readGestureEduModelFlow(BACK))
+            val originalValue = model!!.signalCount
+            underTest.incrementSignalCount(BACK)
+
+            assertThat(model?.signalCount).isEqualTo(originalValue)
+        }
+
+    @Test
+    fun dataUpdatedOnIncrementSignalCountWhenKeyboardConnected() =
+        testScope.runTest {
+            setUpForInitialDelayElapse()
+            whenever(mockUserInputDeviceRepository.isAnyKeyboardConnectedForUser)
+                .thenReturn(flowOf(UserDeviceConnectionStatus(isConnected = true, userId = 0)))
+
+            val model by collectLastValue(repository.readGestureEduModelFlow(ALL_APPS))
+            val originalValue = model!!.signalCount
+            underTest.incrementSignalCount(ALL_APPS)
+
+            assertThat(model?.signalCount).isEqualTo(originalValue + 1)
+        }
+
+    @Test
+    fun dataUnchangedOnIncrementSignalCountWhenKeyboardDisconnected() =
+        testScope.runTest {
+            setUpForInitialDelayElapse()
+            whenever(mockUserInputDeviceRepository.isAnyKeyboardConnectedForUser)
+                .thenReturn(flowOf(UserDeviceConnectionStatus(isConnected = false, userId = 0)))
+
+            val model by collectLastValue(repository.readGestureEduModelFlow(ALL_APPS))
+            val originalValue = model!!.signalCount
+            underTest.incrementSignalCount(ALL_APPS)
+
+            assertThat(model?.signalCount).isEqualTo(originalValue)
+        }
+
+    @Test
+    fun dataUpdatedOnIncrementSignalCountAfterOobeLaunchInitialDelay() =
+        testScope.runTest {
+            setUpForDeviceConnection()
+            whenever(mockTutorialSchedulerRepository.launchTime(any<DeviceType>()))
+                .thenReturn(fakeClock.instant())
+            fakeClock.offset(initialDelayElapsedDuration)
+
+            val model by collectLastValue(repository.readGestureEduModelFlow(BACK))
+            val originalValue = model!!.signalCount
+            underTest.incrementSignalCount(BACK)
+
+            assertThat(model?.signalCount).isEqualTo(originalValue + 1)
+        }
+
+    @Test
+    fun dataUnchangedOnIncrementSignalCountBeforeOobeLaunchInitialDelay() =
+        testScope.runTest {
+            setUpForDeviceConnection()
+            whenever(mockTutorialSchedulerRepository.launchTime(any<DeviceType>()))
+                .thenReturn(fakeClock.instant())
+
+            val model by collectLastValue(repository.readGestureEduModelFlow(BACK))
+            val originalValue = model!!.signalCount
+            underTest.incrementSignalCount(BACK)
+
+            assertThat(model?.signalCount).isEqualTo(originalValue)
+        }
+
+    @Test
+    fun dataUpdatedOnIncrementSignalCountAfterTouchpadConnectionInitialDelay() =
+        testScope.runTest {
+            setUpForDeviceConnection()
+            repository.updateEduDeviceConnectionTime { model ->
+                model.copy(touchpadFirstConnectionTime = fakeClock.instant())
+            }
+            fakeClock.offset(initialDelayElapsedDuration)
+
+            val model by collectLastValue(repository.readGestureEduModelFlow(BACK))
+            val originalValue = model!!.signalCount
+            underTest.incrementSignalCount(BACK)
+
+            assertThat(model?.signalCount).isEqualTo(originalValue + 1)
+        }
+
+    @Test
+    fun dataUnchangedOnIncrementSignalCountBeforeTouchpadConnectionInitialDelay() =
+        testScope.runTest {
+            setUpForDeviceConnection()
+            repository.updateEduDeviceConnectionTime { model ->
+                model.copy(touchpadFirstConnectionTime = fakeClock.instant())
+            }
+
+            val model by collectLastValue(repository.readGestureEduModelFlow(BACK))
+            val originalValue = model!!.signalCount
+            underTest.incrementSignalCount(BACK)
+
+            assertThat(model?.signalCount).isEqualTo(originalValue)
+        }
+
+    @Test
+    fun dataUpdatedOnIncrementSignalCountAfterKeyboardConnectionInitialDelay() =
+        testScope.runTest {
+            setUpForDeviceConnection()
+            repository.updateEduDeviceConnectionTime { model ->
+                model.copy(keyboardFirstConnectionTime = fakeClock.instant())
+            }
+            fakeClock.offset(initialDelayElapsedDuration)
+
+            val model by collectLastValue(repository.readGestureEduModelFlow(ALL_APPS))
+            val originalValue = model!!.signalCount
+            underTest.incrementSignalCount(ALL_APPS)
+
+            assertThat(model?.signalCount).isEqualTo(originalValue + 1)
+        }
+
+    @Test
+    fun dataUnchangedOnIncrementSignalCountBeforeKeyboardConnectionInitialDelay() =
+        testScope.runTest {
+            setUpForDeviceConnection()
+            repository.updateEduDeviceConnectionTime { model ->
+                model.copy(keyboardFirstConnectionTime = fakeClock.instant())
+            }
+
+            val model by collectLastValue(repository.readGestureEduModelFlow(ALL_APPS))
+            val originalValue = model!!.signalCount
+            underTest.incrementSignalCount(ALL_APPS)
+
+            assertThat(model?.signalCount).isEqualTo(originalValue)
+        }
+
+    @Test
+    fun dataUnchangedOnIncrementSignalCountWhenNoSetupTime() =
+        testScope.runTest {
+            whenever(mockUserInputDeviceRepository.isAnyTouchpadConnectedForUser)
+                .thenReturn(flowOf(UserDeviceConnectionStatus(isConnected = true, userId = 0)))
+
+            val model by collectLastValue(repository.readGestureEduModelFlow(BACK))
+            val originalValue = model!!.signalCount
+            underTest.incrementSignalCount(BACK)
+
+            assertThat(model?.signalCount).isEqualTo(originalValue)
+        }
+
+    @Test
     fun dataAddedOnUpdateShortcutTriggerTime() =
         testScope.runTest {
-            val model by
-                collectLastValue(kosmos.contextualEducationRepository.readGestureEduModelFlow(BACK))
+            val model by collectLastValue(repository.readGestureEduModelFlow(BACK))
             assertThat(model?.lastShortcutTriggeredTime).isNull()
             underTest.updateShortcutTriggerTime(BACK)
             assertThat(model?.lastShortcutTriggeredTime).isEqualTo(kosmos.fakeEduClock.instant())
         }
+
+    private suspend fun setUpForInitialDelayElapse() {
+        whenever(mockTutorialSchedulerRepository.launchTime(any<DeviceType>()))
+            .thenReturn(fakeClock.instant())
+        fakeClock.offset(initialDelayElapsedDuration)
+    }
+
+    private fun setUpForDeviceConnection() {
+        whenever(mockUserInputDeviceRepository.isAnyTouchpadConnectedForUser)
+            .thenReturn(flowOf(UserDeviceConnectionStatus(isConnected = true, userId = 0)))
+        whenever(mockUserInputDeviceRepository.isAnyKeyboardConnectedForUser)
+            .thenReturn(flowOf(UserDeviceConnectionStatus(isConnected = true, userId = 0)))
+    }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt
index fd4ed38..686b518 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt
@@ -23,7 +23,7 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.animation.ActivityTransitionAnimator
-import com.android.systemui.haptics.vibratorHelper
+import com.android.systemui.haptics.fakeVibratorHelper
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.log.core.FakeLogBuffer
 import com.android.systemui.qs.qsTileFactory
@@ -50,7 +50,7 @@
 
     @Rule @JvmField val mMockitoRule: MockitoRule = MockitoJUnit.rule()
     private val kosmos = testKosmos()
-    private val vibratorHelper = kosmos.vibratorHelper
+    private val vibratorHelper = kosmos.fakeVibratorHelper
     private val qsTile = kosmos.qsTileFactory.createTile("Test Tile")
     @Mock private lateinit var callback: QSLongPressEffect.Callback
     @Mock private lateinit var controller: ActivityTransitionAnimator.Controller
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
index c5ba02d..4e429c3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
@@ -46,11 +46,10 @@
 import com.android.systemui.keyguard.data.repository.BiometricType.SIDE_FINGERPRINT
 import com.android.systemui.keyguard.data.repository.BiometricType.UNDER_DISPLAY_FINGERPRINT
 import com.android.systemui.keyguard.shared.model.DevicePosture
-import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.res.R
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
-import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
 import com.android.systemui.statusbar.policy.DevicePostureController
+import com.android.systemui.testKosmos
 import com.android.systemui.user.data.repository.FakeUserRepository
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.mockito.whenever
@@ -81,6 +80,8 @@
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
 @RunWith(AndroidJUnit4::class)
 class BiometricSettingsRepositoryTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
+
     private lateinit var underTest: BiometricSettingsRepository
 
     @Mock private lateinit var authController: AuthController
@@ -88,7 +89,6 @@
     @Mock private lateinit var devicePolicyManager: DevicePolicyManager
     @Mock private lateinit var dumpManager: DumpManager
     @Mock private lateinit var biometricManager: BiometricManager
-    @Mock private lateinit var tableLogger: TableLogBuffer
     @Captor
     private lateinit var strongAuthTracker: ArgumentCaptor<LockPatternUtils.StrongAuthTracker>
     @Captor private lateinit var authControllerCallback: ArgumentCaptor<AuthController.Callback>
@@ -99,7 +99,7 @@
     private lateinit var devicePostureRepository: FakeDevicePostureRepository
     private lateinit var facePropertyRepository: FakeFacePropertyRepository
     private lateinit var fingerprintPropertyRepository: FakeFingerprintPropertyRepository
-    private lateinit var mobileConnectionsRepository: FakeMobileConnectionsRepository
+    private val mobileConnectionsRepository = kosmos.fakeMobileConnectionsRepository
 
     private lateinit var testDispatcher: TestDispatcher
     private lateinit var testScope: TestScope
@@ -115,8 +115,6 @@
         devicePostureRepository = FakeDevicePostureRepository()
         facePropertyRepository = FakeFacePropertyRepository()
         fingerprintPropertyRepository = FakeFingerprintPropertyRepository()
-        mobileConnectionsRepository =
-            FakeMobileConnectionsRepository(FakeMobileMappingsProxy(), tableLogger)
     }
 
     private suspend fun createBiometricSettingsRepository() {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt
similarity index 91%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneActionsViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt
index c66ebf3..4253c29 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt
@@ -63,7 +63,7 @@
 @RunWith(ParameterizedAndroidJunit4::class)
 @RunWithLooper
 @EnableSceneContainer
-class LockscreenSceneActionsViewModelTest : SysuiTestCase() {
+class LockscreenUserActionsViewModelTest : SysuiTestCase() {
 
     companion object {
         private const val parameterCount = 6
@@ -170,7 +170,7 @@
 
     @Test
     @EnableFlags(Flags.FLAG_COMMUNAL_HUB)
-    fun destinationScenes() =
+    fun userActions() =
         testScope.runTest {
             underTest.activateIn(this)
             kosmos.fakeDeviceEntryRepository.setLockscreenEnabled(true)
@@ -193,9 +193,9 @@
                     },
             )
 
-            val destinationScenes by collectLastValue(underTest.actions)
+            val userActions by collectLastValue(underTest.actions)
             val downDestination =
-                destinationScenes?.get(
+                userActions?.get(
                     Swipe(
                         SwipeDirection.Down,
                         fromSource = Edge.Top.takeIf { downFromEdge },
@@ -227,11 +227,10 @@
 
             val upScene by
                 collectLastValue(
-                    (destinationScenes?.get(Swipe(SwipeDirection.Up))
-                            as? UserActionResult.ChangeScene)
-                        ?.toScene
-                        ?.let { scene -> kosmos.sceneInteractor.resolveSceneFamily(scene) }
-                        ?: flowOf(null)
+                    (userActions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene?.let {
+                        scene ->
+                        kosmos.sceneInteractor.resolveSceneFamily(scene)
+                    } ?: flowOf(null)
                 )
 
             assertThat(upScene)
@@ -244,11 +243,10 @@
 
             val leftScene by
                 collectLastValue(
-                    (destinationScenes?.get(Swipe(SwipeDirection.Left))
-                            as? UserActionResult.ChangeScene)
-                        ?.toScene
-                        ?.let { scene -> kosmos.sceneInteractor.resolveSceneFamily(scene) }
-                        ?: flowOf(null)
+                    (userActions?.get(Swipe.Left) as? UserActionResult.ChangeScene)?.toScene?.let {
+                        scene ->
+                        kosmos.sceneInteractor.resolveSceneFamily(scene)
+                    } ?: flowOf(null)
                 )
 
             assertThat(leftScene)
@@ -260,8 +258,8 @@
                 )
         }
 
-    private fun createLockscreenSceneViewModel(): LockscreenSceneActionsViewModel {
-        return LockscreenSceneActionsViewModel(
+    private fun createLockscreenSceneViewModel(): LockscreenUserActionsViewModel {
+        return LockscreenUserActionsViewModel(
             deviceEntryInteractor = kosmos.deviceEntryInteractor,
             communalInteractor = kosmos.communalInteractor,
             shadeInteractor = kosmos.shadeInteractor,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt
index 22e5896..c1dcf37 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt
@@ -34,7 +34,6 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.flags.Flags.MEDIA_RESUME_PROGRESS
-import com.android.systemui.flags.Flags.MEDIA_SESSION_ACTIONS
 import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.graphics.imageLoader
 import com.android.systemui.kosmos.testDispatcher
@@ -96,7 +95,6 @@
 
     @Before
     fun setUp() {
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         mediaControllerFactory.setControllerForToken(session.sessionToken, mediaController)
     }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModelTest.kt
similarity index 97%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneActionsViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModelTest.kt
index ed7f96fb..46b02e92 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModelTest.kt
@@ -37,7 +37,7 @@
 import com.android.systemui.scene.domain.resolver.homeSceneFamilyResolver
 import com.android.systemui.scene.shared.model.SceneFamilies
 import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.shade.ui.viewmodel.notificationsShadeSceneActionsViewModel
+import com.android.systemui.shade.ui.viewmodel.notificationsShadeUserActionsViewModel
 import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -52,14 +52,14 @@
 @RunWith(AndroidJUnit4::class)
 @TestableLooper.RunWithLooper
 @EnableSceneContainer
-class NotificationsShadeSceneActionsViewModelTest : SysuiTestCase() {
+class NotificationsShadeUserActionsViewModelTest : SysuiTestCase() {
 
     private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
     private val sceneInteractor by lazy { kosmos.sceneInteractor }
     private val deviceUnlockedInteractor by lazy { kosmos.deviceUnlockedInteractor }
 
-    private val underTest by lazy { kosmos.notificationsShadeSceneActionsViewModel }
+    private val underTest by lazy { kosmos.notificationsShadeUserActionsViewModel }
 
     @Test
     fun upTransitionSceneKey_deviceLocked_lockscreen() =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/airplane/domain/interactor/AirplaneModeTileUserActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/airplane/domain/interactor/AirplaneModeTileUserActionInteractorTest.kt
index 79fcc92..d27e810 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/airplane/domain/interactor/AirplaneModeTileUserActionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/airplane/domain/interactor/AirplaneModeTileUserActionInteractorTest.kt
@@ -29,8 +29,9 @@
 import com.android.systemui.qs.tiles.impl.airplane.domain.model.AirplaneModeTileModel
 import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
 import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
+import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.test.runTest
 import org.junit.Test
@@ -40,8 +41,9 @@
 @EnabledOnRavenwood
 @RunWith(AndroidJUnit4::class)
 class AirplaneModeTileUserActionInteractorTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
 
-    private val mobileConnectionsRepository = FakeMobileConnectionsRepository()
+    private val mobileConnectionsRepository = kosmos.fakeMobileConnectionsRepository
     private val connectivityRepository = FakeConnectivityRepository()
     private val airplaneModeRepository = FakeAirplaneModeRepository()
     private val inputHandler = FakeQSTileIntentUserInputHandler()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractorTest.kt
index 1ea8abc..6f11b2a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractorTest.kt
@@ -33,7 +33,7 @@
 import com.android.systemui.flags.Flags
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.testScope
-import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logcatTableLogBuffer
 import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
 import com.android.systemui.qs.tiles.impl.internet.domain.model.InternetTileModel
 import com.android.systemui.res.R
@@ -86,7 +86,7 @@
     private val wifiInteractor =
         WifiInteractorImpl(connectivityRepository, wifiRepository, testScope.backgroundScope)
 
-    private val tableLogBuffer: TableLogBuffer = mock()
+    private val tableLogBuffer = logcatTableLogBuffer(kosmos, "InternetTileDataInteractorTest")
     private val carrierConfigTracker: CarrierConfigTracker = mock()
 
     private val mobileConnectionsRepository =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractorTest.kt
index a18f450..91d8e2a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractorTest.kt
@@ -206,6 +206,39 @@
             assertThat(tileData?.iconResId).isEqualTo(MODES_DRAWABLE_ID)
         }
 
+    @EnableFlags(Flags.FLAG_MODES_UI)
+    @Test
+    fun getCurrentTileModel_returnsActiveModes() = runTest {
+        var tileData = underTest.getCurrentTileModel()
+        assertThat(tileData.isActivated).isFalse()
+        assertThat(tileData.activeModes).isEmpty()
+
+        // Add active mode
+        zenModeRepository.addMode(id = "One", active = true)
+        tileData = underTest.getCurrentTileModel()
+        assertThat(tileData.isActivated).isTrue()
+        assertThat(tileData.activeModes).containsExactly("Mode One")
+
+        // Add an inactive mode: state hasn't changed
+        zenModeRepository.addMode(id = "Two", active = false)
+        tileData = underTest.getCurrentTileModel()
+        assertThat(tileData.isActivated).isTrue()
+        assertThat(tileData.activeModes).containsExactly("Mode One")
+
+        // Add another active mode
+        zenModeRepository.addMode(id = "Three", active = true)
+        tileData = underTest.getCurrentTileModel()
+        assertThat(tileData.isActivated).isTrue()
+        assertThat(tileData.activeModes).containsExactly("Mode One", "Mode Three").inOrder()
+
+        // Remove a mode and deactivate the other
+        zenModeRepository.removeMode("One")
+        zenModeRepository.deactivateMode("Three")
+        tileData = underTest.getCurrentTileModel()
+        assertThat(tileData.isActivated).isFalse()
+        assertThat(tileData.activeModes).isEmpty()
+    }
+
     private companion object {
         val TEST_USER = UserHandle.of(1)!!
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModelTest.kt
similarity index 97%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModelTest.kt
index ba527d7..32772d2 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModelTest.kt
@@ -53,14 +53,14 @@
 @RunWith(AndroidJUnit4::class)
 @TestableLooper.RunWithLooper
 @EnableSceneContainer
-class QuickSettingsShadeSceneActionsViewModelTest : SysuiTestCase() {
+class QuickSettingsShadeUserActionsViewModelTest : SysuiTestCase() {
 
     private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
     private val sceneInteractor = kosmos.sceneInteractor
     private val deviceUnlockedInteractor = kosmos.deviceUnlockedInteractor
 
-    private val underTest by lazy { kosmos.quickSettingsShadeSceneActionsViewModel }
+    private val underTest by lazy { kosmos.quickSettingsShadeUserActionsViewModel }
 
     @Test
     fun upTransitionSceneKey_deviceLocked_lockscreen() =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsUserActionsViewModelTest.kt
similarity index 98%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsUserActionsViewModelTest.kt
index f26a9db..6986cf8e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsUserActionsViewModelTest.kt
@@ -57,7 +57,7 @@
 @RunWith(AndroidJUnit4::class)
 @RunWithLooper
 @EnableSceneContainer
-class QuickSettingsSceneActionsViewModelTest : SysuiTestCase() {
+class QuickSettingsUserActionsViewModelTest : SysuiTestCase() {
 
     private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
@@ -67,7 +67,7 @@
     private val sceneBackInteractor = kosmos.sceneBackInteractor
     private val sceneContainerStartable = kosmos.sceneContainerStartable
 
-    private lateinit var underTest: QuickSettingsSceneActionsViewModel
+    private lateinit var underTest: QuickSettingsUserActionsViewModel
 
     @Before
     fun setUp() {
@@ -75,7 +75,7 @@
 
         sceneContainerStartable.start()
         underTest =
-            QuickSettingsSceneActionsViewModel(
+            QuickSettingsUserActionsViewModel(
                 qsSceneAdapter = qsFlexiglassAdapter,
                 sceneBackInteractor = sceneBackInteractor,
             )
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
index f365afb..4f7c013 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
@@ -49,7 +49,7 @@
 import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.flags.Flags
 import com.android.systemui.flags.fakeFeatureFlagsClassic
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenSceneActionsViewModel
+import com.android.systemui.keyguard.ui.viewmodel.LockscreenUserActionsViewModel
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.lifecycle.activateIn
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest
@@ -65,10 +65,10 @@
 import com.android.systemui.scene.shared.model.fakeSceneDataSource
 import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
 import com.android.systemui.shade.domain.interactor.shadeInteractor
-import com.android.systemui.shade.ui.viewmodel.ShadeSceneActionsViewModel
 import com.android.systemui.shade.ui.viewmodel.ShadeSceneContentViewModel
-import com.android.systemui.shade.ui.viewmodel.shadeSceneActionsViewModel
+import com.android.systemui.shade.ui.viewmodel.ShadeUserActionsViewModel
 import com.android.systemui.shade.ui.viewmodel.shadeSceneContentViewModel
+import com.android.systemui.shade.ui.viewmodel.shadeUserActionsViewModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
 import com.android.systemui.telephony.data.repository.fakeTelephonyRepository
@@ -145,8 +145,8 @@
     private lateinit var bouncerActionButtonInteractor: BouncerActionButtonInteractor
     private lateinit var bouncerSceneContentViewModel: BouncerSceneContentViewModel
 
-    private val lockscreenSceneActionsViewModel by lazy {
-        LockscreenSceneActionsViewModel(
+    private val mLockscreenUserActionsViewModel by lazy {
+        LockscreenUserActionsViewModel(
             deviceEntryInteractor = deviceEntryInteractor,
             communalInteractor = communalInteractor,
             shadeInteractor = kosmos.shadeInteractor,
@@ -154,7 +154,7 @@
     }
 
     private lateinit var shadeSceneContentViewModel: ShadeSceneContentViewModel
-    private lateinit var shadeSceneActionsViewModel: ShadeSceneActionsViewModel
+    private lateinit var mShadeUserActionsViewModel: ShadeUserActionsViewModel
 
     private val powerInteractor by lazy { kosmos.powerInteractor }
 
@@ -191,14 +191,14 @@
         bouncerSceneContentViewModel = kosmos.bouncerSceneContentViewModel
 
         shadeSceneContentViewModel = kosmos.shadeSceneContentViewModel
-        shadeSceneActionsViewModel = kosmos.shadeSceneActionsViewModel
+        mShadeUserActionsViewModel = kosmos.shadeUserActionsViewModel
 
         val startable = kosmos.sceneContainerStartable
         startable.start()
 
-        lockscreenSceneActionsViewModel.activateIn(testScope)
+        mLockscreenUserActionsViewModel.activateIn(testScope)
         shadeSceneContentViewModel.activateIn(testScope)
-        shadeSceneActionsViewModel.activateIn(testScope)
+        mShadeUserActionsViewModel.activateIn(testScope)
         bouncerSceneContentViewModel.activateIn(testScope)
         sceneContainerViewModel.activateIn(testScope)
 
@@ -229,7 +229,7 @@
     @Test
     fun swipeUpOnLockscreen_enterCorrectPin_unlocksDevice() =
         testScope.runTest {
-            val actions by collectLastValue(lockscreenSceneActionsViewModel.actions)
+            val actions by collectLastValue(mLockscreenUserActionsViewModel.actions)
             val upDestinationSceneKey =
                 (actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
             assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
@@ -250,7 +250,7 @@
         testScope.runTest {
             setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
 
-            val actions by collectLastValue(lockscreenSceneActionsViewModel.actions)
+            val actions by collectLastValue(mLockscreenUserActionsViewModel.actions)
             val upDestinationSceneKey =
                 (actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
             assertThat(upDestinationSceneKey).isEqualTo(Scenes.Gone)
@@ -262,7 +262,7 @@
     @Test
     fun swipeUpOnShadeScene_withAuthMethodSwipe_lockscreenNotDismissed_goesToLockscreen() =
         testScope.runTest {
-            val actions by collectLastValue(shadeSceneActionsViewModel.actions)
+            val actions by collectLastValue(mShadeUserActionsViewModel.actions)
             val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene)
             setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
             assertCurrentScene(Scenes.Lockscreen)
@@ -283,7 +283,7 @@
     @Test
     fun swipeUpOnShadeScene_withAuthMethodSwipe_lockscreenDismissed_goesToGone() =
         testScope.runTest {
-            val actions by collectLastValue(shadeSceneActionsViewModel.actions)
+            val actions by collectLastValue(mShadeUserActionsViewModel.actions)
             val canSwipeToEnter by collectLastValue(deviceEntryInteractor.canSwipeToEnter)
             val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene)
 
@@ -369,7 +369,7 @@
     fun swipeUpOnLockscreenWhileUnlocked_dismissesLockscreen() =
         testScope.runTest {
             unlockDevice()
-            val actions by collectLastValue(lockscreenSceneActionsViewModel.actions)
+            val actions by collectLastValue(mLockscreenUserActionsViewModel.actions)
             val upDestinationSceneKey =
                 (actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
             assertThat(upDestinationSceneKey).isEqualTo(Scenes.Gone)
@@ -392,7 +392,7 @@
     fun dismissingIme_whileOnPasswordBouncer_navigatesToLockscreen() =
         testScope.runTest {
             setAuthMethod(AuthenticationMethodModel.Password)
-            val actions by collectLastValue(lockscreenSceneActionsViewModel.actions)
+            val actions by collectLastValue(mLockscreenUserActionsViewModel.actions)
             val upDestinationSceneKey =
                 (actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
             assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
@@ -411,7 +411,7 @@
     fun bouncerActionButtonClick_opensEmergencyServicesDialer() =
         testScope.runTest {
             setAuthMethod(AuthenticationMethodModel.Password)
-            val actions by collectLastValue(lockscreenSceneActionsViewModel.actions)
+            val actions by collectLastValue(mLockscreenUserActionsViewModel.actions)
             val upDestinationSceneKey =
                 (actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
             assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
@@ -432,7 +432,7 @@
         testScope.runTest {
             setAuthMethod(AuthenticationMethodModel.Password)
             startPhoneCall()
-            val actions by collectLastValue(lockscreenSceneActionsViewModel.actions)
+            val actions by collectLastValue(mLockscreenUserActionsViewModel.actions)
             val upDestinationSceneKey =
                 (actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
             assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index d3b51d1..ec79cc6 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -19,6 +19,7 @@
 package com.android.systemui.scene.domain.startable
 
 import android.app.StatusBarManager
+import android.hardware.face.FaceManager
 import android.os.PowerManager
 import android.view.Display
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -30,6 +31,9 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
+import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
+import com.android.systemui.biometrics.shared.model.FingerprintSensorType
+import com.android.systemui.biometrics.shared.model.SensorStrength
 import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
 import com.android.systemui.bouncer.domain.interactor.bouncerInteractor
 import com.android.systemui.bouncer.shared.logging.BouncerUiEvent
@@ -39,8 +43,14 @@
 import com.android.systemui.concurrency.fakeExecutor
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryHapticsInteractor
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
+import com.android.systemui.deviceentry.shared.model.FailedFaceAuthenticationStatus
+import com.android.systemui.deviceentry.shared.model.SuccessFaceAuthenticationStatus
 import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.haptics.vibratorHelper
+import com.android.systemui.keyevent.data.repository.fakeKeyEventRepository
+import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
 import com.android.systemui.keyguard.data.repository.deviceEntryFingerprintAuthRepository
 import com.android.systemui.keyguard.data.repository.fakeBiometricSettingsRepository
 import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository
@@ -53,11 +63,15 @@
 import com.android.systemui.keyguard.domain.interactor.keyguardEnabledInteractor
 import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.scenetransition.lockscreenSceneTransitionInteractor
+import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
+import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
+import com.android.systemui.keyguard.shared.model.FailFingerprintAuthenticationStatus
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.model.sysUiState
 import com.android.systemui.power.data.repository.fakePowerRepository
+import com.android.systemui.power.data.repository.powerRepository
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
 import com.android.systemui.power.domain.interactor.powerInteractor
@@ -69,6 +83,7 @@
 import com.android.systemui.scene.shared.model.fakeSceneDataSource
 import com.android.systemui.shade.domain.interactor.shadeInteractor
 import com.android.systemui.shared.system.QuickStepContract
+import com.android.systemui.statusbar.VibratorHelper
 import com.android.systemui.statusbar.domain.interactor.keyguardOcclusionInteractor
 import com.android.systemui.statusbar.notification.data.repository.FakeHeadsUpRowRepository
 import com.android.systemui.statusbar.notification.data.repository.HeadsUpRowRepository
@@ -85,6 +100,7 @@
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.advanceTimeBy
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
@@ -92,6 +108,8 @@
 import org.junit.runner.RunWith
 import org.mockito.ArgumentMatchers.anyBoolean
 import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyString
+import org.mockito.Mockito
 import org.mockito.Mockito.clearInvocations
 import org.mockito.Mockito.never
 import org.mockito.Mockito.times
@@ -105,12 +123,14 @@
 
     private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
+    private val deviceEntryHapticsInteractor by lazy { kosmos.deviceEntryHapticsInteractor }
     private val sceneInteractor by lazy { kosmos.sceneInteractor }
     private val bouncerInteractor by lazy { kosmos.bouncerInteractor }
     private val faceAuthRepository by lazy { kosmos.fakeDeviceEntryFaceAuthRepository }
     private val bouncerRepository by lazy { kosmos.fakeKeyguardBouncerRepository }
     private val sysUiState = kosmos.sysUiState
     private val falsingCollector = mock<FalsingCollector>().also { kosmos.falsingCollector = it }
+    private val vibratorHelper = mock<VibratorHelper>().also { kosmos.vibratorHelper = it }
     private val fakeSceneDataSource = kosmos.fakeSceneDataSource
     private val windowController = kosmos.notificationShadeWindowController
     private val centralSurfaces = kosmos.centralSurfaces
@@ -634,6 +654,194 @@
         }
 
     @Test
+    fun playSuccessHaptics_onSuccessfulLockscreenAuth_udfps() =
+        testScope.runTest {
+            val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+            val playSuccessHaptic by
+                collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+
+            setupBiometricAuth(hasUdfps = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+            underTest.start()
+            unlockWithFingerprintAuth()
+
+            assertThat(playSuccessHaptic).isNotNull()
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            verify(vibratorHelper)
+                .vibrateAuthSuccess(
+                    "SceneContainerStartable, $currentSceneKey device-entry::success"
+                )
+            verify(vibratorHelper, never()).vibrateAuthError(anyString())
+
+            updateFingerprintAuthStatus(isSuccess = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Gone)
+        }
+
+    @Test
+    fun playSuccessHaptics_onSuccessfulLockscreenAuth_sfps() =
+        testScope.runTest {
+            val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+            val playSuccessHaptic by
+                collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+
+            setupBiometricAuth(hasSfps = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+            underTest.start()
+            allowHapticsOnSfps()
+            unlockWithFingerprintAuth()
+
+            assertThat(playSuccessHaptic).isNotNull()
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            verify(vibratorHelper)
+                .vibrateAuthSuccess(
+                    "SceneContainerStartable, $currentSceneKey device-entry::success"
+                )
+            verify(vibratorHelper, never()).vibrateAuthError(anyString())
+
+            updateFingerprintAuthStatus(isSuccess = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Gone)
+        }
+
+    @Test
+    fun playErrorHaptics_onFailedLockscreenAuth_udfps() =
+        testScope.runTest {
+            val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+            val playErrorHaptic by collectLastValue(deviceEntryHapticsInteractor.playErrorHaptic)
+
+            setupBiometricAuth(hasUdfps = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+            underTest.start()
+            updateFingerprintAuthStatus(isSuccess = false)
+
+            assertThat(playErrorHaptic).isNotNull()
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            verify(vibratorHelper)
+                .vibrateAuthError("SceneContainerStartable, $currentSceneKey device-entry::error")
+            verify(vibratorHelper, never()).vibrateAuthSuccess(anyString())
+        }
+
+    @Test
+    fun playErrorHaptics_onFailedLockscreenAuth_sfps() =
+        testScope.runTest {
+            val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+            val playErrorHaptic by collectLastValue(deviceEntryHapticsInteractor.playErrorHaptic)
+
+            setupBiometricAuth(hasSfps = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+            underTest.start()
+            updateFingerprintAuthStatus(isSuccess = false)
+
+            assertThat(playErrorHaptic).isNotNull()
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            verify(vibratorHelper)
+                .vibrateAuthError("SceneContainerStartable, $currentSceneKey device-entry::error")
+            verify(vibratorHelper, never()).vibrateAuthSuccess(anyString())
+        }
+
+    @Test
+    fun skipsSuccessHaptics_whenPowerButtonDown_sfps() =
+        testScope.runTest {
+            val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+            val playSuccessHaptic by
+                collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+
+            setupBiometricAuth(hasSfps = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+            underTest.start()
+            allowHapticsOnSfps(isPowerButtonDown = true)
+            unlockWithFingerprintAuth()
+
+            assertThat(playSuccessHaptic).isNull()
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            verify(vibratorHelper, never())
+                .vibrateAuthSuccess(
+                    "SceneContainerStartable, $currentSceneKey device-entry::success"
+                )
+            verify(vibratorHelper, never()).vibrateAuthError(anyString())
+
+            updateFingerprintAuthStatus(isSuccess = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Gone)
+        }
+
+    @Test
+    fun skipsSuccessHaptics_whenPowerButtonRecentlyPressed_sfps() =
+        testScope.runTest {
+            val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+            val playSuccessHaptic by
+                collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+
+            setupBiometricAuth(hasSfps = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+            underTest.start()
+            allowHapticsOnSfps(lastPowerPress = 50)
+            unlockWithFingerprintAuth()
+
+            assertThat(playSuccessHaptic).isNull()
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            verify(vibratorHelper, never())
+                .vibrateAuthSuccess(
+                    "SceneContainerStartable, $currentSceneKey device-entry::success"
+                )
+            verify(vibratorHelper, never()).vibrateAuthError(anyString())
+
+            updateFingerprintAuthStatus(isSuccess = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Gone)
+        }
+
+    @Test
+    fun skipsErrorHaptics_whenPowerButtonDown_sfps() =
+        testScope.runTest {
+            val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+            val playErrorHaptic by collectLastValue(deviceEntryHapticsInteractor.playErrorHaptic)
+
+            setupBiometricAuth(hasSfps = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+            underTest.start()
+            kosmos.fakeKeyEventRepository.setPowerButtonDown(true)
+            updateFingerprintAuthStatus(isSuccess = false)
+
+            assertThat(playErrorHaptic).isNull()
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            verify(vibratorHelper, never())
+                .vibrateAuthError("SceneContainerStartable, $currentSceneKey device-entry::error")
+            verify(vibratorHelper, never()).vibrateAuthSuccess(anyString())
+        }
+
+    @Test
+    fun skipsFaceErrorHaptics_nonSfps_coEx() =
+        testScope.runTest {
+            val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+            val playErrorHaptic by collectLastValue(deviceEntryHapticsInteractor.playErrorHaptic)
+
+            setupBiometricAuth(hasUdfps = true, hasFace = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+            underTest.start()
+            updateFaceAuthStatus(isSuccess = false)
+
+            assertThat(playErrorHaptic).isNull()
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            verify(vibratorHelper, never())
+                .vibrateAuthError("SceneContainerStartable, $currentSceneKey device-entry::error")
+            verify(vibratorHelper, never()).vibrateAuthSuccess(anyString())
+        }
+
+    @Test
     fun hydrateSystemUiState() =
         testScope.runTest {
             val transitionStateFlow = prepareState()
@@ -1192,41 +1400,6 @@
         }
 
     @Test
-    fun hydrateWindowController_setBouncerShowing() =
-        testScope.runTest {
-            underTest.start()
-            val notificationShadeWindowController = kosmos.notificationShadeWindowController
-            val transitionStateFlow = prepareState(initialSceneKey = Scenes.Lockscreen)
-            val currentScene by collectLastValue(sceneInteractor.currentScene)
-            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
-            verify(notificationShadeWindowController, never()).setBouncerShowing(true)
-            verify(notificationShadeWindowController, times(1)).setBouncerShowing(false)
-
-            emulateSceneTransition(transitionStateFlow, Scenes.Bouncer)
-            verify(notificationShadeWindowController, times(1)).setBouncerShowing(true)
-            verify(notificationShadeWindowController, times(1)).setBouncerShowing(false)
-
-            emulateSceneTransition(transitionStateFlow, Scenes.Lockscreen)
-            verify(notificationShadeWindowController, times(1)).setBouncerShowing(true)
-            verify(notificationShadeWindowController, times(2)).setBouncerShowing(false)
-
-            kosmos.deviceEntryFingerprintAuthRepository.setAuthenticationStatus(
-                SuccessFingerprintAuthenticationStatus(0, true)
-            )
-            assertThat(currentScene).isEqualTo(Scenes.Gone)
-            verify(notificationShadeWindowController, times(1)).setBouncerShowing(true)
-            verify(notificationShadeWindowController, times(2)).setBouncerShowing(false)
-
-            emulateSceneTransition(transitionStateFlow, Scenes.Lockscreen)
-            verify(notificationShadeWindowController, times(1)).setBouncerShowing(true)
-            verify(notificationShadeWindowController, times(2)).setBouncerShowing(false)
-
-            emulateSceneTransition(transitionStateFlow, Scenes.Bouncer)
-            verify(notificationShadeWindowController, times(2)).setBouncerShowing(true)
-            verify(notificationShadeWindowController, times(2)).setBouncerShowing(false)
-        }
-
-    @Test
     fun hydrateWindowController_setKeyguardOccluded() =
         testScope.runTest {
             underTest.start()
@@ -1876,4 +2049,92 @@
         FakeHeadsUpRowRepository(key = key, elementKey = Any()).apply {
             this.isPinned.value = isPinned
         }
+
+    private fun setFingerprintSensorType(fingerprintSensorType: FingerprintSensorType) {
+        kosmos.fingerprintPropertyRepository.setProperties(
+            sensorId = 0,
+            strength = SensorStrength.STRONG,
+            sensorType = fingerprintSensorType,
+            sensorLocations = mapOf(),
+        )
+        kosmos.biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
+    }
+
+    private fun setFaceEnrolled() {
+        kosmos.biometricSettingsRepository.setIsFaceAuthEnrolledAndEnabled(true)
+    }
+
+    private fun TestScope.allowHapticsOnSfps(
+        isPowerButtonDown: Boolean = false,
+        lastPowerPress: Long = 10000
+    ) {
+        kosmos.fakeKeyEventRepository.setPowerButtonDown(isPowerButtonDown)
+
+        kosmos.powerRepository.updateWakefulness(
+            WakefulnessState.AWAKE,
+            WakeSleepReason.POWER_BUTTON,
+            WakeSleepReason.POWER_BUTTON,
+            powerButtonLaunchGestureTriggered = false,
+        )
+
+        advanceTimeBy(lastPowerPress)
+        runCurrent()
+    }
+
+    private fun unlockWithFingerprintAuth() {
+        kosmos.fakeKeyguardRepository.setBiometricUnlockSource(
+            BiometricUnlockSource.FINGERPRINT_SENSOR
+        )
+        kosmos.fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockMode.UNLOCK_COLLAPSING)
+    }
+
+    private fun TestScope.setupBiometricAuth(
+        hasSfps: Boolean = false,
+        hasUdfps: Boolean = false,
+        hasFace: Boolean = false
+    ) {
+        if (hasSfps) {
+            setFingerprintSensorType(FingerprintSensorType.POWER_BUTTON)
+        }
+
+        if (hasUdfps) {
+            setFingerprintSensorType(FingerprintSensorType.UDFPS_ULTRASONIC)
+        }
+
+        if (hasFace) {
+            setFaceEnrolled()
+        }
+
+        prepareState(
+            authenticationMethod = AuthenticationMethodModel.Pin,
+            isDeviceUnlocked = false,
+            initialSceneKey = Scenes.Lockscreen,
+        )
+    }
+
+    private fun updateFingerprintAuthStatus(isSuccess: Boolean) {
+        if (isSuccess) {
+            kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+                SuccessFingerprintAuthenticationStatus(0, true)
+            )
+        } else {
+            kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+                FailFingerprintAuthenticationStatus
+            )
+        }
+    }
+
+    private fun updateFaceAuthStatus(isSuccess: Boolean) {
+        if (isSuccess) {
+            kosmos.fakeDeviceEntryFaceAuthRepository.setAuthenticationStatus(
+                SuccessFaceAuthenticationStatus(
+                    successResult = Mockito.mock(FaceManager.AuthenticationResult::class.java)
+                )
+            )
+        } else {
+            kosmos.fakeDeviceEntryFaceAuthRepository.setAuthenticationStatus(
+                FailedFaceAuthenticationStatus()
+            )
+        }
+    }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneSceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt
similarity index 83%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneSceneActionsViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt
index b526275..03106ec 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneSceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt
@@ -43,17 +43,17 @@
 @RunWith(AndroidJUnit4::class)
 @TestableLooper.RunWithLooper
 @EnableSceneContainer
-class GoneSceneActionsViewModelTest : SysuiTestCase() {
+class GoneUserActionsViewModelTest : SysuiTestCase() {
 
     private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
     private val shadeRepository by lazy { kosmos.shadeRepository }
-    private lateinit var underTest: GoneSceneActionsViewModel
+    private lateinit var underTest: GoneUserActionsViewModel
 
     @Before
     fun setUp() {
         underTest =
-            GoneSceneActionsViewModel(
+            GoneUserActionsViewModel(
                 shadeInteractor = kosmos.shadeInteractor,
             )
         underTest.activateIn(testScope)
@@ -62,21 +62,21 @@
     @Test
     fun downTransitionKey_splitShadeEnabled_isGoneToSplitShade() =
         testScope.runTest {
-            val destinationScenes by collectLastValue(underTest.actions)
+            val userActions by collectLastValue(underTest.actions)
             shadeRepository.setShadeLayoutWide(true)
             runCurrent()
 
-            assertThat(destinationScenes?.get(Swipe(SwipeDirection.Down))?.transitionKey)
+            assertThat(userActions?.get(Swipe(SwipeDirection.Down))?.transitionKey)
                 .isEqualTo(ToSplitShade)
         }
 
     @Test
     fun downTransitionKey_splitShadeDisabled_isNull() =
         testScope.runTest {
-            val destinationScenes by collectLastValue(underTest.actions)
+            val userActions by collectLastValue(underTest.actions)
             shadeRepository.setShadeLayoutWide(false)
             runCurrent()
 
-            assertThat(destinationScenes?.get(Swipe(SwipeDirection.Down))?.transitionKey).isNull()
+            assertThat(userActions?.get(Swipe(SwipeDirection.Down))?.transitionKey).isNull()
         }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/UserActionsViewModelTest.kt
similarity index 95%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneActionsViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/UserActionsViewModelTest.kt
index 900f2a4..972afb5 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/UserActionsViewModelTest.kt
@@ -42,12 +42,12 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
-class SceneActionsViewModelTest : SysuiTestCase() {
+class UserActionsViewModelTest : SysuiTestCase() {
 
     private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
 
-    private val underTest = FakeSceneActionsViewModel()
+    private val underTest = FakeUserActionsViewModel()
 
     @Test
     fun actions_emptyBeforeActivation() =
@@ -115,7 +115,7 @@
             assertThat(actions).isEmpty()
         }
 
-    private class FakeSceneActionsViewModel : SceneActionsViewModel() {
+    private class FakeUserActionsViewModel : UserActionsViewModel() {
 
         val upstream = MutableStateFlow<Map<UserAction, UserActionResult>>(emptyMap())
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModelTest.kt
index 8b97739..f5022b9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModelTest.kt
@@ -16,18 +16,28 @@
 
 package com.android.systemui.shade.ui.viewmodel
 
+import android.platform.test.annotations.EnableFlags
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
+import com.android.compose.animation.scene.ObservableTransitionState
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
+import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.shared.model.TransitionStep
 import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -150,4 +160,90 @@
             )
             assertThat(isKeyguardOccluded).isTrue()
         }
+
+    @Test
+    @EnableSceneContainer
+    fun withSceneContainer_bouncerShowing_providesTheCorrectState() =
+        testScope.runTest {
+            val bouncerShowing by collectLastValue(underTest.isBouncerShowing)
+
+            val transitionState =
+                MutableStateFlow<ObservableTransitionState>(
+                    ObservableTransitionState.Idle(Scenes.Lockscreen)
+                )
+            kosmos.sceneInteractor.setTransitionState(transitionState)
+            runCurrent()
+            assertThat(bouncerShowing).isFalse()
+
+            transitionState.value = ObservableTransitionState.Idle(Scenes.Bouncer)
+            runCurrent()
+            assertThat(bouncerShowing).isTrue()
+        }
+
+    @Test
+    @EnableFlags(com.android.systemui.Flags.FLAG_COMPOSE_BOUNCER)
+    fun withComposeBouncer_bouncerShowing_providesTheCorrectState() =
+        testScope.runTest {
+            val bouncerShowing by collectLastValue(underTest.isBouncerShowing)
+
+            kosmos.fakeKeyguardBouncerRepository.setPrimaryShow(isShowing = false)
+            runCurrent()
+            assertThat(bouncerShowing).isFalse()
+
+            kosmos.fakeKeyguardBouncerRepository.setPrimaryShow(isShowing = true)
+            runCurrent()
+            assertThat(bouncerShowing).isTrue()
+        }
+
+    @Test
+    @EnableSceneContainer
+    fun withSceneContainer_doesBouncerRequireIme_providesTheCorrectState() =
+        testScope.runTest {
+            val bouncerRequiresIme by collectLastValue(underTest.doesBouncerRequireIme)
+            kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+                AuthenticationMethodModel.Pin
+            )
+
+            val transitionState =
+                MutableStateFlow<ObservableTransitionState>(
+                    ObservableTransitionState.Idle(Scenes.Bouncer)
+                )
+            kosmos.sceneInteractor.setTransitionState(transitionState)
+            runCurrent()
+            assertThat(bouncerRequiresIme).isFalse()
+
+            // go back to lockscreen
+            transitionState.value = ObservableTransitionState.Idle(Scenes.Lockscreen)
+            runCurrent()
+
+            // change auth method
+            kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+                AuthenticationMethodModel.Password
+            )
+            // go back to bouncer
+            transitionState.value = ObservableTransitionState.Idle(Scenes.Bouncer)
+            runCurrent()
+            assertThat(bouncerRequiresIme).isTrue()
+        }
+
+    @Test
+    @EnableFlags(com.android.systemui.Flags.FLAG_COMPOSE_BOUNCER)
+    fun withComposeBouncer_doesBouncerRequireIme_providesTheCorrectState() =
+        testScope.runTest {
+            val bouncerRequiresIme by collectLastValue(underTest.doesBouncerRequireIme)
+            kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+                AuthenticationMethodModel.Pin
+            )
+
+            kosmos.fakeKeyguardBouncerRepository.setPrimaryShow(isShowing = true)
+            runCurrent()
+            assertThat(bouncerRequiresIme).isFalse()
+
+            kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+                AuthenticationMethodModel.Password
+            )
+            kosmos.fakeKeyguardBouncerRepository.setPrimaryShow(isShowing = true)
+            runCurrent()
+            assertThat(bouncerRequiresIme).isFalse()
+        }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelTest.kt
similarity index 98%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelTest.kt
index a931e65..9f3e126e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelTest.kt
@@ -64,7 +64,7 @@
 @TestableLooper.RunWithLooper
 @EnableSceneContainer
 @DisableFlags(DualShade.FLAG_NAME)
-class ShadeSceneActionsViewModelTest : SysuiTestCase() {
+class ShadeUserActionsViewModelTest : SysuiTestCase() {
 
     private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
@@ -72,7 +72,7 @@
     private val shadeRepository by lazy { kosmos.shadeRepository }
     private val qsSceneAdapter by lazy { kosmos.fakeQSSceneAdapter }
 
-    private val underTest: ShadeSceneActionsViewModel by lazy { kosmos.shadeSceneActionsViewModel }
+    private val underTest: ShadeUserActionsViewModel by lazy { kosmos.shadeUserActionsViewModel }
 
     @Before
     fun setUp() {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
index 75ecb2c..beba162 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
@@ -133,7 +133,8 @@
                 mVisibilityLocationProvider,
                 mVisualStabilityProvider,
                 mWakefulnessLifecycle,
-                mKosmos.getCommunalInteractor(),
+                mKosmos.getCommunalSceneInteractor(),
+                mKosmos.getShadeInteractor(),
                 mKosmos.getKeyguardTransitionInteractor(),
                 mLogger);
         mCoordinator.attach(mNotifPipeline);
@@ -561,11 +562,12 @@
 
     @Test
     public void testCommunalShowingWillNotSuppressReordering() {
-        // GIVEN panel is expanded and communal is showing
+        // GIVEN panel is expanded, communal is showing, and QS is collapsed
         setPulsing(false);
         setFullyDozed(false);
         setSleepy(false);
         setPanelExpanded(true);
+        setQsExpanded(false);
         setCommunalShowing(true);
 
         // Reordering should be allowed
@@ -573,6 +575,20 @@
     }
 
     @Test
+    public void testQsExpandedOverCommunalWillSuppressReordering() {
+        // GIVEN panel is expanded and communal is showing, but QS is expanded
+        setPulsing(false);
+        setFullyDozed(false);
+        setSleepy(false);
+        setPanelExpanded(true);
+        setQsExpanded(true);
+        setCommunalShowing(true);
+
+        // Reordering should not be allowed
+        assertFalse(mNotifStabilityManager.isEntryReorderingAllowed(mEntry));
+    }
+
+    @Test
     public void testQueryingEntryReorderingButNotReportingReorderSuppressedDoesNotInvalidate() {
         // GIVEN visual stability is being maintained b/c panel is expanded
         setPulsing(false);
@@ -631,7 +647,12 @@
                         new ObservableTransitionState.Idle(
                                 isShowing ? CommunalScenes.Communal : CommunalScenes.Blank)
                 );
-        mKosmos.getCommunalRepository().setTransitionState(showingFlow);
+        mKosmos.getCommunalSceneInteractor().setTransitionState(showingFlow);
+        mTestScope.getTestScheduler().runCurrent();
+    }
+
+    private void setQsExpanded(boolean isExpanded) {
+        mKosmos.getShadeRepository().setQsExpansion(isExpanded ? 1.0f : 0.0f);
         mTestScope.getTestScheduler().runCurrent();
     }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
index 1237347..dc24cf7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
@@ -25,14 +25,14 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.common.shared.model.ContentDescription.Companion.loadContentDescription
 import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logcatTableLogBuffer
 import com.android.systemui.statusbar.connectivity.WifiIcons
 import com.android.systemui.statusbar.phone.StatusBarLocation
 import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
 import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
 import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
 import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModelImpl
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
 import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
@@ -44,6 +44,7 @@
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
 import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon
 import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel.Companion.viewModelForLocation
+import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.test.TestScope
@@ -58,10 +59,11 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class WifiViewModelTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
 
     private lateinit var underTest: WifiViewModel
 
-    @Mock private lateinit var tableLogBuffer: TableLogBuffer
+    private val tableLogBuffer = logcatTableLogBuffer(kosmos, "WifiViewModelTest")
     @Mock private lateinit var connectivityConstants: ConnectivityConstants
     @Mock private lateinit var wifiConstants: WifiConstants
     private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
@@ -86,7 +88,7 @@
                 AirplaneModeInteractor(
                     airplaneModeRepository,
                     connectivityRepository,
-                    FakeMobileConnectionsRepository(),
+                    kosmos.fakeMobileConnectionsRepository,
                 ),
                 tableLogBuffer,
                 testScope.backgroundScope,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt
index 639d34d..fb32855 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt
@@ -257,6 +257,36 @@
         }
 
     @Test
+    fun getActiveModes_computesMainActiveMode() = runTest {
+        zenModeRepository.addMode(id = "Bedtime", type = AutomaticZenRule.TYPE_BEDTIME)
+        zenModeRepository.addMode(id = "Other", type = AutomaticZenRule.TYPE_OTHER)
+
+        var activeModes = underTest.getActiveModes()
+        assertThat(activeModes.modeNames).hasSize(0)
+        assertThat(activeModes.mainMode).isNull()
+
+        zenModeRepository.activateMode("Other")
+        activeModes = underTest.getActiveModes()
+        assertThat(activeModes.modeNames).containsExactly("Mode Other")
+        assertThat(activeModes.mainMode?.name).isEqualTo("Mode Other")
+
+        zenModeRepository.activateMode("Bedtime")
+        activeModes = underTest.getActiveModes()
+        assertThat(activeModes.modeNames).containsExactly("Mode Bedtime", "Mode Other").inOrder()
+        assertThat(activeModes.mainMode?.name).isEqualTo("Mode Bedtime")
+
+        zenModeRepository.deactivateMode("Other")
+        activeModes = underTest.getActiveModes()
+        assertThat(activeModes.modeNames).containsExactly("Mode Bedtime")
+        assertThat(activeModes.mainMode?.name).isEqualTo("Mode Bedtime")
+
+        zenModeRepository.deactivateMode("Bedtime")
+        activeModes = underTest.getActiveModes()
+        assertThat(activeModes.modeNames).hasSize(0)
+        assertThat(activeModes.mainMode).isNull()
+    }
+
+    @Test
     fun mainActiveMode_flows() =
         testScope.runTest {
             val mainActiveMode by collectLastValue(underTest.mainActiveMode)
diff --git a/packages/SystemUI/res/color/brightness_slider_track.xml b/packages/SystemUI/res/color/brightness_slider_track.xml
deleted file mode 100644
index 6028769..0000000
--- a/packages/SystemUI/res/color/brightness_slider_track.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-  ~ Copyright (C) 2024 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.
-  -->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@android:color/system_neutral2_500" android:lStar="40" />
-</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/brightness_bar.xml b/packages/SystemUI/res/drawable/brightness_bar.xml
index 2afe164..3d1c1fb 100644
--- a/packages/SystemUI/res/drawable/brightness_bar.xml
+++ b/packages/SystemUI/res/drawable/brightness_bar.xml
@@ -21,7 +21,7 @@
         android:viewportHeight="48">
 <path
     android:pathData="M2,22L302,22A2,2 0,0 1,304 24L304,24A2,2 0,0 1,302 26L2,26A2,2 0,0 1,0 24L0,24A2,2 0,0 1,2 22z"
-    android:fillColor="@color/brightness_slider_track"/>
+    android:fillColor="?androidprv:attr/customColorShadeInactive"/>
 <path
     android:pathData="M24,0L205.71,0A24,24 0,0 1,229.71 24L229.71,24A24,24 0,0 1,205.71 48L24,48A24,24 0,0 1,0 24L0,24A24,24 0,0 1,24 0z"
     android:fillColor="?attr/shadeActive"/>
diff --git a/packages/SystemUI/res/drawable/brightness_progress_drawable.xml b/packages/SystemUI/res/drawable/brightness_progress_drawable.xml
index cae9d6b..ec15b10 100644
--- a/packages/SystemUI/res/drawable/brightness_progress_drawable.xml
+++ b/packages/SystemUI/res/drawable/brightness_progress_drawable.xml
@@ -15,6 +15,7 @@
   ~ limitations under the License.
   -->
 <layer-list xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
             android:paddingMode="stack" >
     <item android:id="@android:id/background"
         android:gravity="center_vertical|fill_horizontal">
@@ -24,7 +25,7 @@
             <shape>
                 <size android:height="@dimen/rounded_slider_track_width" />
                 <corners android:radius="@dimen/rounded_slider_track_corner_radius" />
-                <solid android:color="@color/brightness_slider_track" />
+                <solid android:color="?androidprv:attr/customColorShadeInactive" />
             </shape>
         </inset>
     </item>
diff --git a/packages/SystemUI/res/layout/alert_dialog_button_bar_systemui.xml b/packages/SystemUI/res/layout/alert_dialog_button_bar_systemui.xml
index e06bfdc..368fe82 100644
--- a/packages/SystemUI/res/layout/alert_dialog_button_bar_systemui.xml
+++ b/packages/SystemUI/res/layout/alert_dialog_button_bar_systemui.xml
@@ -52,7 +52,7 @@
         <Button
             android:id="@android:id/button1"
             style="?android:attr/buttonBarPositiveButtonStyle"
-            android:layout_marginStart="8dp"
+            android:layout_marginStart="@dimen/dialog_button_side_margin"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content" />
     </com.android.internal.widget.ButtonBarLayout>
diff --git a/packages/SystemUI/res/layout/screen_share_dialog.xml b/packages/SystemUI/res/layout/screen_share_dialog.xml
index aa083ad..0533c7e 100644
--- a/packages/SystemUI/res/layout/screen_share_dialog.xml
+++ b/packages/SystemUI/res/layout/screen_share_dialog.xml
@@ -64,30 +64,27 @@
             android:layout_height="wrap_content"
             android:text="@string/screenrecord_permission_dialog_warning_entire_screen"
             style="@style/TextAppearance.Dialog.Body.Message"
-            android:gravity="start"/>
+            android:gravity="start"
+            android:textAlignment="gravity"/>
 
         <!-- Buttons -->
         <com.android.internal.widget.ButtonBarLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
-            android:layout_marginTop="@dimen/screenrecord_buttons_margin_top">
+            android:layout_marginTop="@dimen/screenrecord_buttons_margin_top"
+            android:gravity="end">
             <Button
                 android:id="@android:id/button2"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_weight="0"
                 android:text="@string/cancel"
                 style="@style/Widget.Dialog.Button.BorderButton" />
-            <Space
-                android:layout_width="0dp"
-                android:layout_height="match_parent"
-                android:layout_weight="1"/>
             <Button
                 android:id="@android:id/button1"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_weight="0"
+                android:layout_marginStart="@dimen/dialog_button_side_margin"
                 android:text="@string/screenrecord_continue"
                 style="@style/Widget.Dialog.Button" />
         </com.android.internal.widget.ButtonBarLayout>
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index 21f1cfb..c1eff5f 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -16,7 +16,11 @@
 
   NOTE: You might also want to edit: core/res/res/values-night/*.xml
   -->
-<resources>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+    <!-- The dark background color behind the shade -->
+    <color name="shade_scrim_background_dark">@androidprv:color/system_under_surface_dark</color>
+
     <!-- The color of the legacy notifications with customs backgrounds (gingerbread and lollipop.)
     It's fine to override this color since at that point the shade was dark. -->
     <color name="notification_legacy_background_color">@color/GM2_grey_900</color>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 8cf0fb2..a375264 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -29,7 +29,7 @@
     <color name="status_bar_icons_hover_color_dark">#38000000</color> <!-- 22% black -->
 
     <!-- The dark background color behind the shade -->
-    <color name="shade_scrim_background_dark">@*android:color/black</color>
+    <color name="shade_scrim_background_dark">@androidprv:color/system_under_surface_light</color>
 
     <!-- The color of the background in the separated list of the Global Actions menu -->
     <color name="global_actions_separated_background">#F5F5F5</color>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index e5750d2..141d035 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1751,6 +1751,7 @@
 
     <!-- System UI Dialog -->
     <dimen name="dialog_title_text_size">24sp</dimen>
+    <dimen name="dialog_button_side_margin">8dp</dimen>
 
     <!-- Internet panel related dimensions -->
     <dimen name="internet_dialog_list_max_height">662dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d3d757b..be74291 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -3699,6 +3699,22 @@
           -->
     <string name="shortcut_helper_key_combinations_or_separator">or</string>
 
+    <!-- Keyboard touchpad tutorial scheduler-->
+    <!-- Notification title for launching keyboard tutorial [CHAR_LIMIT=100] -->
+    <string name="launch_keyboard_tutorial_notification_title">Navigate using your keyboard</string>
+    <!-- Notification text for launching keyboard tutorial [CHAR_LIMIT=100] -->
+    <string name="launch_keyboard_tutorial_notification_content">Learn keyboards shortcuts</string>
+
+    <!-- Notification title for launching touchpad tutorial [CHAR_LIMIT=100] -->
+    <string name="launch_touchpad_tutorial_notification_title">Navigate using your touchpad</string>
+    <!-- Notification text for launching keyboard tutorial [CHAR_LIMIT=100] -->
+    <string name="launch_touchpad_tutorial_notification_content">Learn touchpad gestures</string>
+
+    <!-- Notification title for launching keyboard tutorial [CHAR_LIMIT=100] -->
+    <string name="launch_keyboard_touchpad_tutorial_notification_title">Navigate using your keyboard and touchpad</string>
+    <!-- Notification text for launching keyboard tutorial [CHAR_LIMIT=100] -->
+    <string name="launch_keyboard_touchpad_tutorial_notification_content">Learn touchpad gestures, keyboards shortcuts, and more</string>
+
     <!-- TOUCHPAD TUTORIAL-->
     <!-- Label for button opening tutorial for back gesture on touchpad [CHAR LIMIT=NONE] -->
     <string name="touchpad_tutorial_back_gesture_button">Back gesture</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 3ef6243..a02c354 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -505,14 +505,14 @@
         <item name="onSurfaceVariant">?androidprv:attr/materialColorOnSurfaceVariant</item>
         <item name="outline">?androidprv:attr/materialColorOutline</item>
 
-        <item name="shadeActive">@color/material_dynamic_primary90</item>
-        <item name="onShadeActive">@color/material_dynamic_primary10</item>
-        <item name="onShadeActiveVariant">@color/material_dynamic_primary30</item>
-        <item name="shadeInactive">@color/material_dynamic_neutral20</item>
-        <item name="onShadeInactive">@color/material_dynamic_neutral90</item>
-        <item name="onShadeInactiveVariant">@color/material_dynamic_neutral_variant80</item>
-        <item name="shadeDisabled">@color/shade_disabled</item>
-        <item name="underSurface">@color/material_dynamic_neutral0</item>
+        <item name="shadeActive">?androidprv:attr/customColorShadeActive</item>
+        <item name="onShadeActive">?androidprv:attr/customColorOnShadeActive</item>
+        <item name="onShadeActiveVariant">?androidprv:attr/customColorOnShadeActiveVariant</item>
+        <item name="shadeInactive">?androidprv:attr/customColorShadeInactive</item>
+        <item name="onShadeInactive">?androidprv:attr/customColorOnShadeInactive</item>
+        <item name="onShadeInactiveVariant">?androidprv:attr/customColorOnShadeInactiveVariant</item>
+        <item name="shadeDisabled">?androidprv:attr/customColorShadeDisabled</item>
+        <item name="underSurface">?androidprv:attr/customColorUnderSurface</item>
         <item name="android:itemTextAppearance">@style/Control.MenuItem</item>
     </style>
 
diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java
index 7733841..5e36539 100644
--- a/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java
+++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java
@@ -17,6 +17,7 @@
 package com.android.keyguard;
 
 import static com.android.systemui.DejankUtils.whitelistIpcs;
+import static com.android.systemui.Flags.msdlFeedback;
 
 import android.annotation.SuppressLint;
 import android.app.ActivityOptions;
@@ -46,6 +47,9 @@
 import com.android.systemui.util.EmergencyDialerConstants;
 import com.android.systemui.util.ViewController;
 
+import com.google.android.msdl.data.model.MSDLToken;
+import com.google.android.msdl.domain.MSDLPlayer;
+
 import java.util.concurrent.Executor;
 
 import javax.inject.Inject;
@@ -67,6 +71,7 @@
     private final Executor mMainExecutor;
     private final Executor mBackgroundExecutor;
     private final SelectedUserInteractor mSelectedUserInteractor;
+    private final MSDLPlayer mMSDLPlayer;
 
     private final KeyguardUpdateMonitorCallback mInfoCallback =
             new KeyguardUpdateMonitorCallback() {
@@ -99,7 +104,8 @@
             MetricsLogger metricsLogger,
             LockPatternUtils lockPatternUtils,
             Executor mainExecutor, Executor backgroundExecutor,
-            SelectedUserInteractor selectedUserInteractor) {
+            SelectedUserInteractor selectedUserInteractor,
+            MSDLPlayer msdlPlayer) {
         super(view);
         mConfigurationController = configurationController;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
@@ -112,6 +118,7 @@
         mMainExecutor = mainExecutor;
         mBackgroundExecutor = backgroundExecutor;
         mSelectedUserInteractor = selectedUserInteractor;
+        mMSDLPlayer = msdlPlayer;
     }
 
     @Override
@@ -165,6 +172,9 @@
     @SuppressLint("MissingPermission")
     public void takeEmergencyCallAction() {
         mMetricsLogger.action(MetricsEvent.ACTION_EMERGENCY_CALL);
+        if (msdlFeedback()) {
+            mMSDLPlayer.playToken(MSDLToken.KEYPRESS_RETURN, null);
+        }
         if (mPowerManager != null) {
             mPowerManager.userActivity(SystemClock.uptimeMillis(), true);
         }
@@ -221,6 +231,7 @@
         private final Executor mMainExecutor;
         private final Executor mBackgroundExecutor;
         private final SelectedUserInteractor mSelectedUserInteractor;
+        private final MSDLPlayer mMSDLPlayer;
 
         @Inject
         public Factory(ConfigurationController configurationController,
@@ -233,7 +244,8 @@
                 LockPatternUtils lockPatternUtils,
                 @Main Executor mainExecutor,
                 @Background Executor backgroundExecutor,
-                SelectedUserInteractor selectedUserInteractor) {
+                SelectedUserInteractor selectedUserInteractor,
+                MSDLPlayer msdlPlayer) {
 
             mConfigurationController = configurationController;
             mKeyguardUpdateMonitor = keyguardUpdateMonitor;
@@ -246,6 +258,7 @@
             mMainExecutor = mainExecutor;
             mBackgroundExecutor = backgroundExecutor;
             mSelectedUserInteractor = selectedUserInteractor;
+            mMSDLPlayer = msdlPlayer;
         }
 
         /** Construct an {@link com.android.keyguard.EmergencyButtonController}. */
@@ -253,7 +266,7 @@
             return new EmergencyButtonController(view, mConfigurationController,
                     mKeyguardUpdateMonitor, mPowerManager, mActivityTaskManager, mShadeController,
                     mTelecomManager, mMetricsLogger, mLockPatternUtils, mMainExecutor,
-                    mBackgroundExecutor, mSelectedUserInteractor);
+                    mBackgroundExecutor, mSelectedUserInteractor, mMSDLPlayer);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt
index cc8dce79..49dadce 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt
@@ -2,13 +2,11 @@
 
 import android.view.ViewGroup
 import com.android.keyguard.KeyguardMessageAreaController
-import com.android.keyguard.ViewMediatorCallback
 import com.android.keyguard.dagger.KeyguardBouncerComponent
-import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
 import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor
-import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
 import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlags
 import com.android.systemui.bouncer.ui.BouncerDialogFactory
+import com.android.systemui.bouncer.ui.viewmodel.BouncerContainerViewModel
 import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel
 import com.android.systemui.bouncer.ui.viewmodel.KeyguardBouncerViewModel
 import com.android.systemui.dagger.SysUISingleton
@@ -39,12 +37,9 @@
 data class ComposeBouncerDependencies
 @Inject
 constructor(
-    val legacyInteractor: PrimaryBouncerInteractor,
     val viewModelFactory: BouncerSceneContentViewModel.Factory,
     val dialogFactory: BouncerDialogFactory,
-    val authenticationInteractor: AuthenticationInteractor,
-    val viewMediatorCallback: ViewMediatorCallback?,
-    val selectedUserInteractor: SelectedUserInteractor,
+    val bouncerContainerViewModelFactory: BouncerContainerViewModel.Factory,
 )
 
 /**
@@ -63,12 +58,9 @@
             val deps = composeBouncerDependencies.get()
             ComposeBouncerViewBinder.bind(
                 view,
-                deps.legacyInteractor,
                 deps.viewModelFactory,
                 deps.dialogFactory,
-                deps.authenticationInteractor,
-                deps.selectedUserInteractor,
-                deps.viewMediatorCallback,
+                deps.bouncerContainerViewModelFactory,
             )
         } else {
             val deps = legacyBouncerDependencies.get()
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt
index c4bbd9c..b5e54d5 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt
@@ -5,89 +5,55 @@
 import androidx.activity.OnBackPressedDispatcherOwner
 import androidx.activity.setViewTreeOnBackPressedDispatcherOwner
 import androidx.compose.ui.platform.ComposeView
-import androidx.core.view.isVisible
+import androidx.core.view.isGone
 import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.repeatOnLifecycle
-import com.android.keyguard.ViewMediatorCallback
-import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
-import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
 import com.android.systemui.bouncer.ui.BouncerDialogFactory
 import com.android.systemui.bouncer.ui.composable.BouncerContainer
+import com.android.systemui.bouncer.ui.viewmodel.BouncerContainerViewModel
 import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel
+import com.android.systemui.lifecycle.WindowLifecycleState
 import com.android.systemui.lifecycle.repeatWhenAttached
-import com.android.systemui.user.domain.interactor.SelectedUserInteractor
-import kotlinx.coroutines.flow.collectLatest
-import kotlinx.coroutines.launch
+import com.android.systemui.lifecycle.setSnapshotBinding
+import com.android.systemui.lifecycle.viewModel
+import kotlinx.coroutines.awaitCancellation
 
 /** View binder responsible for binding the compose version of the bouncer. */
 object ComposeBouncerViewBinder {
     fun bind(
         view: ViewGroup,
-        legacyInteractor: PrimaryBouncerInteractor,
         viewModelFactory: BouncerSceneContentViewModel.Factory,
         dialogFactory: BouncerDialogFactory,
-        authenticationInteractor: AuthenticationInteractor,
-        selectedUserInteractor: SelectedUserInteractor,
-        viewMediatorCallback: ViewMediatorCallback?,
+        bouncerContainerViewModelFactory: BouncerContainerViewModel.Factory,
     ) {
-        view.addView(
-            ComposeView(view.context).apply {
-                repeatWhenAttached {
-                    repeatOnLifecycle(Lifecycle.State.CREATED) {
-                        setViewTreeOnBackPressedDispatcherOwner(
-                            object : OnBackPressedDispatcherOwner {
-                                override val onBackPressedDispatcher =
-                                    OnBackPressedDispatcher().apply {
-                                        setOnBackInvokedDispatcher(
-                                            view.viewRootImpl.onBackInvokedDispatcher
-                                        )
-                                    }
-
-                                override val lifecycle: Lifecycle =
-                                    this@repeatWhenAttached.lifecycle
-                            }
-                        )
-                        setContent { BouncerContainer(viewModelFactory, dialogFactory) }
-                    }
-                }
-            }
-        )
-
         view.repeatWhenAttached {
-            repeatOnLifecycle(Lifecycle.State.CREATED) {
-                launch {
-                    legacyInteractor.isShowing.collectLatest { bouncerShowing ->
-                        view.isVisible = bouncerShowing
-                    }
-                }
-
-                launch {
-                    authenticationInteractor.onAuthenticationResult.collectLatest {
-                        authenticationSucceeded ->
-                        if (authenticationSucceeded) {
-                            // Some dismiss actions require that keyguard be dismissed right away or
-                            // deferred until something else later on dismisses keyguard (eg. end of
-                            // a hide animation).
-                            val deferKeyguardDone =
-                                legacyInteractor.bouncerDismissAction?.onDismissAction?.onDismiss()
-                            legacyInteractor.setDismissAction(null, null)
-
-                            viewMediatorCallback?.let {
-                                val selectedUserId = selectedUserInteractor.getSelectedUserId()
-                                if (deferKeyguardDone == true) {
-                                    it.keyguardDonePending(selectedUserId)
-                                } else {
-                                    it.keyguardDone(selectedUserId)
+            view.viewModel(
+                minWindowLifecycleState = WindowLifecycleState.ATTACHED,
+                factory = { bouncerContainerViewModelFactory.create() },
+                traceName = "ComposeBouncerViewBinder",
+            ) { viewModel ->
+                try {
+                    view.setViewTreeOnBackPressedDispatcherOwner(
+                        object : OnBackPressedDispatcherOwner {
+                            override val onBackPressedDispatcher =
+                                OnBackPressedDispatcher().apply {
+                                    setOnBackInvokedDispatcher(
+                                        view.viewRootImpl.onBackInvokedDispatcher
+                                    )
                                 }
-                            }
+
+                            override val lifecycle: Lifecycle = this@repeatWhenAttached.lifecycle
                         }
-                    }
-                }
-                launch {
-                    legacyInteractor.startingDisappearAnimation.collectLatest {
-                        it.run()
-                        legacyInteractor.hide()
-                    }
+                    )
+
+                    view.addView(
+                        ComposeView(view.context).apply {
+                            setContent { BouncerContainer(viewModelFactory, dialogFactory) }
+                        }
+                    )
+                    view.setSnapshotBinding { view.isGone = !viewModel.isVisible }
+                    awaitCancellation()
+                } finally {
+                    view.removeAllViews()
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerContainerViewModel.kt
new file mode 100644
index 0000000..d223657
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerContainerViewModel.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2024 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.bouncer.ui.viewmodel
+
+import androidx.compose.runtime.getValue
+import com.android.keyguard.ViewMediatorCallback
+import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.lifecycle.ExclusiveActivatable
+import com.android.systemui.lifecycle.Hydrator
+import com.android.systemui.user.domain.interactor.SelectedUserInteractor
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.launch
+
+class BouncerContainerViewModel
+@AssistedInject
+constructor(
+    private val legacyInteractor: PrimaryBouncerInteractor,
+    private val authenticationInteractor: AuthenticationInteractor,
+    private val selectedUserInteractor: SelectedUserInteractor,
+    private val viewMediatorCallback: ViewMediatorCallback?,
+) : ExclusiveActivatable() {
+
+    private val hydrator = Hydrator("BouncerContainerViewModel")
+
+    val isVisible: Boolean by
+        hydrator.hydratedStateOf(traceName = "isVisible", source = legacyInteractor.isShowing)
+
+    override suspend fun onActivated(): Nothing {
+        coroutineScope {
+            launch {
+                authenticationInteractor.onAuthenticationResult.collect { authenticationSucceeded ->
+                    if (authenticationSucceeded) {
+                        // Some dismiss actions require that keyguard be dismissed right away or
+                        // deferred until something else later on dismisses keyguard (eg. end of
+                        // a hide animation).
+                        val deferKeyguardDone =
+                            legacyInteractor.bouncerDismissAction?.onDismissAction?.onDismiss()
+                        legacyInteractor.setDismissAction(null, null)
+
+                        viewMediatorCallback?.let {
+                            val selectedUserId = selectedUserInteractor.getSelectedUserId()
+                            if (deferKeyguardDone == true) {
+                                it.keyguardDonePending(selectedUserId)
+                            } else {
+                                it.keyguardDone(selectedUserId)
+                            }
+                        }
+                    }
+                }
+            }
+
+            launch {
+                legacyInteractor.startingDisappearAnimation.collect {
+                    it.run()
+                    legacyInteractor.hide()
+                }
+            }
+
+            hydrator.activate()
+        }
+    }
+
+    @AssistedFactory
+    interface Factory {
+        fun create(): BouncerContainerViewModel
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerUserActionsViewModel.kt
similarity index 90%
rename from packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModel.kt
rename to packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerUserActionsViewModel.kt
index 2d57e5b..4fe6fc6 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerUserActionsViewModel.kt
@@ -22,7 +22,7 @@
 import com.android.compose.animation.scene.UserAction
 import com.android.compose.animation.scene.UserActionResult
 import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
 import kotlinx.coroutines.flow.map
@@ -31,11 +31,11 @@
  * Models UI state for user actions that can lead to navigation to other scenes when showing the
  * bouncer scene.
  */
-class BouncerSceneActionsViewModel
+class BouncerUserActionsViewModel
 @AssistedInject
 constructor(
     private val bouncerInteractor: BouncerInteractor,
-) : SceneActionsViewModel() {
+) : UserActionsViewModel() {
 
     override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
         bouncerInteractor.dismissDestination
@@ -50,6 +50,6 @@
 
     @AssistedFactory
     interface Factory {
-        fun create(): BouncerSceneActionsViewModel
+        fun create(): BouncerUserActionsViewModel
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
index d2caefd..e1ba93c 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
@@ -76,7 +76,6 @@
     private final boolean mTestHarness;
     private final MetricsLogger mMetricsLogger;
     private int mIsFalseTouchCalls;
-    private FeatureFlags mFeatureFlags;
     private static final Queue<String> RECENT_INFO_LOG =
             new ArrayDeque<>(RECENT_INFO_LOG_SIZE + 1);
     private static final Queue<DebugSwipeRecord> RECENT_SWIPES =
@@ -186,8 +185,7 @@
             DoubleTapClassifier doubleTapClassifier, HistoryTracker historyTracker,
             KeyguardStateController keyguardStateController,
             AccessibilityManager accessibilityManager,
-            @TestHarness boolean testHarness,
-            FeatureFlags featureFlags) {
+            @TestHarness boolean testHarness) {
         mDataProvider = falsingDataProvider;
         mMetricsLogger = metricsLogger;
         mClassifiers = classifiers;
@@ -198,7 +196,6 @@
         mKeyguardStateController = keyguardStateController;
         mAccessibilityManager = accessibilityManager;
         mTestHarness = testHarness;
-        mFeatureFlags = featureFlags;
 
         mDataProvider.addSessionListener(mSessionListener);
         mDataProvider.addGestureCompleteListener(mGestureFinalizedListener);
@@ -399,8 +396,7 @@
                 || mDataProvider.isA11yAction()
                 || mDataProvider.isFromTrackpad()
                 || mDataProvider.isFromKeyboard()
-                || (mFeatureFlags.isEnabled(Flags.FALSING_OFF_FOR_UNFOLDED)
-                    && mDataProvider.isUnfolded());
+                || mDataProvider.isUnfolded();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayWindow.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayWindow.java
index 0dc6fda..dc3b50c 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayWindow.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayWindow.java
@@ -27,6 +27,7 @@
 import android.view.WindowInsets;
 import android.view.WindowManager;
 
+import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
 import com.android.internal.policy.PhoneWindow;
 import com.android.systemui.clipboardoverlay.dagger.ClipboardOverlayModule.OverlayWindowContext;
 import com.android.systemui.screenshot.FloatingWindowUtil;
@@ -44,6 +45,7 @@
 
     private final Context mContext;
     private final WindowManager mWindowManager;
+    private final ViewCaptureAwareWindowManager mViewCaptureAwareWindowManager;
     private final WindowManager.LayoutParams mWindowLayoutParams;
 
     private boolean mKeyboardVisible;
@@ -52,7 +54,9 @@
     private Runnable mOnOrientationChangeListener;
 
     @Inject
-    ClipboardOverlayWindow(@OverlayWindowContext Context context) {
+    ClipboardOverlayWindow(@OverlayWindowContext Context context,
+            @OverlayWindowContext ViewCaptureAwareWindowManager viewCaptureAwareWindowManager,
+            @OverlayWindowContext WindowManager windowManager) {
         super(context);
         mContext = context;
         mOrientation = mContext.getResources().getConfiguration().orientation;
@@ -61,10 +65,11 @@
         requestFeature(Window.FEATURE_NO_TITLE);
         requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
         setBackgroundDrawableResource(android.R.color.transparent);
-        mWindowManager = mContext.getSystemService(WindowManager.class);
+        mWindowManager = windowManager;
+        mViewCaptureAwareWindowManager = viewCaptureAwareWindowManager;
         mWindowLayoutParams = FloatingWindowUtil.getFloatingWindowParams();
         mWindowLayoutParams.setTitle("ClipboardOverlay");
-        setWindowManager(mWindowManager, null, null);
+        setWindowManager(windowManager, null, null);
         setWindowFocusable(false);
     }
 
@@ -81,10 +86,12 @@
 
         attach();
         withWindowAttached(() -> {
-            WindowInsets currentInsets = mWindowManager.getCurrentWindowMetrics().getWindowInsets();
+            WindowInsets currentInsets = mWindowManager.getCurrentWindowMetrics()
+                    .getWindowInsets();
             mKeyboardVisible = currentInsets.isVisible(WindowInsets.Type.ime());
             peekDecorView().getViewTreeObserver().addOnGlobalLayoutListener(() -> {
-                WindowInsets insets = mWindowManager.getCurrentWindowMetrics().getWindowInsets();
+                WindowInsets insets = mWindowManager.getCurrentWindowMetrics()
+                        .getWindowInsets();
                 boolean keyboardVisible = insets.isVisible(WindowInsets.Type.ime());
                 if (keyboardVisible != mKeyboardVisible) {
                     mKeyboardVisible = keyboardVisible;
@@ -105,7 +112,7 @@
     void remove() {
         final View decorView = peekDecorView();
         if (decorView != null && decorView.isAttachedToWindow()) {
-            mWindowManager.removeViewImmediate(decorView);
+            mViewCaptureAwareWindowManager.removeViewImmediate(decorView);
         }
     }
 
@@ -139,7 +146,7 @@
         if (decorView.isAttachedToWindow()) {
             return;
         }
-        mWindowManager.addView(decorView, mWindowLayoutParams);
+        mViewCaptureAwareWindowManager.addView(decorView, mWindowLayoutParams);
         decorView.requestApplyInsets();
     }
 
@@ -160,7 +167,7 @@
         }
         final View decorView = peekDecorView();
         if (decorView != null && decorView.isAttachedToWindow()) {
-            mWindowManager.updateViewLayout(decorView, mWindowLayoutParams);
+            mViewCaptureAwareWindowManager.updateViewLayout(decorView, mWindowLayoutParams);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java
index ff9fba4..307a07f 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java
@@ -18,17 +18,24 @@
 
 import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
 
+import static com.android.systemui.Flags.enableViewCaptureTracing;
+import static com.android.systemui.util.ConvenienceExtensionsKt.toKotlinLazy;
+
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
 import android.content.Context;
 import android.hardware.display.DisplayManager;
 import android.view.Display;
 import android.view.LayoutInflater;
+import android.view.WindowManager;
 
+import com.android.app.viewcapture.ViewCapture;
+import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
 import com.android.systemui.clipboardoverlay.ClipboardOverlayView;
 import com.android.systemui.res.R;
 import com.android.systemui.settings.DisplayTracker;
 
+import dagger.Lazy;
 import dagger.Module;
 import dagger.Provides;
 
@@ -61,6 +68,28 @@
                 R.layout.clipboard_overlay, null);
     }
 
+    /**
+     *
+     */
+    @Provides
+    @OverlayWindowContext
+    static WindowManager provideWindowManager(@OverlayWindowContext Context context) {
+        return context.getSystemService(WindowManager.class);
+    }
+
+    /**
+     *
+     */
+    @Provides
+    @OverlayWindowContext
+    static ViewCaptureAwareWindowManager provideViewCaptureAwareWindowManager(
+            @OverlayWindowContext WindowManager windowManager,
+            Lazy<ViewCapture> daggerLazyViewCapture) {
+        return new ViewCaptureAwareWindowManager(windowManager,
+                /* lazyViewCapture= */ toKotlinLazy(daggerLazyViewCapture),
+                /* isViewCaptureEnabled= */ enableViewCaptureTracing());
+    }
+
     @Qualifier
     @Documented
     @Retention(RUNTIME)
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationState.kt b/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationState.kt
index 578389b..13f6bba 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationState.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationState.kt
@@ -23,35 +23,25 @@
 import androidx.annotation.DimenRes
 import androidx.annotation.LayoutRes
 import com.android.settingslib.Utils
-import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.statusbar.policy.onDensityOrFontScaleChanged
 import com.android.systemui.statusbar.policy.onThemeChanged
 import com.android.systemui.util.kotlin.emitOnStart
-import javax.inject.Inject
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.merge
 
-/** Configuration-aware-state-tracking utilities. */
-class ConfigurationState
-@Inject
-constructor(
-    private val configurationController: ConfigurationController,
-    @Application private val context: Context,
-    private val layoutInflater: LayoutInflater,
-) {
+interface ConfigurationState {
     /**
      * Returns a [Flow] that emits a dimension pixel size that is kept in sync with the device
      * configuration.
      *
      * @see android.content.res.Resources.getDimensionPixelSize
      */
-    fun getDimensionPixelSize(@DimenRes id: Int): Flow<Int> {
-        return configurationController.onDensityOrFontScaleChanged.emitOnStart().map {
-            context.resources.getDimensionPixelSize(id)
-        }
-    }
+    fun getDimensionPixelSize(@DimenRes id: Int): Flow<Int>
 
     /**
      * Returns a [Flow] that emits a dimension pixel size that is kept in sync with the device
@@ -59,22 +49,14 @@
      *
      * @see android.content.res.Resources.getDimensionPixelSize
      */
-    fun getDimensionPixelOffset(@DimenRes id: Int): Flow<Int> {
-        return configurationController.onDensityOrFontScaleChanged.emitOnStart().map {
-            context.resources.getDimensionPixelOffset(id)
-        }
-    }
+    fun getDimensionPixelOffset(@DimenRes id: Int): Flow<Int>
 
     /**
      * Returns a [Flow] that emits a color that is kept in sync with the device theme.
      *
      * @see Utils.getColorAttrDefaultColor
      */
-    fun getColorAttr(@AttrRes id: Int, @ColorInt defaultValue: Int): Flow<Int> {
-        return configurationController.onThemeChanged.emitOnStart().map {
-            Utils.getColorAttrDefaultColor(context, id, defaultValue)
-        }
-    }
+    fun getColorAttr(@AttrRes id: Int, @ColorInt defaultValue: Int): Flow<Int>
 
     /**
      * Returns a [Flow] that emits a [View] that is re-inflated as necessary to remain in sync with
@@ -87,6 +69,65 @@
         @LayoutRes id: Int,
         root: ViewGroup?,
         attachToRoot: Boolean,
+    ): Flow<T>
+}
+
+/** Configuration-aware-state-tracking utilities. */
+class ConfigurationStateImpl
+@AssistedInject
+constructor(
+    @Assisted private val configurationController: ConfigurationController,
+    @Assisted private val context: Context,
+) : ConfigurationState {
+
+    private val layoutInflater = LayoutInflater.from(context)
+
+    /**
+     * Returns a [Flow] that emits a dimension pixel size that is kept in sync with the device
+     * configuration.
+     *
+     * @see android.content.res.Resources.getDimensionPixelSize
+     */
+    override fun getDimensionPixelSize(@DimenRes id: Int): Flow<Int> {
+        return configurationController.onDensityOrFontScaleChanged.emitOnStart().map {
+            context.resources.getDimensionPixelSize(id)
+        }
+    }
+
+    /**
+     * Returns a [Flow] that emits a dimension pixel size that is kept in sync with the device
+     * configuration.
+     *
+     * @see android.content.res.Resources.getDimensionPixelSize
+     */
+    override fun getDimensionPixelOffset(@DimenRes id: Int): Flow<Int> {
+        return configurationController.onDensityOrFontScaleChanged.emitOnStart().map {
+            context.resources.getDimensionPixelOffset(id)
+        }
+    }
+
+    /**
+     * Returns a [Flow] that emits a color that is kept in sync with the device theme.
+     *
+     * @see Utils.getColorAttrDefaultColor
+     */
+    override fun getColorAttr(@AttrRes id: Int, @ColorInt defaultValue: Int): Flow<Int> {
+        return configurationController.onThemeChanged.emitOnStart().map {
+            Utils.getColorAttrDefaultColor(context, id, defaultValue)
+        }
+    }
+
+    /**
+     * Returns a [Flow] that emits a [View] that is re-inflated as necessary to remain in sync with
+     * the device configuration.
+     *
+     * @see LayoutInflater.inflate
+     */
+    @Suppress("UNCHECKED_CAST")
+    override fun <T : View> inflateLayout(
+        @LayoutRes id: Int,
+        root: ViewGroup?,
+        attachToRoot: Boolean,
     ): Flow<T> {
         // TODO(b/305930747): This may lead to duplicate invocations if both flows emit, find a
         //  solution to only emit one event.
@@ -97,4 +138,16 @@
             .emitOnStart()
             .map { layoutInflater.inflate(id, root, attachToRoot) as T }
     }
+
+    @AssistedFactory
+    interface Factory {
+        /**
+         * Creates a configurationState for a given context. The [configurationController] is
+         * supposed to give config events specific for that context.
+         */
+        fun create(
+            context: Context,
+            configurationController: ConfigurationController
+        ): ConfigurationStateImpl
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationStateModule.kt b/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationStateModule.kt
new file mode 100644
index 0000000..b36da3b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationStateModule.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2024 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.common.ui
+
+import android.content.Context
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.statusbar.policy.ConfigurationController
+import dagger.Binds
+import dagger.Module
+import dagger.Provides
+import javax.inject.Qualifier
+
+/**
+ * Annotates elements that provide information from the global configuration.
+ *
+ * The global configuration is the one associted with the main display. Secondary displays will
+ * apply override to the global configuration. Elements annotated with this shouldn't be used for
+ * secondary displays.
+ */
+@Qualifier @Retention(AnnotationRetention.RUNTIME) annotation class GlobalConfig
+
+@Module
+interface ConfigurationStateModule {
+
+    /**
+     * Deprecated: [ConfigurationState] should be injected only with the correct annotation. For
+     * now, without annotation the global config associated state is provided.
+     */
+    @Binds
+    fun provideGlobalConfigurationState(
+        @GlobalConfig configurationState: ConfigurationState
+    ): ConfigurationState
+
+    companion object {
+        @SysUISingleton
+        @Provides
+        @GlobalConfig
+        fun provideGlobalConfigurationState(
+            configStateFactory: ConfigurationStateImpl.Factory,
+            configurationController: ConfigurationController,
+            @Application context: Context,
+        ): ConfigurationState {
+            return configStateFactory.create(context, configurationController)
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index 1dd3722..3fe6669 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -21,6 +21,7 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.InitController;
 import com.android.systemui.SystemUIAppComponentFactoryBase;
+import com.android.systemui.common.ui.GlobalConfig;
 import com.android.systemui.dagger.qualifiers.PerUser;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.keyguard.KeyguardSliceProvider;
@@ -127,6 +128,7 @@
      * Creates a ContextComponentHelper.
      */
     @SysUISingleton
+    @GlobalConfig
     ConfigurationController getConfigurationController();
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 411cbd5..b55108d 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -48,6 +48,7 @@
 import com.android.systemui.classifier.FalsingModule;
 import com.android.systemui.clipboardoverlay.dagger.ClipboardOverlayModule;
 import com.android.systemui.common.data.CommonDataLayerModule;
+import com.android.systemui.common.ui.ConfigurationStateModule;
 import com.android.systemui.common.usagestats.data.CommonUsageStatsDataLayerModule;
 import com.android.systemui.communal.dagger.CommunalModule;
 import com.android.systemui.complication.dagger.ComplicationComponent;
@@ -207,6 +208,7 @@
         ClockRegistryModule.class,
         CommunalModule.class,
         CommonDataLayerModule.class,
+        ConfigurationStateModule.class,
         CommonUsageStatsDataLayerModule.class,
         ConfigurationControllerModule.class,
         ConnectivityModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt
index 87eeebf..3b2d771 100644
--- a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt
@@ -24,8 +24,6 @@
 import com.android.systemui.contextualeducation.GestureType
 import com.android.systemui.contextualeducation.GestureType.ALL_APPS
 import com.android.systemui.contextualeducation.GestureType.BACK
-import com.android.systemui.contextualeducation.GestureType.HOME
-import com.android.systemui.contextualeducation.GestureType.OVERVIEW
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.education.dagger.ContextualEducationModule.EduClock
@@ -68,11 +66,9 @@
 
     private val keyboardShortcutTriggered: Flow<GestureType> = conflatedCallbackFlow {
         val listener = KeyGestureEventListener { event ->
+            // Only store keyboard shortcut time for gestures providing keyboard education
             val shortcutType =
                 when (event.keyGestureType) {
-                    KeyGestureEvent.KEY_GESTURE_TYPE_BACK -> BACK
-                    KeyGestureEvent.KEY_GESTURE_TYPE_HOME -> HOME
-                    KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS -> OVERVIEW
                     KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS -> ALL_APPS
                     else -> null
                 }
@@ -87,6 +83,7 @@
     }
 
     override fun start() {
+        // Listen to back gesture model changes and trigger education if needed
         backgroundScope.launch {
             contextualEducationInteractor.backGestureModelFlow.collect {
                 if (isUsageSessionExpired(it)) {
@@ -98,6 +95,7 @@
             }
         }
 
+        // Listen to touchpad connection changes and update the first connection time
         backgroundScope.launch {
             userInputDeviceRepository.isAnyTouchpadConnectedForUser.collect {
                 if (
@@ -111,6 +109,7 @@
             }
         }
 
+        // Listen to keyboard connection changes and update the first connection time
         backgroundScope.launch {
             userInputDeviceRepository.isAnyKeyboardConnectedForUser.collect {
                 if (
@@ -124,6 +123,7 @@
             }
         }
 
+        // Listen to keyboard shortcut triggered and update the last trigger time
         backgroundScope.launch {
             keyboardShortcutTriggered.collect {
                 contextualEducationInteractor.updateShortcutTriggerTime(it)
diff --git a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduStatsInteractor.kt b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduStatsInteractor.kt
index 3223433..7821f69 100644
--- a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduStatsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduStatsInteractor.kt
@@ -16,11 +16,25 @@
 
 package com.android.systemui.education.domain.interactor
 
+import android.os.SystemProperties
+import com.android.systemui.contextualeducation.GestureType
+import com.android.systemui.contextualeducation.GestureType.ALL_APPS
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.contextualeducation.GestureType
+import com.android.systemui.education.dagger.ContextualEducationModule.EduClock
+import com.android.systemui.inputdevice.data.repository.UserInputDeviceRepository
+import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType
+import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType.KEYBOARD
+import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType.TOUCHPAD
+import com.android.systemui.inputdevice.tutorial.data.repository.TutorialSchedulerRepository
+import java.time.Clock
 import javax.inject.Inject
+import kotlin.time.Duration
+import kotlin.time.Duration.Companion.hours
+import kotlin.time.DurationUnit
+import kotlin.time.toDuration
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.launch
 
 /**
@@ -39,12 +53,29 @@
 @Inject
 constructor(
     @Background private val backgroundScope: CoroutineScope,
-    private val contextualEducationInteractor: ContextualEducationInteractor
+    private val contextualEducationInteractor: ContextualEducationInteractor,
+    private val inputDeviceRepository: UserInputDeviceRepository,
+    private val tutorialRepository: TutorialSchedulerRepository,
+    @EduClock private val clock: Clock,
 ) : KeyboardTouchpadEduStatsInteractor {
 
+    companion object {
+        val initialDelayDuration: Duration
+            get() =
+                SystemProperties.getLong(
+                        "persist.contextual_edu.initial_delay_sec",
+                        /* defaultValue= */ 72.hours.inWholeSeconds
+                    )
+                    .toDuration(DurationUnit.SECONDS)
+    }
+
     override fun incrementSignalCount(gestureType: GestureType) {
-        // Todo: check if keyboard/touchpad is connected before update
-        backgroundScope.launch { contextualEducationInteractor.incrementSignalCount(gestureType) }
+        backgroundScope.launch {
+            val targetDevice = getTargetDevice(gestureType)
+            if (isTargetDeviceConnected(targetDevice) && hasInitialDelayElapsed(targetDevice)) {
+                contextualEducationInteractor.incrementSignalCount(gestureType)
+            }
+        }
     }
 
     override fun updateShortcutTriggerTime(gestureType: GestureType) {
@@ -52,4 +83,31 @@
             contextualEducationInteractor.updateShortcutTriggerTime(gestureType)
         }
     }
+
+    private suspend fun isTargetDeviceConnected(deviceType: DeviceType): Boolean {
+        if (deviceType == KEYBOARD) {
+            return inputDeviceRepository.isAnyKeyboardConnectedForUser.first().isConnected
+        } else if (deviceType == TOUCHPAD) {
+            return inputDeviceRepository.isAnyTouchpadConnectedForUser.first().isConnected
+        }
+        return false
+    }
+
+    /**
+     * Keyboard shortcut education would be provided for All Apps. Touchpad gesture education would
+     * be provided for the rest of the gesture types (i.e. Home, Overview, Back). This method maps
+     * gesture to its target education device.
+     */
+    private fun getTargetDevice(gestureType: GestureType) =
+        when (gestureType) {
+            ALL_APPS -> KEYBOARD
+            else -> TOUCHPAD
+        }
+
+    private suspend fun hasInitialDelayElapsed(deviceType: DeviceType): Boolean {
+        val oobeLaunchTime = tutorialRepository.launchTime(deviceType) ?: return false
+        return clock
+            .instant()
+            .isAfter(oobeLaunchTime.plusSeconds(initialDelayDuration.inWholeSeconds))
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index bb73f56..c9fafce 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -98,9 +98,6 @@
     @JvmField
     val AUTO_PIN_CONFIRMATION = releasedFlag("auto_pin_confirmation", "auto_pin_confirmation")
 
-    // TODO(b/262859270): Tracking Bug
-    @JvmField val FALSING_OFF_FOR_UNFOLDED = releasedFlag("falsing_off_for_unfolded")
-
     /** Enables code to show contextual loyalty cards in wallet entrypoints */
     // TODO(b/294110497): Tracking Bug
     @JvmField
@@ -233,9 +230,6 @@
     // TODO(b/254512697): Tracking Bug
     val MEDIA_TAP_TO_TRANSFER = releasedFlag("media_tap_to_transfer")
 
-    // TODO(b/254512502): Tracking Bug
-    val MEDIA_SESSION_ACTIONS = unreleasedFlag("media_session_actions")
-
     // TODO(b/254512654): Tracking Bug
     @JvmField val DREAM_MEDIA_COMPLICATION = unreleasedFlag("dream_media_complication")
 
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartable.kt
index e8e1dd4..7ecacdc 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartable.kt
@@ -18,20 +18,20 @@
 
 import com.android.systemui.CoreStartable
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.inputdevice.tutorial.domain.interactor.TutorialSchedulerInteractor
+import com.android.systemui.inputdevice.tutorial.ui.TutorialNotificationCoordinator
 import com.android.systemui.shared.Flags.newTouchpadGesturesTutorial
 import dagger.Lazy
 import javax.inject.Inject
 
-/** A [CoreStartable] to launch a scheduler for keyboard and touchpad education */
+/** A [CoreStartable] to launch a scheduler for keyboard and touchpad tutorial notification */
 @SysUISingleton
 class KeyboardTouchpadTutorialCoreStartable
 @Inject
-constructor(private val tutorialSchedulerInteractor: Lazy<TutorialSchedulerInteractor>) :
+constructor(private val tutorialNotificationCoordinator: Lazy<TutorialNotificationCoordinator>) :
     CoreStartable {
     override fun start() {
         if (newTouchpadGesturesTutorial()) {
-            tutorialSchedulerInteractor.get().start()
+            tutorialNotificationCoordinator.get().start()
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt
index a8d7dad..cfc913f 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt
@@ -17,9 +17,7 @@
 package com.android.systemui.inputdevice.tutorial.domain.interactor
 
 import android.os.SystemProperties
-import android.util.Log
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType
 import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType.KEYBOARD
 import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType.TOUCHPAD
@@ -31,23 +29,22 @@
 import javax.inject.Inject
 import kotlin.time.Duration.Companion.hours
 import kotlin.time.toKotlinDuration
-import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.merge
-import kotlinx.coroutines.launch
 
 /**
- * When the first time a keyboard or touchpad is connected, wait for [LAUNCH_DELAY], then launch the
- * tutorial as soon as there's a connected device
+ * When the first time a keyboard or touchpad is connected, wait for [LAUNCH_DELAY], and as soon as
+ * there's a connected device, show a notification to launch the tutorial.
  */
 @SysUISingleton
 class TutorialSchedulerInteractor
 @Inject
 constructor(
-    @Background private val backgroundScope: CoroutineScope,
     keyboardRepository: KeyboardRepository,
     touchpadRepository: TouchpadRepository,
     private val repo: TutorialSchedulerRepository
@@ -58,17 +55,6 @@
             TOUCHPAD to touchpadRepository.isAnyTouchpadConnected
         )
 
-    fun start() {
-        backgroundScope.launch {
-            // Merging two flows to ensure that launch tutorial is launched consecutively in order
-            // to avoid race condition
-            merge(touchpadScheduleFlow, keyboardScheduleFlow).collect {
-                val tutorialType = resolveTutorialType(it)
-                launchTutorial(tutorialType)
-            }
-        }
-    }
-
     private val touchpadScheduleFlow = flow {
         if (!repo.isLaunched(TOUCHPAD)) {
             schedule(TOUCHPAD)
@@ -95,14 +81,19 @@
     private suspend fun waitForDeviceConnection(deviceType: DeviceType) =
         isAnyDeviceConnected[deviceType]!!.filter { it }.first()
 
-    private suspend fun launchTutorial(tutorialType: TutorialType) {
-        if (tutorialType == TutorialType.KEYBOARD || tutorialType == TutorialType.BOTH)
-            repo.updateLaunchTime(KEYBOARD, Instant.now())
-        if (tutorialType == TutorialType.TOUCHPAD || tutorialType == TutorialType.BOTH)
-            repo.updateLaunchTime(TOUCHPAD, Instant.now())
-        // TODO: launch tutorial
-        Log.d(TAG, "Launch tutorial for $tutorialType")
-    }
+    // Merging two flows ensures that tutorial is launched consecutively to avoid race condition
+    val tutorials: Flow<TutorialType> =
+        merge(touchpadScheduleFlow, keyboardScheduleFlow).map {
+            val tutorialType = resolveTutorialType(it)
+
+            // TODO: notifying time is not oobe launching time - move these updates into oobe
+            if (tutorialType == TutorialType.KEYBOARD || tutorialType == TutorialType.BOTH)
+                repo.updateLaunchTime(KEYBOARD, Instant.now())
+            if (tutorialType == TutorialType.TOUCHPAD || tutorialType == TutorialType.BOTH)
+                repo.updateLaunchTime(TOUCHPAD, Instant.now())
+
+            tutorialType
+        }
 
     private suspend fun resolveTutorialType(deviceType: DeviceType): TutorialType {
         // Resolve the type of tutorial depending on which device are connected when the tutorial is
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/TutorialNotificationCoordinator.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/TutorialNotificationCoordinator.kt
new file mode 100644
index 0000000..5d9dda3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/TutorialNotificationCoordinator.kt
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2024 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.inputdevice.tutorial.ui
+
+import android.app.Notification
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import androidx.core.app.NotificationCompat
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.inputdevice.tutorial.domain.interactor.TutorialSchedulerInteractor
+import com.android.systemui.inputdevice.tutorial.domain.interactor.TutorialSchedulerInteractor.Companion.TAG
+import com.android.systemui.inputdevice.tutorial.domain.interactor.TutorialSchedulerInteractor.TutorialType
+import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity
+import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_BOTH
+import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEY
+import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEYBOARD
+import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_TOUCHPAD
+import com.android.systemui.res.R
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+
+/** When the scheduler is due, show a notification to launch tutorial */
+@SysUISingleton
+class TutorialNotificationCoordinator
+@Inject
+constructor(
+    @Background private val backgroundScope: CoroutineScope,
+    @Application private val context: Context,
+    private val tutorialSchedulerInteractor: TutorialSchedulerInteractor,
+    private val notificationManager: NotificationManager
+) {
+    fun start() {
+        backgroundScope.launch {
+            tutorialSchedulerInteractor.tutorials.collect { showNotification(it) }
+        }
+    }
+
+    // By sharing the same tag and id, we update the content of existing notification instead of
+    // creating multiple notifications
+    private fun showNotification(tutorialType: TutorialType) {
+        if (tutorialType == TutorialType.NONE) return
+
+        if (notificationManager.getNotificationChannel(CHANNEL_ID) == null)
+            createNotificationChannel()
+
+        // Replace "System UI" app name with "Android System"
+        val extras = Bundle()
+        extras.putString(
+            Notification.EXTRA_SUBSTITUTE_APP_NAME,
+            context.getString(com.android.internal.R.string.android_system_label)
+        )
+
+        val info = getNotificationInfo(tutorialType)!!
+        val notification =
+            NotificationCompat.Builder(context, CHANNEL_ID)
+                .setSmallIcon(R.drawable.ic_settings)
+                .setContentTitle(info.title)
+                .setContentText(info.text)
+                .setContentIntent(createPendingIntent(info.type))
+                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
+                .setAutoCancel(true)
+                .addExtras(extras)
+                .build()
+
+        notificationManager.notify(TAG, NOTIFICATION_ID, notification)
+    }
+
+    private fun createNotificationChannel() {
+        val channel =
+            NotificationChannel(
+                CHANNEL_ID,
+                context.getString(com.android.internal.R.string.android_system_label),
+                NotificationManager.IMPORTANCE_DEFAULT
+            )
+        notificationManager.createNotificationChannel(channel)
+    }
+
+    private fun createPendingIntent(tutorialType: String): PendingIntent {
+        val intent =
+            Intent(context, KeyboardTouchpadTutorialActivity::class.java).apply {
+                putExtra(INTENT_TUTORIAL_TYPE_KEY, tutorialType)
+                flags = Intent.FLAG_ACTIVITY_NEW_TASK
+            }
+        return PendingIntent.getActivity(
+            context,
+            /* requestCode= */ 0,
+            intent,
+            PendingIntent.FLAG_IMMUTABLE
+        )
+    }
+
+    private data class NotificationInfo(val title: String, val text: String, val type: String)
+
+    private fun getNotificationInfo(tutorialType: TutorialType): NotificationInfo? =
+        when (tutorialType) {
+            TutorialType.KEYBOARD ->
+                NotificationInfo(
+                    context.getString(R.string.launch_keyboard_tutorial_notification_title),
+                    context.getString(R.string.launch_keyboard_tutorial_notification_content),
+                    INTENT_TUTORIAL_TYPE_KEYBOARD
+                )
+            TutorialType.TOUCHPAD ->
+                NotificationInfo(
+                    context.getString(R.string.launch_touchpad_tutorial_notification_title),
+                    context.getString(R.string.launch_touchpad_tutorial_notification_content),
+                    INTENT_TUTORIAL_TYPE_TOUCHPAD
+                )
+            TutorialType.BOTH ->
+                NotificationInfo(
+                    context.getString(
+                        R.string.launch_keyboard_touchpad_tutorial_notification_title
+                    ),
+                    context.getString(
+                        R.string.launch_keyboard_touchpad_tutorial_notification_content
+                    ),
+                    INTENT_TUTORIAL_TYPE_BOTH
+                )
+            TutorialType.NONE -> null
+        }
+
+    companion object {
+        private const val CHANNEL_ID = "TutorialSchedulerNotificationChannel"
+        private const val NOTIFICATION_ID = 5566
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt
index 8debe79..1adc285 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt
@@ -54,6 +54,7 @@
         const val INTENT_TUTORIAL_TYPE_KEY = "tutorial_type"
         const val INTENT_TUTORIAL_TYPE_TOUCHPAD = "touchpad"
         const val INTENT_TUTORIAL_TYPE_KEYBOARD = "keyboard"
+        const val INTENT_TUTORIAL_TYPE_BOTH = "both"
     }
 
     private val vm by
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/NewPickerUiKeyguardPreview.kt b/packages/SystemUI/src/com/android/systemui/keyguard/NewPickerUiKeyguardPreview.kt
deleted file mode 100644
index 7e09a10..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/NewPickerUiKeyguardPreview.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2024 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.keyguard
-
-import com.android.systemui.Flags
-
-/** Helper for reading or using the new picker UI flag. */
-@Suppress("NOTHING_TO_INLINE")
-object NewPickerUiKeyguardPreview {
-
-    /** Is the new picker UI enabled */
-    @JvmStatic
-    inline val isEnabled
-        get() = Flags.newPickerUi()
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt
index 7087752..ec52055 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt
@@ -101,7 +101,7 @@
         secureSettings
             .observerFlow(
                 names = arrayOf(Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK),
-                userId = UserHandle.USER_SYSTEM,
+                userId = UserHandle.USER_ALL,
             )
             .onStart { emit(Unit) } // Forces an initial update.
             .map { withContext(backgroundDispatcher) { getClockSize() } }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepository.kt
index a1e4af5..b67fd4b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepository.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.keyguard.data.repository
 
 import android.content.Context
+import android.os.UserHandle
 import android.provider.Settings
 import android.view.View
 import com.android.systemui.dagger.SysUISingleton
@@ -37,6 +38,7 @@
 interface KeyguardSmartspaceRepository {
     val bcSmartspaceVisibility: StateFlow<Int>
     val isWeatherEnabled: StateFlow<Boolean>
+
     fun setBcSmartspaceVisibility(visibility: Int)
 }
 
@@ -55,7 +57,7 @@
         secureSettings
             .observerFlow(
                 names = arrayOf(Settings.Secure.LOCK_SCREEN_WEATHER_ENABLED),
-                userId = userTracker.userId,
+                userId = UserHandle.USER_ALL,
             )
             .onStart { emit(Unit) }
             .map { getLockscreenWeatherEnabled() }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt
index fe4ebfe..72740d5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt
@@ -20,7 +20,6 @@
 import androidx.annotation.VisibleForTesting
 import com.android.app.tracing.FlowTracing.traceEmissionCount
 import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.keyguard.NewPickerUiKeyguardPreview
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
@@ -29,6 +28,7 @@
 import com.android.systemui.keyguard.shared.quickaffordance.ActivationState
 import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
+import com.android.systemui.shared.Flags
 import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
 import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated
 import javax.inject.Inject
@@ -169,7 +169,7 @@
 
     /** An observable for the view-model of the "start button" quick affordance. */
     val startButton: Flow<KeyguardQuickAffordanceViewModel> =
-        if (NewPickerUiKeyguardPreview.isEnabled) {
+        if (Flags.newCustomizationPickerUi()) {
             previewAffordances.flatMapLatestConflated {
                 button(
                     position = KeyguardQuickAffordancePosition.BOTTOM_START,
@@ -184,7 +184,7 @@
 
     /** An observable for the view-model of the "end button" quick affordance. */
     val endButton: Flow<KeyguardQuickAffordanceViewModel> =
-        if (NewPickerUiKeyguardPreview.isEnabled) {
+        if (Flags.newCustomizationPickerUi()) {
             previewAffordances.flatMapLatestConflated {
                 button(
                     position = KeyguardQuickAffordancePosition.BOTTOM_END,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModel.kt
similarity index 96%
rename from packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneActionsViewModel.kt
rename to packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModel.kt
index 2819e61..dd47678 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModel.kt
@@ -28,7 +28,7 @@
 import com.android.systemui.scene.shared.model.SceneFamilies
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.shared.model.TransitionKeys.ToSplitShade
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.shade.shared.model.ShadeMode
 import com.android.systemui.util.kotlin.filterValuesNotNull
@@ -40,13 +40,13 @@
 import kotlinx.coroutines.flow.flowOf
 
 /** Models UI state and handles user input for the lockscreen scene. */
-class LockscreenSceneActionsViewModel
+class LockscreenUserActionsViewModel
 @AssistedInject
 constructor(
     private val deviceEntryInteractor: DeviceEntryInteractor,
     private val communalInteractor: CommunalInteractor,
     private val shadeInteractor: ShadeInteractor,
-) : SceneActionsViewModel() {
+) : UserActionsViewModel() {
 
     override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
         shadeInteractor.isShadeTouchable
@@ -119,6 +119,6 @@
 
     @AssistedFactory
     interface Factory {
-        fun create(): LockscreenSceneActionsViewModel
+        fun create(): LockscreenUserActionsViewModel
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
index 2089cce5..89a599a 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
@@ -16,19 +16,17 @@
 
 package com.android.systemui.log.table
 
+import android.annotation.SuppressLint
 import android.icu.text.SimpleDateFormat
 import android.os.Trace
 import com.android.systemui.Dumpable
 import com.android.systemui.common.buffer.RingBuffer
-import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.log.LogcatEchoTracker
 import com.android.systemui.log.core.LogLevel
 import com.android.systemui.plugins.log.TableLogBufferBase
 import com.android.systemui.util.time.SystemClock
 import java.io.PrintWriter
 import java.util.Locale
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.CoroutineScope
 
 /**
  * A logger that logs changes in table format.
@@ -75,13 +73,12 @@
  *
  * @param maxSize the maximum size of the buffer. Must be > 0.
  */
+@SuppressLint("DumpableNotRegistered") // Registered as dumpable in [TableLogBufferFactory]
 class TableLogBuffer(
     maxSize: Int,
     private val name: String,
     private val systemClock: SystemClock,
     private val logcatEchoTracker: LogcatEchoTracker,
-    @Background private val bgDispatcher: CoroutineDispatcher,
-    private val coroutineScope: CoroutineScope,
     private val localLogcat: LogProxy = LogProxyDefault(),
 ) : Dumpable, TableLogBufferBase {
     init {
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
index ff523ae..425e674e 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
@@ -17,15 +17,11 @@
 package com.android.systemui.log.table
 
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.log.LogBufferHelper.Companion.adjustMaxSize
 import com.android.systemui.log.LogcatEchoTracker
 import com.android.systemui.util.time.SystemClock
 import javax.inject.Inject
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.CoroutineScope
 
 @SysUISingleton
 class TableLogBufferFactory
@@ -34,8 +30,6 @@
     private val dumpManager: DumpManager,
     private val systemClock: SystemClock,
     private val logcatEchoTracker: LogcatEchoTracker,
-    @Background private val bgDispatcher: CoroutineDispatcher,
-    @Application private val coroutineScope: CoroutineScope,
 ) {
     private val existingBuffers = mutableMapOf<String, TableLogBuffer>()
 
@@ -58,8 +52,6 @@
                 name,
                 systemClock,
                 logcatEchoTracker,
-                bgDispatcher,
-                coroutineScope,
             )
         dumpManager.registerTableLogBuffer(name, tableBuffer)
         return tableBuffer
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
index a65243d..d4af1b5 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
@@ -29,9 +29,8 @@
      * Check whether media control actions should be based on PlaybackState instead of notification
      */
     fun areMediaSessionActionsEnabled(packageName: String, user: UserHandle): Boolean {
-        val enabled = StatusBarManager.useMediaSessionActionsForApp(packageName, user)
         // Allow global override with flag
-        return enabled || featureFlags.isEnabled(Flags.MEDIA_SESSION_ACTIONS)
+        return StatusBarManager.useMediaSessionActionsForApp(packageName, user)
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
index 9b1ca1e..6440205 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
@@ -122,8 +122,10 @@
         @Provides
         @MediaProjectionAppSelector
         @MediaProjectionAppSelectorScope
-        fun bindConfigurationController(context: Context): ConfigurationController =
-            ConfigurationControllerImpl(context)
+        fun bindConfigurationController(
+            context: Context,
+            configurationControlleFactory: ConfigurationControllerImpl.Factory
+        ): ConfigurationController = configurationControlleFactory.create(context)
 
         @Provides fun bindIconFactory(context: Context): IconFactory = IconFactory.obtain(context)
 
diff --git a/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayActionsViewModel.kt
index 6ef83e2..b6868c1 100644
--- a/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayActionsViewModel.kt
@@ -21,13 +21,13 @@
 import com.android.compose.animation.scene.UserAction
 import com.android.compose.animation.scene.UserActionResult
 import com.android.systemui.scene.shared.model.Overlays
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
 
 /** Models the UI state for the user actions for navigating to other scenes or overlays. */
 class NotificationsShadeOverlayActionsViewModel @AssistedInject constructor() :
-    SceneActionsViewModel() {
+    UserActionsViewModel() {
 
     override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
         setActions(
diff --git a/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModel.kt
similarity index 85%
rename from packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneActionsViewModel.kt
rename to packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModel.kt
index 572a0ca..a5c07bc 100644
--- a/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModel.kt
@@ -21,15 +21,15 @@
 import com.android.compose.animation.scene.UserAction
 import com.android.compose.animation.scene.UserActionResult
 import com.android.systemui.scene.shared.model.SceneFamilies
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
 
 /**
  * Models the UI state for the user actions that the user can perform to navigate to other scenes.
  */
-class NotificationsShadeSceneActionsViewModel @AssistedInject constructor() :
-    SceneActionsViewModel() {
+class NotificationsShadeUserActionsViewModel @AssistedInject constructor() :
+    UserActionsViewModel() {
 
     override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
         setActions(
@@ -42,6 +42,6 @@
 
     @AssistedFactory
     interface Factory {
-        fun create(): NotificationsShadeSceneActionsViewModel
+        fun create(): NotificationsShadeUserActionsViewModel
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt
index 313cb30..7d23fbd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt
@@ -22,6 +22,7 @@
 import android.os.Looper
 import android.service.quicksettings.Tile
 import androidx.annotation.DrawableRes
+import androidx.annotation.VisibleForTesting
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.coroutineScope
 import androidx.lifecycle.repeatOnLifecycle
@@ -63,7 +64,7 @@
     activityStarter: ActivityStarter,
     qsLogger: QSLogger,
     qsTileConfigProvider: QSTileConfigProvider,
-    dataInteractor: ModesTileDataInteractor,
+    private val dataInteractor: ModesTileDataInteractor,
     private val tileMapper: ModesTileMapper,
     private val userActionInteractor: ModesTileUserActionInteractor,
 ) :
@@ -110,19 +111,21 @@
 
     override fun getLongClickIntent(): Intent = userActionInteractor.longClickIntent
 
-    override fun handleUpdateState(state: QSTile.State?, arg: Any?) {
-        if (arg is ModesTileModel) {
-            tileState = tileMapper.map(config, arg)
+    @VisibleForTesting
+    public override fun handleUpdateState(state: QSTile.State?, arg: Any?) {
+        // This runBlocking() will block @Background. Due to caches, it's expected to be fast.
+        val model =
+            if (arg is ModesTileModel) arg else runBlocking { dataInteractor.getCurrentTileModel() }
 
-            state?.apply {
-                this.state = tileState.activationState.legacyState
-                val tileStateIcon = tileState.icon()
-                icon = tileStateIcon?.asQSTileIcon() ?: ResourceIcon.get(ICON_RES_ID)
-                label = tileLabel
-                secondaryLabel = tileState.secondaryLabel
-                contentDescription = tileState.contentDescription
-                expandedAccessibilityClassName = tileState.expandedAccessibilityClassName
-            }
+        tileState = tileMapper.map(config, model)
+        state?.apply {
+            this.state = tileState.activationState.legacyState
+            val tileStateIcon = tileState.icon()
+            icon = tileStateIcon?.asQSTileIcon() ?: ResourceIcon.get(ICON_RES_ID)
+            label = tileLabel
+            secondaryLabel = tileState.secondaryLabel
+            contentDescription = tileState.contentDescription
+            expandedAccessibilityClassName = tileState.expandedAccessibilityClassName
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt
index 6173091..c2d112e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt
@@ -25,8 +25,8 @@
 import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
 import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor
 import com.android.systemui.qs.tiles.impl.modes.domain.model.ModesTileModel
-import com.android.systemui.res.R
 import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor
+import com.android.systemui.statusbar.policy.domain.model.ActiveZenModes
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.flow.Flow
@@ -54,31 +54,35 @@
      */
     fun tileData() =
         zenModeInteractor.activeModes
-            .map { activeModes ->
-                val modesIconResId = com.android.internal.R.drawable.ic_zen_priority_modes
-
-                if (usesModeIcons()) {
-                    val mainModeDrawable = activeModes.mainMode?.icon?.drawable
-                    val iconResId = if (mainModeDrawable == null) modesIconResId else null
-
-                    ModesTileModel(
-                        isActivated = activeModes.isAnyActive(),
-                        icon = (mainModeDrawable ?: context.getDrawable(modesIconResId)!!).asIcon(),
-                        iconResId = iconResId,
-                        activeModes = activeModes.modeNames
-                    )
-                } else {
-                    ModesTileModel(
-                        isActivated = activeModes.isAnyActive(),
-                        icon = context.getDrawable(modesIconResId)!!.asIcon(),
-                        iconResId = modesIconResId,
-                        activeModes = activeModes.modeNames
-                    )
-                }
-            }
+            .map { activeModes -> buildTileData(activeModes) }
             .flowOn(bgDispatcher)
             .distinctUntilChanged()
 
+    suspend fun getCurrentTileModel() = buildTileData(zenModeInteractor.getActiveModes())
+
+    private fun buildTileData(activeModes: ActiveZenModes): ModesTileModel {
+        val modesIconResId = com.android.internal.R.drawable.ic_zen_priority_modes
+
+        if (usesModeIcons()) {
+            val mainModeDrawable = activeModes.mainMode?.icon?.drawable
+            val iconResId = if (mainModeDrawable == null) modesIconResId else null
+
+            return ModesTileModel(
+                isActivated = activeModes.isAnyActive(),
+                icon = (mainModeDrawable ?: context.getDrawable(modesIconResId)!!).asIcon(),
+                iconResId = iconResId,
+                activeModes = activeModes.modeNames
+            )
+        } else {
+            return ModesTileModel(
+                isActivated = activeModes.isAnyActive(),
+                icon = context.getDrawable(modesIconResId)!!.asIcon(),
+                iconResId = modesIconResId,
+                activeModes = activeModes.modeNames
+            )
+        }
+    }
+
     override fun availability(user: UserHandle): Flow<Boolean> = flowOf(Flags.modesUi())
 
     private fun usesModeIcons() = Flags.modesApi() && Flags.modesUi() && Flags.modesUiIcons()
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModel.kt
index a264f51..f77386d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModel.kt
@@ -39,7 +39,7 @@
 /**
  * Models UI state needed for rendering the content of the quick settings scene.
  *
- * Different from [QuickSettingsSceneActionsViewModel] that models the UI state needed to figure out
+ * Different from [QuickSettingsUserActionsViewModel] that models the UI state needed to figure out
  * which user actions can trigger navigation to other scenes.
  */
 class QuickSettingsSceneContentViewModel
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayActionsViewModel.kt
index 9538392..61c4c8c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayActionsViewModel.kt
@@ -21,13 +21,13 @@
 import com.android.compose.animation.scene.UserAction
 import com.android.compose.animation.scene.UserActionResult
 import com.android.systemui.scene.shared.model.Overlays
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
 
 /** Models the UI state for the user actions for navigating to other scenes or overlays. */
 class QuickSettingsShadeOverlayActionsViewModel @AssistedInject constructor() :
-    SceneActionsViewModel() {
+    UserActionsViewModel() {
 
     override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
         setActions(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneContentViewModel.kt
index 5185828..d01b33b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneContentViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneContentViewModel.kt
@@ -22,7 +22,7 @@
 /**
  * Models UI state used to render the content of the quick settings shade scene.
  *
- * Different from [QuickSettingsShadeSceneActionsViewModel], which only models user actions that can
+ * Different from [QuickSettingsShadeUserActionsViewModel], which only models user actions that can
  * be performed to navigate to other scenes.
  */
 class QuickSettingsShadeSceneContentViewModel
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModel.kt
similarity index 90%
rename from packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModel.kt
rename to packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModel.kt
index 9690aab..d3dc302 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModel.kt
@@ -21,7 +21,7 @@
 import com.android.compose.animation.scene.UserAction
 import com.android.compose.animation.scene.UserActionResult
 import com.android.systemui.scene.shared.model.SceneFamilies
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
 import kotlinx.coroutines.flow.map
@@ -32,11 +32,11 @@
  * Different from the [QuickSettingsShadeSceneContentViewModel] which models the _content_ of the
  * scene.
  */
-class QuickSettingsShadeSceneActionsViewModel
+class QuickSettingsShadeUserActionsViewModel
 @AssistedInject
 constructor(
     val quickSettingsContainerViewModel: QuickSettingsContainerViewModel,
-) : SceneActionsViewModel() {
+) : UserActionsViewModel() {
 
     override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
         quickSettingsContainerViewModel.editModeViewModel.isEditing
@@ -53,6 +53,6 @@
 
     @AssistedFactory
     interface Factory {
-        fun create(): QuickSettingsShadeSceneActionsViewModel
+        fun create(): QuickSettingsShadeUserActionsViewModel
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsUserActionsViewModel.kt
similarity index 94%
rename from packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModel.kt
rename to packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsUserActionsViewModel.kt
index 2bb5dc66..54e5cac 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsUserActionsViewModel.kt
@@ -27,7 +27,7 @@
 import com.android.systemui.scene.domain.interactor.SceneBackInteractor
 import com.android.systemui.scene.shared.model.SceneFamilies
 import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
 import kotlinx.coroutines.flow.Flow
@@ -42,12 +42,12 @@
  * Different from [QuickSettingsSceneContentViewModel] that models UI state needed for rendering the
  * content of the quick settings scene.
  */
-class QuickSettingsSceneActionsViewModel
+class QuickSettingsUserActionsViewModel
 @AssistedInject
 constructor(
     private val qsSceneAdapter: QSSceneAdapter,
     sceneBackInteractor: SceneBackInteractor,
-) : SceneActionsViewModel() {
+) : UserActionsViewModel() {
 
     private val backScene: Flow<SceneKey> =
         sceneBackInteractor.backScene
@@ -82,6 +82,6 @@
 
     @AssistedFactory
     interface Factory {
-        fun create(): QuickSettingsSceneActionsViewModel
+        fun create(): QuickSettingsUserActionsViewModel
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recordissue/CustomTraceState.kt b/packages/SystemUI/src/com/android/systemui/recordissue/CustomTraceState.kt
index 14dfcc5..b0eaf9f 100644
--- a/packages/SystemUI/src/com/android/systemui/recordissue/CustomTraceState.kt
+++ b/packages/SystemUI/src/com/android/systemui/recordissue/CustomTraceState.kt
@@ -21,6 +21,10 @@
 import com.android.traceur.PresetTraceConfigs.getDefaultConfig
 import com.android.traceur.TraceConfig
 
+/**
+ * This class encapsulates the values that go into a customized record issue trace config, part of
+ * the RecordIssueTile feature. This class stores the last configuration chosen by power users.
+ */
 class CustomTraceState(private val prefs: SharedPreferences) {
 
     private var enabledTags: Set<String>?
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
index 0a7526a..e251c9e 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
@@ -36,6 +36,7 @@
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.DisplayId
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
 import com.android.systemui.deviceentry.domain.interactor.DeviceUnlockedInteractor
 import com.android.systemui.deviceentry.shared.model.DeviceUnlockSource
@@ -62,6 +63,7 @@
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.statusbar.NotificationShadeWindowController
 import com.android.systemui.statusbar.SysuiStatusBarStateController
+import com.android.systemui.statusbar.VibratorHelper
 import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNotificationInteractor
 import com.android.systemui.statusbar.phone.CentralSurfaces
 import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor
@@ -78,6 +80,7 @@
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.coroutineScope
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.collectLatest
 import kotlinx.coroutines.flow.combine
@@ -107,6 +110,7 @@
     @Application private val applicationScope: CoroutineScope,
     private val sceneInteractor: SceneInteractor,
     private val deviceEntryInteractor: DeviceEntryInteractor,
+    private val deviceEntryHapticsInteractor: DeviceEntryHapticsInteractor,
     private val deviceUnlockedInteractor: DeviceUnlockedInteractor,
     private val bouncerInteractor: BouncerInteractor,
     private val keyguardInteractor: KeyguardInteractor,
@@ -134,6 +138,7 @@
     private val dismissCallbackRegistry: DismissCallbackRegistry,
     private val statusBarStateController: SysuiStatusBarStateController,
     private val alternateBouncerInteractor: AlternateBouncerInteractor,
+    private val vibratorHelper: VibratorHelper,
 ) : CoreStartable {
     private val centralSurfaces: CentralSurfaces?
         get() = centralSurfacesOptLazy.get().getOrNull()
@@ -148,6 +153,7 @@
             respondToFalsingDetections()
             hydrateInteractionState()
             handleBouncerOverscroll()
+            handleDeviceEntryHapticsWhileDeviceLocked()
             hydrateWindowController()
             hydrateBackStack()
             resetShadeSessions()
@@ -525,6 +531,37 @@
         }
     }
 
+    private fun handleDeviceEntryHapticsWhileDeviceLocked() {
+        applicationScope.launch {
+            deviceEntryInteractor.isDeviceEntered.collectLatest { isDeviceEntered ->
+                // Only check for haptics signals before device is entered
+                if (!isDeviceEntered) {
+                    coroutineScope {
+                        launch {
+                            deviceEntryHapticsInteractor.playSuccessHaptic
+                                .sample(sceneInteractor.currentScene)
+                                .collect { currentScene ->
+                                    vibratorHelper.vibrateAuthSuccess(
+                                        "$TAG, $currentScene device-entry::success"
+                                    )
+                                }
+                        }
+
+                        launch {
+                            deviceEntryHapticsInteractor.playErrorHaptic
+                                .sample(sceneInteractor.currentScene)
+                                .collect { currentScene ->
+                                    vibratorHelper.vibrateAuthError(
+                                        "$TAG, $currentScene device-entry::error"
+                                    )
+                                }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     /** Keeps [SysUiState] up-to-date */
     private fun hydrateSystemUiState() {
         applicationScope.launch {
@@ -571,15 +608,6 @@
         }
 
         applicationScope.launch {
-            sceneInteractor.currentScene
-                .map { it == Scenes.Bouncer }
-                .distinctUntilChanged()
-                .collect { isBouncerShowing ->
-                    windowController.setBouncerShowing(isBouncerShowing)
-                }
-        }
-
-        applicationScope.launch {
             occlusionInteractor.invisibleDueToOcclusion.collect { invisibleDueToOcclusion ->
                 windowController.setKeyguardOccluded(invisibleDueToOcclusion)
             }
@@ -817,4 +845,8 @@
                 .collectLatest { deviceEntryInteractor.refreshLockscreenEnabled() }
         }
     }
+
+    companion object {
+        private const val TAG = "SceneContainerStartable"
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModel.kt
similarity index 95%
rename from packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneSceneActionsViewModel.kt
rename to packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModel.kt
index 7b0e7f4..ea4122a 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneSceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModel.kt
@@ -29,11 +29,11 @@
 import dagger.assisted.AssistedInject
 import kotlinx.coroutines.flow.map
 
-class GoneSceneActionsViewModel
+class GoneUserActionsViewModel
 @AssistedInject
 constructor(
     private val shadeInteractor: ShadeInteractor,
-) : SceneActionsViewModel() {
+) : UserActionsViewModel() {
 
     override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
         shadeInteractor.shadeMode
@@ -69,6 +69,6 @@
 
     @AssistedFactory
     interface Factory {
-        fun create(): GoneSceneActionsViewModel
+        fun create(): GoneUserActionsViewModel
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/UserActionsViewModel.kt
similarity index 91%
rename from packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneActionsViewModel.kt
rename to packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/UserActionsViewModel.kt
index 0766130..57628d0 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/UserActionsViewModel.kt
@@ -25,15 +25,13 @@
 import kotlinx.coroutines.flow.asStateFlow
 
 /**
- * Base class for view-models that need to keep a map of scene actions (also known as "destination
- * scenes") up-to-date.
+ * Base class for view-models that need to keep a map of user actions up-to-date.
  *
  * Subclasses need only to override [hydrateActions], suspending forever if they need; they don't
  * need to worry about resetting the value of [actions] when the view-model is deactivated/canceled,
  * this base class takes care of it.
  */
-// TODO(b/363206563): Rename to UserActionsViewModel.
-abstract class SceneActionsViewModel : ExclusiveActivatable() {
+abstract class UserActionsViewModel : ExclusiveActivatable() {
 
     private val _actions = MutableStateFlow<Map<UserAction, UserActionResult>>(emptyMap())
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
index 7e0454c..3f3ad13 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
@@ -49,6 +49,7 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.Flags;
 import com.android.systemui.biometrics.AuthController;
+import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlags;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.communal.domain.interactor.CommunalInteractor;
 import com.android.systemui.dagger.SysUISingleton;
@@ -342,6 +343,12 @@
                     this::setKeyguardOccluded
             );
         }
+        if (ComposeBouncerFlags.INSTANCE.isComposeBouncerOrSceneContainerEnabled()) {
+            collectFlow(mWindowRootView, mNotificationShadeWindowModel.isBouncerShowing(),
+                    this::setBouncerShowing);
+            collectFlow(mWindowRootView, mNotificationShadeWindowModel.getDoesBouncerRequireIme(),
+                    this::setKeyguardNeedsInput);
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModel.kt
index 9c4bf1f..9655d92 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModel.kt
@@ -16,16 +16,25 @@
 
 package com.android.systemui.shade.ui.viewmodel
 
+import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlags
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.Edge
 import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
 import com.android.systemui.keyguard.shared.model.KeyguardState.GLANCEABLE_HUB
 import com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.util.kotlin.BooleanFlowOperators.any
+import com.android.systemui.util.kotlin.sample
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flow
 import kotlinx.coroutines.flow.map
 
 /** Models UI state for the shade window. */
@@ -34,6 +43,9 @@
 @Inject
 constructor(
     keyguardTransitionInteractor: KeyguardTransitionInteractor,
+    sceneInteractor: dagger.Lazy<SceneInteractor>,
+    authenticationInteractor: dagger.Lazy<AuthenticationInteractor>,
+    primaryBouncerInteractor: PrimaryBouncerInteractor,
 ) {
     /**
      * Considered to be occluded if in OCCLUDED, DREAMING, GLANCEABLE_HUB/Communal, or transitioning
@@ -70,4 +82,53 @@
                 ),
             )
             .any()
+
+    /**
+     * Whether bouncer is currently showing or not.
+     *
+     * Applicable only when either [SceneContainerFlag] or [ComposeBouncerFlags] are enabled,
+     * otherwise it throws an error.
+     */
+    val isBouncerShowing: Flow<Boolean> =
+        when {
+            SceneContainerFlag.isEnabled -> {
+                sceneInteractor.get().transitionState.map { it.isIdle(Scenes.Bouncer) }
+            }
+            ComposeBouncerFlags.isOnlyComposeBouncerEnabled() -> primaryBouncerInteractor.isShowing
+            else ->
+                flow {
+                    error(
+                        "Consume this flow only when SceneContainerFlag " +
+                            "or ComposeBouncerFlags are enabled"
+                    )
+                }
+        }.distinctUntilChanged()
+
+    /**
+     * Whether the bouncer currently require IME for device entry.
+     *
+     * This emits true when the authentication method is set to password and the bouncer is
+     * currently showing. Throws an error when this is used without either [SceneContainerFlag] or
+     * [ComposeBouncerFlags]
+     */
+    val doesBouncerRequireIme: Flow<Boolean> =
+        if (ComposeBouncerFlags.isComposeBouncerOrSceneContainerEnabled()) {
+                // This is required to make the window, where the bouncer resides,
+                // focusable. InputMethodManager allows IME to be shown only for views
+                // in windows that do not have the FLAG_NOT_FOCUSABLE flag.
+
+                isBouncerShowing
+                    .sample(authenticationInteractor.get().authenticationMethod, ::Pair)
+                    .map { (showing, authMethod) ->
+                        showing && authMethod == AuthenticationMethodModel.Password
+                    }
+            } else {
+                flow {
+                    error(
+                        "Consume this flow only when SceneContainerFlag " +
+                            "or ComposeBouncerFlags are enabled"
+                    )
+                }
+            }
+            .distinctUntilChanged()
 }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModel.kt
index 7c70759..ce4c081 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModel.kt
@@ -43,7 +43,7 @@
 /**
  * Models UI state used to render the content of the shade scene.
  *
- * Different from [ShadeSceneActionsViewModel], which only models user actions that can be performed
+ * Different from [ShadeUserActionsViewModel], which only models user actions that can be performed
  * to navigate to other scenes.
  */
 class ShadeSceneContentViewModel
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModel.kt
similarity index 93%
rename from packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModel.kt
rename to packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModel.kt
index ab71913..f8a850a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModel.kt
@@ -24,7 +24,7 @@
 import com.android.systemui.scene.shared.model.SceneFamilies
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.shared.model.TransitionKeys.ToSplitShade
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.shade.shared.model.ShadeMode
 import dagger.assisted.AssistedFactory
@@ -36,12 +36,12 @@
  *
  * Different from the [ShadeSceneContentViewModel] which models the _content_ of the scene.
  */
-class ShadeSceneActionsViewModel
+class ShadeUserActionsViewModel
 @AssistedInject
 constructor(
     private val qsSceneAdapter: QSSceneAdapter,
     private val shadeInteractor: ShadeInteractor,
-) : SceneActionsViewModel() {
+) : UserActionsViewModel() {
 
     override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
         combine(
@@ -71,6 +71,6 @@
 
     @AssistedFactory
     interface Factory {
-        fun create(): ShadeSceneActionsViewModel
+        fun create(): ShadeUserActionsViewModel
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ImmersiveModeConfirmation.java b/packages/SystemUI/src/com/android/systemui/statusbar/ImmersiveModeConfirmation.java
index 2b9daef..5ef5a7d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ImmersiveModeConfirmation.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ImmersiveModeConfirmation.java
@@ -79,6 +79,7 @@
 import com.android.app.viewcapture.ViewCapture;
 import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
 import com.android.systemui.CoreStartable;
+import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.res.R;
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.shared.system.TaskStackChangeListeners;
@@ -107,6 +108,7 @@
     private Context mDisplayContext;
     private final Context mSysUiContext;
     private final Handler mHandler = new H(Looper.getMainLooper());
+    private final Handler mBackgroundHandler;
     private long mShowDelayMs = 0L;
     private final IBinder mWindowToken = new Binder();
     private final CommandQueue mCommandQueue;
@@ -139,7 +141,8 @@
     @Inject
     public ImmersiveModeConfirmation(Context context, CommandQueue commandQueue,
                                      SecureSettings secureSettings,
-                                     dagger.Lazy<ViewCapture> daggerLazyViewCapture) {
+                                     dagger.Lazy<ViewCapture> daggerLazyViewCapture,
+                                     @Background Handler backgroundHandler) {
         mSysUiContext = context;
         final Display display = mSysUiContext.getDisplay();
         mDisplayContext = display.getDisplayId() == DEFAULT_DISPLAY
@@ -147,6 +150,7 @@
         mCommandQueue = commandQueue;
         mSecureSettings = secureSettings;
         mLazyViewCapture = toKotlinLazy(daggerLazyViewCapture);
+        mBackgroundHandler = backgroundHandler;
     }
 
     boolean loadSetting(int currentUserId) {
@@ -329,7 +333,7 @@
                 }
             }
             TaskStackChangeListeners.getInstance().registerTaskStackListener(this);
-            mContentObserver = new ContentObserver(mHandler) {
+            mContentObserver = new ContentObserver(mBackgroundHandler) {
                 @Override
                 public void onChange(boolean selfChange) {
                     onSettingChanged(mSysUiContext.getUserId());
@@ -343,6 +347,9 @@
             mSecureSettings.registerContentObserverForUserSync(
                     Settings.Secure.USER_SETUP_COMPLETE, mContentObserver,
                     UserHandle.USER_CURRENT);
+            mBackgroundHandler.post(() -> {
+                loadSetting(UserHandle.USER_CURRENT);
+            });
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 2b44c2f..87f360e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -415,8 +415,8 @@
         if (!levelEquals) {
             setImageLevel(icon.iconLevel);
         }
-        if (usesModeIcons()) {
-            setScaleType(icon.shape == Shape.FIXED_SPACE ? ScaleType.FIT_CENTER : ScaleType.CENTER);
+        if (usesModeIcons() && icon.shape == Shape.FIXED_SPACE) {
+            setScaleType(ScaleType.FIT_CENTER);
         }
         if (!visibilityEquals) {
             setVisibility(icon.visible && !mBlocked ? VISIBLE : GONE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
index 3a2f95e..6d0148a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
@@ -22,7 +22,7 @@
 import androidx.annotation.VisibleForTesting;
 
 import com.android.systemui.Dumpable;
-import com.android.systemui.communal.domain.interactor.CommunalInteractor;
+import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dump.DumpManager;
@@ -32,6 +32,7 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.scene.shared.flag.SceneContainerFlag;
 import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractor;
+import com.android.systemui.shade.domain.interactor.ShadeInteractor;
 import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
 import com.android.systemui.statusbar.notification.collection.GroupEntry;
 import com.android.systemui.statusbar.notification.collection.ListEntry;
@@ -43,6 +44,7 @@
 import com.android.systemui.statusbar.notification.shared.NotificationMinimalismPrototype;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.util.concurrency.DelayableExecutor;
+import com.android.systemui.util.kotlin.BooleanFlowOperators;
 import com.android.systemui.util.kotlin.JavaAdapter;
 
 import java.io.PrintWriter;
@@ -70,7 +72,8 @@
     private final VisibilityLocationProvider mVisibilityLocationProvider;
     private final VisualStabilityProvider mVisualStabilityProvider;
     private final WakefulnessLifecycle mWakefulnessLifecycle;
-    private final CommunalInteractor mCommunalInteractor;
+    private final CommunalSceneInteractor mCommunalSceneInteractor;
+    private final ShadeInteractor mShadeInteractor;
     private final KeyguardTransitionInteractor mKeyguardTransitionInteractor;
     private final VisualStabilityCoordinatorLogger mLogger;
 
@@ -110,7 +113,8 @@
             VisibilityLocationProvider visibilityLocationProvider,
             VisualStabilityProvider visualStabilityProvider,
             WakefulnessLifecycle wakefulnessLifecycle,
-            CommunalInteractor communalInteractor,
+            CommunalSceneInteractor communalSceneInteractor,
+            ShadeInteractor shadeInteractor,
             KeyguardTransitionInteractor keyguardTransitionInteractor,
             VisualStabilityCoordinatorLogger logger) {
         mHeadsUpManager = headsUpManager;
@@ -122,7 +126,8 @@
         mWakefulnessLifecycle = wakefulnessLifecycle;
         mStatusBarStateController = statusBarStateController;
         mDelayableExecutor = delayableExecutor;
-        mCommunalInteractor = communalInteractor;
+        mCommunalSceneInteractor = communalSceneInteractor;
+        mShadeInteractor = shadeInteractor;
         mKeyguardTransitionInteractor = keyguardTransitionInteractor;
         mLogger = logger;
 
@@ -141,7 +146,11 @@
                 this::onShadeOrQsClosingChanged);
         mJavaAdapter.alwaysCollectFlow(mShadeAnimationInteractor.isLaunchingActivity(),
                 this::onLaunchingActivityChanged);
-        mJavaAdapter.alwaysCollectFlow(mCommunalInteractor.isIdleOnCommunal(),
+        mJavaAdapter.alwaysCollectFlow(
+                BooleanFlowOperators.INSTANCE.allOf(
+                        mCommunalSceneInteractor.isIdleOnCommunal(),
+                        BooleanFlowOperators.INSTANCE.not(mShadeInteractor.isAnyFullyExpanded())
+                ),
                 this::onCommunalShowingChanged);
 
         if (SceneContainerFlag.isEnabled()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/Notifications.proto b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/Notifications.proto
index ce4356a..18d4a04 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/Notifications.proto
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/Notifications.proto
@@ -18,7 +18,7 @@
 
 /**
  * NotificationList proto from atoms.proto, duplicated here so that it's accessible in the build.
- * Must be kept in sync with the version in atoms.proto.
+ * Must be kept in sync with the version in stats/atoms/sysui/sysui_atoms.proto.
  */
 
 message Notification {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
index 2f3719a..1431b28 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
@@ -533,8 +533,15 @@
         if (mDozeAmount == 1.0f && !isPulseExpanding()) {
             return mShelf.getHeight();
         }
-        int height = (int) Math.max(mLayoutMinHeight,
-                Math.min(mLayoutHeight, mContentHeight) - mTopPadding);
+        int height;
+        if (SceneContainerFlag.isEnabled()) {
+            // TODO(b/192348384): This is probably incorrect as mContentHeight is not up to date.
+            //  Consider removing usages of getInnerHeight in flexiglass if possible.
+            height = (int) Math.min(mLayoutHeight, mContentHeight) - mTopPadding;
+        } else {
+            height = (int) Math.max(mLayoutMinHeight,
+                    Math.min(mLayoutHeight, mContentHeight) - mTopPadding);
+        }
         if (ignorePulseHeight) {
             return height;
         }
@@ -571,6 +578,7 @@
     }
 
     public void setLayoutMinHeight(int layoutMinHeight) {
+        SceneContainerFlag.assertInLegacyMode();
         mLayoutMinHeight = layoutMinHeight;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 036e21c..48e69893 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -1308,8 +1308,10 @@
     }
 
     private void updateAlgorithmLayoutMinHeight() {
-        mAmbientState.setLayoutMinHeight(mQsFullScreen || isHeadsUpTransition()
-                ? getLayoutMinHeightInternal() : 0);
+        if (!SceneContainerFlag.isEnabled()) {
+            mAmbientState.setLayoutMinHeight(mQsFullScreen || isHeadsUpTransition()
+                    ? getLayoutMinHeightInternal() : 0);
+        }
     }
 
     /**
@@ -2799,6 +2801,7 @@
     }
 
     private int getLayoutMinHeightInternal() {
+        SceneContainerFlag.assertInLegacyMode();
         if (isHeadsUpTransition()) {
             ExpandableNotificationRow trackedHeadsUpRow = mAmbientState.getTrackedHeadsUpRow();
             if (trackedHeadsUpRow.isAboveShelf()) {
@@ -3707,7 +3710,7 @@
         if (!isScrollingEnabled()) {
             return false;
         }
-        if (isInsideQsHeader(ev) && !mIsBeingDragged) {
+        if (!isInScrollableRegion(ev) && !mIsBeingDragged) {
             return false;
         }
         mForcedScroll = null;
@@ -3875,11 +3878,26 @@
         return mFlingAfterUpEvent;
     }
 
-    protected boolean isInsideQsHeader(MotionEvent ev) {
-        if (SceneContainerFlag.isEnabled()) {
-            return ev.getY() < mAmbientState.getStackTop();
+    /** Is this touch event inside the scrollable region? */
+    @VisibleForTesting
+    boolean isInScrollableRegion(MotionEvent ev) {
+        if (!SceneContainerFlag.isEnabled()) {
+            return !isInsideQsHeader(ev);
+        }
+        ShadeScrimShape shape = mScrollViewFields.getScrimClippingShape();
+        if (shape == null) {
+            return true; // When there is no scrim, consider this event scrollable.
         }
 
+        ShadeScrimBounds bounds = shape.getBounds();
+        return ev.getX() >= bounds.getLeft()
+                && ev.getX() <= bounds.getRight()
+                && ev.getY() >= bounds.getTop()
+                && ev.getY() <= bounds.getBottom();
+    }
+
+    protected boolean isInsideQsHeader(MotionEvent ev) {
+        SceneContainerFlag.assertInLegacyMode();
         if (QSComposeFragment.isEnabled()) {
             if (mQSHeaderBoundsProvider == null) {
                 return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
index 2e1ab38..bb5aa23 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
@@ -20,16 +20,17 @@
 import android.graphics.Rect
 import android.os.LocaleList
 import android.view.View.LAYOUT_DIRECTION_RTL
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener
-import javax.inject.Inject
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
 
-@SysUISingleton
-class ConfigurationControllerImpl @Inject constructor(
-        @Application context: Context,
-        ) : ConfigurationController {
+class ConfigurationControllerImpl
+@AssistedInject
+constructor(
+    @Assisted private val context: Context,
+) : ConfigurationController {
 
     private val listeners: MutableList<ConfigurationListener> = ArrayList()
     private val lastConfig = Configuration()
@@ -40,18 +41,17 @@
     private val inCarMode: Boolean
     private var uiMode: Int = 0
     private var localeList: LocaleList? = null
-    private val context: Context
     private var layoutDirection: Int
     private var orientation = Configuration.ORIENTATION_UNDEFINED
 
     init {
         val currentConfig = context.resources.configuration
-        this.context = context
         fontScale = currentConfig.fontScale
         density = currentConfig.densityDpi
         smallestScreenWidth = currentConfig.smallestScreenWidthDp
         maxBounds.set(currentConfig.windowConfiguration.maxBounds)
-        inCarMode = currentConfig.uiMode and Configuration.UI_MODE_TYPE_MASK ==
+        inCarMode =
+            currentConfig.uiMode and Configuration.UI_MODE_TYPE_MASK ==
                 Configuration.UI_MODE_TYPE_CAR
         uiMode = currentConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK
         localeList = currentConfig.locales
@@ -60,29 +60,20 @@
 
     override fun notifyThemeChanged() {
         // Avoid concurrent modification exception
-        val listeners = synchronized(this.listeners) {
-           ArrayList(this.listeners)
-        }
+        val listeners = synchronized(this.listeners) { ArrayList(this.listeners) }
 
-        listeners.filterForEach({ this.listeners.contains(it) }) {
-            it.onThemeChanged()
-        }
+        listeners.filterForEach({ this.listeners.contains(it) }) { it.onThemeChanged() }
     }
 
     override fun onConfigurationChanged(newConfig: Configuration) {
         // Avoid concurrent modification exception
-        val listeners = synchronized(this.listeners) {
-           ArrayList(this.listeners)
-        }
-        listeners.filterForEach({ this.listeners.contains(it) }) {
-            it.onConfigChanged(newConfig)
-        }
+        val listeners = synchronized(this.listeners) { ArrayList(this.listeners) }
+        listeners.filterForEach({ this.listeners.contains(it) }) { it.onConfigChanged(newConfig) }
         val fontScale = newConfig.fontScale
         val density = newConfig.densityDpi
         val uiMode = newConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK
         val uiModeChanged = uiMode != this.uiMode
-        if (density != this.density || fontScale != this.fontScale ||
-                inCarMode && uiModeChanged) {
+        if (density != this.density || fontScale != this.fontScale || inCarMode && uiModeChanged) {
             listeners.filterForEach({ this.listeners.contains(it) }) {
                 it.onDensityOrFontScaleChanged()
             }
@@ -105,17 +96,13 @@
             // would be a direct reference to windowConfiguration.maxBounds, so the if statement
             // above would always fail. See b/245799099 for more information.
             this.maxBounds.set(maxBounds)
-            listeners.filterForEach({ this.listeners.contains(it) }) {
-                it.onMaxBoundsChanged()
-            }
+            listeners.filterForEach({ this.listeners.contains(it) }) { it.onMaxBoundsChanged() }
         }
 
         val localeList = newConfig.locales
         if (localeList != this.localeList) {
             this.localeList = localeList
-            listeners.filterForEach({ this.listeners.contains(it) }) {
-                it.onLocaleListChanged()
-            }
+            listeners.filterForEach({ this.listeners.contains(it) }) { it.onLocaleListChanged() }
         }
 
         if (uiModeChanged) {
@@ -124,9 +111,7 @@
             context.theme.applyStyle(context.themeResId, true)
 
             this.uiMode = uiMode
-            listeners.filterForEach({ this.listeners.contains(it) }) {
-                it.onUiModeChanged()
-            }
+            listeners.filterForEach({ this.listeners.contains(it) }) { it.onUiModeChanged() }
         }
 
         if (layoutDirection != newConfig.layoutDirection) {
@@ -137,9 +122,7 @@
         }
 
         if (lastConfig.updateFrom(newConfig) and ActivityInfo.CONFIG_ASSETS_PATHS != 0) {
-            listeners.filterForEach({ this.listeners.contains(it) }) {
-                it.onThemeChanged()
-            }
+            listeners.filterForEach({ this.listeners.contains(it) }) { it.onThemeChanged() }
         }
 
         val newOrientation = newConfig.orientation
@@ -152,16 +135,12 @@
     }
 
     override fun addCallback(listener: ConfigurationListener) {
-        synchronized(listeners) {
-            listeners.add(listener)
-        }
+        synchronized(listeners) { listeners.add(listener) }
         listener.onDensityOrFontScaleChanged()
     }
 
     override fun removeCallback(listener: ConfigurationListener) {
-        synchronized(listeners) {
-            listeners.remove(listener)
-        }
+        synchronized(listeners) { listeners.remove(listener) }
     }
 
     override fun isLayoutRtl(): Boolean {
@@ -176,6 +155,15 @@
             else -> "err"
         }
     }
+
+    @AssistedFactory
+    interface Factory {
+        /**
+         * Creates a [ConfigurationController] that uses [context] to resolve the current
+         * configuration and resources.
+         */
+        fun create(context: Context): ConfigurationControllerImpl
+    }
 }
 
 // This could be done with a Collection.filter and Collection.forEach, but Collection.filter
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerStartable.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerStartable.kt
index 90ebaf2..8f4279e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerStartable.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.phone
 
 import com.android.systemui.CoreStartable
+import com.android.systemui.common.ui.GlobalConfig
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener
@@ -26,7 +27,7 @@
 class ConfigurationControllerStartable
 @Inject
 constructor(
-    private val configurationController: ConfigurationController,
+    @GlobalConfig private val configurationController: ConfigurationController,
     private val listeners: Set<@JvmSuppressWildcards ConfigurationListener>
 ) : CoreStartable {
     override fun start() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index c3da7fc..178c318 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -435,13 +435,14 @@
 
     /** Should only be called from {@link KeyguardStatusBarViewController}. */
     void onOverlayChanged() {
-        int theme = Utils.getThemeAttr(mContext, com.android.internal.R.attr.textAppearanceSmall);
-        mCarrierLabel.setTextAppearance(theme);
+        final int carrierTheme = R.style.TextAppearance_StatusBar_Clock;
+        mCarrierLabel.setTextAppearance(carrierTheme);
         mBatteryView.updatePercentView();
 
+        final int userSwitcherTheme = R.style.TextAppearance_StatusBar_UserChip;
         TextView userSwitcherName = mUserSwitcherContainer.findViewById(R.id.current_user_name);
         if (userSwitcherName != null) {
-            userSwitcherName.setTextAppearance(theme);
+            userSwitcherName.setTextAppearance(userSwitcherTheme);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
index 6cebcbd..b81af86 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
@@ -23,7 +23,9 @@
 import com.android.internal.R;
 import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager;
 import com.android.settingslib.notification.modes.ZenIconLoader;
+import com.android.systemui.common.ui.GlobalConfig;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Application;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dagger.qualifiers.UiBackground;
 import com.android.systemui.log.LogBuffer;
@@ -103,9 +105,12 @@
     @Binds
     CastController provideCastController(CastControllerImpl controllerImpl);
 
-    /** */
+    /**
+     * @deprecated: unscoped configuration controller shouldn't be injected as it might lead to
+     * wrong updates in case of secondary displays.
+     */
     @Binds
-    ConfigurationController bindConfigurationController(ConfigurationControllerImpl impl);
+    ConfigurationController bindConfigurationController(@GlobalConfig ConfigurationController impl);
 
     /** */
     @Binds
@@ -181,6 +186,15 @@
             DevicePostureControllerImpl devicePostureControllerImpl);
 
     /** */
+    @Provides
+    @SysUISingleton
+    @GlobalConfig
+    static ConfigurationController provideGlobalConfigurationController(
+            @Application Context context, ConfigurationControllerImpl.Factory factory) {
+        return factory.create(context);
+    }
+
+    /** */
     @SysUISingleton
     @Provides
     static AccessPointControllerImpl  provideAccessPointControllerImpl(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt
index 93c631f..dbeaa59 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt
@@ -83,19 +83,21 @@
     /** Flow returning the currently active mode(s), if any. */
     val activeModes: Flow<ActiveZenModes> =
         modes
-            .map { modes ->
-                val activeModesList =
-                    modes
-                        .filter { mode -> mode.isActive }
-                        .sortedWith(ZenMode.PRIORITIZING_COMPARATOR)
-                val mainActiveMode =
-                    activeModesList.firstOrNull()?.let { ZenModeInfo(it.name, getModeIcon(it)) }
-
-                ActiveZenModes(activeModesList.map { m -> m.name }, mainActiveMode)
-            }
+            .map { modes -> buildActiveZenModes(modes) }
             .flowOn(bgDispatcher)
             .distinctUntilChanged()
 
+    suspend fun getActiveModes() = buildActiveZenModes(zenModeRepository.getModes())
+
+    private suspend fun buildActiveZenModes(modes: List<ZenMode>): ActiveZenModes {
+        val activeModesList =
+            modes.filter { mode -> mode.isActive }.sortedWith(ZenMode.PRIORITIZING_COMPARATOR)
+        val mainActiveMode =
+            activeModesList.firstOrNull()?.let { ZenModeInfo(it.name, getModeIcon(it)) }
+
+        return ActiveZenModes(activeModesList.map { m -> m.name }, mainActiveMode)
+    }
+
     val mainActiveMode: Flow<ZenModeInfo?> =
         activeModes.map { a -> a.mainMode }.distinctUntilChanged()
 
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index 28effe9..8934d8f 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -1280,6 +1280,8 @@
 
     private final class Receiver extends BroadcastReceiver {
 
+        private static final int STREAM_UNKNOWN = -1;
+
         public void init() {
             final IntentFilter filter = new IntentFilter();
             filter.addAction(AudioManager.VOLUME_CHANGED_ACTION);
@@ -1301,30 +1303,39 @@
             final String action = intent.getAction();
             boolean changed = false;
             if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) {
-                final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
+                final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE,
+                        STREAM_UNKNOWN);
                 final int level = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1);
                 final int oldLevel = intent
                         .getIntExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, -1);
                 if (D.BUG) Log.d(TAG, "onReceive VOLUME_CHANGED_ACTION stream=" + stream
                         + " level=" + level + " oldLevel=" + oldLevel);
-                changed = updateStreamLevelW(stream, level);
+                if (stream != STREAM_UNKNOWN) {
+                    changed = updateStreamLevelW(stream, level);
+                }
             } else if (action.equals(AudioManager.STREAM_DEVICES_CHANGED_ACTION)) {
-                final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
+                final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE,
+                        STREAM_UNKNOWN);
                 final int devices = intent
                         .getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_DEVICES, -1);
                 final int oldDevices = intent
                         .getIntExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_DEVICES, -1);
                 if (D.BUG) Log.d(TAG, "onReceive STREAM_DEVICES_CHANGED_ACTION stream="
                         + stream + " devices=" + devices + " oldDevices=" + oldDevices);
-                changed = checkRoutedToBluetoothW(stream);
-                changed |= onVolumeChangedW(stream, 0);
+                if (stream != STREAM_UNKNOWN) {
+                    changed |= checkRoutedToBluetoothW(stream);
+                    changed |= onVolumeChangedW(stream, 0);
+                }
             } else if (action.equals(AudioManager.STREAM_MUTE_CHANGED_ACTION)) {
-                final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
+                final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE,
+                        STREAM_UNKNOWN);
                 final boolean muted = intent
                         .getBooleanExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, false);
                 if (D.BUG) Log.d(TAG, "onReceive STREAM_MUTE_CHANGED_ACTION stream=" + stream
                         + " muted=" + muted);
-                changed = updateStreamMuteW(stream, muted);
+                if (stream != STREAM_UNKNOWN) {
+                    changed = updateStreamMuteW(stream, muted);
+                }
             } else if (action.equals(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED)) {
                 if (D.BUG) Log.d(TAG, "onReceive ACTION_EFFECTS_SUPPRESSOR_CHANGED");
                 changed = updateEffectsSuppressorW(mNoMan.getEffectsSuppressor());
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt
index 347605d..43a78035 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt
@@ -19,6 +19,7 @@
 import android.app.ActivityTaskManager
 import android.content.pm.PackageManager
 import android.os.PowerManager
+import android.platform.test.annotations.EnableFlags
 import android.telecom.TelecomManager
 import android.telephony.TelephonyManager
 import android.testing.TestableLooper
@@ -26,14 +27,20 @@
 import androidx.test.filters.SmallTest
 import com.android.internal.logging.MetricsLogger
 import com.android.internal.widget.LockPatternUtils
+import com.android.systemui.Flags
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.haptics.msdl.FakeMSDLPlayer
+import com.android.systemui.haptics.msdl.msdlPlayer
 import com.android.systemui.shade.ShadeController
 import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.testKosmos
 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.time.FakeSystemClock
+import com.google.android.msdl.data.model.MSDLToken
+import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -64,6 +71,8 @@
     val fakeSystemClock = FakeSystemClock()
     val mainExecutor = FakeExecutor(fakeSystemClock)
     val backgroundExecutor = FakeExecutor(fakeSystemClock)
+    private val kosmos = testKosmos()
+    private val msdlPlayer: FakeMSDLPlayer = kosmos.msdlPlayer
 
     lateinit var underTest: EmergencyButtonController
 
@@ -84,6 +93,7 @@
                 mainExecutor,
                 backgroundExecutor,
                 mSelectedUserInteractor,
+                msdlPlayer,
             )
         context.setMockPackageManager(packageManager)
         Mockito.`when`(emergencyButton.context).thenReturn(context)
@@ -113,4 +123,13 @@
                 /* isSecure= */ eq(true)
             )
     }
+
+    @Test
+    @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+    fun takeEmergencyCallAction_withMSDLFeedback_playsEmergencyButtonTokenAndNullAttributes() {
+        underTest.takeEmergencyCallAction()
+
+        assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.KEYPRESS_RETURN)
+        assertThat(msdlPlayer.latestPropertiesPlayed).isNull()
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
index 88bfcf0..a1bea06 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
@@ -39,8 +39,6 @@
 import com.android.internal.logging.testing.FakeMetricsLogger;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.classifier.FalsingDataProvider.GestureFinalizedListener;
-import com.android.systemui.flags.FakeFeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
@@ -84,7 +82,6 @@
     private AccessibilityManager mAccessibilityManager;
 
     private final FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
-    private final FakeFeatureFlags mFakeFeatureFlags = new FakeFeatureFlags();
 
     private final FalsingClassifier.Result mFalsedResult =
             FalsingClassifier.Result.falsed(1, getClass().getSimpleName(), "");
@@ -110,7 +107,7 @@
         mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider,
                 mMetricsLogger, mClassifiers, mSingleTapClassfier, mLongTapClassifier,
                 mDoubleTapClassifier, mHistoryTracker, mKeyguardStateController,
-                mAccessibilityManager, false, mFakeFeatureFlags);
+                mAccessibilityManager, false);
 
 
         ArgumentCaptor<GestureFinalizedListener> gestureCompleteListenerCaptor =
@@ -120,7 +117,6 @@
                 gestureCompleteListenerCaptor.capture());
 
         mGestureFinalizedListener = gestureCompleteListenerCaptor.getValue();
-        mFakeFeatureFlags.set(Flags.FALSING_OFF_FOR_UNFOLDED, true);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt
index 933ddb5..4a80d72 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt
@@ -21,7 +21,7 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.haptics.vibratorHelper
+import com.android.systemui.haptics.fakeVibratorHelper
 import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.time.fakeSystemClock
@@ -47,6 +47,7 @@
     private val lowTickDuration = 12 // Mocked duration of a low tick
     private val dragTextureThresholdMillis =
         lowTickDuration * config.numberOfLowTicks + config.deltaMillisForDragInterval
+    private val vibratorHelper = kosmos.fakeVibratorHelper
     private lateinit var sliderHapticFeedbackProvider: SliderHapticFeedbackProvider
 
     @Before
@@ -56,11 +57,11 @@
         whenever(velocityTracker.getAxisVelocity(config.velocityAxis))
             .thenReturn(config.maxVelocityToScale)
 
-        kosmos.vibratorHelper.primitiveDurations[VibrationEffect.Composition.PRIMITIVE_LOW_TICK] =
+        vibratorHelper.primitiveDurations[VibrationEffect.Composition.PRIMITIVE_LOW_TICK] =
             lowTickDuration
         sliderHapticFeedbackProvider =
             SliderHapticFeedbackProvider(
-                kosmos.vibratorHelper,
+                vibratorHelper,
                 velocityTracker,
                 config,
                 kosmos.fakeSystemClock,
@@ -136,7 +137,7 @@
             sliderHapticFeedbackProvider.onUpperBookend()
             sliderHapticFeedbackProvider.onUpperBookend()
 
-            assertEquals(/* expected=*/ 1, vibratorHelper.timesVibratedWithEffect(vibration))
+            assertEquals(/* expected= */ 1, vibratorHelper.timesVibratedWithEffect(vibration))
         }
 
     @Test
@@ -162,7 +163,7 @@
             sliderHapticFeedbackProvider.onProgress(progress)
 
             // THEN the correct composition only plays once
-            assertEquals(/* expected=*/ 1, vibratorHelper.timesVibratedWithEffect(ticks.compose()))
+            assertEquals(/* expected= */ 1, vibratorHelper.timesVibratedWithEffect(ticks.compose()))
         }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialNotificationCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialNotificationCoordinatorTest.kt
new file mode 100644
index 0000000..945f953
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialNotificationCoordinatorTest.kt
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2024 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.inputdevice.tutorial.domain.interactor
+
+import android.app.Notification
+import android.app.NotificationManager
+import androidx.annotation.StringRes
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.inputdevice.tutorial.data.repository.TutorialSchedulerRepository
+import com.android.systemui.inputdevice.tutorial.ui.TutorialNotificationCoordinator
+import com.android.systemui.keyboard.data.repository.FakeKeyboardRepository
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.res.R
+import com.android.systemui.touchpad.data.repository.FakeTouchpadRepository
+import com.google.common.truth.Truth.assertThat
+import kotlin.time.Duration.Companion.hours
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.advanceTimeBy
+import kotlinx.coroutines.test.runTest
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.junit.MockitoJUnit
+import org.mockito.kotlin.any
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.never
+import org.mockito.kotlin.verify
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class TutorialNotificationCoordinatorTest : SysuiTestCase() {
+
+    private lateinit var underTest: TutorialNotificationCoordinator
+    private val kosmos = Kosmos()
+    private val testScope = kosmos.testScope
+    private val keyboardRepository = FakeKeyboardRepository()
+    private val touchpadRepository = FakeTouchpadRepository()
+    private lateinit var dataStoreScope: CoroutineScope
+    private lateinit var repository: TutorialSchedulerRepository
+    @Mock private lateinit var notificationManager: NotificationManager
+    @Captor private lateinit var notificationCaptor: ArgumentCaptor<Notification>
+    @get:Rule val rule = MockitoJUnit.rule()
+
+    @Before
+    fun setup() {
+        dataStoreScope = CoroutineScope(Dispatchers.Unconfined)
+        repository =
+            TutorialSchedulerRepository(
+                context,
+                dataStoreScope,
+                dataStoreName = "TutorialNotificationCoordinatorTest"
+            )
+        val interactor =
+            TutorialSchedulerInteractor(keyboardRepository, touchpadRepository, repository)
+        underTest =
+            TutorialNotificationCoordinator(
+                testScope.backgroundScope,
+                context,
+                interactor,
+                notificationManager
+            )
+        notificationCaptor = ArgumentCaptor.forClass(Notification::class.java)
+        underTest.start()
+    }
+
+    @After
+    fun clear() {
+        runBlocking { repository.clearDataStore() }
+        dataStoreScope.cancel()
+    }
+
+    @Test
+    fun showKeyboardNotification() =
+        testScope.runTest {
+            keyboardRepository.setIsAnyKeyboardConnected(true)
+            advanceTimeBy(LAUNCH_DELAY)
+            verifyNotification(
+                R.string.launch_keyboard_tutorial_notification_title,
+                R.string.launch_keyboard_tutorial_notification_content
+            )
+        }
+
+    @Test
+    fun showTouchpadNotification() =
+        testScope.runTest {
+            touchpadRepository.setIsAnyTouchpadConnected(true)
+            advanceTimeBy(LAUNCH_DELAY)
+            verifyNotification(
+                R.string.launch_touchpad_tutorial_notification_title,
+                R.string.launch_touchpad_tutorial_notification_content
+            )
+        }
+
+    @Test
+    fun showKeyboardTouchpadNotification() =
+        testScope.runTest {
+            keyboardRepository.setIsAnyKeyboardConnected(true)
+            touchpadRepository.setIsAnyTouchpadConnected(true)
+            advanceTimeBy(LAUNCH_DELAY)
+            verifyNotification(
+                R.string.launch_keyboard_touchpad_tutorial_notification_title,
+                R.string.launch_keyboard_touchpad_tutorial_notification_content
+            )
+        }
+
+    @Test
+    fun doNotShowNotification() =
+        testScope.runTest {
+            advanceTimeBy(LAUNCH_DELAY)
+            verify(notificationManager, never()).notify(eq(TAG), eq(NOTIFICATION_ID), any())
+        }
+
+    private fun verifyNotification(@StringRes titleResId: Int, @StringRes contentResId: Int) {
+        verify(notificationManager)
+            .notify(eq(TAG), eq(NOTIFICATION_ID), notificationCaptor.capture())
+        val notification = notificationCaptor.value
+        val actualTitle = notification.getString(Notification.EXTRA_TITLE)
+        val actualContent = notification.getString(Notification.EXTRA_TEXT)
+        assertThat(actualTitle).isEqualTo(context.getString(titleResId))
+        assertThat(actualContent).isEqualTo(context.getString(contentResId))
+    }
+
+    private fun Notification.getString(key: String): String =
+        this.extras?.getCharSequence(key).toString()
+
+    companion object {
+        private const val TAG = "TutorialSchedulerInteractor"
+        private const val NOTIFICATION_ID = 5566
+        private val LAUNCH_DELAY = 72.hours
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractorTest.kt
index 432f7af..650f9dc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractorTest.kt
@@ -32,6 +32,8 @@
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.cancel
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.launch
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.test.advanceTimeBy
 import kotlinx.coroutines.test.runTest
@@ -63,13 +65,7 @@
                 dataStoreName = "TutorialSchedulerInteractorTest"
             )
         underTest =
-            TutorialSchedulerInteractor(
-                testScope.backgroundScope,
-                keyboardRepository,
-                touchpadRepository,
-                schedulerRepository
-            )
-        underTest.start()
+            TutorialSchedulerInteractor(keyboardRepository, touchpadRepository, schedulerRepository)
     }
 
     @After
@@ -81,80 +77,90 @@
     @Test
     fun connectKeyboard_delayElapse_launchForKeyboard() =
         testScope.runTest {
+            launchAndAssert(TutorialType.KEYBOARD)
+
             keyboardRepository.setIsAnyKeyboardConnected(true)
             advanceTimeBy(LAUNCH_DELAY)
-            assertLaunch(TutorialType.KEYBOARD)
         }
 
     @Test
     fun connectBothDevices_delayElapse_launchForBoth() =
         testScope.runTest {
+            launchAndAssert(TutorialType.BOTH)
+
             keyboardRepository.setIsAnyKeyboardConnected(true)
             touchpadRepository.setIsAnyTouchpadConnected(true)
             advanceTimeBy(LAUNCH_DELAY)
-            assertLaunch(TutorialType.BOTH)
         }
 
     @Test
     fun connectBothDevice_delayNotElapse_launchNothing() =
         testScope.runTest {
+            launchAndAssert(TutorialType.NONE)
+
             keyboardRepository.setIsAnyKeyboardConnected(true)
             touchpadRepository.setIsAnyTouchpadConnected(true)
             advanceTimeBy(A_SHORT_PERIOD_OF_TIME)
-            assertLaunch(TutorialType.NONE)
         }
 
     @Test
     fun nothingConnect_delayElapse_launchNothing() =
         testScope.runTest {
+            launchAndAssert(TutorialType.NONE)
+
             keyboardRepository.setIsAnyKeyboardConnected(false)
             touchpadRepository.setIsAnyTouchpadConnected(false)
             advanceTimeBy(LAUNCH_DELAY)
-            assertLaunch(TutorialType.NONE)
         }
 
     @Test
     fun connectKeyboard_thenTouchpad_delayElapse_launchForBoth() =
         testScope.runTest {
+            launchAndAssert(TutorialType.BOTH)
+
             keyboardRepository.setIsAnyKeyboardConnected(true)
             advanceTimeBy(A_SHORT_PERIOD_OF_TIME)
             touchpadRepository.setIsAnyTouchpadConnected(true)
             advanceTimeBy(REMAINING_TIME)
-            assertLaunch(TutorialType.BOTH)
         }
 
     @Test
     fun connectKeyboard_thenTouchpad_removeKeyboard_delayElapse_launchNothing() =
         testScope.runTest {
+            launchAndAssert(TutorialType.NONE)
+
             keyboardRepository.setIsAnyKeyboardConnected(true)
             advanceTimeBy(A_SHORT_PERIOD_OF_TIME)
             touchpadRepository.setIsAnyTouchpadConnected(true)
             keyboardRepository.setIsAnyKeyboardConnected(false)
             advanceTimeBy(REMAINING_TIME)
-            assertLaunch(TutorialType.NONE)
         }
 
-    // TODO: likely to be changed after we update TutorialSchedulerInteractor.launchTutorial
-    private suspend fun assertLaunch(tutorialType: TutorialType) {
-        when (tutorialType) {
-            TutorialType.KEYBOARD -> {
-                assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isTrue()
-                assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isFalse()
-            }
-            TutorialType.TOUCHPAD -> {
-                assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isFalse()
-                assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isTrue()
-            }
-            TutorialType.BOTH -> {
-                assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isTrue()
-                assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isTrue()
-            }
-            TutorialType.NONE -> {
-                assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isFalse()
-                assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isFalse()
+    private suspend fun launchAndAssert(expectedTutorial: TutorialType) =
+        testScope.backgroundScope.launch {
+            val actualTutorial = underTest.tutorials.first()
+            assertThat(actualTutorial).isEqualTo(expectedTutorial)
+
+            // TODO: need to update after we move launch into the tutorial
+            when (expectedTutorial) {
+                TutorialType.KEYBOARD -> {
+                    assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isTrue()
+                    assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isFalse()
+                }
+                TutorialType.TOUCHPAD -> {
+                    assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isFalse()
+                    assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isTrue()
+                }
+                TutorialType.BOTH -> {
+                    assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isTrue()
+                    assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isTrue()
+                }
+                TutorialType.NONE -> {
+                    assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isFalse()
+                    assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isFalse()
+                }
             }
         }
-    }
 
     companion object {
         private val LAUNCH_DELAY = 72.hours
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
index 7de088d..720f2e1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
@@ -404,7 +404,7 @@
         }
 
     @Test
-    @EnableFlags(com.android.systemui.Flags.FLAG_NEW_PICKER_UI)
+    @EnableFlags(com.android.systemui.shared.Flags.FLAG_NEW_CUSTOMIZATION_PICKER_UI)
     fun startButton_inPreviewMode_onPreviewQuickAffordanceSelected() =
         testScope.runTest {
             underTest.onPreviewSlotSelected(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt
index e55cb12..030b172 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt
@@ -19,8 +19,8 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.log.LogcatEchoTrackerAlways
 import com.android.systemui.log.table.TableChange.Companion.IS_INITIAL_PREFIX
-import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
 import java.io.PrintWriter
@@ -57,9 +57,7 @@
                 MAX_SIZE,
                 BUFFER_NAME,
                 systemClock,
-                mock(),
-                testDispatcher,
-                testScope.backgroundScope,
+                LogcatEchoTrackerAlways(),
             )
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt
index 8c62bc2..dfd964f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt
@@ -20,25 +20,20 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
-import com.android.systemui.util.mockito.mock
+import com.android.systemui.log.LogcatEchoTrackerAlways
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.kotlin.mock
 
-@OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class TableLogBufferFactoryTest : SysuiTestCase() {
     private val dumpManager: DumpManager = mock()
     private val systemClock = FakeSystemClock()
-    private val testDispatcher = UnconfinedTestDispatcher()
-    private val testScope = TestScope(testDispatcher)
     private val underTest =
-        TableLogBufferFactory(dumpManager, systemClock, mock(), testDispatcher, testScope)
+        TableLogBufferFactory(dumpManager, systemClock, LogcatEchoTrackerAlways())
 
     @Test
     fun create_alwaysCreatesNewInstance() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt
index ace562b..9c4c862 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt
@@ -23,22 +23,18 @@
 import com.android.systemui.log.core.LogLevel
 import com.android.systemui.log.table.TableChange.Companion.IS_INITIAL_PREFIX
 import com.android.systemui.log.table.TableChange.Companion.MAX_STRING_LENGTH
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.eq
-import com.android.systemui.util.mockito.mock
-import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
 import java.io.PrintWriter
 import java.io.StringWriter
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
 
-@OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class TableLogBufferTest : SysuiTestCase() {
@@ -49,9 +45,6 @@
     private lateinit var logcatEchoTracker: LogcatEchoTracker
     private lateinit var localLogcat: FakeLogProxy
 
-    private val testDispatcher = UnconfinedTestDispatcher()
-    private val testScope = TestScope(testDispatcher)
-
     @Before
     fun setup() {
         localLogcat = FakeLogProxy()
@@ -65,8 +58,6 @@
                 NAME,
                 systemClock,
                 logcatEchoTracker,
-                testDispatcher,
-                testScope.backgroundScope,
                 localLogcat = localLogcat,
             )
     }
@@ -78,8 +69,6 @@
             "name",
             systemClock,
             logcatEchoTracker,
-            testDispatcher,
-            testScope.backgroundScope,
             localLogcat = localLogcat,
         )
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt
index fd53b5ba..ad7a5b6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt
@@ -56,7 +56,6 @@
 import com.android.systemui.flags.Flags.MEDIA_RESUME_PROGRESS
 import com.android.systemui.flags.Flags.MEDIA_RETAIN_RECOMMENDATIONS
 import com.android.systemui.flags.Flags.MEDIA_RETAIN_SESSIONS
-import com.android.systemui.flags.Flags.MEDIA_SESSION_ACTIONS
 import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.kosmos.testDispatcher
 import com.android.systemui.kosmos.testScope
@@ -317,7 +316,6 @@
         whenever(mediaSmartspaceTarget.iconGrid).thenReturn(validRecommendationList)
         whenever(mediaSmartspaceTarget.creationTimeMillis).thenReturn(SMARTSPACE_CREATION_TIME)
         whenever(mediaSmartspaceTarget.expiryTimeMillis).thenReturn(SMARTSPACE_EXPIRY_TIME)
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, false)
         fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, false)
         fakeFeatureFlags.set(MEDIA_RESUME_PROGRESS, false)
         fakeFeatureFlags.set(MEDIA_REMOTE_RESUME, false)
@@ -1671,7 +1669,6 @@
     @Test
     fun testPlaybackActions_noState_usesNotification() {
         val desc = "Notification Action"
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         whenever(controller.playbackState).thenReturn(null)
 
         val notifWithAction =
@@ -1705,7 +1702,6 @@
     @Test
     fun testPlaybackActions_hasPrevNext() {
         val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4")
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         val stateActions =
             PlaybackState.ACTION_PLAY or
                 PlaybackState.ACTION_SKIP_TO_PREVIOUS or
@@ -1749,7 +1745,6 @@
     @Test
     fun testPlaybackActions_noPrevNext_usesCustom() {
         val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4", "custom 5")
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         val stateActions = PlaybackState.ACTION_PLAY
         val stateBuilder = PlaybackState.Builder().setActions(stateActions)
         customDesc.forEach {
@@ -1781,7 +1776,6 @@
 
     @Test
     fun testPlaybackActions_connecting() {
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         val stateActions = PlaybackState.ACTION_PLAY
         val stateBuilder =
             PlaybackState.Builder()
@@ -1802,7 +1796,6 @@
     @Test
     fun testPlaybackActions_reservedSpace() {
         val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4")
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         val stateActions = PlaybackState.ACTION_PLAY
         val stateBuilder = PlaybackState.Builder().setActions(stateActions)
         customDesc.forEach {
@@ -1840,7 +1833,6 @@
 
     @Test
     fun testPlaybackActions_playPause_hasButton() {
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         val stateActions = PlaybackState.ACTION_PLAY_PAUSE
         val stateBuilder = PlaybackState.Builder().setActions(stateActions)
         whenever(controller.playbackState).thenReturn(stateBuilder.build())
@@ -1939,7 +1931,6 @@
 
     @Test
     fun testPlaybackState_PauseWhenFlagTrue_keyExists_callsListener() {
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         val state = PlaybackState.Builder().setState(PlaybackState.STATE_PAUSED, 0L, 1f).build()
         whenever(controller.playbackState).thenReturn(state)
 
@@ -2161,7 +2152,6 @@
     @Test
     fun testRetain_sessionPlayer_notifRemoved_doesNotChange() {
         fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         addPlaybackStateAction()
 
         // When a media control with PlaybackState actions is added, times out,
@@ -2181,7 +2171,6 @@
     @Test
     fun testRetain_sessionPlayer_sessionDestroyed_setToResume() {
         fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         addPlaybackStateAction()
 
         // When a media control with PlaybackState actions is added, times out,
@@ -2215,7 +2204,6 @@
     @Test
     fun testRetain_sessionPlayer_destroyedWhileActive_noResume_fullyRemoved() {
         fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         addPlaybackStateAction()
 
         // When a media control using session actions is added, and then the session is destroyed
@@ -2235,7 +2223,6 @@
     @Test
     fun testRetain_sessionPlayer_canResume_destroyedWhileActive_setToResume() {
         fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         addPlaybackStateAction()
 
         // When a media control using session actions and that does allow resumption is added,
@@ -2268,7 +2255,6 @@
 
     @Test
     fun testSessionPlayer_sessionDestroyed_noResume_fullyRemoved() {
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         addPlaybackStateAction()
 
         // When a media control with PlaybackState actions is added, times out,
@@ -2295,7 +2281,6 @@
 
     @Test
     fun testSessionPlayer_destroyedWhileActive_noResume_fullyRemoved() {
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         addPlaybackStateAction()
 
         // When a media control using session actions is added, and then the session is destroyed
@@ -2314,7 +2299,6 @@
 
     @Test
     fun testSessionPlayer_canResume_destroyedWhileActive_setToResume() {
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         addPlaybackStateAction()
 
         // When a media control using session actions and that does allow resumption is added,
@@ -2348,7 +2332,6 @@
     @Test
     fun testSessionDestroyed_noNotificationKey_stillRemoved() {
         fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
 
         // When a notiifcation is added and then removed before it is fully processed
         mediaDataManager.onNotificationAdded(KEY, mediaNotification)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
index f4c2b47..c0f503d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
@@ -61,7 +61,6 @@
 import com.android.systemui.flags.Flags.MEDIA_RESUME_PROGRESS
 import com.android.systemui.flags.Flags.MEDIA_RETAIN_RECOMMENDATIONS
 import com.android.systemui.flags.Flags.MEDIA_RETAIN_SESSIONS
-import com.android.systemui.flags.Flags.MEDIA_SESSION_ACTIONS
 import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.kosmos.testDispatcher
 import com.android.systemui.kosmos.testScope
@@ -338,7 +337,6 @@
         whenever(mediaSmartspaceTarget.iconGrid).thenReturn(validRecommendationList)
         whenever(mediaSmartspaceTarget.creationTimeMillis).thenReturn(SMARTSPACE_CREATION_TIME)
         whenever(mediaSmartspaceTarget.expiryTimeMillis).thenReturn(SMARTSPACE_EXPIRY_TIME)
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, false)
         fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, false)
         fakeFeatureFlags.set(MEDIA_RESUME_PROGRESS, false)
         fakeFeatureFlags.set(MEDIA_REMOTE_RESUME, false)
@@ -1680,7 +1678,6 @@
     @Test
     fun testPlaybackActions_noState_usesNotification() {
         val desc = "Notification Action"
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         whenever(controller.playbackState).thenReturn(null)
 
         val notifWithAction =
@@ -1714,7 +1711,6 @@
     @Test
     fun testPlaybackActions_hasPrevNext() {
         val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4")
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         val stateActions =
             PlaybackState.ACTION_PLAY or
                 PlaybackState.ACTION_SKIP_TO_PREVIOUS or
@@ -1758,7 +1754,6 @@
     @Test
     fun testPlaybackActions_noPrevNext_usesCustom() {
         val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4", "custom 5")
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         val stateActions = PlaybackState.ACTION_PLAY
         val stateBuilder = PlaybackState.Builder().setActions(stateActions)
         customDesc.forEach {
@@ -1790,7 +1785,6 @@
 
     @Test
     fun testPlaybackActions_connecting() {
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         val stateActions = PlaybackState.ACTION_PLAY
         val stateBuilder =
             PlaybackState.Builder()
@@ -1811,7 +1805,6 @@
     @Test
     @EnableFlags(Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE)
     fun postWithPlaybackActions_drawablesReused() {
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true)
         whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true)
         val stateActions =
@@ -1845,7 +1838,6 @@
     @Test
     @DisableFlags(Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE)
     fun postWithPlaybackActions_drawablesNotReused() {
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true)
         whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true)
         val stateActions =
@@ -1879,7 +1871,6 @@
     @Test
     fun testPlaybackActions_reservedSpace() {
         val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4")
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         val stateActions = PlaybackState.ACTION_PLAY
         val stateBuilder = PlaybackState.Builder().setActions(stateActions)
         customDesc.forEach {
@@ -1917,7 +1908,6 @@
 
     @Test
     fun testPlaybackActions_playPause_hasButton() {
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         val stateActions = PlaybackState.ACTION_PLAY_PAUSE
         val stateBuilder = PlaybackState.Builder().setActions(stateActions)
         whenever(controller.playbackState).thenReturn(stateBuilder.build())
@@ -2016,7 +2006,6 @@
 
     @Test
     fun testPlaybackState_PauseWhenFlagTrue_keyExists_callsListener() {
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         val state = PlaybackState.Builder().setState(PlaybackState.STATE_PAUSED, 0L, 1f).build()
         whenever(controller.playbackState).thenReturn(state)
 
@@ -2237,7 +2226,6 @@
     @Test
     fun testRetain_sessionPlayer_notifRemoved_doesNotChange() {
         fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         addPlaybackStateAction()
 
         // When a media control with PlaybackState actions is added, times out,
@@ -2257,7 +2245,6 @@
     @Test
     fun testRetain_sessionPlayer_sessionDestroyed_setToResume() {
         fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         addPlaybackStateAction()
 
         // When a media control with PlaybackState actions is added, times out,
@@ -2291,7 +2278,6 @@
     @Test
     fun testRetain_sessionPlayer_destroyedWhileActive_noResume_fullyRemoved() {
         fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         addPlaybackStateAction()
 
         // When a media control using session actions is added, and then the session is destroyed
@@ -2311,7 +2297,6 @@
     @Test
     fun testRetain_sessionPlayer_canResume_destroyedWhileActive_setToResume() {
         fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         addPlaybackStateAction()
 
         // When a media control using session actions and that does allow resumption is added,
@@ -2344,7 +2329,6 @@
 
     @Test
     fun testSessionPlayer_sessionDestroyed_noResume_fullyRemoved() {
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         addPlaybackStateAction()
 
         // When a media control with PlaybackState actions is added, times out,
@@ -2371,7 +2355,6 @@
 
     @Test
     fun testSessionPlayer_destroyedWhileActive_noResume_fullyRemoved() {
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         addPlaybackStateAction()
 
         // When a media control using session actions is added, and then the session is destroyed
@@ -2390,7 +2373,6 @@
 
     @Test
     fun testSessionPlayer_canResume_destroyedWhileActive_setToResume() {
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
         addPlaybackStateAction()
 
         // When a media control using session actions and that does allow resumption is added,
@@ -2424,7 +2406,6 @@
     @Test
     fun testSessionDestroyed_noNotificationKey_stillRemoved() {
         fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
-        fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
 
         // When a notiifcation is added and then removed before it is fully processed
         mediaDataProcessor.onNotificationAdded(KEY, mediaNotification)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ModesTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ModesTileTest.kt
index d2dcf4d..848c8db 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ModesTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ModesTileTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.qs.tiles
 
+import android.graphics.drawable.TestStubDrawable
 import android.os.Handler
 import android.platform.test.annotations.EnableFlags
 import android.service.quicksettings.Tile
@@ -26,9 +27,11 @@
 import com.android.internal.logging.MetricsLogger
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.classifier.FalsingManagerFake
+import com.android.systemui.common.shared.model.asIcon
 import com.android.systemui.kosmos.testDispatcher
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.plugins.qs.QSTile
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.qs.QSHost
 import com.android.systemui.qs.QsEventLogger
@@ -36,6 +39,7 @@
 import com.android.systemui.qs.tiles.base.actions.FakeQSTileIntentUserInputHandler
 import com.android.systemui.qs.tiles.impl.modes.domain.interactor.ModesTileDataInteractor
 import com.android.systemui.qs.tiles.impl.modes.domain.interactor.ModesTileUserActionInteractor
+import com.android.systemui.qs.tiles.impl.modes.domain.model.ModesTileModel
 import com.android.systemui.qs.tiles.impl.modes.ui.ModesTileMapper
 import com.android.systemui.qs.tiles.viewmodel.QSTileConfigProvider
 import com.android.systemui.qs.tiles.viewmodel.QSTileConfigTestBuilder
@@ -168,4 +172,43 @@
 
             assertThat(underTest.state.state).isEqualTo(Tile.STATE_ACTIVE)
         }
+
+    @Test
+    fun handleUpdateState_withTileModel_updatesState() =
+        testScope.runTest {
+            val tileState =
+                QSTile.State().apply {
+                    state = Tile.STATE_INACTIVE
+                    secondaryLabel = "Old secondary label"
+                }
+            val model =
+                ModesTileModel(
+                    isActivated = true,
+                    activeModes = listOf("One", "Two"),
+                    icon = TestStubDrawable().asIcon()
+                )
+
+            underTest.handleUpdateState(tileState, model)
+
+            assertThat(tileState.state).isEqualTo(Tile.STATE_ACTIVE)
+            assertThat(tileState.secondaryLabel).isEqualTo("2 modes are active")
+        }
+
+    @Test
+    fun handleUpdateState_withNull_updatesState() =
+        testScope.runTest {
+            val tileState =
+                QSTile.State().apply {
+                    state = Tile.STATE_INACTIVE
+                    secondaryLabel = "Old secondary label"
+                }
+            zenModeRepository.addMode("One", active = true)
+            zenModeRepository.addMode("Two", active = true)
+            runCurrent()
+
+            underTest.handleUpdateState(tileState, null)
+
+            assertThat(tileState.state).isEqualTo(Tile.STATE_ACTIVE)
+            assertThat(tileState.secondaryLabel).isEqualTo("2 modes are active")
+        }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recordissue/CustomTraceStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/recordissue/CustomTraceStateTest.kt
new file mode 100644
index 0000000..d8618fa
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/recordissue/CustomTraceStateTest.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2024 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.recordissue
+
+import android.testing.TestableLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.recordissue.RecordIssueModule.Companion.TILE_SPEC
+import com.android.traceur.PresetTraceConfigs
+import com.google.common.truth.Truth
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.MockitoAnnotations
+
+/**
+ * CustomTraceState is customized Traceur settings for power users. These settings determine what
+ * tracing is used during the Record Issue Quick Settings flow. This class tests that those features
+ * are persistently and accurately stored across sessions.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+class CustomTraceStateTest : SysuiTestCase() {
+
+    private lateinit var underTest: CustomTraceState
+
+    @Before
+    fun setup() {
+        underTest = CustomTraceState(context.getSharedPreferences(TILE_SPEC, 0))
+        MockitoAnnotations.initMocks(this)
+    }
+
+    @Test
+    fun trace_config_is_stored_accurately() {
+        val expected = PresetTraceConfigs.getUiConfig()
+
+        underTest.traceConfig = expected
+
+        val actual = underTest.traceConfig
+        Truth.assertThat(actual.longTrace).isEqualTo(expected.longTrace)
+        Truth.assertThat(actual.maxLongTraceSizeMb).isEqualTo(expected.maxLongTraceSizeMb)
+        Truth.assertThat(actual.maxLongTraceDurationMinutes)
+            .isEqualTo(expected.maxLongTraceDurationMinutes)
+        Truth.assertThat(actual.apps).isEqualTo(expected.apps)
+        Truth.assertThat(actual.winscope).isEqualTo(expected.winscope)
+        Truth.assertThat(actual.attachToBugreport).isEqualTo(expected.attachToBugreport)
+        Truth.assertThat(actual.bufferSizeKb).isEqualTo(expected.bufferSizeKb)
+        Truth.assertThat(actual.tags).isEqualTo(expected.tags)
+    }
+
+    @Test
+    fun trace_config_is_persistently_stored_between_instances() {
+        val expected = PresetTraceConfigs.getUiConfig()
+
+        underTest.traceConfig = expected
+
+        val actual = CustomTraceState(context.getSharedPreferences(TILE_SPEC, 0)).traceConfig
+        Truth.assertThat(actual.longTrace).isEqualTo(expected.longTrace)
+        Truth.assertThat(actual.maxLongTraceSizeMb).isEqualTo(expected.maxLongTraceSizeMb)
+        Truth.assertThat(actual.maxLongTraceDurationMinutes)
+            .isEqualTo(expected.maxLongTraceDurationMinutes)
+        Truth.assertThat(actual.apps).isEqualTo(expected.apps)
+        Truth.assertThat(actual.winscope).isEqualTo(expected.winscope)
+        Truth.assertThat(actual.attachToBugreport).isEqualTo(expected.attachToBugreport)
+        Truth.assertThat(actual.bufferSizeKb).isEqualTo(expected.bufferSizeKb)
+        Truth.assertThat(actual.tags).isEqualTo(expected.tags)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recordissue/IssueRecordingStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/recordissue/IssueRecordingStateTest.kt
new file mode 100644
index 0000000..4ab3c7b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/recordissue/IssueRecordingStateTest.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2024 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.recordissue
+
+import android.testing.TestableLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.settings.userFileManager
+import com.android.systemui.settings.userTracker
+import com.google.common.truth.Truth
+import java.util.concurrent.CountDownLatch
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+class IssueRecordingStateTest : SysuiTestCase() {
+
+    private val kosmos = Kosmos()
+    private lateinit var underTest: IssueRecordingState
+
+    @Before
+    fun setup() {
+        underTest = IssueRecordingState(kosmos.userTracker, kosmos.userFileManager)
+    }
+
+    @Test
+    fun takeBugreport_isSaved_betweenDifferentSessions() {
+        val expected = true
+
+        underTest.takeBugreport = expected
+        underTest = IssueRecordingState(kosmos.userTracker, kosmos.userFileManager)
+
+        Truth.assertThat(underTest.takeBugreport).isEqualTo(expected)
+    }
+
+    @Test
+    fun recordScreen_isSaved_betweenDifferentSessions() {
+        val expected = true
+
+        underTest.recordScreen = expected
+        underTest = IssueRecordingState(kosmos.userTracker, kosmos.userFileManager)
+
+        Truth.assertThat(underTest.recordScreen).isEqualTo(expected)
+    }
+
+    @Test
+    fun hasUserApprovedScreenRecording_isTrue_afterBeingMarkedAsCompleted() {
+        underTest.markUserApprovalForScreenRecording()
+        underTest = IssueRecordingState(kosmos.userTracker, kosmos.userFileManager)
+
+        Truth.assertThat(underTest.hasUserApprovedScreenRecording).isEqualTo(true)
+    }
+
+    @Test
+    fun tagTitles_areSavedConsistently() {
+        val expected = setOf("a", "b", "c")
+
+        underTest.tagTitles = expected
+        underTest = IssueRecordingState(kosmos.userTracker, kosmos.userFileManager)
+
+        Truth.assertThat(underTest.tagTitles).isEqualTo(expected)
+    }
+
+    @Test
+    fun isRecording_callsListeners_onTheValueChanging() {
+        val count = CountDownLatch(1)
+        val listener = Runnable { count.countDown() }
+
+        underTest.addListener(listener)
+        underTest.isRecording = true
+
+        Truth.assertThat(count.count).isEqualTo(0)
+    }
+
+    @Test
+    fun isRecording_callsOnlyListeners_whoHaveNotBeenRemoved() {
+        val count1 = CountDownLatch(1)
+        val count2 = CountDownLatch(1)
+        val listener1 = Runnable { count1.countDown() }
+        val listener2 = Runnable { count2.countDown() }
+
+        underTest.addListener(listener1)
+        underTest.removeListener(listener1)
+        underTest.addListener(listener2)
+        underTest.isRecording = true
+
+        Truth.assertThat(count1.count).isEqualTo(1)
+        Truth.assertThat(count2.count).isEqualTo(0)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/OperatorNameViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/OperatorNameViewControllerTest.kt
index 396d017..d6b3b91 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/OperatorNameViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/OperatorNameViewControllerTest.kt
@@ -28,7 +28,7 @@
 import com.android.systemui.plugins.DarkIconDispatcher
 import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
 import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.util.FakeSubscriptionManagerProxy
 import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
 import com.android.systemui.tuner.TunerService
@@ -71,7 +71,6 @@
 
     private val airplaneModeRepository = FakeAirplaneModeRepository()
     private val connectivityRepository = FakeConnectivityRepository()
-    private val mobileConnectionsRepository = FakeMobileConnectionsRepository()
 
     @Before
     fun setup() {
@@ -81,7 +80,7 @@
             AirplaneModeInteractor(
                 airplaneModeRepository,
                 connectivityRepository,
-                mobileConnectionsRepository,
+                kosmos.fakeMobileConnectionsRepository,
             )
 
         underTest =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java
index a0d231b..60a1855 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java
@@ -51,6 +51,7 @@
 import android.platform.test.annotations.EnableFlags;
 import android.service.notification.StatusBarNotification;
 import android.view.ViewGroup;
+import android.widget.ImageView;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -431,6 +432,32 @@
                 mIconView.getIconScale(), 0.01f);
     }
 
+    @Test
+    @EnableFlags({Flags.FLAG_MODES_UI, Flags.FLAG_MODES_UI_ICONS})
+    public void set_iconThatWantsFixedSpace_setsScaleType() {
+        mIconView.setScaleType(ImageView.ScaleType.FIT_START);
+        StatusBarIcon icon = new StatusBarIcon(UserHandle.ALL, "mockPackage",
+                Icon.createWithResource(mContext, R.drawable.ic_android), 0, 0, "",
+                StatusBarIcon.Type.SystemIcon, StatusBarIcon.Shape.FIXED_SPACE);
+
+        mIconView.set(icon);
+
+        assertThat(mIconView.getScaleType()).isEqualTo(ImageView.ScaleType.FIT_CENTER);
+    }
+
+    @Test
+    @EnableFlags({Flags.FLAG_MODES_UI, Flags.FLAG_MODES_UI_ICONS})
+    public void set_iconWithOtherShape_keepsScaleType() {
+        mIconView.setScaleType(ImageView.ScaleType.FIT_START);
+        StatusBarIcon icon = new StatusBarIcon(UserHandle.ALL, "mockPackage",
+                Icon.createWithResource(mContext, R.drawable.ic_android), 0, 0, "",
+                StatusBarIcon.Type.SystemIcon, StatusBarIcon.Shape.WRAP_CONTENT);
+
+        mIconView.set(icon);
+
+        assertThat(mIconView.getScaleType()).isEqualTo(ImageView.ScaleType.FIT_START);
+    }
+
     private static StatusBarNotification getMockSbn() {
         StatusBarNotification sbn = mock(StatusBarNotification.class);
         when(sbn.getNotification()).thenReturn(mock(Notification.class));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index a18de68..a06f4d2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -95,6 +95,8 @@
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
 import com.android.systemui.statusbar.notification.shared.NotificationThrottleHun;
+import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds;
+import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimShape;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -893,7 +895,7 @@
 
     @Test
     @DisableFlags({QSComposeFragment.FLAG_NAME, NewQsUI.FLAG_NAME})
-    @DisableSceneContainer // TODO(b/312473478): address lack of QS Header
+    @DisableSceneContainer
     public void testInsideQSHeader_noOffset() {
         ViewGroup qsHeader = mock(ViewGroup.class);
         Rect boundsOnScreen = new Rect(0, 0, 1000, 1000);
@@ -911,7 +913,7 @@
 
     @Test
     @DisableFlags({QSComposeFragment.FLAG_NAME, NewQsUI.FLAG_NAME})
-    @DisableSceneContainer // TODO(b/312473478): address lack of QS Header
+    @DisableSceneContainer
     public void testInsideQSHeader_Offset() {
         ViewGroup qsHeader = mock(ViewGroup.class);
         Rect boundsOnScreen = new Rect(100, 100, 1000, 1000);
@@ -932,7 +934,7 @@
 
     @Test
     @EnableFlags({QSComposeFragment.FLAG_NAME, NewQsUI.FLAG_NAME})
-    @DisableSceneContainer // TODO(b/312473478): address lack of QS Header
+    @DisableSceneContainer
     public void testInsideQSHeader_noOffset_qsCompose() {
         ViewGroup qsHeader = mock(ViewGroup.class);
         Rect boundsOnScreen = new Rect(0, 0, 1000, 1000);
@@ -959,7 +961,7 @@
 
     @Test
     @EnableFlags({QSComposeFragment.FLAG_NAME, NewQsUI.FLAG_NAME})
-    @DisableSceneContainer // TODO(b/312473478): address lack of QS Header
+    @DisableSceneContainer
     public void testInsideQSHeader_Offset_qsCompose() {
         ViewGroup qsHeader = mock(ViewGroup.class);
         Rect boundsOnScreen = new Rect(100, 100, 1000, 1000);
@@ -988,6 +990,53 @@
     }
 
     @Test
+    @EnableSceneContainer
+    public void testIsInsideScrollableRegion_noScrim() {
+        mStackScroller.setLeftTopRightBottom(0, 0, 2000, 2000);
+
+        MotionEvent event = transformEventForView(createMotionEvent(250f, 250f), mStackScroller);
+        assertThat(mStackScroller.isInScrollableRegion(event)).isTrue();
+    }
+
+    @Test
+    @EnableSceneContainer
+    public void testIsInsideScrollableRegion_noOffset() {
+        mStackScroller.setLeftTopRightBottom(0, 0, 1000, 2000);
+        mStackScroller.setScrimClippingShape(createScrimShape(100, 500, 900, 2000));
+
+        MotionEvent event1 = transformEventForView(createMotionEvent(500f, 400f), mStackScroller);
+        assertThat(mStackScroller.isInScrollableRegion(event1)).isFalse();
+
+        MotionEvent event2 = transformEventForView(createMotionEvent(50, 1000f), mStackScroller);
+        assertThat(mStackScroller.isInScrollableRegion(event2)).isFalse();
+
+        MotionEvent event3 = transformEventForView(createMotionEvent(950f, 1000f), mStackScroller);
+        assertThat(mStackScroller.isInScrollableRegion(event3)).isFalse();
+
+        MotionEvent event4 = transformEventForView(createMotionEvent(500f, 1000f), mStackScroller);
+        assertThat(mStackScroller.isInScrollableRegion(event4)).isTrue();
+    }
+
+    @Test
+    @EnableSceneContainer
+    public void testIsInsideScrollableRegion_offset() {
+        mStackScroller.setLeftTopRightBottom(1000, 0, 2000, 2000);
+        mStackScroller.setScrimClippingShape(createScrimShape(100, 500, 900, 2000));
+
+        MotionEvent event1 = transformEventForView(createMotionEvent(1500f, 400f), mStackScroller);
+        assertThat(mStackScroller.isInScrollableRegion(event1)).isFalse();
+
+        MotionEvent event2 = transformEventForView(createMotionEvent(1050, 1000f), mStackScroller);
+        assertThat(mStackScroller.isInScrollableRegion(event2)).isFalse();
+
+        MotionEvent event3 = transformEventForView(createMotionEvent(1950f, 1000f), mStackScroller);
+        assertThat(mStackScroller.isInScrollableRegion(event3)).isFalse();
+
+        MotionEvent event4 = transformEventForView(createMotionEvent(1500f, 1000f), mStackScroller);
+        assertThat(mStackScroller.isInScrollableRegion(event4)).isTrue();
+    }
+
+    @Test
     @DisableSceneContainer // TODO(b/312473478): address disabled test
     public void setFractionToShade_recomputesStackHeight() {
         mStackScroller.setFractionToShade(1f);
@@ -1438,7 +1487,7 @@
     private static MotionEvent transformEventForView(MotionEvent event, View view) {
         // From `ViewGroup#dispatchTransformedTouchEvent`
         MotionEvent transformed = event.copy();
-        transformed.offsetLocation(-view.getTop(), -view.getLeft());
+        transformed.offsetLocation(/* deltaX = */-view.getLeft(), /* deltaY = */ -view.getTop());
         return transformed;
     }
 
@@ -1474,4 +1523,9 @@
     }
 
     private abstract static class BooleanConsumer implements Consumer<Boolean> { }
+
+    private ShadeScrimShape createScrimShape(int left, int top, int right, int bottom) {
+        ShadeScrimBounds bounds = new ShadeScrimBounds(left, top, right, bottom);
+        return new ShadeScrimShape(bounds, 0, 0);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorTest.kt
index db3e533..7901f47 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorTest.kt
@@ -19,13 +19,11 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
-import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
 import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
-import com.android.systemui.util.mockito.mock
+import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.launchIn
@@ -39,9 +37,9 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class AirplaneModeInteractorTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
 
-    private val mobileConnectionsRepository =
-        FakeMobileConnectionsRepository(FakeMobileMappingsProxy(), mock<TableLogBuffer> {})
+    private val mobileConnectionsRepository = kosmos.fakeMobileConnectionsRepository
     private val airplaneModeRepository = FakeAirplaneModeRepository()
     private val connectivityRepository = FakeConnectivityRepository()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt
index b823333..8beed01 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt
@@ -19,12 +19,13 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logcatTableLogBuffer
 import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
 import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
 import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
+import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
@@ -35,7 +36,6 @@
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.mockito.Mock
 import org.mockito.MockitoAnnotations
 
 @SmallTest
@@ -43,10 +43,11 @@
 @Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
 @RunWith(AndroidJUnit4::class)
 class AirplaneModeViewModelImplTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
 
     private lateinit var underTest: AirplaneModeViewModelImpl
 
-    @Mock private lateinit var logger: TableLogBuffer
+    private val logger = logcatTableLogBuffer(kosmos, "AirplaneModeViewModelImplTest")
     private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
     private lateinit var connectivityRepository: FakeConnectivityRepository
     private lateinit var interactor: AirplaneModeInteractor
@@ -61,7 +62,7 @@
             AirplaneModeInteractor(
                 airplaneModeRepository,
                 connectivityRepository,
-                FakeMobileConnectionsRepository(),
+                kosmos.fakeMobileConnectionsRepository,
             )
         scope = CoroutineScope(IMMEDIATE)
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
index 7d586cd..36f5236 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
@@ -27,7 +27,7 @@
 import com.android.systemui.demomode.DemoModeController
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.log.table.TableLogBufferFactory
+import com.android.systemui.log.table.tableLogBufferFactory
 import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
@@ -42,11 +42,11 @@
 import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
+import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.kotlinArgumentCaptor
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
@@ -56,7 +56,6 @@
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
 import org.junit.After
 import org.junit.Before
 import org.junit.Test
@@ -75,12 +74,13 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class MobileRepositorySwitcherTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
+
     private lateinit var underTest: MobileRepositorySwitcher
     private lateinit var realRepo: MobileConnectionsRepositoryImpl
     private lateinit var demoRepo: DemoMobileConnectionsRepository
     private lateinit var mobileDataSource: DemoModeMobileConnectionDataSource
     private lateinit var wifiDataSource: DemoModeWifiDataSource
-    private lateinit var logFactory: TableLogBufferFactory
     private lateinit var wifiRepository: FakeWifiRepository
     private lateinit var connectivityRepository: ConnectivityRepository
 
@@ -95,16 +95,12 @@
     private val mobileMappings = FakeMobileMappingsProxy()
     private val subscriptionManagerProxy = FakeSubscriptionManagerProxy()
 
-    private val testDispatcher = UnconfinedTestDispatcher()
     private val scope = CoroutineScope(IMMEDIATE)
 
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
-        logFactory =
-            TableLogBufferFactory(dumpManager, FakeSystemClock(), mock(), testDispatcher, scope)
-
         // Never start in demo mode
         whenever(demoModeController.isInDemoMode).thenReturn(false)
 
@@ -147,7 +143,7 @@
                 wifiDataSource = wifiDataSource,
                 scope = scope,
                 context = context,
-                logFactory = logFactory,
+                logFactory = kosmos.tableLogBufferFactory,
             )
 
         underTest =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
index db6f5927..7d32021 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
@@ -23,16 +23,16 @@
 import com.android.settingslib.SignalIcon
 import com.android.settingslib.mobile.TelephonyIcons
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.log.table.TableLogBufferFactory
+import com.android.systemui.log.table.tableLogBufferFactory
 import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
 import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
+import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.Job
@@ -43,12 +43,11 @@
 import kotlinx.coroutines.test.UnconfinedTestDispatcher
 import kotlinx.coroutines.test.runTest
 import org.junit.After
-import platform.test.runner.parameterized.ParameterizedAndroidJunit4
-import platform.test.runner.parameterized.Parameters
-import platform.test.runner.parameterized.Parameter
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
 
 /**
  * Parameterized test for all of the common values of [FakeNetworkEventModel]. This test simply
@@ -60,19 +59,11 @@
 @RunWith(ParameterizedAndroidJunit4::class)
 internal class DemoMobileConnectionParameterizedTest(private val testCase: TestCase) :
     SysuiTestCase() {
+    private val kosmos = testKosmos()
 
     private val testDispatcher = UnconfinedTestDispatcher()
     private val testScope = TestScope(testDispatcher)
 
-    private val logFactory =
-        TableLogBufferFactory(
-            mock(),
-            FakeSystemClock(),
-            mock(),
-            testDispatcher,
-            testScope.backgroundScope,
-        )
-
     private val fakeNetworkEventFlow = MutableStateFlow<FakeNetworkEventModel?>(null)
     private val fakeWifiEventFlow = MutableStateFlow<FakeWifiEventModel?>(null)
 
@@ -99,7 +90,7 @@
                 wifiDataSource = mockWifiDataSource,
                 scope = testScope.backgroundScope,
                 context = context,
-                logFactory = logFactory,
+                logFactory = kosmos.tableLogBufferFactory,
             )
 
         connectionsRepo.startProcessingCommands()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
index 5e0d2fb0..5017dda 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
@@ -24,8 +24,7 @@
 import com.android.settingslib.SignalIcon
 import com.android.settingslib.mobile.TelephonyIcons.THREE_G
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.log.table.TableLogBufferFactory
+import com.android.systemui.log.table.tableLogBufferFactory
 import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
@@ -34,9 +33,9 @@
 import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
+import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
 import junit.framework.Assert
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -56,21 +55,13 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
-    private val dumpManager: DumpManager = mock()
+    private val kosmos = testKosmos()
 
     private val testDispatcher = UnconfinedTestDispatcher()
     private val testScope = TestScope(testDispatcher)
 
     private val fakeNetworkEventFlow = MutableStateFlow<FakeNetworkEventModel?>(null)
     private val fakeWifiEventFlow = MutableStateFlow<FakeWifiEventModel?>(null)
-    private val logFactory =
-        TableLogBufferFactory(
-            dumpManager,
-            FakeSystemClock(),
-            mock(),
-            testDispatcher,
-            testScope.backgroundScope,
-        )
 
     private lateinit var underTest: DemoMobileConnectionsRepository
     private lateinit var mobileDataSource: DemoModeMobileConnectionDataSource
@@ -94,7 +85,7 @@
                 wifiDataSource = wifiDataSource,
                 scope = testScope.backgroundScope,
                 context = context,
-                logFactory = logFactory,
+                logFactory = kosmos.tableLogBufferFactory,
             )
 
         underTest.startProcessingCommands()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
index fd4c370..c029850 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
@@ -29,8 +29,8 @@
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.FakeFeatureFlagsClassic
 import com.android.systemui.flags.Flags.ROAMING_INDICATOR_VIA_DISPLAY_INFO
-import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.log.table.TableLogBufferFactory
+import com.android.systemui.log.table.logcatTableLogBuffer
+import com.android.systemui.log.table.tableLogBufferFactory
 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
@@ -42,11 +42,11 @@
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.getTelephonyCallbackForType
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
+import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
 import java.io.PrintWriter
 import java.io.StringWriter
@@ -73,23 +73,16 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class FullMobileConnectionRepositoryTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
+
     private lateinit var underTest: FullMobileConnectionRepository
 
     private val flags =
         FakeFeatureFlagsClassic().also { it.set(ROAMING_INDICATOR_VIA_DISPLAY_INFO, true) }
 
-    private val systemClock = FakeSystemClock()
     private val testDispatcher = UnconfinedTestDispatcher()
     private val testScope = TestScope(testDispatcher)
-    private val tableLogBuffer =
-        TableLogBuffer(
-            maxSize = 100,
-            name = "TestName",
-            systemClock,
-            mock(),
-            testDispatcher,
-            testScope.backgroundScope,
-        )
+    private val tableLogBuffer = logcatTableLogBuffer(kosmos, "TestName")
     private val mobileFactory = mock<MobileConnectionRepositoryImpl.Factory>()
     private val carrierMergedFactory = mock<CarrierMergedConnectionRepository.Factory>()
     private val connectivityManager = mock<ConnectivityManager>()
@@ -372,19 +365,10 @@
     @Test
     fun factory_reusesLogBuffersForSameConnection() =
         testScope.runTest {
-            val realLoggerFactory =
-                TableLogBufferFactory(
-                    mock(),
-                    FakeSystemClock(),
-                    mock(),
-                    testDispatcher,
-                    testScope.backgroundScope,
-                )
-
             val factory =
                 FullMobileConnectionRepository.Factory(
                     scope = testScope.backgroundScope,
-                    realLoggerFactory,
+                    kosmos.tableLogBufferFactory,
                     mobileFactory,
                     carrierMergedFactory,
                 )
@@ -416,19 +400,10 @@
     @Test
     fun factory_reusesLogBuffersForSameSubIDevenIfCarrierMerged() =
         testScope.runTest {
-            val realLoggerFactory =
-                TableLogBufferFactory(
-                    mock(),
-                    FakeSystemClock(),
-                    mock(),
-                    testDispatcher,
-                    testScope.backgroundScope,
-                )
-
             val factory =
                 FullMobileConnectionRepository.Factory(
                     scope = testScope.backgroundScope,
-                    realLoggerFactory,
+                    kosmos.tableLogBufferFactory,
                     mobileFactory,
                     carrierMergedFactory,
                 )
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
index 171520f..fe408e3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
@@ -88,7 +88,6 @@
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest.Companion.configWithOverride
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest.Companion.createTestConfig
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.signalStrength
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.telephonyDisplayInfo
@@ -121,7 +120,6 @@
 @RunWith(AndroidJUnit4::class)
 class MobileConnectionRepositoryTest : SysuiTestCase() {
     private lateinit var underTest: MobileConnectionRepositoryImpl
-    private lateinit var connectionsRepo: FakeMobileConnectionsRepository
 
     private val flags =
         FakeFeatureFlagsClassic().also { it.set(ROAMING_INDICATOR_VIA_DISPLAY_INFO, true) }
@@ -156,8 +154,6 @@
         MockitoAnnotations.initMocks(this)
         whenever(telephonyManager.subscriptionId).thenReturn(SUB_1_ID)
 
-        connectionsRepo = FakeMobileConnectionsRepository(mobileMappings, tableLogger)
-
         underTest =
             MobileConnectionRepositoryImpl(
                 SUB_1_ID,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt
index 2ab8c0a..0d82c79 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt
@@ -42,7 +42,6 @@
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.getTelephonyCallbackForType
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.signalStrength
 import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
@@ -97,7 +96,6 @@
 @SmallTest
 class MobileConnectionTelephonySmokeTests : SysuiTestCase() {
     private lateinit var underTest: MobileConnectionRepositoryImpl
-    private lateinit var connectionsRepo: FakeMobileConnectionsRepository
 
     private val flags =
         FakeFeatureFlagsClassic().also { it.set(Flags.ROAMING_INDICATOR_VIA_DISPLAY_INFO, true) }
@@ -123,12 +121,6 @@
         MockitoAnnotations.initMocks(this)
         whenever(telephonyManager.subscriptionId).thenReturn(SUB_1_ID)
 
-        connectionsRepo =
-            FakeMobileConnectionsRepository(
-                mobileMappings,
-                tableLogger,
-            )
-
         underTest =
             MobileConnectionRepositoryImpl(
                 SUB_1_ID,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
index e439aff..4fd830d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
@@ -18,7 +18,6 @@
 
 import android.platform.test.annotations.EnableFlags
 import android.telephony.CellSignalStrength
-import android.telephony.SubscriptionManager.PROFILE_CLASS_UNSET
 import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
@@ -27,12 +26,12 @@
 import com.android.settingslib.mobile.TelephonyIcons
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.log.table.logcatTableLogBuffer
 import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.CarrierMergedNetworkType
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.OverrideNetworkType
-import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor.Companion.FIVE_G_OVERRIDE
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor.Companion.FOUR_G
@@ -40,12 +39,12 @@
 import com.android.systemui.statusbar.pipeline.mobile.domain.model.NetworkTypeIconModel
 import com.android.systemui.statusbar.pipeline.mobile.domain.model.SignalIconModel
 import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
+import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.test.TestScope
@@ -61,21 +60,18 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class MobileIconInteractorTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
+
     private lateinit var underTest: MobileIconInteractor
     private val mobileMappingsProxy = FakeMobileMappingsProxy()
     private val mobileIconsInteractor = FakeMobileIconsInteractor(mobileMappingsProxy, mock())
 
-    private val subscriptionModel =
-        MutableStateFlow(
-            SubscriptionModel(
-                subscriptionId = SUB_1_ID,
-                carrierName = DEFAULT_NAME,
-                profileClass = PROFILE_CLASS_UNSET,
-            )
+    private val connectionRepository =
+        FakeMobileConnectionRepository(
+            SUB_1_ID,
+            logcatTableLogBuffer(kosmos, "MobileIconInteractorTest"),
         )
 
-    private val connectionRepository = FakeMobileConnectionRepository(SUB_1_ID, mock())
-
     private val testDispatcher = UnconfinedTestDispatcher()
     private val testScope = TestScope(testDispatcher)
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
index e218fba..f6d439a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
@@ -28,7 +28,7 @@
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.FakeFeatureFlagsClassic
 import com.android.systemui.flags.Flags
-import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logcatTableLogBuffer
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
@@ -36,10 +36,10 @@
 import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
 import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
 import com.android.systemui.statusbar.policy.data.repository.FakeUserSetupRepository
+import com.android.systemui.testKosmos
 import com.android.systemui.util.CarrierConfigTracker
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
 import java.util.UUID
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -58,6 +58,8 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class MobileIconsInteractorTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
+
     private lateinit var underTest: MobileIconsInteractor
     private lateinit var connectivityRepository: FakeConnectivityRepository
     private lateinit var connectionsRepository: FakeMobileConnectionsRepository
@@ -71,15 +73,7 @@
     private val testDispatcher = StandardTestDispatcher()
     private val testScope = TestScope(testDispatcher)
 
-    private val tableLogBuffer =
-        TableLogBuffer(
-            8,
-            "MobileIconsInteractorTest",
-            FakeSystemClock(),
-            mock(),
-            testDispatcher,
-            testScope.backgroundScope,
-        )
+    private val tableLogBuffer = logcatTableLogBuffer(kosmos, "MobileIconsInteractorTest")
 
     @Mock private lateinit var carrierConfigTracker: CarrierConfigTracker
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileViewTest.kt
index 42cb660..84846a1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileViewTest.kt
@@ -28,12 +28,12 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.flags.FakeFeatureFlagsClassic
 import com.android.systemui.flags.Flags
-import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logcatTableLogBuffer
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.StatusBarIconView
 import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
 import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconInteractor
 import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger
 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.LocationBasedMobileViewModel
@@ -41,6 +41,7 @@
 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.QsMobileIconViewModel
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
 import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
+import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -58,13 +59,13 @@
 @RunWithLooper(setAsMainLooper = true)
 @OptIn(ExperimentalCoroutinesApi::class)
 class ModernStatusBarMobileViewTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
 
     private lateinit var testableLooper: TestableLooper
     private val testDispatcher = UnconfinedTestDispatcher()
     private val testScope = TestScope(testDispatcher)
     private val flags = FakeFeatureFlagsClassic().also { it.set(Flags.NEW_NETWORK_SLICE_UI, false) }
 
-    @Mock private lateinit var tableLogBuffer: TableLogBuffer
     @Mock private lateinit var viewLogger: MobileViewLogger
     @Mock private lateinit var constants: ConnectivityConstants
     private lateinit var interactor: FakeMobileIconInteractor
@@ -88,10 +89,11 @@
             AirplaneModeInteractor(
                 airplaneModeRepository,
                 FakeConnectivityRepository(),
-                FakeMobileConnectionsRepository(),
+                kosmos.fakeMobileConnectionsRepository,
             )
 
-        interactor = FakeMobileIconInteractor(tableLogBuffer)
+        interactor =
+            FakeMobileIconInteractor(logcatTableLogBuffer(kosmos, "ModernStatusBarMobileViewTest"))
         createViewModel()
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt
index deb9fcf..f99fcac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt
@@ -21,24 +21,23 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.flags.FakeFeatureFlagsClassic
 import com.android.systemui.flags.Flags
-import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logcatTableLogBuffer
 import com.android.systemui.statusbar.connectivity.MobileIconCarrierIdOverridesFake
-import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
 import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
 import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
 import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconInteractor
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconInteractorImpl
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractorImpl
 import com.android.systemui.statusbar.pipeline.mobile.domain.model.SignalIconModel
-import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
 import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
 import com.android.systemui.statusbar.policy.data.repository.FakeUserSetupRepository
+import com.android.systemui.testKosmos
 import com.android.systemui.util.CarrierConfigTracker
 import com.android.systemui.util.mockito.mock
 import com.google.common.truth.Truth.assertThat
@@ -59,13 +58,15 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class LocationBasedMobileIconViewModelTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
+
     private lateinit var commonImpl: MobileIconViewModelCommon
     private lateinit var homeIcon: HomeMobileIconViewModel
     private lateinit var qsIcon: QsMobileIconViewModel
     private lateinit var keyguardIcon: KeyguardMobileIconViewModel
     private lateinit var iconsInteractor: MobileIconsInteractor
     private lateinit var interactor: MobileIconInteractor
-    private lateinit var connectionsRepository: FakeMobileConnectionsRepository
+    private val connectionsRepository = kosmos.fakeMobileConnectionsRepository
     private lateinit var repository: FakeMobileConnectionRepository
     private lateinit var airplaneModeInteractor: AirplaneModeInteractor
 
@@ -76,9 +77,9 @@
             it.set(Flags.FILTER_PROVISIONING_NETWORK_SUBSCRIPTIONS, true)
         }
 
-    @Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags
     @Mock private lateinit var constants: ConnectivityConstants
-    @Mock private lateinit var tableLogBuffer: TableLogBuffer
+    private val tableLogBuffer =
+        logcatTableLogBuffer(kosmos, "LocationBasedMobileIconViewModelTest")
     @Mock private lateinit var carrierConfigTracker: CarrierConfigTracker
 
     private val testDispatcher = UnconfinedTestDispatcher()
@@ -91,10 +92,8 @@
             AirplaneModeInteractor(
                 FakeAirplaneModeRepository(),
                 FakeConnectivityRepository(),
-                FakeMobileConnectionsRepository(),
+                connectionsRepository,
             )
-        connectionsRepository =
-            FakeMobileConnectionsRepository(FakeMobileMappingsProxy(), tableLogBuffer)
         repository =
             FakeMobileConnectionRepository(SUB_1_ID, tableLogBuffer).apply {
                 isInService.value = true
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
index e510924..4c7cdfa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
@@ -34,7 +34,7 @@
 import com.android.systemui.flags.FakeFeatureFlagsClassic
 import com.android.systemui.flags.Flags
 import com.android.systemui.flags.Flags.NEW_NETWORK_SLICE_UI
-import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logcatTableLogBuffer
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.connectivity.MobileIconCarrierIdOverridesFake
 import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
@@ -42,6 +42,7 @@
 import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconInteractorImpl
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractorImpl
 import com.android.systemui.statusbar.pipeline.mobile.domain.model.SignalIconModel
@@ -51,6 +52,7 @@
 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
 import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
 import com.android.systemui.statusbar.policy.data.repository.FakeUserSetupRepository
+import com.android.systemui.testKosmos
 import com.android.systemui.util.CarrierConfigTracker
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
@@ -74,6 +76,8 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class MobileIconViewModelTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
+
     private var connectivityRepository = FakeConnectivityRepository()
 
     private lateinit var underTest: MobileIconViewModel
@@ -84,7 +88,7 @@
     private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
     private lateinit var airplaneModeInteractor: AirplaneModeInteractor
     @Mock private lateinit var constants: ConnectivityConstants
-    @Mock private lateinit var tableLogBuffer: TableLogBuffer
+    private val tableLogBuffer = logcatTableLogBuffer(kosmos, "MobileIconViewModelTest")
     @Mock private lateinit var carrierConfigTracker: CarrierConfigTracker
 
     private val flags =
@@ -118,7 +122,7 @@
             AirplaneModeInteractor(
                 airplaneModeRepository,
                 connectivityRepository,
-                FakeMobileConnectionsRepository(),
+                kosmos.fakeMobileConnectionsRepository,
             )
 
         iconsInteractor =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
index 47899a6..31ba837 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
@@ -24,11 +24,10 @@
 import com.android.systemui.flags.FakeFeatureFlagsClassic
 import com.android.systemui.flags.Flags
 import com.android.systemui.statusbar.phone.StatusBarLocation
-import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
 import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
 import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor
 import com.android.systemui.statusbar.pipeline.mobile.domain.model.NetworkTypeIconModel
 import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger
@@ -36,6 +35,7 @@
 import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
 import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
+import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.mock
 import com.google.common.truth.Truth.assertThat
 import junit.framework.Assert.assertFalse
@@ -58,12 +58,13 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class MobileIconsViewModelTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
+
     private lateinit var underTest: MobileIconsViewModel
     private val interactor = FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock())
     private val flags = FakeFeatureFlagsClassic().also { it.set(Flags.NEW_NETWORK_SLICE_UI, false) }
 
     private lateinit var airplaneModeInteractor: AirplaneModeInteractor
-    @Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags
     @Mock private lateinit var constants: ConnectivityConstants
     @Mock private lateinit var logger: MobileViewLogger
     @Mock private lateinit var verboseLogger: VerboseMobileViewLogger
@@ -79,7 +80,7 @@
             AirplaneModeInteractor(
                 FakeAirplaneModeRepository(),
                 FakeConnectivityRepository(),
-                FakeMobileConnectionsRepository(),
+                kosmos.fakeMobileConnectionsRepository,
             )
 
         underTest =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt
index 2238bff..50f262c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt
@@ -26,7 +26,7 @@
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.FakeFeatureFlagsClassic
 import com.android.systemui.flags.Flags
-import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logcatTableLogBuffer
 import com.android.systemui.qs.tileimpl.QSTileImpl.ResourceIcon
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.connectivity.WifiIcons
@@ -49,6 +49,7 @@
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiScanEntry
 import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon
 import com.android.systemui.statusbar.policy.data.repository.FakeUserSetupRepository
+import com.android.systemui.testKosmos
 import com.android.systemui.util.CarrierConfigTracker
 import com.android.systemui.util.mockito.mock
 import com.google.common.truth.Truth.assertThat
@@ -61,6 +62,8 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class InternetTileViewModelTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
+
     private lateinit var underTest: InternetTileViewModel
     private lateinit var mobileIconsInteractor: MobileIconsInteractor
 
@@ -73,7 +76,7 @@
     private val wifiInteractor =
         WifiInteractorImpl(connectivityRepository, wifiRepository, testScope.backgroundScope)
 
-    private val tableLogBuffer: TableLogBuffer = mock()
+    private val tableLogBuffer = logcatTableLogBuffer(kosmos, "InternetTileViewModelTest")
     private val carrierConfigTracker: CarrierConfigTracker = mock()
 
     private val mobileConnectionsRepository =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
index 80b10c0..161c4f5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
@@ -26,7 +26,7 @@
 import android.widget.ImageView
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logcatTableLogBuffer
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.StatusBarIconView.STATE_DOT
 import com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN
@@ -36,7 +36,7 @@
 import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
 import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
 import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModelImpl
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
 import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
@@ -47,6 +47,7 @@
 import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel
 import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel.Companion.viewModelForLocation
 import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.WifiViewModel
+import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
@@ -61,10 +62,11 @@
 @RunWith(AndroidTestingRunner::class)
 @RunWithLooper(setAsMainLooper = true)
 class ModernStatusBarWifiViewTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
 
     private lateinit var testableLooper: TestableLooper
 
-    @Mock private lateinit var tableLogBuffer: TableLogBuffer
+    private val tableLogBuffer = logcatTableLogBuffer(kosmos, "ModernStatusBarWifiViewTest")
     @Mock private lateinit var connectivityConstants: ConnectivityConstants
     @Mock private lateinit var wifiConstants: WifiConstants
     private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
@@ -91,7 +93,7 @@
                 AirplaneModeInteractor(
                     airplaneModeRepository,
                     connectivityRepository,
-                    FakeMobileConnectionsRepository(),
+                    kosmos.fakeMobileConnectionsRepository,
                 ),
                 tableLogBuffer,
                 scope,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
index 489319e..d2a4bf3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
@@ -31,7 +31,7 @@
 import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
 import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
 import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModelImpl
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
 import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
 import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
@@ -42,6 +42,7 @@
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
 import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon
 import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon.Companion.NO_INTERNET
+import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
@@ -64,6 +65,7 @@
 @RunWith(Parameterized::class)
 internal class WifiViewModelIconParameterizedTest(private val testCase: TestCase) :
     SysuiTestCase() {
+    private val kosmos = testKosmos()
 
     private lateinit var underTest: WifiViewModel
 
@@ -91,7 +93,7 @@
                 AirplaneModeInteractor(
                     airplaneModeRepository,
                     connectivityRepository,
-                    FakeMobileConnectionsRepository(),
+                    kosmos.fakeMobileConnectionsRepository,
                 ),
                 tableLogBuffer,
                 scope,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt
index 171be97..649e4e8 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt
@@ -33,16 +33,16 @@
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.StateFlow
 
-val Kosmos.bouncerSceneActionsViewModel by Fixture {
-    BouncerSceneActionsViewModel(
+val Kosmos.bouncerUserActionsViewModel by Fixture {
+    BouncerUserActionsViewModel(
         bouncerInteractor = bouncerInteractor,
     )
 }
 
-val Kosmos.bouncerSceneActionsViewModelFactory by Fixture {
-    object : BouncerSceneActionsViewModel.Factory {
-        override fun create(): BouncerSceneActionsViewModel {
-            return bouncerSceneActionsViewModel
+val Kosmos.bouncerUserActionsViewModelFactory by Fixture {
+    object : BouncerUserActionsViewModel.Factory {
+        override fun create(): BouncerUserActionsViewModel {
+            return bouncerUserActionsViewModel
         }
     }
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/ConfigurationStateKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/ConfigurationStateKosmos.kt
index 86a8ae5..1ef3464 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/ConfigurationStateKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/ConfigurationStateKosmos.kt
@@ -17,11 +17,8 @@
 package com.android.systemui.common.ui
 
 import android.content.applicationContext
-import android.view.layoutInflater
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.statusbar.policy.configurationController
 
 val Kosmos.configurationState: ConfigurationState by
-    Kosmos.Fixture {
-        ConfigurationState(configurationController, applicationContext, layoutInflater)
-    }
+    Kosmos.Fixture { ConfigurationStateImpl(configurationController, applicationContext) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorKosmos.kt
index 811c653..7ccacb6 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorKosmos.kt
@@ -19,6 +19,7 @@
 import android.hardware.input.InputManager
 import com.android.systemui.education.data.repository.fakeEduClock
 import com.android.systemui.inputdevice.data.repository.UserInputDeviceRepository
+import com.android.systemui.inputdevice.tutorial.data.repository.TutorialSchedulerRepository
 import com.android.systemui.keyboard.data.repository.keyboardRepository
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.testDispatcher
@@ -50,6 +51,12 @@
     Kosmos.Fixture {
         KeyboardTouchpadEduStatsInteractorImpl(
             backgroundScope = testScope.backgroundScope,
-            contextualEducationInteractor = contextualEducationInteractor
+            contextualEducationInteractor = contextualEducationInteractor,
+            inputDeviceRepository = mockUserInputDeviceRepository,
+            tutorialRepository = mockTutorialSchedulerRepository,
+            clock = fakeEduClock
         )
     }
+
+var mockUserInputDeviceRepository = mock<UserInputDeviceRepository>()
+var mockTutorialSchedulerRepository = mock<TutorialSchedulerRepository>()
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/VibratorHelperKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/VibratorHelperKosmos.kt
index 434953f..ff71f2f 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/VibratorHelperKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/VibratorHelperKosmos.kt
@@ -17,5 +17,7 @@
 package com.android.systemui.haptics
 
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.statusbar.VibratorHelper
 
-var Kosmos.vibratorHelper by Kosmos.Fixture { FakeVibratorHelper() }
+var Kosmos.vibratorHelper: VibratorHelper by Kosmos.Fixture { fakeVibratorHelper }
+val Kosmos.fakeVibratorHelper by Kosmos.Fixture { FakeVibratorHelper() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/log/table/TableLogBufferFactoryKosmos.kt
similarity index 61%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/log/table/TableLogBufferFactoryKosmos.kt
index 128a7fc..c55dc6a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/log/table/TableLogBufferFactoryKosmos.kt
@@ -14,13 +14,18 @@
  * limitations under the License.
  */
 
-package com.android.systemui.qs.ui.viewmodel
+package com.android.systemui.log.table
 
+import com.android.systemui.dump.dumpManager
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.log.LogcatEchoTrackerAlways
+import com.android.systemui.util.time.fakeSystemClock
 
-val Kosmos.quickSettingsShadeSceneActionsViewModel: QuickSettingsShadeSceneActionsViewModel by
+val Kosmos.tableLogBufferFactory: TableLogBufferFactory by
     Kosmos.Fixture {
-        QuickSettingsShadeSceneActionsViewModel(
-            quickSettingsContainerViewModel = quickSettingsContainerViewModel,
+        TableLogBufferFactory(
+            dumpManager = dumpManager,
+            systemClock = fakeSystemClock,
+            logcatEchoTracker = LogcatEchoTrackerAlways(),
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/log/table/TableLogBufferHelper.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/log/table/TableLogBufferHelper.kt
new file mode 100644
index 0000000..64c3974
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/log/table/TableLogBufferHelper.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 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.log.table
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.log.LogcatEchoTrackerAlways
+import com.android.systemui.util.time.SystemClock
+import com.android.systemui.util.time.fakeSystemClock
+
+/**
+ * Creates a [TableLogBuffer] that will echo everything to logcat, which is useful for debugging
+ * tests.
+ */
+fun logcatTableLogBuffer(kosmos: Kosmos, name: String = "EchoToLogcatTableLogBuffer") =
+    logcatTableLogBuffer(kosmos.fakeSystemClock, name)
+
+/**
+ * Creates a [TableLogBuffer] that will echo everything to logcat, which is useful for debugging
+ * tests.
+ */
+fun logcatTableLogBuffer(systemClock: SystemClock, name: String = "EchoToLogcatTableLogBuffer") =
+    TableLogBuffer(maxSize = 50, name, systemClock, logcatEchoTracker = LogcatEchoTrackerAlways())
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModelKosmos.kt
similarity index 85%
rename from packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelKosmos.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModelKosmos.kt
index 128a7fc..06592b1 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModelKosmos.kt
@@ -18,9 +18,9 @@
 
 import com.android.systemui.kosmos.Kosmos
 
-val Kosmos.quickSettingsShadeSceneActionsViewModel: QuickSettingsShadeSceneActionsViewModel by
+val Kosmos.quickSettingsShadeUserActionsViewModel: QuickSettingsShadeUserActionsViewModel by
     Kosmos.Fixture {
-        QuickSettingsShadeSceneActionsViewModel(
+        QuickSettingsShadeUserActionsViewModel(
             quickSettingsContainerViewModel = quickSettingsContainerViewModel,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
index 53b6a2e..b612a8b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
@@ -24,8 +24,10 @@
 import com.android.systemui.classifier.falsingCollector
 import com.android.systemui.classifier.falsingManager
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryFaceAuthInteractor
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryHapticsInteractor
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
 import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
+import com.android.systemui.haptics.vibratorHelper
 import com.android.systemui.keyguard.dismissCallbackRegistry
 import com.android.systemui.keyguard.domain.interactor.keyguardEnabledInteractor
 import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
@@ -55,6 +57,7 @@
         applicationScope = testScope.backgroundScope,
         sceneInteractor = sceneInteractor,
         deviceEntryInteractor = deviceEntryInteractor,
+        deviceEntryHapticsInteractor = deviceEntryHapticsInteractor,
         deviceUnlockedInteractor = deviceUnlockedInteractor,
         bouncerInteractor = bouncerInteractor,
         keyguardInteractor = keyguardInteractor,
@@ -82,5 +85,6 @@
         dismissCallbackRegistry = dismissCallbackRegistry,
         statusBarStateController = sysuiStatusBarStateController,
         alternateBouncerInteractor = alternateBouncerInteractor,
+        vibratorHelper = vibratorHelper,
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeSceneActionsViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeUserActionsViewModelKosmos.kt
similarity index 81%
rename from packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeSceneActionsViewModelKosmos.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeUserActionsViewModelKosmos.kt
index f792ab9..6345c40 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeSceneActionsViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeUserActionsViewModelKosmos.kt
@@ -18,7 +18,7 @@
 
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
-import com.android.systemui.notifications.ui.viewmodel.NotificationsShadeSceneActionsViewModel
+import com.android.systemui.notifications.ui.viewmodel.NotificationsShadeUserActionsViewModel
 
-val Kosmos.notificationsShadeSceneActionsViewModel:
-    NotificationsShadeSceneActionsViewModel by Fixture { NotificationsShadeSceneActionsViewModel() }
+val Kosmos.notificationsShadeUserActionsViewModel:
+    NotificationsShadeUserActionsViewModel by Fixture { NotificationsShadeUserActionsViewModel() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeWindowModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeWindowModelKosmos.kt
index 4b42e07..9742595 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeWindowModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeWindowModelKosmos.kt
@@ -16,12 +16,18 @@
 
 package com.android.systemui.shade.ui.viewmodel
 
+import com.android.systemui.authentication.domain.interactor.authenticationInteractor
+import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor
 import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.scene.domain.interactor.sceneInteractor
 
 val Kosmos.notificationShadeWindowModel: NotificationShadeWindowModel by
     Kosmos.Fixture {
         NotificationShadeWindowModel(
             keyguardTransitionInteractor,
+            sceneInteractor = { sceneInteractor },
+            authenticationInteractor = { authenticationInteractor },
+            primaryBouncerInteractor = primaryBouncerInteractor,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelKosmos.kt
similarity index 89%
rename from packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModelKosmos.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelKosmos.kt
index 2387aa8..48c5121 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelKosmos.kt
@@ -21,8 +21,8 @@
 import com.android.systemui.qs.ui.adapter.qsSceneAdapter
 import com.android.systemui.shade.domain.interactor.shadeInteractor
 
-val Kosmos.shadeSceneActionsViewModel: ShadeSceneActionsViewModel by Fixture {
-    ShadeSceneActionsViewModel(
+val Kosmos.shadeUserActionsViewModel: ShadeUserActionsViewModel by Fixture {
+    ShadeUserActionsViewModel(
         qsSceneAdapter = qsSceneAdapter,
         shadeInteractor = shadeInteractor,
     )
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorKosmos.kt
index 386c7c5..d76defe 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorKosmos.kt
@@ -18,7 +18,7 @@
 
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
 
 val Kosmos.airplaneModeInteractor: AirplaneModeInteractor by
@@ -26,6 +26,6 @@
         AirplaneModeInteractor(
             FakeAirplaneModeRepository(),
             FakeConnectivityRepository(),
-            FakeMobileConnectionsRepository(),
+            fakeMobileConnectionsRepository,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt
index e7be639..de73d33 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt
@@ -26,14 +26,13 @@
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
 import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
 import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
-import com.android.systemui.util.mockito.mock
 import kotlinx.coroutines.flow.MutableSharedFlow
 import kotlinx.coroutines.flow.MutableStateFlow
 
 // TODO(b/261632894): remove this in favor of the real impl or DemoMobileConnectionsRepository
 class FakeMobileConnectionsRepository(
     mobileMappings: MobileMappingsProxy = FakeMobileMappingsProxy(),
-    val tableLogBuffer: TableLogBuffer = mock<TableLogBuffer> {},
+    val tableLogBuffer: TableLogBuffer,
 ) : MobileConnectionsRepository {
 
     val GSM_KEY = mobileMappings.toIconKey(GSM)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionsRepositoryKosmos.kt
index 9d62ea5..cd22f1d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionsRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionsRepositoryKosmos.kt
@@ -18,10 +18,12 @@
 
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
-import com.android.systemui.util.mockito.mock
+import com.android.systemui.log.table.logcatTableLogBuffer
 
 val Kosmos.fakeMobileConnectionsRepository by Fixture {
-    FakeMobileConnectionsRepository(tableLogBuffer = mock())
+    FakeMobileConnectionsRepository(
+        tableLogBuffer = logcatTableLogBuffer(this, "FakeMobileConnectionsRepository"),
+    )
 }
 
 val Kosmos.mobileConnectionsRepository by
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt
index 1fa6c3f..888351f 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt
@@ -33,6 +33,12 @@
 
 class FakeAudioRepository : AudioRepository {
 
+    private val unMutableStreams =
+        setOf(
+            AudioManager.STREAM_VOICE_CALL,
+            AudioManager.STREAM_ALARM,
+        )
+
     private val mutableMode = MutableStateFlow(AudioManager.MODE_NORMAL)
     override val mode: StateFlow<Int> = mutableMode.asStateFlow()
 
@@ -73,7 +79,7 @@
                     volume = 0,
                     minVolume = 0,
                     maxVolume = 10,
-                    isAffectedByMute = false,
+                    isAffectedByMute = audioStream.value !in unMutableStreams,
                     isAffectedByRingerMode = false,
                     isMuted = false,
                 )
diff --git a/ravenwood/OWNERS b/ravenwood/OWNERS
index badfca0..f7b13d1 100644
--- a/ravenwood/OWNERS
+++ b/ravenwood/OWNERS
@@ -1,8 +1,8 @@
 set noparent
 
-jsharkey@google.com
-omakoto@google.com
-dplotnikov@google.com
+topjohnwu@google.com
+hackbod@google.com  #{LAST_RESORT_SUGGESTION}
+
 
 per-file ravenwood-annotation-allowed-classes.txt = dplotnikov@google.com
 per-file texts/ravenwood-annotation-allowed-classes.txt = dplotnikov@google.com
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java
index 7a160955..7d99166 100644
--- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java
@@ -203,10 +203,6 @@
             // so record it and throw it when the test actually started.
             log("Fatal: Exception detected in constructor: " + th.getMessage() + "\n"
                     + Log.getStackTraceString(th));
-            if (true) {
-                // TODO(b/363094647) Remove this
-                throw th;
-            }
             mExceptionInConstructor = new RuntimeException("Exception detected in constructor",
                     th);
             mDescription = Description.createTestDescription(testClass, "Constructor");
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/RavenwoodEnvironment_host.java b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/RavenwoodEnvironment_host.java
index f894b0e..58f6bbb 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/RavenwoodEnvironment_host.java
+++ b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/RavenwoodEnvironment_host.java
@@ -36,7 +36,7 @@
     /**
      * Called from {@link RavenwoodEnvironment#ensureRavenwoodInitialized()}.
      */
-    public static void ensureRavenwoodInitialized() {
+    public static void nativeEnsureRavenwoodInitialized() {
 
         // TODO Unify it with the initialization code in RavenwoodAwareTestRunnerHook.
 
@@ -63,14 +63,14 @@
     /**
      * Called from {@link RavenwoodEnvironment#getRavenwoodRuntimePath()}.
      */
-    public static String getRavenwoodRuntimePath(RavenwoodEnvironment env) {
+    public static String nativeGetRavenwoodRuntimePath(RavenwoodEnvironment env) {
         return RavenwoodCommonUtils.getRavenwoodRuntimePath();
     }
 
     /**
      * Called from {@link RavenwoodEnvironment#fromAddress(long)}.
      */
-    public static <T> T fromAddress(RavenwoodEnvironment env, long address) {
+    public static <T> T nativeFromAddress(RavenwoodEnvironment env, long address) {
         return JvmWorkaround.getInstance().fromAddress(address);
     }
 }
diff --git a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
index 34239b8..9c86389 100644
--- a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
+++ b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
@@ -9,17 +9,13 @@
 com.android.internal.logging.testing.UiEventLoggerFake
 com.android.internal.os.AndroidPrintStream
 com.android.internal.os.BatteryStatsHistory
-com.android.internal.os.BatteryStatsHistory$TraceDelegate
-com.android.internal.os.BatteryStatsHistory$VarintParceler
 com.android.internal.os.BatteryStatsHistoryIterator
 com.android.internal.os.Clock
 com.android.internal.os.LongArrayMultiStateCounter
-com.android.internal.os.LongArrayMultiStateCounter$LongArrayContainer
 com.android.internal.os.LongMultiStateCounter
 com.android.internal.os.MonotonicClock
 com.android.internal.os.PowerProfile
 com.android.internal.os.PowerStats
-com.android.internal.os.PowerStats$Descriptor
 com.android.internal.os.RuntimeInit
 com.android.internal.power.EnergyConsumerStats
 com.android.internal.power.ModemPowerProfile
@@ -123,15 +119,9 @@
 android.os.BaseBundle
 android.os.BatteryConsumer
 android.os.BatteryStats
-android.os.BatteryStats$HistoryItem
-android.os.BatteryStats$HistoryStepDetails
-android.os.BatteryStats$HistoryTag
-android.os.BatteryStats$LongCounter
-android.os.BatteryStats$ProcessStateChange
 android.os.BatteryUsageStats
 android.os.BatteryUsageStatsQuery
 android.os.Binder
-android.os.Binder$IdentitySupplier
 android.os.BluetoothBatteryStats
 android.os.Broadcaster
 android.os.Build
@@ -142,7 +132,6 @@
 android.os.DeadObjectException
 android.os.DeadSystemException
 android.os.FileUtils
-android.os.FileUtils$MemoryPipe
 android.os.Handler
 android.os.HandlerExecutor
 android.os.HandlerThread
@@ -154,8 +143,6 @@
 android.os.PackageTagsList
 android.os.Parcel
 android.os.ParcelFileDescriptor
-android.os.ParcelFileDescriptor$AutoCloseInputStream
-android.os.ParcelFileDescriptor$AutoCloseOutputStream
 android.os.ParcelFormatException
 android.os.ParcelUuid
 android.os.Parcelable
@@ -169,7 +156,6 @@
 android.os.RemoteException
 android.os.ResultReceiver
 android.os.ServiceManager
-android.os.ServiceManager$ServiceNotFoundException
 android.os.ServiceSpecificException
 android.os.StrictMode
 android.os.SystemClock
@@ -180,18 +166,14 @@
 android.os.Trace
 android.os.TransactionTooLargeException
 android.os.UserBatteryConsumer
-android.os.UserBatteryConsumer$Builder
 android.os.UidBatteryConsumer
-android.os.UidBatteryConsumer$Builder
 android.os.UserHandle
 android.os.UserManager
 android.os.VibrationAttributes
-android.os.VibrationAttributes$Builder
 android.os.WakeLockStats
 android.os.WorkSource
 
 android.content.ClipData
-android.content.ClipData$Item
 android.content.ClipDescription
 android.content.ClipboardManager
 android.content.ComponentName
@@ -208,11 +190,7 @@
 android.content.pm.ComponentInfo
 android.content.pm.PackageInfo
 android.content.pm.PackageItemInfo
-android.content.pm.PackageManager$Flags
-android.content.pm.PackageManager$PackageInfoFlags
-android.content.pm.PackageManager$ApplicationInfoFlags
-android.content.pm.PackageManager$ComponentInfoFlags
-android.content.pm.PackageManager$ResolveInfoFlags
+android.content.pm.PackageManager
 android.content.pm.PathPermission
 android.content.pm.ProviderInfo
 android.content.pm.ResolveInfo
@@ -223,7 +201,6 @@
 android.content.res.ApkAssets
 android.content.res.AssetFileDescriptor
 android.content.res.AssetManager
-android.content.res.AssetManager$Builder
 android.content.res.ColorStateList
 android.content.res.ConfigurationBoundResourceCache
 android.content.res.Configuration
@@ -237,7 +214,6 @@
 android.content.res.FontScaleConverterImpl
 android.content.res.FontScaleConverterFactory
 android.content.res.Resources
-android.content.res.Resources$Theme
 android.content.res.ResourceId
 android.content.res.ResourcesImpl
 android.content.res.ResourcesKey
@@ -260,7 +236,6 @@
 android.database.DataSetObservable
 android.database.DataSetObserver
 android.database.MatrixCursor
-android.database.MatrixCursor$RowBuilder
 android.database.MergeCursor
 android.database.Observable
 android.database.SQLException
@@ -268,7 +243,6 @@
 android.database.sqlite.SQLiteException
 
 android.text.TextUtils
-android.text.TextUtils$SimpleStringSplitter
 
 android.accounts.Account
 
@@ -298,14 +272,11 @@
 android.app.Instrumentation
 android.app.LocaleConfig
 android.app.ResourcesManager
-android.app.ResourcesManager$UpdateHandler
 android.app.WindowConfiguration
 
 android.metrics.LogMaker
 
 android.view.Display
-android.view.Display$HdrCapabilities
-android.view.Display$Mode
 android.view.DisplayAdjustments
 android.view.DisplayInfo
 android.view.inputmethod.InputBinding
diff --git a/ravenwood/texts/ravenwood-standard-options.txt b/ravenwood/texts/ravenwood-standard-options.txt
index f64f26d..952ab82 100644
--- a/ravenwood/texts/ravenwood-standard-options.txt
+++ b/ravenwood/texts/ravenwood-standard-options.txt
@@ -6,8 +6,6 @@
 --default-throw
 
 # Uncomment below lines to enable each feature.
-# --enable-non-stub-method-check
---no-non-stub-method-check
 
 #--default-method-call-hook
 #    com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
diff --git a/services/accessibility/accessibility.aconfig b/services/accessibility/accessibility.aconfig
index 08cc9c3..ffa4841 100644
--- a/services/accessibility/accessibility.aconfig
+++ b/services/accessibility/accessibility.aconfig
@@ -117,7 +117,7 @@
     name: "enable_magnification_follows_mouse"
     namespace: "accessibility"
     description: "Whether to enable mouse following for fullscreen magnification"
-    bug: "335494097"
+    bug: "354696546"
 }
 
 flag {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index d16a665..1b2447e 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -26,6 +26,7 @@
 import android.annotation.NonNull;
 import android.content.Context;
 import android.graphics.Region;
+import android.hardware.input.InputManager;
 import android.os.Looper;
 import android.os.PowerManager;
 import android.os.SystemClock;
@@ -57,6 +58,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Objects;
 import java.util.StringJoiner;
 
 /**
@@ -748,6 +750,7 @@
 
         if ((mEnabledFeatures & FLAG_FEATURE_MOUSE_KEYS) != 0) {
             mMouseKeysInterceptor = new MouseKeysInterceptor(mAms,
+                    Objects.requireNonNull(mContext.getSystemService(InputManager.class)),
                     Looper.myLooper(),
                     Display.DEFAULT_DISPLAY);
             addFirstEventHandler(Display.DEFAULT_DISPLAY, mMouseKeysInterceptor);
diff --git a/services/accessibility/java/com/android/server/accessibility/MouseKeysInterceptor.java b/services/accessibility/java/com/android/server/accessibility/MouseKeysInterceptor.java
index 2ce5c2b..54368ca 100644
--- a/services/accessibility/java/com/android/server/accessibility/MouseKeysInterceptor.java
+++ b/services/accessibility/java/com/android/server/accessibility/MouseKeysInterceptor.java
@@ -23,6 +23,7 @@
 import android.annotation.RequiresPermission;
 import android.companion.virtual.VirtualDeviceManager;
 import android.companion.virtual.VirtualDeviceParams;
+import android.hardware.input.InputManager;
 import android.hardware.input.VirtualMouse;
 import android.hardware.input.VirtualMouseButtonEvent;
 import android.hardware.input.VirtualMouseConfig;
@@ -34,8 +35,11 @@
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.view.InputDevice;
 import android.view.KeyEvent;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.server.LocalServices;
 import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
 
@@ -60,7 +64,7 @@
  * mouse keys of each physical keyboard will control a single (global) mouse pointer.
  */
 public class MouseKeysInterceptor extends BaseEventStreamTransformation
-        implements Handler.Callback {
+        implements Handler.Callback, InputManager.InputDeviceListener {
     private static final String LOG_TAG = "MouseKeysInterceptor";
 
     // To enable these logs, run: 'adb shell setprop log.tag.MouseKeysInterceptor DEBUG'
@@ -77,10 +81,19 @@
 
     private final AccessibilityManagerService mAms;
     private final Handler mHandler;
+    private final InputManager mInputManager;
 
     /** Thread to wait for virtual mouse creation to complete */
     private final Thread mCreateVirtualMouseThread;
 
+    /**
+     * Map of device IDs to a map of key codes to their corresponding {@link MouseKeyEvent} values.
+     * To ensure thread safety for the map, all access and modification of the map
+     * should happen on the same thread, i.e., on the handler thread.
+     */
+    private final SparseArray<SparseArray<MouseKeyEvent>> mDeviceKeyCodeMap =
+            new SparseArray<>();
+
     VirtualDeviceManager.VirtualDevice mVirtualDevice = null;
 
     private VirtualMouse mVirtualMouse = null;
@@ -102,6 +115,21 @@
     /** Whether scroll toggle is on */
     private boolean mScrollToggleOn = false;
 
+    /** The ID of the input device that is currently active */
+    private int mActiveInputDeviceId = 0;
+
+    /**
+     * Enum representing different types of mouse key events, each associated with a specific
+     * key code.
+     *
+     * <p> These events correspond to various mouse actions such as directional movements,
+     * clicks, and scrolls, mapped to specific keys on the keyboard.
+     * The key codes here are the QWERTY key codes, and should be accessed via
+     * {@link MouseKeyEvent#getKeyCode(InputDevice)}
+     * so that it is mapped to the equivalent key on the keyboard layout of the keyboard device
+     * that is actually in use.
+     * </p>
+     */
     public enum MouseKeyEvent {
         DIAGONAL_UP_LEFT_MOVE(KeyEvent.KEYCODE_7),
         UP_MOVE_OR_SCROLL(KeyEvent.KEYCODE_8),
@@ -117,34 +145,64 @@
         RELEASE(KeyEvent.KEYCODE_COMMA),
         SCROLL_TOGGLE(KeyEvent.KEYCODE_PERIOD);
 
-        private final int mKeyCode;
+        private final int mLocationKeyCode;
         MouseKeyEvent(int enumValue) {
-            mKeyCode = enumValue;
+            mLocationKeyCode = enumValue;
         }
 
-        private static final SparseArray<MouseKeyEvent> VALUE_TO_ENUM_MAP = new SparseArray<>();
-
-        static {
-            for (MouseKeyEvent type : MouseKeyEvent.values()) {
-                VALUE_TO_ENUM_MAP.put(type.mKeyCode, type);
-            }
-        }
-
+        @VisibleForTesting
         public final int getKeyCodeValue() {
-            return mKeyCode;
+            return mLocationKeyCode;
         }
 
         /**
-         * Convert int value of the key code to corresponding MouseEvent enum. If no matching
-         * value is found, this will return {@code null}.
+         * Get the key code associated with the given MouseKeyEvent for the given keyboard
+         * input device, taking into account its layout.
+         * The default is to return the keycode for the default layout (QWERTY).
+         * We check if the input device has been generated using {@link InputDevice#getGeneration()}
+         * to test with the default {@link MouseKeyEvent} values in the unit tests.
+         */
+        public int getKeyCode(InputDevice inputDevice) {
+            if (inputDevice.getGeneration() == -1) {
+                return mLocationKeyCode;
+            }
+            return inputDevice.getKeyCodeForKeyLocation(mLocationKeyCode);
+        }
+
+        /**
+         * Convert int value of the key code to corresponding {@link MouseKeyEvent}
+         * enum for a particular device ID.
+         * If no matching value is found, this will return {@code null}.
          */
         @Nullable
-        public static MouseKeyEvent from(int value) {
-            return VALUE_TO_ENUM_MAP.get(value);
+        public static MouseKeyEvent from(int keyCode, int deviceId,
+                SparseArray<SparseArray<MouseKeyEvent>> deviceKeyCodeMap) {
+            SparseArray<MouseKeyEvent> keyCodeToEnumMap = deviceKeyCodeMap.get(deviceId);
+            if (keyCodeToEnumMap != null) {
+                return keyCodeToEnumMap.get(keyCode);
+            }
+            return null;
         }
     }
 
     /**
+     * Create a map of key codes to their corresponding {@link MouseKeyEvent} values
+     * for a specific input device.
+     * The key for {@code mDeviceKeyCodeMap} is the deviceId.
+     * The key for {@code keyCodeToEnumMap} is the keycode for each
+     * {@link MouseKeyEvent} according to the keyboard layout of the input device.
+     */
+    public void initializeDeviceToEnumMap(InputDevice inputDevice) {
+        int deviceId = inputDevice.getId();
+        SparseArray<MouseKeyEvent> keyCodeToEnumMap = new SparseArray<>();
+        for (MouseKeyEvent mouseKeyEventType : MouseKeyEvent.values()) {
+            int keyCode = mouseKeyEventType.getKeyCode(inputDevice);
+            keyCodeToEnumMap.put(keyCode, mouseKeyEventType);
+        }
+        mDeviceKeyCodeMap.put(deviceId, keyCodeToEnumMap);
+    }
+
+    /**
      * Construct a new MouseKeysInterceptor.
      *
      * @param service The service to notify of key events
@@ -152,8 +210,10 @@
      * @param displayId Display ID to send mouse events to
      */
     @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
-    public MouseKeysInterceptor(AccessibilityManagerService service, Looper looper, int displayId) {
+    public MouseKeysInterceptor(AccessibilityManagerService service,
+            InputManager inputManager, Looper looper, int displayId) {
         mAms = service;
+        mInputManager = inputManager;
         mHandler = new Handler(looper, this);
         // Create the virtual mouse on a separate thread since virtual device creation
         // should happen on an auxiliary thread, and not from the handler's thread.
@@ -163,6 +223,9 @@
             mVirtualMouse = createVirtualMouse(displayId);
         });
         mCreateVirtualMouseThread.start();
+        // Register an input device listener to watch when input devices are
+        // added, removed or reconfigured.
+        mInputManager.registerInputDeviceListener(this, mHandler);
     }
 
     /**
@@ -215,7 +278,8 @@
      */
     @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
     private void performMouseScrollAction(int keyCode) {
-        MouseKeyEvent mouseKeyEvent = MouseKeyEvent.from(keyCode);
+        MouseKeyEvent mouseKeyEvent = MouseKeyEvent.from(
+                keyCode, mActiveInputDeviceId, mDeviceKeyCodeMap);
         float y = switch (mouseKeyEvent) {
             case UP_MOVE_OR_SCROLL -> 1.0f;
             case DOWN_MOVE_OR_SCROLL -> -1.0f;
@@ -247,15 +311,18 @@
      */
     @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
     private void performMouseButtonAction(int keyCode) {
-        MouseKeyEvent mouseKeyEvent = MouseKeyEvent.from(keyCode);
+        MouseKeyEvent mouseKeyEvent = MouseKeyEvent.from(
+                keyCode, mActiveInputDeviceId, mDeviceKeyCodeMap);
         int buttonCode = switch (mouseKeyEvent) {
             case LEFT_CLICK -> VirtualMouseButtonEvent.BUTTON_PRIMARY;
             case RIGHT_CLICK -> VirtualMouseButtonEvent.BUTTON_SECONDARY;
             default -> VirtualMouseButtonEvent.BUTTON_UNKNOWN;
         };
         if (buttonCode != VirtualMouseButtonEvent.BUTTON_UNKNOWN) {
-            sendVirtualMouseButtonEvent(buttonCode, VirtualMouseButtonEvent.ACTION_BUTTON_PRESS);
-            sendVirtualMouseButtonEvent(buttonCode, VirtualMouseButtonEvent.ACTION_BUTTON_RELEASE);
+            sendVirtualMouseButtonEvent(buttonCode,
+                    VirtualMouseButtonEvent.ACTION_BUTTON_PRESS);
+            sendVirtualMouseButtonEvent(buttonCode,
+                    VirtualMouseButtonEvent.ACTION_BUTTON_RELEASE);
         }
         if (DEBUG) {
             if (buttonCode == VirtualMouseButtonEvent.BUTTON_UNKNOWN) {
@@ -293,7 +360,9 @@
     private void performMousePointerAction(int keyCode) {
         float x = 0f;
         float y = 0f;
-        MouseKeyEvent mouseKeyEvent = MouseKeyEvent.from(keyCode);
+        MouseKeyEvent mouseKeyEvent = MouseKeyEvent.from(
+                keyCode, mActiveInputDeviceId, mDeviceKeyCodeMap);
+
         switch (mouseKeyEvent) {
             case DIAGONAL_DOWN_LEFT_MOVE -> {
                 x = -MOUSE_POINTER_MOVEMENT_STEP / sqrt(2);
@@ -339,18 +408,19 @@
         }
     }
 
-    private boolean isMouseKey(int keyCode) {
-        return MouseKeyEvent.VALUE_TO_ENUM_MAP.contains(keyCode);
+    private boolean isMouseKey(int keyCode, int deviceId) {
+        SparseArray<MouseKeyEvent> keyCodeToEnumMap = mDeviceKeyCodeMap.get(deviceId);
+        return keyCodeToEnumMap.contains(keyCode);
     }
 
-    private boolean isMouseButtonKey(int keyCode) {
-        return keyCode == MouseKeyEvent.LEFT_CLICK.getKeyCodeValue()
-                || keyCode == MouseKeyEvent.RIGHT_CLICK.getKeyCodeValue();
+    private boolean isMouseButtonKey(int keyCode, InputDevice inputDevice) {
+        return keyCode == MouseKeyEvent.LEFT_CLICK.getKeyCode(inputDevice)
+                || keyCode == MouseKeyEvent.RIGHT_CLICK.getKeyCode(inputDevice);
     }
 
-    private boolean isMouseScrollKey(int keyCode) {
-        return keyCode == MouseKeyEvent.UP_MOVE_OR_SCROLL.getKeyCodeValue()
-                || keyCode == MouseKeyEvent.DOWN_MOVE_OR_SCROLL.getKeyCodeValue();
+    private boolean isMouseScrollKey(int keyCode, InputDevice inputDevice) {
+        return keyCode == MouseKeyEvent.UP_MOVE_OR_SCROLL.getKeyCode(inputDevice)
+                || keyCode == MouseKeyEvent.DOWN_MOVE_OR_SCROLL.getKeyCode(inputDevice);
     }
 
     /**
@@ -373,7 +443,7 @@
     }
 
     /**
-     * Handles key events and forwards mouse key events to the virtual mouse.
+     * Handles key events and forwards mouse key events to the virtual mouse on the handler thread.
      *
      * @param event The key event to handle.
      * @param policyFlags The policy flags associated with the key event.
@@ -385,31 +455,45 @@
             mAms.getTraceManager().logTrace(LOG_TAG + ".onKeyEvent",
                     FLAGS_INPUT_FILTER, "event=" + event + ";policyFlags=" + policyFlags);
         }
+
+        mHandler.post(() -> {
+            onKeyEventInternal(event, policyFlags);
+        });
+    }
+
+    @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
+    private void onKeyEventInternal(KeyEvent event, int policyFlags) {
         boolean isDown = event.getAction() == KeyEvent.ACTION_DOWN;
         int keyCode = event.getKeyCode();
+        mActiveInputDeviceId = event.getDeviceId();
+        InputDevice inputDevice = mInputManager.getInputDevice(mActiveInputDeviceId);
 
-        if (!isMouseKey(keyCode)) {
+        if (!mDeviceKeyCodeMap.contains(mActiveInputDeviceId)) {
+            initializeDeviceToEnumMap(inputDevice);
+        }
+
+        if (!isMouseKey(keyCode, mActiveInputDeviceId)) {
             // Pass non-mouse key events to the next handler
             super.onKeyEvent(event, policyFlags);
         } else if (isDown) {
-            if (keyCode == MouseKeyEvent.SCROLL_TOGGLE.getKeyCodeValue()) {
+            if (keyCode == MouseKeyEvent.SCROLL_TOGGLE.getKeyCode(inputDevice)) {
                 mScrollToggleOn = !mScrollToggleOn;
                 if (DEBUG) {
                     Slog.d(LOG_TAG, "Scroll toggle " + (mScrollToggleOn ? "ON" : "OFF"));
                 }
-            } else if (keyCode == MouseKeyEvent.HOLD.getKeyCodeValue()) {
+            } else if (keyCode == MouseKeyEvent.HOLD.getKeyCode(inputDevice)) {
                 sendVirtualMouseButtonEvent(
                         VirtualMouseButtonEvent.BUTTON_PRIMARY,
                         VirtualMouseButtonEvent.ACTION_BUTTON_PRESS
                 );
-            } else if (keyCode == MouseKeyEvent.RELEASE.getKeyCodeValue()) {
+            } else if (keyCode == MouseKeyEvent.RELEASE.getKeyCode(inputDevice)) {
                 sendVirtualMouseButtonEvent(
                         VirtualMouseButtonEvent.BUTTON_PRIMARY,
                         VirtualMouseButtonEvent.ACTION_BUTTON_RELEASE
                 );
-            } else if (isMouseButtonKey(keyCode)) {
+            } else if (isMouseButtonKey(keyCode, inputDevice)) {
                 performMouseButtonAction(keyCode);
-            } else if (mScrollToggleOn && isMouseScrollKey(keyCode)) {
+            } else if (mScrollToggleOn && isMouseScrollKey(keyCode, inputDevice)) {
                 // If the scroll key is pressed down and no other key is active,
                 // set it as the active key and send a message to scroll the pointer
                 if (mActiveScrollKey == KEY_NOT_SET) {
@@ -439,7 +523,8 @@
                 mHandler.removeMessages(MESSAGE_SCROLL_MOUSE_POINTER);
             } else {
                 Slog.i(LOG_TAG, "Dropping event with key code: '" + keyCode
-                        + "', with no matching down event from deviceId = " + event.getDeviceId());
+                        + "', with no matching down event from deviceId = "
+                        + event.getDeviceId());
             }
         }
     }
@@ -503,12 +588,40 @@
     @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
     @Override
     public void onDestroy() {
-        // Clear mouse state
-        mActiveMoveKey = KEY_NOT_SET;
-        mActiveScrollKey = KEY_NOT_SET;
-        mLastTimeKeyActionPerformed = 0;
+        mHandler.post(() -> {
+            // Clear mouse state
+            mActiveMoveKey = KEY_NOT_SET;
+            mActiveScrollKey = KEY_NOT_SET;
+            mLastTimeKeyActionPerformed = 0;
+            mDeviceKeyCodeMap.clear();
+        });
 
         mHandler.removeCallbacksAndMessages(null);
         mVirtualDevice.close();
     }
+
+    @Override
+    public void onInputDeviceAdded(int deviceId) {
+    }
+
+    @Override
+    public void onInputDeviceRemoved(int deviceId) {
+        mDeviceKeyCodeMap.remove(deviceId);
+    }
+
+    /**
+     * The user can change the keyboard layout from settings at anytime, which would change
+     * key character map for that device. Hence, we should use this callback to
+     * update the key code to enum mapping if there is a change in the physical keyboard detected.
+     *
+     * @param deviceId The id of the input device that changed.
+     */
+    @Override
+    public void onInputDeviceChanged(int deviceId) {
+        InputDevice inputDevice = mInputManager.getInputDevice(deviceId);
+        // Update the enum mapping only if input device that changed is a keyboard
+        if (inputDevice.isFullKeyboard() && !mDeviceKeyCodeMap.contains(deviceId)) {
+            initializeDeviceToEnumMap(inputDevice);
+        }
+    }
 }
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index 14a3211..dc0b4b8 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -48,6 +48,7 @@
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityManager;
 import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillManager;
 import android.view.autofill.AutofillValue;
 import android.view.autofill.IAutofillWindowPresenter;
 import android.widget.BaseAdapter;
@@ -82,7 +83,6 @@
             com.android.internal.R.style.Theme_DeviceDefault_Light_Autofill;
     private static final int THEME_ID_DARK =
             com.android.internal.R.style.Theme_DeviceDefault_Autofill;
-    private static final int AUTOFILL_CREDMAN_MAX_VISIBLE_DATASETS = 5;
 
     private static final TypedValue sTempTypedValue = new TypedValue();
 
@@ -113,9 +113,11 @@
 
     private final @NonNull Callback mCallback;
 
+    private final @NonNull WindowManager mWindowManager;
+
     private final @Nullable View mHeader;
     private final @NonNull ListView mListView;
-    private final @Nullable View mFooter;
+    private @Nullable View mFooter;
 
     private final @Nullable ItemsAdapter mAdapter;
 
@@ -134,6 +136,8 @@
 
     private int mMaxInputLengthForAutofill;
 
+    private final boolean mIsCredmanAutofillSession;
+
     public static boolean isFullScreen(Context context) {
         if (sFullScreenMode != null) {
             if (sVerbose) Slog.v(TAG, "forcing full-screen mode to " + sFullScreenMode);
@@ -158,6 +162,9 @@
         mContext = new ContextThemeWrapper(context, mThemeId);
         mUserContext = Helper.getUserContext(mContext);
         mMaxInputLengthForAutofill = maxInputLengthForAutofill;
+        mIsCredmanAutofillSession = (Flags.autofillCredmanIntegration()
+            && ((response.getFlags() & FLAG_CREDENTIAL_MANAGER_RESPONSE) != 0));
+        mWindowManager = mContext.getSystemService(WindowManager.class);
 
         final LayoutInflater inflater = LayoutInflater.from(mContext);
 
@@ -167,7 +174,8 @@
         final ViewGroup decor;
         if (mFullScreen) {
             decor = (ViewGroup) inflater.inflate(R.layout.autofill_dataset_picker_fullscreen, null);
-        } else if (headerPresentation != null || footerPresentation != null) {
+        } else if (headerPresentation != null
+                || footerPresentation != null || mIsCredmanAutofillSession) {
             decor = (ViewGroup) inflater.inflate(R.layout.autofill_dataset_picker_header_footer,
                     null);
         } else {
@@ -219,11 +227,7 @@
             if (sVerbose) {
                 Slog.v(TAG, "overriding maximum visible datasets to " + mVisibleDatasetsMaxCount);
             }
-        } else if (Flags.autofillCredmanIntegration() && (
-                (response.getFlags() & FLAG_CREDENTIAL_MANAGER_RESPONSE) != 0)) {
-            mVisibleDatasetsMaxCount = AUTOFILL_CREDMAN_MAX_VISIBLE_DATASETS;
-        }
-        else {
+        } else {
             mVisibleDatasetsMaxCount = mContext.getResources()
                     .getInteger(com.android.internal.R.integer.autofill_max_visible_datasets);
         }
@@ -301,7 +305,7 @@
                 mHeader = null;
             }
 
-            if (footerPresentation != null) {
+            if (footerPresentation != null && !mIsCredmanAutofillSession) {
                 final LinearLayout footerContainer =
                         decor.findViewById(R.id.autofill_dataset_footer);
                 if (footerContainer != null) {
@@ -366,7 +370,22 @@
                     }
 
                     applyCancelAction(view, response.getCancelIds());
-                    items.add(new ViewItem(dataset, filterPattern, filterable, valueText, view));
+                    if (AutofillManager.PINNED_DATASET_ID.equals(dataset.getId())
+                            && mIsCredmanAutofillSession && !items.isEmpty()) {
+                        final LinearLayout footerContainer =
+                                decor.findViewById(R.id.autofill_dataset_footer);
+                        if (sVerbose) {
+                          Slog.v(TAG, "adding footer");
+                        }
+                        mFooter = view;
+                        footerContainer.addView(mFooter);
+                        footerContainer.setVisibility(View.VISIBLE);
+                        footerContainer.setClickable(true);
+                        footerContainer.setOnClickListener(v -> mCallback.onDatasetPicked(dataset));
+                    } else {
+                        items.add(
+                            new ViewItem(dataset, filterPattern, filterable, valueText, view));
+                    }
                 }
             }
 
@@ -459,12 +478,9 @@
                 if (updateContentSize()) {
                     requestShowFillUi();
                 }
-                if (mAdapter.getCount() > mVisibleDatasetsMaxCount) {
-                    mListView.setVerticalScrollBarEnabled(true);
-                    mListView.onVisibilityAggregated(true);
-                } else {
-                    mListView.setVerticalScrollBarEnabled(false);
-                }
+                mListView.setVerticalScrollBarEnabled(true);
+                mListView.onVisibilityAggregated(true);
+
                 if (mAdapter.getCount() != oldCount) {
                     mListView.requestLayout();
                 }
@@ -578,11 +594,18 @@
         return changed;
     }
 
+    private boolean heightLesserThanDisplayScreen(int height) {
+        // Don't update list height for credential options beyond 80% of display window even if we
+        // are still under the max visible number of datasets. This could happen when font or
+        // display size is set to large.
+        return height < (0.8 * mWindowManager.getCurrentWindowMetrics().getBounds().height());
+    }
+
     private boolean updateHeight(View view, Point maxSize) {
         boolean changed = false;
         final int clampedMeasuredHeight = Math.min(view.getMeasuredHeight(), maxSize.y);
         final int newContentHeight = mContentHeight + clampedMeasuredHeight;
-        if (newContentHeight != mContentHeight) {
+        if (newContentHeight != mContentHeight && heightLesserThanDisplayScreen(newContentHeight)) {
             mContentHeight = newContentHeight;
             changed = true;
         }
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 07e5f2e..d86bae1 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -224,6 +224,9 @@
     /** Extended timeout for the system server watchdog for vold#partition operation. */
     private static final int PARTITION_OPERATION_WATCHDOG_TIMEOUT_MS = 3 * 60 * 1000;
 
+    private static final Pattern OBB_FILE_PATH = Pattern.compile(
+            "(?i)(^/storage/[^/]+/(?:([0-9]+)/)?Android/obb/)([^/]+)/([^/]+\\.obb)");
+
     @GuardedBy("mLock")
     private final Set<Integer> mFuseMountedUser = new ArraySet<>();
 
@@ -3144,7 +3147,9 @@
         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");
+        Objects.requireNonNull(obbInfo, "obbInfo cannot be null");
+
+        validateObbInfo(obbInfo, rawPath);
 
         final int callingUid = Binder.getCallingUid();
         final ObbState obbState = new ObbState(rawPath, canonicalPath,
@@ -3156,6 +3161,34 @@
             Slog.i(TAG, "Send to OBB handler: " + action.toString());
     }
 
+    private void validateObbInfo(ObbInfo obbInfo, String rawPath) {
+        String obbFilePath;
+        try {
+            obbFilePath = new File(rawPath).getCanonicalPath();
+        } catch (IOException ex) {
+            throw new RuntimeException("Failed to resolve path" + rawPath + " : " + ex);
+        }
+
+        Matcher matcher = OBB_FILE_PATH.matcher(obbFilePath);
+
+        if (matcher.matches()) {
+            int userId = UserHandle.getUserId(Binder.getCallingUid());
+            String pathUserId = matcher.group(2);
+            String pathPackageName = matcher.group(3);
+            if ((pathUserId != null && Integer.parseInt(pathUserId) != userId)
+                    || (pathUserId == null && userId != mCurrentUserId)) {
+                throw new SecurityException(
+                        "Path " + obbFilePath + "does not correspond to calling userId " + userId);
+            }
+            if (obbInfo != null && !obbInfo.packageName.equals(pathPackageName)) {
+                throw new SecurityException("Path " + obbFilePath
+                        + " does not contain package name " + pathPackageName);
+            }
+        } else {
+            throw new SecurityException("Invalid path to Obb file : " + obbFilePath);
+        }
+    }
+
     @Override
     public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) {
         Objects.requireNonNull(rawPath, "rawPath cannot be null");
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index d121535..e13b0a4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5426,7 +5426,9 @@
             for (int i=0; i<intents.length; i++) {
                 Intent intent = intents[i];
                 if (intent != null) {
-                    intent.prepareToEnterSystemServer();
+                    if (intent.hasFileDescriptors()) {
+                        throw new IllegalArgumentException("File descriptors passed in Intent");
+                    }
                     if (type == ActivityManager.INTENT_SENDER_BROADCAST &&
                             (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
                         throw new IllegalArgumentException(
@@ -5459,6 +5461,7 @@
                         }
                     }
                     intents[i] = new Intent(intent);
+                    intents[i].removeExtendedFlags(Intent.EXTENDED_FLAG_FILTER_MISMATCH);
                 }
             }
             if (resolvedTypes != null && resolvedTypes.length != intents.length) {
@@ -13591,7 +13594,12 @@
         enforceNotIsolatedCaller("startService");
         enforceAllowedToStartOrBindServiceIfSdkSandbox(service);
         if (service != null) {
-            service.prepareToEnterSystemServer();
+            // Refuse possible leaked file descriptors
+            if (service.hasFileDescriptors()) {
+                throw new IllegalArgumentException("File descriptors passed in Intent");
+            }
+            // Remove existing mismatch flag so it can be properly updated later
+            service.removeExtendedFlags(Intent.EXTENDED_FLAG_FILTER_MISMATCH);
         }
 
         if (callingPackage == null) {
@@ -13828,7 +13836,12 @@
         enforceAllowedToStartOrBindServiceIfSdkSandbox(service);
 
         if (service != null) {
-            service.prepareToEnterSystemServer();
+            // Refuse possible leaked file descriptors
+            if (service.hasFileDescriptors()) {
+                throw new IllegalArgumentException("File descriptors passed in Intent");
+            }
+            // Remove existing mismatch flag so it can be properly updated later
+            service.removeExtendedFlags(Intent.EXTENDED_FLAG_FILTER_MISMATCH);
         }
 
         if (callingPackage == null) {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 8e87342..955b75d 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -123,31 +123,16 @@
 import com.android.server.net.BaseNetworkObserver;
 import com.android.server.pm.UserManagerInternal;
 import com.android.server.power.optimization.Flags;
-import com.android.server.power.stats.AggregatedPowerStatsConfig;
-import com.android.server.power.stats.AmbientDisplayPowerStatsProcessor;
-import com.android.server.power.stats.AudioPowerStatsProcessor;
 import com.android.server.power.stats.BatteryExternalStatsWorker;
 import com.android.server.power.stats.BatteryStatsDumpHelperImpl;
 import com.android.server.power.stats.BatteryStatsImpl;
 import com.android.server.power.stats.BatteryUsageStatsProvider;
-import com.android.server.power.stats.BluetoothPowerStatsProcessor;
-import com.android.server.power.stats.CameraPowerStatsProcessor;
-import com.android.server.power.stats.CpuPowerStatsProcessor;
-import com.android.server.power.stats.CustomEnergyConsumerPowerStatsProcessor;
-import com.android.server.power.stats.FlashlightPowerStatsProcessor;
-import com.android.server.power.stats.GnssPowerStatsProcessor;
-import com.android.server.power.stats.MobileRadioPowerStatsProcessor;
-import com.android.server.power.stats.PhoneCallPowerStatsProcessor;
-import com.android.server.power.stats.PowerStatsAggregator;
-import com.android.server.power.stats.PowerStatsExporter;
+import com.android.server.power.stats.PowerAttributor;
 import com.android.server.power.stats.PowerStatsScheduler;
 import com.android.server.power.stats.PowerStatsStore;
 import com.android.server.power.stats.PowerStatsUidResolver;
-import com.android.server.power.stats.ScreenPowerStatsProcessor;
-import com.android.server.power.stats.SensorPowerStatsProcessor;
 import com.android.server.power.stats.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
-import com.android.server.power.stats.VideoPowerStatsProcessor;
-import com.android.server.power.stats.WifiPowerStatsProcessor;
+import com.android.server.power.stats.processor.MultiStatePowerAttributor;
 import com.android.server.power.stats.wakeups.CpuWakeupStats;
 
 import java.io.File;
@@ -207,7 +192,7 @@
     private final AtomicFile mConfigFile;
     private final BatteryStats.BatteryStatsDumpHelper mDumpHelper;
     private final PowerStatsUidResolver mPowerStatsUidResolver = new PowerStatsUidResolver();
-    private final AggregatedPowerStatsConfig mAggregatedPowerStatsConfig;
+    private final PowerAttributor mPowerAttributor;
 
     private volatile boolean mMonitorEnabled = true;
 
@@ -445,14 +430,12 @@
             mStats.startTrackingSystemServerCpuTime();
         }
 
-        mAggregatedPowerStatsConfig = createAggregatedPowerStatsConfig();
-        mPowerStatsStore = new PowerStatsStore(systemDir, mHandler, mAggregatedPowerStatsConfig);
+        mPowerStatsStore = new PowerStatsStore(systemDir, mHandler);
+        mPowerAttributor = new MultiStatePowerAttributor(mContext, mPowerStatsStore, mPowerProfile,
+                mCpuScalingPolicies, mPowerStatsUidResolver);
         mPowerStatsScheduler = createPowerStatsScheduler(mContext);
-        PowerStatsExporter powerStatsExporter =
-                new PowerStatsExporter(mPowerStatsStore,
-                        new PowerStatsAggregator(mAggregatedPowerStatsConfig, mStats.getHistory()));
         mBatteryUsageStatsProvider = new BatteryUsageStatsProvider(context,
-                powerStatsExporter, mPowerProfile, mCpuScalingPolicies,
+                mPowerAttributor, mPowerProfile, mCpuScalingPolicies,
                 mPowerStatsStore, Clock.SYSTEM_CLOCK);
         mStats.saveBatteryUsageStatsOnReset(mBatteryUsageStatsProvider, mPowerStatsStore);
         mDumpHelper = new BatteryStatsDumpHelperImpl(mBatteryUsageStatsProvider);
@@ -472,154 +455,11 @@
                             onAlarmListener, aHandler);
                 };
         return new PowerStatsScheduler(mStats::schedulePowerStatsSampleCollection,
-                new PowerStatsAggregator(mAggregatedPowerStatsConfig,
-                        mStats.getHistory()), aggregatedPowerStatsSpanDuration,
+                mStats.getHistory(), mPowerAttributor, aggregatedPowerStatsSpanDuration,
                 powerStatsAggregationPeriod, mPowerStatsStore, alarmScheduler, Clock.SYSTEM_CLOCK,
                 mMonotonicClock, () -> mStats.getHistory().getStartTime(), mHandler);
     }
 
-    private AggregatedPowerStatsConfig createAggregatedPowerStatsConfig() {
-        AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig();
-        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_CPU)
-                .trackDeviceStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN)
-                .trackUidStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN,
-                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
-                .setProcessorSupplier(
-                        () -> new CpuPowerStatsProcessor(mPowerProfile, mCpuScalingPolicies));
-
-        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_SCREEN)
-                .trackDeviceStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN)
-                .trackUidStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN)
-                .setProcessorSupplier(
-                        () -> new ScreenPowerStatsProcessor(mPowerProfile));
-
-        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY,
-                        BatteryConsumer.POWER_COMPONENT_SCREEN)
-                .setProcessorSupplier(AmbientDisplayPowerStatsProcessor::new);
-
-        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
-                .trackDeviceStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN)
-                .trackUidStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN,
-                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
-                .setProcessorSupplier(
-                        () -> new MobileRadioPowerStatsProcessor(mPowerProfile));
-
-        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_PHONE,
-                        BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
-                .setProcessorSupplier(PhoneCallPowerStatsProcessor::new);
-
-        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_WIFI)
-                .trackDeviceStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN)
-                .trackUidStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN,
-                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
-                .setProcessorSupplier(
-                        () -> new WifiPowerStatsProcessor(mPowerProfile));
-
-        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_BLUETOOTH)
-                .trackDeviceStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN)
-                .trackUidStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN,
-                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
-                .setProcessorSupplier(
-                        () -> new BluetoothPowerStatsProcessor(mPowerProfile));
-
-        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_AUDIO)
-                .trackDeviceStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN)
-                .trackUidStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN,
-                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
-                .setProcessorSupplier(
-                        () -> new AudioPowerStatsProcessor(mPowerProfile, mPowerStatsUidResolver));
-
-        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_VIDEO)
-                .trackDeviceStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN)
-                .trackUidStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN,
-                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
-                .setProcessorSupplier(
-                        () -> new VideoPowerStatsProcessor(mPowerProfile, mPowerStatsUidResolver));
-
-        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT)
-                .trackDeviceStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN)
-                .trackUidStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN,
-                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
-                .setProcessorSupplier(
-                        () -> new FlashlightPowerStatsProcessor(mPowerProfile,
-                                mPowerStatsUidResolver));
-
-        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_CAMERA)
-                .trackDeviceStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN)
-                .trackUidStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN,
-                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
-                .setProcessorSupplier(
-                        () -> new CameraPowerStatsProcessor(mPowerProfile, mPowerStatsUidResolver));
-
-        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_GNSS)
-                .trackDeviceStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN)
-                .trackUidStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN,
-                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
-                .setProcessorSupplier(
-                        () -> new GnssPowerStatsProcessor(mPowerProfile, mPowerStatsUidResolver));
-
-        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_SENSORS)
-                .trackDeviceStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN)
-                .trackUidStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN,
-                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
-                .setProcessorSupplier(() -> new SensorPowerStatsProcessor(
-                        () -> mContext.getSystemService(SensorManager.class)));
-
-        config.trackCustomPowerComponents(CustomEnergyConsumerPowerStatsProcessor::new)
-                .trackDeviceStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN)
-                .trackUidStates(
-                        AggregatedPowerStatsConfig.STATE_POWER,
-                        AggregatedPowerStatsConfig.STATE_SCREEN,
-                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE);
-        return config;
-    }
-
     private void setPowerStatsThrottlePeriods(BatteryStatsImpl.BatteryStatsConfig.Builder builder,
             String configString) {
         if (configString == null) {
@@ -664,83 +504,84 @@
     }
 
     public void systemServicesReady() {
+        MultiStatePowerAttributor attributor = (MultiStatePowerAttributor) mPowerAttributor;
         mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_CPU,
                 Flags.streamlinedBatteryStats());
-        mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+        attributor.setPowerComponentSupported(
                 BatteryConsumer.POWER_COMPONENT_CPU,
                 Flags.streamlinedBatteryStats());
 
         mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_SCREEN,
                 Flags.streamlinedMiscBatteryStats());
-        mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+        attributor.setPowerComponentSupported(
                 BatteryConsumer.POWER_COMPONENT_SCREEN,
                 Flags.streamlinedMiscBatteryStats());
 
         mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY,
                 Flags.streamlinedMiscBatteryStats());
-        mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+        attributor.setPowerComponentSupported(
                 BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY,
                 Flags.streamlinedMiscBatteryStats());
 
         mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO,
                 Flags.streamlinedConnectivityBatteryStats());
-        mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+        attributor.setPowerComponentSupported(
                 BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO,
                 Flags.streamlinedConnectivityBatteryStats());
-        mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+        attributor.setPowerComponentSupported(
                 BatteryConsumer.POWER_COMPONENT_PHONE,
                 Flags.streamlinedConnectivityBatteryStats());
 
         mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_WIFI,
                 Flags.streamlinedConnectivityBatteryStats());
-        mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+        attributor.setPowerComponentSupported(
                 BatteryConsumer.POWER_COMPONENT_WIFI,
                 Flags.streamlinedConnectivityBatteryStats());
 
         mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
                 Flags.streamlinedConnectivityBatteryStats());
-        mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+        attributor.setPowerComponentSupported(
                 BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
                 Flags.streamlinedConnectivityBatteryStats());
 
         mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_AUDIO,
                 Flags.streamlinedMiscBatteryStats());
-        mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+        attributor.setPowerComponentSupported(
                 BatteryConsumer.POWER_COMPONENT_AUDIO,
                 Flags.streamlinedMiscBatteryStats());
 
         mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_VIDEO,
                 Flags.streamlinedMiscBatteryStats());
-        mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+        attributor.setPowerComponentSupported(
                 BatteryConsumer.POWER_COMPONENT_VIDEO,
                 Flags.streamlinedMiscBatteryStats());
 
         mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT,
                 Flags.streamlinedMiscBatteryStats());
-        mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+        attributor.setPowerComponentSupported(
                 BatteryConsumer.POWER_COMPONENT_FLASHLIGHT,
                 Flags.streamlinedMiscBatteryStats());
 
         mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_GNSS,
                 Flags.streamlinedMiscBatteryStats());
-        mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+        attributor.setPowerComponentSupported(
                 BatteryConsumer.POWER_COMPONENT_GNSS,
                 Flags.streamlinedMiscBatteryStats());
 
-        mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+        attributor.setPowerComponentSupported(
                 BatteryConsumer.POWER_COMPONENT_SENSORS,
                 Flags.streamlinedMiscBatteryStats());
 
         mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_CAMERA,
                 Flags.streamlinedMiscBatteryStats());
-        mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+        attributor.setPowerComponentSupported(
                 BatteryConsumer.POWER_COMPONENT_CAMERA,
                 Flags.streamlinedMiscBatteryStats());
 
         // By convention POWER_COMPONENT_ANY represents custom Energy Consumers
         mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_ANY,
                 Flags.streamlinedMiscBatteryStats());
-        mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+        attributor.setPowerComponentSupported(
                 BatteryConsumer.POWER_COMPONENT_ANY,
                 Flags.streamlinedMiscBatteryStats());
 
diff --git a/services/core/java/com/android/server/am/BroadcastController.java b/services/core/java/com/android/server/am/BroadcastController.java
index 32026b2..f7085b4 100644
--- a/services/core/java/com/android/server/am/BroadcastController.java
+++ b/services/core/java/com/android/server/am/BroadcastController.java
@@ -1808,7 +1808,12 @@
 
     final Intent verifyBroadcastLocked(Intent intent) {
         if (intent != null) {
-            intent.prepareToEnterSystemServer();
+            // Refuse possible leaked file descriptors
+            if (intent.hasFileDescriptors()) {
+                throw new IllegalArgumentException("File descriptors passed in Intent");
+            }
+            // Remove existing mismatch flag so it can be properly updated later
+            intent.removeExtendedFlags(Intent.EXTENDED_FLAG_FILTER_MISMATCH);
         }
 
         int flags = intent.getFlags();
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 0e266f5..7e3f613 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1126,26 +1126,31 @@
         final int numLru = lruList.size();
         if (mConstants.USE_TIERED_CACHED_ADJ) {
             final long now = mInjector.getUptimeMillis();
+            int uiTargetAdj = 10;
             for (int i = numLru - 1; i >= 0; i--) {
                 ProcessRecord app = lruList.get(i);
                 final ProcessStateRecord state = app.mState;
                 final ProcessCachedOptimizerRecord opt = app.mOptRecord;
-                if (!app.isKilledByAm() && app.getThread() != null && state.getCurAdj()
-                        >= UNKNOWN_ADJ) {
+                if (!app.isKilledByAm() && app.getThread() != null
+                        && (state.getCurAdj() >= UNKNOWN_ADJ
+                            || (state.hasShownUi() && state.getCurAdj() >= CACHED_APP_MIN_ADJ))) {
                     final ProcessServiceRecord psr = app.mServices;
                     int targetAdj = CACHED_APP_MIN_ADJ;
 
                     if (opt != null && opt.isFreezeExempt()) {
                         // BIND_WAIVE_PRIORITY and the like get oom_adj 900
                         targetAdj += 0;
+                    } else if (state.hasShownUi() && uiTargetAdj < 15) {
+                        // The most recent 5 apps that have shown UI get 910-914
+                        targetAdj += uiTargetAdj++;
                     } else if ((state.getSetAdj() >= CACHED_APP_MIN_ADJ)
                             && (state.getLastStateTime()
                                     + mConstants.TIERED_CACHED_ADJ_DECAY_TIME) < now) {
                         // Older cached apps get 950
                         targetAdj += 50;
                     } else {
-                        // Newer cached apps get 910
-                        targetAdj += 10;
+                        // Newer cached apps get 920
+                        targetAdj += 20;
                     }
                     state.setCurRawAdj(targetAdj);
                     state.setCurAdj(psr.modifyRawOomAdj(targetAdj));
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 154b52b..6ae6f3d 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -33,7 +33,6 @@
 import static android.app.AppOpsManager.MODE_ERRORED;
 import static android.app.AppOpsManager.MODE_FOREGROUND;
 import static android.app.AppOpsManager.MODE_IGNORED;
-import static android.app.AppOpsManager.OP_BLUETOOTH_CONNECT;
 import static android.app.AppOpsManager.OP_CAMERA;
 import static android.app.AppOpsManager.OP_CAMERA_SANDBOXED;
 import static android.app.AppOpsManager.OP_FLAGS_ALL;
@@ -3115,11 +3114,6 @@
                     packageName);
         }
         if (!isIncomingPackageValid(packageName, UserHandle.getUserId(uid))) {
-            // TODO(b/302609140): Remove extra logging after this issue is diagnosed.
-            if (code == OP_BLUETOOTH_CONNECT) {
-                Slog.e(TAG, "noting OP_BLUETOOTH_CONNECT returned MODE_ERRORED as incoming "
-                        + "package: " + packageName + " and uid: " + uid + " is invalid");
-            }
             return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag,
                     packageName);
         }
@@ -3149,13 +3143,6 @@
             }
         } catch (SecurityException e) {
             logVerifyAndGetBypassFailure(uid, e, "noteOperation");
-            // TODO(b/302609140): Remove extra logging after this issue is diagnosed.
-            if (code == OP_BLUETOOTH_CONNECT) {
-                Slog.e(TAG, "noting OP_BLUETOOTH_CONNECT returned MODE_ERRORED as"
-                        + " verifyAndGetBypass returned a SecurityException for package: "
-                        + packageName + " and uid: " + uid + " and attributionTag: "
-                        + attributionTag, e);
-            }
             return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag,
                     packageName);
         }
@@ -3173,17 +3160,6 @@
                 if (DEBUG) Slog.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
                         + " package " + packageName + "flags: " +
                         AppOpsManager.flagsToString(flags));
-                // TODO(b/302609140): Remove extra logging after this issue is diagnosed.
-                if (code == OP_BLUETOOTH_CONNECT) {
-                    Slog.e(TAG, "noting OP_BLUETOOTH_CONNECT returned MODE_ERRORED as"
-                            + " #getOpsLocked returned null for"
-                            + " uid: " + uid
-                            + " packageName: " + packageName
-                            + " attributionTag: " + attributionTag
-                            + " pvr.isAttributionTagValid: " + pvr.isAttributionTagValid
-                            + " pvr.bypass: " + pvr.bypass);
-                    Slog.e(TAG, "mUidStates.get(" + uid + "): " + mUidStates.get(uid));
-                }
                 return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag,
                         packageName);
             }
@@ -3228,11 +3204,6 @@
                     attributedOp.rejected(uidState.getState(), flags);
                     scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag,
                             virtualDeviceId, flags, uidMode);
-                    // TODO(b/302609140): Remove extra logging after this issue is diagnosed.
-                    if (code == OP_BLUETOOTH_CONNECT && uidMode == MODE_ERRORED) {
-                        Slog.e(TAG, "noting OP_BLUETOOTH_CONNECT returned MODE_ERRORED as"
-                                + " uid mode is MODE_ERRORED");
-                    }
                     return new SyncNotedAppOp(uidMode, code, attributionTag, packageName);
                 }
             } else {
@@ -3252,11 +3223,6 @@
                     attributedOp.rejected(uidState.getState(), flags);
                     scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag,
                             virtualDeviceId, flags, mode);
-                    // TODO(b/302609140): Remove extra logging after this issue is diagnosed.
-                    if (code == OP_BLUETOOTH_CONNECT && mode == MODE_ERRORED) {
-                        Slog.e(TAG, "noting OP_BLUETOOTH_CONNECT returned MODE_ERRORED as"
-                                + " package mode is MODE_ERRORED");
-                    }
                     return new SyncNotedAppOp(mode, code, attributionTag, packageName);
                 }
             }
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index 70f3193..7e26356 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -1302,7 +1302,7 @@
         mEventLogger.enqueue((new EventLogger.StringEvent(
                 "abandonAudioFocus() from uid/pid " + Binder.getCallingUid()
                     + "/" + Binder.getCallingPid()
-                    + " clientId=" + clientId))
+                    + " clientId=" + clientId + " callingPack=" + callingPackageName))
                 .printLog(TAG));
         try {
             // this will take care of notifying the new focus owner if needed
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 99ad65d..0abd9bc 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -354,7 +354,7 @@
             new CopyOnWriteArrayList<>();
 
     /** All {@link DisplayPowerController}s indexed by {@link LogicalDisplay} ID. */
-    private final SparseArray<DisplayPowerControllerInterface> mDisplayPowerControllers =
+    private final SparseArray<DisplayPowerController> mDisplayPowerControllers =
             new SparseArray<>();
 
     /** {@link DisplayBlanker} used by all {@link DisplayPowerController}s. */
@@ -726,7 +726,7 @@
                 if (logicalDisplay.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) {
                     return;
                 }
-                final DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(
+                final DisplayPowerController dpc = mDisplayPowerControllers.get(
                         logicalDisplay.getDisplayIdLocked());
                 if (dpc == null) {
                     return;
@@ -2058,7 +2058,7 @@
             configurePreferredDisplayModeLocked(display);
         }
 
-        DisplayPowerControllerInterface dpc = addDisplayPowerControllerLocked(display);
+        DisplayPowerController dpc = addDisplayPowerControllerLocked(display);
         if (dpc != null) {
             final int leadDisplayId = display.getLeadDisplayIdLocked();
             updateDisplayPowerControllerLeaderLocked(dpc, leadDisplayId);
@@ -2067,7 +2067,7 @@
             // that the follower display was added before the lead display.
             mLogicalDisplayMapper.forEachLocked(d -> {
                 if (d.getLeadDisplayIdLocked() == displayId) {
-                    DisplayPowerControllerInterface followerDpc =
+                    DisplayPowerController followerDpc =
                             mDisplayPowerControllers.get(d.getDisplayIdLocked());
                     if (followerDpc != null) {
                         updateDisplayPowerControllerLeaderLocked(followerDpc, displayId);
@@ -2151,7 +2151,7 @@
         scheduleTraversalLocked(false);
         mPersistentDataStore.saveIfNeeded();
 
-        DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
+        DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
         if (dpc != null) {
             final int leadDisplayId = display.getLeadDisplayIdLocked();
             updateDisplayPowerControllerLeaderLocked(dpc, leadDisplayId);
@@ -2165,7 +2165,7 @@
     }
 
     private void updateDisplayPowerControllerLeaderLocked(
-            @NonNull DisplayPowerControllerInterface dpc, int leadDisplayId) {
+            @NonNull DisplayPowerController dpc, int leadDisplayId) {
         if (dpc.getLeadDisplayId() == leadDisplayId) {
             // Lead display hasn't changed, nothing to do.
             return;
@@ -2174,7 +2174,7 @@
         // If it has changed, then we need to unregister from the previous leader if there was one.
         final int prevLeaderId = dpc.getLeadDisplayId();
         if (prevLeaderId != Layout.NO_LEAD_DISPLAY) {
-            final DisplayPowerControllerInterface prevLeader =
+            final DisplayPowerController prevLeader =
                     mDisplayPowerControllers.get(prevLeaderId);
             if (prevLeader != null) {
                 prevLeader.removeDisplayBrightnessFollower(dpc);
@@ -2183,7 +2183,7 @@
 
         // And then, if it's following, register it with the new one.
         if (leadDisplayId != Layout.NO_LEAD_DISPLAY) {
-            final DisplayPowerControllerInterface newLeader =
+            final DisplayPowerController newLeader =
                     mDisplayPowerControllers.get(leadDisplayId);
             if (newLeader != null) {
                 newLeader.addDisplayBrightnessFollower(dpc);
@@ -2224,7 +2224,7 @@
     private void releaseDisplayAndEmitEvent(LogicalDisplay display, int event) {
         final int displayId = display.getDisplayIdLocked();
 
-        final DisplayPowerControllerInterface dpc =
+        final DisplayPowerController dpc =
                 mDisplayPowerControllers.removeReturnOld(displayId);
         if (dpc != null) {
             updateDisplayPowerControllerLeaderLocked(dpc, Layout.NO_LEAD_DISPLAY);
@@ -2271,7 +2271,7 @@
 
     private void handleLogicalDisplayDeviceStateTransitionLocked(@NonNull LogicalDisplay display) {
         final int displayId = display.getDisplayIdLocked();
-        final DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
+        final DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
         if (dpc != null) {
             final int leadDisplayId = display.getLeadDisplayIdLocked();
             updateDisplayPowerControllerLeaderLocked(dpc, leadDisplayId);
@@ -2692,14 +2692,14 @@
             if (userId != mCurrentUserId) {
                 return;
             }
-            DisplayPowerControllerInterface dpc = getDpcFromUniqueIdLocked(uniqueId);
+            DisplayPowerController dpc = getDpcFromUniqueIdLocked(uniqueId);
             if (dpc != null) {
                 dpc.setBrightnessConfiguration(c, /* shouldResetShortTermModel= */ true);
             }
         }
     }
 
-    private DisplayPowerControllerInterface getDpcFromUniqueIdLocked(String uniqueId) {
+    private DisplayPowerController getDpcFromUniqueIdLocked(String uniqueId) {
         final DisplayDevice displayDevice = mDisplayDeviceRepo.getByUniqueIdLocked(uniqueId);
         final LogicalDisplay logicalDisplay = mLogicalDisplayMapper.getDisplayLocked(displayDevice);
         if (logicalDisplay != null) {
@@ -2740,7 +2740,7 @@
                 final BrightnessConfiguration config =
                         getBrightnessConfigForDisplayWithPdsFallbackLocked(uniqueId, userSerial);
                 if (config != null) {
-                    final DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(
+                    final DisplayPowerController dpc = mDisplayPowerControllers.get(
                             logicalDisplay.getDisplayIdLocked());
                     if (dpc != null) {
                         dpc.setBrightnessConfiguration(config,
@@ -2987,7 +2987,7 @@
 
     void setAutoBrightnessLoggingEnabled(boolean enabled) {
         synchronized (mSyncRoot) {
-            final DisplayPowerControllerInterface displayPowerController =
+            final DisplayPowerController displayPowerController =
                     mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY);
             if (displayPowerController != null) {
                 displayPowerController.setAutoBrightnessLoggingEnabled(enabled);
@@ -2997,7 +2997,7 @@
 
     void setDisplayWhiteBalanceLoggingEnabled(boolean enabled) {
         synchronized (mSyncRoot) {
-            final DisplayPowerControllerInterface displayPowerController =
+            final DisplayPowerController displayPowerController =
                     mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY);
             if (displayPowerController != null) {
                 displayPowerController.setDisplayWhiteBalanceLoggingEnabled(enabled);
@@ -3023,7 +3023,7 @@
 
     void setAmbientColorTemperatureOverride(float cct) {
         synchronized (mSyncRoot) {
-            final DisplayPowerControllerInterface displayPowerController =
+            final DisplayPowerController displayPowerController =
                     mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY);
             if (displayPowerController != null) {
                 displayPowerController.setAmbientColorTemperatureOverride(cct);
@@ -3033,7 +3033,7 @@
 
     void setDockedAndIdleEnabled(boolean enabled, int displayId) {
         synchronized (mSyncRoot) {
-            final DisplayPowerControllerInterface displayPowerController =
+            final DisplayPowerController displayPowerController =
                     mDisplayPowerControllers.get(displayId);
             if (displayPowerController != null) {
                 displayPowerController.setAutomaticScreenBrightnessMode(enabled
@@ -3571,7 +3571,7 @@
     }
 
     @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
-    private DisplayPowerControllerInterface addDisplayPowerControllerLocked(
+    private DisplayPowerController addDisplayPowerControllerLocked(
             LogicalDisplay display) {
         if (mPowerHandler == null) {
             // initPowerManagement has not yet been called.
@@ -3585,7 +3585,7 @@
         final int userSerial = getUserManager().getUserSerialNumber(mContext.getUserId());
         final BrightnessSetting brightnessSetting = new BrightnessSetting(userSerial,
                 mPersistentDataStore, display, mSyncRoot);
-        final DisplayPowerControllerInterface displayPowerController;
+        final DisplayPowerController displayPowerController;
 
         // If display is internal and has a HighBrightnessModeMetadata mapping, use that.
         // Or create a new one and use that.
@@ -4373,7 +4373,7 @@
                                     uniqueId, userSerial);
                     if (config == null) {
                         // Get default configuration
-                        DisplayPowerControllerInterface dpc = getDpcFromUniqueIdLocked(uniqueId);
+                        DisplayPowerController dpc = getDpcFromUniqueIdLocked(uniqueId);
                         if (dpc != null) {
                             config = dpc.getDefaultBrightnessConfiguration();
                         }
@@ -4427,7 +4427,7 @@
                     if (display == null || !display.isEnabledLocked()) {
                         return null;
                     }
-                    DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
+                    DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
                     if (dpc != null) {
                         return dpc.getBrightnessInfo();
                     }
@@ -4472,7 +4472,7 @@
             final long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mSyncRoot) {
-                    DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
+                    DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
                     if (dpc != null) {
                         dpc.setBrightness(brightness);
                     }
@@ -4492,7 +4492,7 @@
             final long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mSyncRoot) {
-                    DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
+                    DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
                     if (dpc != null) {
                         brightness = dpc.getScreenBrightnessSetting();
                     }
@@ -4819,7 +4819,7 @@
                             id).getPrimaryDisplayDeviceLocked();
                     final int flags = displayDevice.getDisplayDeviceInfoLocked().flags;
                     if ((flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
-                        final DisplayPowerControllerInterface displayPowerController =
+                        final DisplayPowerController displayPowerController =
                                 mDisplayPowerControllers.get(id);
                         if (displayPowerController != null) {
                             ready &= displayPowerController.requestPowerState(request,
@@ -5200,7 +5200,7 @@
                     return null;
                 }
 
-                DisplayPowerControllerInterface displayPowerController =
+                DisplayPowerController displayPowerController =
                         mDisplayPowerControllers.get(logicalDisplay.getDisplayIdLocked());
                 if (displayPowerController == null) {
                     Slog.w(TAG,
diff --git a/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java b/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java
index a188e79..b05a96e 100644
--- a/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java
+++ b/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java
@@ -39,12 +39,12 @@
 
     @Nullable
     private final DisplayManagerInternal.DisplayOffloader mDisplayOffloader;
-    private final DisplayPowerControllerInterface mDisplayPowerController;
+    private final DisplayPowerController mDisplayPowerController;
     private boolean mIsActive;
 
     public DisplayOffloadSessionImpl(
             @Nullable DisplayManagerInternal.DisplayOffloader displayOffloader,
-            DisplayPowerControllerInterface displayPowerController) {
+            DisplayPowerController displayPowerController) {
         mDisplayOffloader = displayOffloader;
         mDisplayPowerController = displayPowerController;
     }
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index bf559c1..bb2bed7 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -126,7 +126,7 @@
  * slower by changing the "animator duration scale" option in Development Settings.
  */
 final class DisplayPowerController implements AutomaticBrightnessController.Callbacks,
-        DisplayWhiteBalanceController.Callbacks, DisplayPowerControllerInterface {
+        DisplayWhiteBalanceController.Callbacks{
     private static final String SCREEN_ON_BLOCKED_TRACE_NAME = "Screen on blocked";
     private static final String SCREEN_OFF_BLOCKED_TRACE_NAME = "Screen off blocked";
 
@@ -481,7 +481,7 @@
     // DPCs following the brightness of this DPC. This is used in concurrent displays mode - there
     // is one lead display, the additional displays follow the brightness value of the lead display.
     @GuardedBy("mLock")
-    private final SparseArray<DisplayPowerControllerInterface> mDisplayBrightnessFollowers =
+    private final SparseArray<DisplayPowerController> mDisplayBrightnessFollowers =
             new SparseArray();
 
     private boolean mBootCompleted;
@@ -679,7 +679,6 @@
     /**
      * Returns true if the proximity sensor screen-off function is available.
      */
-    @Override
     public boolean isProximitySensorAvailable() {
         return mDisplayPowerProximityStateController.isProximitySensorAvailable();
     }
@@ -691,7 +690,6 @@
      * @param includePackage if false will null out the package name in events
      */
     @Nullable
-    @Override
     public ParceledListSlice<BrightnessChangeEvent> getBrightnessEvents(
             @UserIdInt int userId, boolean includePackage) {
         if (mBrightnessTracker == null) {
@@ -700,7 +698,6 @@
         return mBrightnessTracker.getEvents(userId, includePackage);
     }
 
-    @Override
     public void onSwitchUser(@UserIdInt int newUserId, int userSerial, float newBrightness) {
         Message msg = mHandler.obtainMessage(MSG_SWITCH_USER, newUserId, userSerial, newBrightness);
         mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
@@ -737,7 +734,6 @@
     }
 
     @Nullable
-    @Override
     public ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats(
             @UserIdInt int userId) {
         if (mBrightnessTracker == null) {
@@ -749,7 +745,6 @@
     /**
      * Persist the brightness slider events and ambient brightness stats to disk.
      */
-    @Override
     public void persistBrightnessTrackerState() {
         if (mBrightnessTracker != null) {
             mBrightnessTracker.persistBrightnessTrackerState();
@@ -806,7 +801,6 @@
         }
     }
 
-    @Override
     public void overrideDozeScreenState(int displayState, @Display.StateReason int reason) {
         Slog.i(TAG, "New offload doze override: " + Display.stateToString(displayState));
         if (mDisplayOffloadSession != null
@@ -833,7 +827,6 @@
         }
     }
 
-    @Override
     public void setDisplayOffloadSession(DisplayOffloadSession session) {
         if (session == mDisplayOffloadSession) {
             return;
@@ -842,7 +835,6 @@
         mDisplayOffloadSession = session;
     }
 
-    @Override
     public BrightnessConfiguration getDefaultBrightnessConfiguration() {
         if (mAutomaticBrightnessController == null) {
             return null;
@@ -857,7 +849,6 @@
      *
      * Make sure DisplayManagerService.mSyncRoot lock is held when this is called
      */
-    @Override
     public void onDisplayChanged(HighBrightnessModeMetadata hbmMetadata, int leadDisplayId) {
         mLeadDisplayId = leadDisplayId;
         final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
@@ -939,7 +930,6 @@
      * This method should be called when the DisplayPowerController is no longer in use; i.e. when
      * the {@link #mDisplayId display} has been removed.
      */
-    @Override
     public void stop() {
         synchronized (mLock) {
             clearDisplayBrightnessFollowersLocked();
@@ -1216,7 +1206,6 @@
         }
     }
 
-    @Override
     public void setAutomaticScreenBrightnessMode(
             @AutomaticBrightnessController.AutomaticBrightnessMode int mode) {
         Message msg = mHandler.obtainMessage();
@@ -1314,7 +1303,7 @@
         boolean mustInitialize = false;
         mBrightnessReasonTemp.set(null);
         mTempBrightnessEvent.reset();
-        SparseArray<DisplayPowerControllerInterface> displayBrightnessFollowers;
+        SparseArray<DisplayPowerController> displayBrightnessFollowers;
         synchronized (mLock) {
             if (mStopped) {
                 return;
@@ -1547,7 +1536,7 @@
         float ambientLux = mAutomaticBrightnessController == null ? 0
                 : mAutomaticBrightnessController.getAmbientLux();
         for (int i = 0; i < displayBrightnessFollowers.size(); i++) {
-            DisplayPowerControllerInterface follower = displayBrightnessFollowers.valueAt(i);
+            DisplayPowerController follower = displayBrightnessFollowers.valueAt(i);
             follower.setBrightnessToFollow(rawBrightnessState,
                     mDisplayBrightnessController.convertToNits(rawBrightnessState),
                     ambientLux, slowChange);
@@ -1904,7 +1893,6 @@
         }
     }
 
-    @Override
     public void updateBrightness() {
         sendUpdatePowerState();
     }
@@ -1913,12 +1901,10 @@
      * Ignores the proximity sensor until the sensor state changes, but only if the sensor is
      * currently enabled and forcing the screen to be dark.
      */
-    @Override
     public void ignoreProximitySensorUntilChanged() {
         mDisplayPowerProximityStateController.ignoreProximitySensorUntilChanged();
     }
 
-    @Override
     public void setBrightnessConfiguration(BrightnessConfiguration c,
             boolean shouldResetShortTermModel) {
         Message msg = mHandler.obtainMessage(MSG_CONFIGURE_BRIGHTNESS,
@@ -1926,28 +1912,24 @@
         msg.sendToTarget();
     }
 
-    @Override
     public void setTemporaryBrightness(float brightness) {
         Message msg = mHandler.obtainMessage(MSG_SET_TEMPORARY_BRIGHTNESS,
                 Float.floatToIntBits(brightness), 0 /*unused*/);
         msg.sendToTarget();
     }
 
-    @Override
     public void setTemporaryAutoBrightnessAdjustment(float adjustment) {
         Message msg = mHandler.obtainMessage(MSG_SET_TEMPORARY_AUTO_BRIGHTNESS_ADJUSTMENT,
                 Float.floatToIntBits(adjustment), 0 /*unused*/);
         msg.sendToTarget();
     }
 
-    @Override
     public void setBrightnessFromOffload(float brightness) {
         Message msg = mHandler.obtainMessage(MSG_SET_BRIGHTNESS_FROM_OFFLOAD,
                 Float.floatToIntBits(brightness), 0 /*unused*/);
         mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
     }
 
-    @Override
     public float[] getAutoBrightnessLevels(
             @AutomaticBrightnessController.AutomaticBrightnessMode int mode) {
         int preset = Settings.System.getIntForUser(mContext.getContentResolver(),
@@ -1956,7 +1938,6 @@
         return mDisplayDeviceConfig.getAutoBrightnessBrighteningLevels(mode, preset);
     }
 
-    @Override
     public float[] getAutoBrightnessLuxLevels(
             @AutomaticBrightnessController.AutomaticBrightnessMode int mode) {
         int preset = Settings.System.getIntForUser(mContext.getContentResolver(),
@@ -1965,7 +1946,6 @@
         return mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsLux(mode, preset);
     }
 
-    @Override
     public BrightnessInfo getBrightnessInfo() {
         synchronized (mCachedBrightnessInfo) {
             return new BrightnessInfo(
@@ -1979,7 +1959,6 @@
         }
     }
 
-    @Override
     public void onBootCompleted() {
         Message msg = mHandler.obtainMessage(MSG_BOOT_COMPLETED);
         mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
@@ -2495,18 +2474,14 @@
         }
     }
 
-
-    @Override
     public float getScreenBrightnessSetting() {
         return mDisplayBrightnessController.getScreenBrightnessSetting();
     }
 
-    @Override
     public float getDozeBrightnessForOffload() {
         return mDisplayBrightnessController.getCurrentBrightness() * mDozeScaleFactor;
     }
 
-    @Override
     public void setBrightness(float brightness) {
         // After HBMController and NBMController migration to Clampers framework
         // currentBrightnessMax should be taken from clampers controller
@@ -2515,7 +2490,6 @@
                 mBrightnessRangeController.getCurrentBrightnessMax());
     }
 
-    @Override
     public void setBrightness(float brightness, int userSerial) {
         // After HBMController and NBMController migration to Clampers framework
         // currentBrightnessMax should be taken from clampers controller
@@ -2524,17 +2498,14 @@
                 mBrightnessRangeController.getCurrentBrightnessMax());
     }
 
-    @Override
     public int getDisplayId() {
         return mDisplayId;
     }
 
-    @Override
     public int getLeadDisplayId() {
         return mLeadDisplayId;
     }
 
-    @Override
     public void setBrightnessToFollow(float leadDisplayBrightness, float nits, float ambientLux,
             boolean slowChange) {
         mBrightnessRangeController.onAmbientLuxChange(ambientLux);
@@ -2595,16 +2566,14 @@
                 mAutomaticBrightnessController.getLastSensorTimestamps());
     }
 
-    @Override
-    public void addDisplayBrightnessFollower(DisplayPowerControllerInterface follower) {
+    public void addDisplayBrightnessFollower(DisplayPowerController follower) {
         synchronized (mLock) {
             mDisplayBrightnessFollowers.append(follower.getDisplayId(), follower);
             sendUpdatePowerStateLocked();
         }
     }
 
-    @Override
-    public void removeDisplayBrightnessFollower(DisplayPowerControllerInterface follower) {
+    public void removeDisplayBrightnessFollower(DisplayPowerController follower) {
         synchronized (mLock) {
             mDisplayBrightnessFollowers.remove(follower.getDisplayId());
             mHandler.postAtTime(() -> follower.setBrightnessToFollow(
@@ -2616,7 +2585,7 @@
     @GuardedBy("mLock")
     private void clearDisplayBrightnessFollowersLocked() {
         for (int i = 0; i < mDisplayBrightnessFollowers.size(); i++) {
-            DisplayPowerControllerInterface follower = mDisplayBrightnessFollowers.valueAt(i);
+            DisplayPowerController follower = mDisplayBrightnessFollowers.valueAt(i);
             mHandler.postAtTime(() -> follower.setBrightnessToFollow(
                     PowerManager.BRIGHTNESS_INVALID_FLOAT, BrightnessMappingStrategy.INVALID_NITS,
                     /* ambientLux= */ 0, /* slowChange= */ false), mClock.uptimeMillis());
@@ -2624,7 +2593,6 @@
         mDisplayBrightnessFollowers.clear();
     }
 
-    @Override
     public void dump(final PrintWriter pw) {
         synchronized (mLock) {
             pw.println();
@@ -3161,19 +3129,17 @@
         }
     }
 
-    @Override
     public void setAutoBrightnessLoggingEnabled(boolean enabled) {
         if (mAutomaticBrightnessController != null) {
             mAutomaticBrightnessController.setLoggingEnabled(enabled);
         }
     }
 
-    @Override // DisplayWhiteBalanceController.Callbacks
+    // DisplayWhiteBalanceController.Callbacks
     public void updateWhiteBalance() {
         sendUpdatePowerState();
     }
 
-    @Override
     public void setDisplayWhiteBalanceLoggingEnabled(boolean enabled) {
         Message msg = mHandler.obtainMessage();
         msg.what = MSG_SET_DWBC_LOGGING_ENABLED;
@@ -3181,7 +3147,6 @@
         msg.sendToTarget();
     }
 
-    @Override
     public void setAmbientColorTemperatureOverride(float cct) {
         Message msg = mHandler.obtainMessage();
         msg.what = MSG_SET_DWBC_COLOR_OVERRIDE;
diff --git a/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java b/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
deleted file mode 100644
index d28578a..0000000
--- a/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2022 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.display;
-
-import android.content.pm.ParceledListSlice;
-import android.hardware.display.AmbientBrightnessDayStats;
-import android.hardware.display.BrightnessChangeEvent;
-import android.hardware.display.BrightnessConfiguration;
-import android.hardware.display.BrightnessInfo;
-import android.hardware.display.DisplayManagerInternal;
-import android.os.PowerManager;
-import android.view.Display;
-
-import java.io.PrintWriter;
-
-/**
- * An interface to manage the display's power state and brightness
- */
-public interface DisplayPowerControllerInterface {
-    /**
-     * Notified when the display is changed.
-     *
-     * We use this to apply any changes that might be needed when displays get swapped on foldable
-     * devices, when layouts change, etc.
-     *
-     * Must be called while holding the SyncRoot lock.
-     *
-     * @param hbmInfo The high brightness mode metadata, like
-     *                remaining time and hbm events, for the corresponding
-     *                physical display, to make sure we stay within the safety margins.
-     * @param leadDisplayId The display who is considered our "leader" for things like brightness.
-     */
-    void onDisplayChanged(HighBrightnessModeMetadata hbmInfo, int leadDisplayId);
-
-    /**
-     * Unregisters all listeners and interrupts all running threads; halting future work.
-     *
-     * This method should be called when the DisplayPowerController is no longer in use; i.e. when
-     * the display has been removed.
-     */
-    void stop();
-
-    /**
-     * Used to update the display's BrightnessConfiguration
-     * @param config The new BrightnessConfiguration
-     */
-    void setBrightnessConfiguration(BrightnessConfiguration config,
-            boolean shouldResetShortTermModel);
-
-    /**
-     * Used to set the ambient color temperature of the Display
-     * @param ambientColorTemperature The target ambientColorTemperature
-     */
-    void setAmbientColorTemperatureOverride(float ambientColorTemperature);
-
-    /**
-     * Used to decide the associated AutomaticBrightnessController's BrightnessMode
-     * @param mode The auto-brightness mode
-     */
-    void setAutomaticScreenBrightnessMode(
-            @AutomaticBrightnessController.AutomaticBrightnessMode int mode);
-
-    /**
-     * Used to enable/disable the logging of the WhileBalance associated entities
-     * @param enabled Flag which represents if the logging is the be enabled
-     */
-    void setDisplayWhiteBalanceLoggingEnabled(boolean enabled);
-
-    /**
-     * Used to dump the state.
-     * @param writer The PrintWriter used to dump the state.
-     */
-    void dump(PrintWriter writer);
-
-    /**
-     * Used to get the ambient brightness stats
-     */
-    ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats(int userId);
-
-    /**
-     * Get the default brightness configuration
-     */
-    BrightnessConfiguration getDefaultBrightnessConfiguration();
-
-    /**
-     * Set the screen brightness of the associated display
-     * @param brightness The value to which the brightness is to be set
-     */
-    void setBrightness(float brightness);
-
-    /**
-     * Set the screen brightness of the associated display
-     * @param brightness The value to which the brightness is to be set
-     * @param userSerial The user for which the brightness value is to be set.
-     */
-    void setBrightness(float brightness, int userSerial);
-
-    /**
-     * Checks if the proximity sensor is available
-     */
-    boolean isProximitySensorAvailable();
-
-    /**
-     * Persist the brightness slider events and ambient brightness stats to disk.
-     */
-    void persistBrightnessTrackerState();
-
-    /**
-     * Ignores the proximity sensor until the sensor state changes, but only if the sensor is
-     * currently enabled and forcing the screen to be dark.
-     */
-    void ignoreProximitySensorUntilChanged();
-
-    /**
-     * Requests a new power state.
-     *
-     * @param request The requested power state.
-     * @param waitForNegativeProximity If true, issues a request to wait for
-     * negative proximity before turning the screen back on,
-     * assuming the screen was turned off by the proximity sensor.
-     * @return True if display is ready, false if there are important changes that must
-     * be made asynchronously.
-     */
-    boolean requestPowerState(DisplayManagerInternal.DisplayPowerRequest request,
-            boolean waitForNegativeProximity);
-
-    /**
-     * Overrides the current doze screen state.
-     *
-     * @param displayState the new doze display state.
-     * @param reason the reason behind the new doze display state.
-     */
-    void overrideDozeScreenState(int displayState, @Display.StateReason int reason);
-
-    void setDisplayOffloadSession(DisplayManagerInternal.DisplayOffloadSession session);
-
-    /**
-     * Sets up the temporary autobrightness adjustment when the user is yet to settle down to a
-     * value.
-     */
-    void setTemporaryAutoBrightnessAdjustment(float adjustment);
-
-    /**
-     * Sets temporary brightness from the offload chip until we get a brightness value from
-     * the light sensor.
-     * @param brightness The brightness value between {@link PowerManager.BRIGHTNESS_MIN} and
-     * {@link PowerManager.BRIGHTNESS_MAX}. Values outside of that range will be ignored.
-     */
-    void setBrightnessFromOffload(float brightness);
-
-    /**
-     * Gets the screen brightness setting
-     */
-    float getScreenBrightnessSetting();
-
-    /**
-     * Gets the brightness value used when the device is in doze
-     */
-    float getDozeBrightnessForOffload();
-
-    /**
-     * Sets up the temporary brightness for the associated display
-     */
-    void setTemporaryBrightness(float brightness);
-
-    /**
-     * Gets the associated {@link BrightnessInfo}
-     */
-    BrightnessInfo getBrightnessInfo();
-
-    /**
-     * Get the {@link BrightnessChangeEvent}s for the specified user.
-     */
-    ParceledListSlice<BrightnessChangeEvent> getBrightnessEvents(int userId, boolean hasUsageStats);
-
-    /**
-     * Sets up the logging for the associated {@link AutomaticBrightnessController}
-     * @param enabled Flag to represent if the logging is to be enabled
-     */
-    void setAutoBrightnessLoggingEnabled(boolean enabled);
-
-    /**
-     * Handles the changes to be done to update the brightness when the user is changed
-     * @param newUserId The new userId
-     * @param userSerial The serial number of the new user
-     * @param newBrightness The brightness for the new user
-     */
-    void onSwitchUser(int newUserId, int userSerial, float newBrightness);
-
-    /**
-     * Get the ID of the display associated with this DPC.
-     * @return The display ID
-     */
-    int getDisplayId();
-
-    /**
-     * Get the ID of the display that is the leader of this DPC.
-     *
-     * Note that this is different than the display associated with the DPC. The leader is another
-     * display which we follow for things like brightness.
-     *
-     * Must be called while holding the SyncRoot lock.
-     */
-    int getLeadDisplayId();
-
-    /**
-     * Set the brightness to follow if this is an additional display in a set of concurrent
-     * displays.
-     * @param leadDisplayBrightness The brightness of the lead display in the set of concurrent
-     *                              displays
-     * @param nits The brightness value in nits if the device supports nits. Set to a negative
-     *             number otherwise.
-     * @param ambientLux The lux value that will be passed to {@link HighBrightnessModeController}
-     * @param slowChange Indicates whether we should slowly animate to the given brightness value.
-     */
-    void setBrightnessToFollow(float leadDisplayBrightness, float nits, float ambientLux,
-            boolean slowChange);
-
-    /**
-     * Add an additional display that will copy the brightness value from this display. This is used
-     * when the device is in concurrent displays mode.
-     * @param follower The DPC that should copy the brightness value from this DPC
-     */
-    void addDisplayBrightnessFollower(DisplayPowerControllerInterface follower);
-
-    /**
-     * Removes the given display from the list of brightness followers.
-     * @param follower The DPC to remove from the followers list
-     */
-    void removeDisplayBrightnessFollower(DisplayPowerControllerInterface follower);
-
-    /**
-     * Indicate that boot has been completed and the screen is ready to update.
-     */
-    void onBootCompleted();
-
-    /**
-     * Get the brightness levels used to determine automatic brightness based on lux levels.
-     * @param mode The auto-brightness mode
-     * @return The brightness levels for the specified mode. The values are between
-     * {@link PowerManager.BRIGHTNESS_MIN} and {@link PowerManager.BRIGHTNESS_MAX}.
-     */
-    float[] getAutoBrightnessLevels(
-            @AutomaticBrightnessController.AutomaticBrightnessMode int mode);
-
-    /**
-     * Get the lux levels used to determine automatic brightness.
-     * @param mode The auto-brightness mode
-     * @return The lux levels for the specified mode
-     */
-    float[] getAutoBrightnessLuxLevels(
-            @AutomaticBrightnessController.AutomaticBrightnessMode int mode);
-}
diff --git a/services/core/java/com/android/server/input/debug/TouchpadDebugView.java b/services/core/java/com/android/server/input/debug/TouchpadDebugView.java
index 5fca771..7785ffb 100644
--- a/services/core/java/com/android/server/input/debug/TouchpadDebugView.java
+++ b/services/core/java/com/android/server/input/debug/TouchpadDebugView.java
@@ -16,23 +16,69 @@
 
 package com.android.server.input.debug;
 
+import android.annotation.NonNull;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.util.Slog;
 import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.ViewConfiguration;
+import android.view.WindowManager;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
-public class TouchpadDebugView extends LinearLayout {
+import java.util.Objects;
 
+public class TouchpadDebugView extends LinearLayout {
     /**
      * Input device ID for the touchpad that this debug view is displaying.
      */
     private final int mTouchpadId;
 
+    @NonNull
+    private final WindowManager mWindowManager;
+
+    @NonNull
+    private final WindowManager.LayoutParams mWindowLayoutParams;
+
+    private final int mTouchSlop;
+
+    private float mTouchDownX;
+    private float mTouchDownY;
+    private int mScreenWidth;
+    private int mScreenHeight;
+    private int mWindowLocationBeforeDragX;
+    private int mWindowLocationBeforeDragY;
+
     public TouchpadDebugView(Context context, int touchpadId) {
         super(context);
         mTouchpadId = touchpadId;
+        mWindowManager =
+                Objects.requireNonNull(getContext().getSystemService(WindowManager.class));
         init(context);
+        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+
+        // TODO(b/360137366): Use the hardware properties to initialise layout parameters.
+        mWindowLayoutParams = new WindowManager.LayoutParams();
+        mWindowLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+        mWindowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+        mWindowLayoutParams.privateFlags |=
+                WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
+        mWindowLayoutParams.setFitInsetsTypes(0);
+        mWindowLayoutParams.layoutInDisplayCutoutMode =
+                WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+        mWindowLayoutParams.format = PixelFormat.TRANSLUCENT;
+        mWindowLayoutParams.setTitle("TouchpadDebugView - display " + mContext.getDisplayId());
+
+        mWindowLayoutParams.x = 40;
+        mWindowLayoutParams.y = 100;
+        mWindowLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
+        mWindowLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
+        mWindowLayoutParams.gravity = Gravity.TOP | Gravity.LEFT;
     }
 
     private void init(Context context) {
@@ -43,14 +89,12 @@
         setBackgroundColor(Color.TRANSPARENT);
 
         // TODO(b/286551975): Replace this content with the touchpad debug view.
-
         TextView textView1 = new TextView(context);
         textView1.setBackgroundColor(Color.parseColor("#FFFF0000"));
         textView1.setTextSize(20);
         textView1.setText("Touchpad Debug View 1");
         textView1.setGravity(Gravity.CENTER);
         textView1.setTextColor(Color.WHITE);
-
         textView1.setLayoutParams(new LayoutParams(1000, 200));
 
         TextView textView2 = new TextView(context);
@@ -63,9 +107,98 @@
 
         addView(textView1);
         addView(textView2);
+
+        updateScreenDimensions();
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        float deltaX;
+        float deltaY;
+        switch (event.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                mWindowLocationBeforeDragX = mWindowLayoutParams.x;
+                mWindowLocationBeforeDragY = mWindowLayoutParams.y;
+                mTouchDownX = event.getRawX() - mWindowLocationBeforeDragX;
+                mTouchDownY = event.getRawY() - mWindowLocationBeforeDragY;
+                return true;
+
+            case MotionEvent.ACTION_MOVE:
+                deltaX = event.getRawX() - mWindowLayoutParams.x - mTouchDownX;
+                deltaY = event.getRawY() - mWindowLayoutParams.y - mTouchDownY;
+                Slog.d("TouchpadDebugView", "Slop = " + mTouchSlop);
+                if (isSlopExceeded(deltaX, deltaY)) {
+                    Slog.d("TouchpadDebugView", "Slop exceeded");
+                    mWindowLayoutParams.x =
+                            Math.max(0, Math.min((int) (event.getRawX() - mTouchDownX),
+                                    mScreenWidth - this.getWidth()));
+                    mWindowLayoutParams.y =
+                            Math.max(0, Math.min((int) (event.getRawY() - mTouchDownY),
+                                    mScreenHeight - this.getHeight()));
+
+                    Slog.d("TouchpadDebugView", "New position X: "
+                            + mWindowLayoutParams.x + ", Y: " + mWindowLayoutParams.y);
+
+                    mWindowManager.updateViewLayout(this, mWindowLayoutParams);
+                }
+                return true;
+
+            case MotionEvent.ACTION_UP:
+                deltaX = event.getRawX() - mWindowLayoutParams.x - mTouchDownX;
+                deltaY = event.getRawY() - mWindowLayoutParams.y - mTouchDownY;
+                if (!isSlopExceeded(deltaX, deltaY)) {
+                    performClick();
+                }
+                return true;
+
+            case MotionEvent.ACTION_CANCEL:
+                // Move the window back to the original position
+                mWindowLayoutParams.x = mWindowLocationBeforeDragX;
+                mWindowLayoutParams.y = mWindowLocationBeforeDragY;
+                mWindowManager.updateViewLayout(this, mWindowLayoutParams);
+                return true;
+
+            default:
+                return super.onTouchEvent(event);
+        }
+    }
+
+    @Override
+    public boolean performClick() {
+        super.performClick();
+        Slog.d("TouchpadDebugView", "You clicked me!");
+        return true;
+    }
+
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        updateScreenDimensions();
+
+        // Adjust view position to stay within screen bounds after rotation
+        mWindowLayoutParams.x =
+                Math.max(0, Math.min(mWindowLayoutParams.x, mScreenWidth - getWidth()));
+        mWindowLayoutParams.y =
+                Math.max(0, Math.min(mWindowLayoutParams.y, mScreenHeight - getHeight()));
+        mWindowManager.updateViewLayout(this, mWindowLayoutParams);
+    }
+
+    private boolean isSlopExceeded(float deltaX, float deltaY) {
+        return deltaX * deltaX + deltaY * deltaY >= mTouchSlop * mTouchSlop;
+    }
+
+    private void updateScreenDimensions() {
+        Rect windowBounds =
+                mWindowManager.getCurrentWindowMetrics().getBounds();
+        mScreenWidth = windowBounds.width();
+        mScreenHeight = windowBounds.height();
     }
 
     public int getTouchpadId() {
         return mTouchpadId;
     }
+
+    public WindowManager.LayoutParams getWindowLayoutParams() {
+        return mWindowLayoutParams;
+    }
 }
diff --git a/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java b/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java
index c7760c6..1e59167 100644
--- a/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java
+++ b/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java
@@ -18,14 +18,12 @@
 
 import android.annotation.Nullable;
 import android.content.Context;
-import android.graphics.PixelFormat;
 import android.hardware.display.DisplayManager;
 import android.hardware.input.InputManager;
 import android.os.Handler;
 import android.os.Looper;
 import android.util.Slog;
 import android.view.Display;
-import android.view.Gravity;
 import android.view.InputDevice;
 import android.view.WindowManager;
 
@@ -36,12 +34,14 @@
 
 public class TouchpadDebugViewController {
 
-    private static final String TAG = "TouchpadDebugViewController";
+    private static final String TAG = "TouchpadDebugView";
 
     private final Context mContext;
     private final Handler mHandler;
+
     @Nullable
     private TouchpadDebugView mTouchpadDebugView;
+
     private final InputManagerService mInputManagerService;
 
     public TouchpadDebugViewController(Context context, Looper looper,
@@ -95,32 +95,15 @@
                 mContext.getSystemService(WindowManager.class));
 
         mTouchpadDebugView = new TouchpadDebugView(mContext, touchpadId);
+        final WindowManager.LayoutParams mWindowLayoutParams =
+                mTouchpadDebugView.getWindowLayoutParams();
 
-        final WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
-        lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
-        lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
-        lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
-        lp.setFitInsetsTypes(0);
-        lp.layoutInDisplayCutoutMode =
-                WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-        lp.format = PixelFormat.TRANSLUCENT;
-        lp.setTitle("TouchpadDebugView - display " + mContext.getDisplayId());
-        lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
-
-        lp.x = 40;
-        lp.y = 100;
-        lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
-        lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
-        lp.gravity = Gravity.TOP | Gravity.LEFT;
-
-        wm.addView(mTouchpadDebugView, lp);
+        wm.addView(mTouchpadDebugView, mWindowLayoutParams);
         Slog.d(TAG, "Touchpad debug view created.");
 
         TouchpadHardwareProperties mTouchpadHardwareProperties =
                 mInputManagerService.getTouchpadHardwareProperties(
                         touchpadId);
-        // TODO(b/360137366): Use the hardware properties to initialise layout parameters.
         if (mTouchpadHardwareProperties != null) {
             Slog.d(TAG, mTouchpadHardwareProperties.toString());
         } else {
diff --git a/services/core/java/com/android/server/inputmethod/IInputMethodManagerImpl.java b/services/core/java/com/android/server/inputmethod/IInputMethodManagerImpl.java
index 58e3452..e1f26d6 100644
--- a/services/core/java/com/android/server/inputmethod/IInputMethodManagerImpl.java
+++ b/services/core/java/com/android/server/inputmethod/IInputMethodManagerImpl.java
@@ -116,11 +116,11 @@
         boolean showSoftInput(IInputMethodClient client, IBinder windowToken,
                 @Nullable ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
                 @MotionEvent.ToolType int lastClickToolType, ResultReceiver resultReceiver,
-                @SoftInputShowHideReason int reason);
+                @SoftInputShowHideReason int reason, boolean async);
 
         boolean hideSoftInput(IInputMethodClient client, IBinder windowToken,
                 @Nullable ImeTracker.Token statsToken, @InputMethodManager.HideFlags int flags,
-                ResultReceiver resultReceiver, @SoftInputShowHideReason int reason);
+                ResultReceiver resultReceiver, @SoftInputShowHideReason int reason, boolean async);
 
         @PermissionVerified(Manifest.permission.TEST_INPUT_METHOD)
         void hideSoftInputFromServerForTest();
@@ -132,7 +132,8 @@
                 @Nullable EditorInfo editorInfo, IRemoteInputConnection inputConnection,
                 IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
                 int unverifiedTargetSdkVersion, @UserIdInt int userId,
-                @NonNull ImeOnBackInvokedDispatcher imeDispatcher, int startInputSeq);
+                @NonNull ImeOnBackInvokedDispatcher imeDispatcher, int startInputSeq,
+                boolean useAsyncShowHideMethod);
 
         InputBindResult startInputOrWindowGainedFocus(
                 @StartInputReason int startInputReason, IInputMethodClient client,
@@ -290,17 +291,17 @@
     public boolean showSoftInput(IInputMethodClient client, IBinder windowToken,
             @NonNull ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
             @MotionEvent.ToolType int lastClickToolType, ResultReceiver resultReceiver,
-            @SoftInputShowHideReason int reason) {
+            @SoftInputShowHideReason int reason, boolean async) {
         return mCallback.showSoftInput(client, windowToken, statsToken, flags, lastClickToolType,
-                resultReceiver, reason);
+                resultReceiver, reason, async);
     }
 
     @Override
     public boolean hideSoftInput(IInputMethodClient client, IBinder windowToken,
             @NonNull ImeTracker.Token statsToken, @InputMethodManager.HideFlags int flags,
-            ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
+            ResultReceiver resultReceiver, @SoftInputShowHideReason int reason, boolean async) {
         return mCallback.hideSoftInput(client, windowToken, statsToken, flags, resultReceiver,
-                reason);
+                reason, async);
     }
 
     @EnforcePermission(Manifest.permission.TEST_INPUT_METHOD)
@@ -336,11 +337,13 @@
             IRemoteInputConnection inputConnection,
             IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
             int unverifiedTargetSdkVersion, @UserIdInt int userId,
-            @NonNull ImeOnBackInvokedDispatcher imeDispatcher, int startInputSeq) {
+            @NonNull ImeOnBackInvokedDispatcher imeDispatcher, int startInputSeq,
+            boolean useAsyncShowHideMethod) {
         mCallback.startInputOrWindowGainedFocusAsync(
                 startInputReason, client, windowToken, startInputFlags, softInputMode,
                 windowFlags, editorInfo, inputConnection, remoteAccessibilityInputConnection,
-                unverifiedTargetSdkVersion, userId, imeDispatcher, startInputSeq);
+                unverifiedTargetSdkVersion, userId, imeDispatcher, startInputSeq,
+                useAsyncShowHideMethod);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 2ad0d2a..7cfd2cc 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -3086,7 +3086,7 @@
     public boolean showSoftInput(IInputMethodClient client, IBinder windowToken,
             @NonNull ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
             int lastClickToolType, ResultReceiver resultReceiver,
-            @SoftInputShowHideReason int reason) {
+            @SoftInputShowHideReason int reason, boolean async) {
         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.showSoftInput");
         ImeTracing.getInstance().triggerManagerServiceDump(
                 "InputMethodManagerService#showSoftInput", mDumper);
@@ -3533,7 +3533,7 @@
     @Override
     public boolean hideSoftInput(IInputMethodClient client, IBinder windowToken,
             @NonNull ImeTracker.Token statsToken, @InputMethodManager.HideFlags int flags,
-            ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
+            ResultReceiver resultReceiver, @SoftInputShowHideReason int reason, boolean async) {
         ImeTracing.getInstance().triggerManagerServiceDump(
                 "InputMethodManagerService#hideSoftInput", mDumper);
         synchronized (ImfLock.class) {
@@ -3675,7 +3675,8 @@
             IRemoteInputConnection inputConnection,
             IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
             int unverifiedTargetSdkVersion, @UserIdInt int userId,
-            @NonNull ImeOnBackInvokedDispatcher imeDispatcher, int startInputSeq) {
+            @NonNull ImeOnBackInvokedDispatcher imeDispatcher, int startInputSeq,
+            boolean useAsyncShowHideMethod) {
         // implemented by ZeroJankProxy
     }
 
diff --git a/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java b/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java
index c940a9c..214aa1d 100644
--- a/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java
+++ b/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java
@@ -77,6 +77,7 @@
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
 
 /**
  * A proxy that processes all {@link IInputMethodManager} calls asynchronously.
@@ -175,19 +176,45 @@
     public boolean showSoftInput(IInputMethodClient client, IBinder windowToken,
             @Nullable ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
             @MotionEvent.ToolType int lastClickToolType, ResultReceiver resultReceiver,
-            @SoftInputShowHideReason int reason) {
-        offload(() -> mInner.showSoftInput(
-                client, windowToken, statsToken, flags, lastClickToolType, resultReceiver, reason));
-        return true;
+            @SoftInputShowHideReason int reason, boolean async) {
+
+        if (async) {
+            offload(() -> mInner.showSoftInput(
+                    client, windowToken, statsToken, flags, lastClickToolType, resultReceiver,
+                    reason, async));
+            return true;
+        } else {
+            final var future = CompletableFuture.supplyAsync(
+                    () -> mInner.showSoftInput(
+                            client,
+                            windowToken,
+                            statsToken,
+                            flags,
+                            lastClickToolType,
+                            resultReceiver,
+                            reason,
+                            async),
+                    this::offload);
+            return future.completeOnTimeout(false, 1, TimeUnit.SECONDS).join();
+        }
     }
 
     @Override
     public boolean hideSoftInput(IInputMethodClient client, IBinder windowToken,
             @Nullable ImeTracker.Token statsToken, @InputMethodManager.HideFlags int flags,
-            ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
-        offload(() -> mInner.hideSoftInput(
-                client, windowToken, statsToken, flags, resultReceiver, reason));
-        return true;
+            ResultReceiver resultReceiver, @SoftInputShowHideReason int reason, boolean async) {
+
+        if (async) {
+            offload(() -> mInner.hideSoftInput(
+                    client, windowToken, statsToken, flags, resultReceiver, reason, async));
+            return true;
+        } else {
+            final var future = CompletableFuture.supplyAsync(
+                    () -> mInner.hideSoftInput(
+                            client, windowToken, statsToken, flags, resultReceiver, reason, async),
+                    this::offload);
+            return future.completeOnTimeout(false, 1, TimeUnit.SECONDS).join();
+        }
     }
 
     @Override
@@ -207,7 +234,8 @@
             IRemoteInputConnection inputConnection,
             IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
             int unverifiedTargetSdkVersion, @UserIdInt int userId,
-            @NonNull ImeOnBackInvokedDispatcher imeDispatcher, int startInputSeq) {
+            @NonNull ImeOnBackInvokedDispatcher imeDispatcher, int startInputSeq,
+            boolean useAsyncShowHideMethod) {
         offload(() -> {
             InputBindResult result = mInner.startInputOrWindowGainedFocus(startInputReason, client,
                     windowToken, startInputFlags, softInputMode, windowFlags,
diff --git a/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java b/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
index c8cb54f..bad959a 100644
--- a/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
+++ b/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
@@ -19,6 +19,9 @@
 import static android.app.UiModeManager.MODE_ATTENTION_THEME_OVERLAY_NIGHT;
 import static android.app.UiModeManager.MODE_ATTENTION_THEME_OVERLAY_OFF;
 
+import static com.android.server.notification.ZenLog.traceApplyDeviceEffect;
+import static com.android.server.notification.ZenLog.traceScheduleApplyDeviceEffect;
+
 import android.app.UiModeManager;
 import android.app.WallpaperManager;
 import android.content.BroadcastReceiver;
@@ -77,6 +80,8 @@
             if (mLastAppliedEffects.shouldSuppressAmbientDisplay()
                     != effects.shouldSuppressAmbientDisplay()) {
                 try {
+                    traceApplyDeviceEffect("suppressAmbientDisplay",
+                            effects.shouldSuppressAmbientDisplay());
                     mPowerManager.suppressAmbientDisplay(SUPPRESS_AMBIENT_DISPLAY_TOKEN,
                             effects.shouldSuppressAmbientDisplay());
                 } catch (Exception e) {
@@ -87,6 +92,8 @@
             if (mLastAppliedEffects.shouldDisplayGrayscale() != effects.shouldDisplayGrayscale()) {
                 if (mColorDisplayManager != null) {
                     try {
+                        traceApplyDeviceEffect("displayGrayscale",
+                                effects.shouldDisplayGrayscale());
                         mColorDisplayManager.setSaturationLevel(
                                 effects.shouldDisplayGrayscale() ? SATURATION_LEVEL_GRAYSCALE
                                         : SATURATION_LEVEL_FULL_COLOR);
@@ -99,6 +106,7 @@
             if (mLastAppliedEffects.shouldDimWallpaper() != effects.shouldDimWallpaper()) {
                 if (mWallpaperManager != null) {
                     try {
+                        traceApplyDeviceEffect("dimWallpaper", effects.shouldDimWallpaper());
                         mWallpaperManager.setWallpaperDimAmount(
                                 effects.shouldDimWallpaper() ? WALLPAPER_DIM_AMOUNT_DIMMED
                                         : WALLPAPER_DIM_AMOUNT_NORMAL);
@@ -134,6 +142,7 @@
             unregisterScreenOffReceiver();
             updateNightModeImmediately(useNightMode);
         } else {
+            traceScheduleApplyDeviceEffect("nightMode", useNightMode);
             registerScreenOffReceiver();
         }
     }
@@ -150,6 +159,7 @@
     private void updateNightModeImmediately(boolean useNightMode) {
         Binder.withCleanCallingIdentity(() -> {
             try {
+                traceApplyDeviceEffect("nightMode", useNightMode);
                 mUiModeManager.setAttentionModeThemeOverlay(
                         useNightMode ? MODE_ATTENTION_THEME_OVERLAY_NIGHT
                                 : MODE_ATTENTION_THEME_OVERLAY_OFF);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index dbe778e..54e9189 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -7600,16 +7600,14 @@
                     + " trying to post for invalid pkg " + pkg + " in user " + incomingUserId);
         }
 
-        if (android.app.Flags.secureAllowlistToken()) {
-            IBinder allowlistToken = notification.getAllowlistToken();
-            if (allowlistToken != null && allowlistToken != ALLOWLIST_TOKEN) {
-                throw new SecurityException(
-                        "Unexpected allowlist token received from " + callingUid);
-            }
-            // allowlistToken is populated by unparceling, so it can be null if the notification was
-            // posted from inside system_server. Ensure it's the expected value.
-            notification.overrideAllowlistToken(ALLOWLIST_TOKEN);
+        IBinder allowlistToken = notification.getAllowlistToken();
+        if (allowlistToken != null && allowlistToken != ALLOWLIST_TOKEN) {
+            throw new SecurityException(
+                    "Unexpected allowlist token received from " + callingUid);
         }
+        // allowlistToken is populated by unparceling, so it can be null if the notification was
+        // posted from inside system_server. Ensure it's the expected value.
+        notification.overrideAllowlistToken(ALLOWLIST_TOKEN);
 
         checkRestrictedCategories(notification);
 
@@ -8774,12 +8772,10 @@
          */
         private boolean enqueueNotification() {
             synchronized (mNotificationLock) {
-                if (android.app.Flags.secureAllowlistToken()) {
-                    // allowlistToken is populated by unparceling, so it will be absent if the
-                    // EnqueueNotificationRunnable is created directly by NMS (as we do for group
-                    // summaries) instead of via notify(). Fix that.
-                    r.getNotification().overrideAllowlistToken(ALLOWLIST_TOKEN);
-                }
+                // allowlistToken is populated by unparceling, so it will be absent if the
+                // EnqueueNotificationRunnable is created directly by NMS (as we do for group
+                // summaries) instead of via notify(). Fix that.
+                r.getNotification().overrideAllowlistToken(ALLOWLIST_TOKEN);
 
                 final long snoozeAt =
                         mSnoozeHelper.getSnoozeTimeForUnpostedNotification(
diff --git a/services/core/java/com/android/server/notification/ZenLog.java b/services/core/java/com/android/server/notification/ZenLog.java
index 82c5733..1aa5ac0 100644
--- a/services/core/java/com/android/server/notification/ZenLog.java
+++ b/services/core/java/com/android/server/notification/ZenLog.java
@@ -23,18 +23,15 @@
 import android.os.Build;
 import android.os.RemoteException;
 import android.provider.Settings.Global;
-import android.service.notification.Condition;
 import android.service.notification.IConditionProvider;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.ZenModeConfig;
 import android.service.notification.ZenModeDiff;
 import android.util.LocalLog;
-import android.util.Log;
-import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
 
 import java.io.PrintWriter;
-import java.text.SimpleDateFormat;
-import java.util.Date;
 import java.util.List;
 
 public class ZenLog {
@@ -61,6 +58,8 @@
     private static final int TYPE_RECORD_CALLER = 19;
     private static final int TYPE_CHECK_REPEAT_CALLER = 20;
     private static final int TYPE_ALERT_ON_UPDATED_INTERCEPT = 21;
+    private static final int TYPE_APPLY_DEVICE_EFFECT = 22;
+    private static final int TYPE_SCHEDULE_APPLY_DEVICE_EFFECT = 23;
 
     public static void traceIntercepted(NotificationRecord record, String reason) {
         append(TYPE_INTERCEPTED, record.getKey() + "," + reason);
@@ -173,6 +172,14 @@
                 + ", given uri=" + hasUri);
     }
 
+    public static void traceApplyDeviceEffect(String effect, boolean newValue) {
+        append(TYPE_APPLY_DEVICE_EFFECT, effect + " -> " + newValue);
+    }
+
+    public static void traceScheduleApplyDeviceEffect(String effect, boolean scheduledValue) {
+        append(TYPE_SCHEDULE_APPLY_DEVICE_EFFECT, effect + " -> " + scheduledValue);
+    }
+
     private static String subscribeResult(IConditionProvider provider, RemoteException e) {
         return provider == null ? "no provider" : e != null ? e.getMessage() : "ok";
     }
@@ -196,6 +203,8 @@
             case TYPE_RECORD_CALLER: return "record_caller";
             case TYPE_CHECK_REPEAT_CALLER: return "check_repeat_caller";
             case TYPE_ALERT_ON_UPDATED_INTERCEPT: return "alert_on_updated_intercept";
+            case TYPE_APPLY_DEVICE_EFFECT: return "apply_device_effect";
+            case TYPE_SCHEDULE_APPLY_DEVICE_EFFECT: return "schedule_device_effect";
             default: return "unknown";
         }
     }
@@ -273,4 +282,14 @@
             STATE_CHANGES.dump(prefix, pw);
         }
     }
+
+    @VisibleForTesting(/* otherwise = VisibleForTesting.NONE */)
+    public static void clear() {
+        synchronized (INTERCEPTION_EVENTS) {
+            INTERCEPTION_EVENTS.clear();
+        }
+        synchronized (STATE_CHANGES) {
+            STATE_CHANGES.clear();
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 333b3e2..2ada9ae4 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -2125,17 +2125,25 @@
     @GuardedBy("mConfigLock")
     private void applyCustomPolicy(ZenPolicy policy, ZenRule rule, boolean useManualConfig) {
         if (rule.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
-            policy.apply(new ZenPolicy.Builder()
-                    .disallowAllSounds()
-                    .allowPriorityChannels(false)
-                    .build());
+            if (Flags.modesApi() && Flags.modesUi()) {
+                policy.apply(ZenPolicy.getBasePolicyInterruptionFilterNone());
+            } else {
+                policy.apply(new ZenPolicy.Builder()
+                        .disallowAllSounds()
+                        .allowPriorityChannels(false)
+                        .build());
+            }
         } else if (rule.zenMode == Global.ZEN_MODE_ALARMS) {
-            policy.apply(new ZenPolicy.Builder()
-                    .disallowAllSounds()
-                    .allowAlarms(true)
-                    .allowMedia(true)
-                    .allowPriorityChannels(false)
-                    .build());
+            if (Flags.modesApi() && Flags.modesUi()) {
+                policy.apply(ZenPolicy.getBasePolicyInterruptionFilterAlarms());
+            } else {
+                policy.apply(new ZenPolicy.Builder()
+                        .disallowAllSounds()
+                        .allowAlarms(true)
+                        .allowMedia(true)
+                        .allowPriorityChannels(false)
+                        .build());
+            }
         } else if (rule.zenPolicy != null) {
             policy.apply(rule.zenPolicy);
         } else {
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 1317866..662c792 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -209,6 +209,7 @@
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
 
+
 final class InstallPackageHelper {
     private final PackageManagerService mPm;
     private final AppDataHelper mAppDataHelper;
@@ -989,15 +990,6 @@
         return false;
     }
 
-    void installPackagesTraced(List<InstallRequest> requests) {
-        try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) {
-            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages");
-            installPackagesLI(requests);
-        } finally {
-            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
-        }
-    }
-
     /**
      * Installs one or more packages atomically. This operation is broken up into four phases:
      * <ul>
@@ -1017,15 +1009,31 @@
      *
      * Failure at any phase will result in a full failure to install all packages.
      */
-    @GuardedBy("mPm.mInstallLock")
-    private void installPackagesLI(List<InstallRequest> requests) {
-        final Set<String> scannedPackages = new ArraySet<>(requests.size());
-        final Map<String, Settings.VersionInfo> versionInfos = new ArrayMap<>(requests.size());
-        final Map<String, Boolean> createdAppId = new ArrayMap<>(requests.size());
-        CriticalEventLog.getInstance().logInstallPackagesStarted();
+    void installPackagesTraced(List<InstallRequest> requests) {
+        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages");
         boolean success = false;
+        final Map<String, Boolean> createdAppId = new ArrayMap<>(requests.size());
+        final Map<String, Settings.VersionInfo> versionInfos = new ArrayMap<>(requests.size());
         try {
-            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackagesLI");
+            CriticalEventLog.getInstance().logInstallPackagesStarted();
+
+            if (prepareInstallPackages(requests)
+                    && scanInstallPackages(requests, createdAppId, versionInfos)) {
+                List<ReconciledPackage> reconciledPackages =
+                        reconcileInstallPackages(requests, versionInfos);
+                if (reconciledPackages != null && commitInstallPackages(reconciledPackages)) {
+                    success = true;
+                }
+            }
+        } finally {
+            completeInstallProcess(requests, createdAppId, success);
+            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+        }
+    }
+
+    private boolean prepareInstallPackages(List<InstallRequest> requests) {
+        // TODO: will remove the locking after doRename is moved out of prepare
+        try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) {
             for (InstallRequest request : requests) {
                 try {
                     Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "preparePackage");
@@ -1036,17 +1044,27 @@
                             prepareFailure.getMessage());
                     request.setOriginPackage(prepareFailure.mConflictingPackage);
                     request.setOriginPermission(prepareFailure.mConflictingPermission);
-                    return;
+                    return false;
                 } finally {
                     request.onPrepareFinished();
                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                 }
+            }
+        }
+        return true;
+    }
 
+    private boolean scanInstallPackages(List<InstallRequest> requests,
+            Map<String, Boolean> createdAppId, Map<String, Settings.VersionInfo> versionInfos) {
+        // TODO(b/362840929): remove locker
+        try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) {
+            final Set<String> scannedPackages = new ArraySet<>(requests.size());
+            for (InstallRequest request : requests) {
                 final ParsedPackage packageToScan = request.getParsedPackage();
                 if (packageToScan == null) {
                     request.setError(INSTALL_FAILED_SESSION_INVALID,
                             "Failed to obtain package to scan");
-                    return;
+                    return false;
                 }
                 request.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
                 final String packageName = packageToScan.getPackageName();
@@ -1064,7 +1082,7 @@
                                 "Duplicate package "
                                         + packageName
                                         + " in multi-package install request.");
-                        return;
+                        return false;
                     }
                     if (!checkNoAppStorageIsConsistent(
                             request.getScanRequestOldPackage(), packageToScan)) {
@@ -1074,7 +1092,7 @@
                                 INSTALL_FAILED_UPDATE_INCOMPATIBLE,
                                 "Update attempted to change value of "
                                         + PackageManager.PROPERTY_NO_APP_DATA_STORAGE);
-                        return;
+                        return false;
                     }
                     final boolean isApex = (request.getScanFlags() & SCAN_AS_APEX) != 0;
                     final boolean isSdkLibrary = packageToScan.isSdkLibrary();
@@ -1087,7 +1105,7 @@
                             mPm.getSettingsVersionForPackage(packageToScan));
                 } catch (PackageManagerException e) {
                     request.setError("Scanning Failed.", e);
-                    return;
+                    return false;
                 }
                 if (request.isArchived()) {
                     final SparseArray<String> responsibleInstallerTitles =
@@ -1099,17 +1117,22 @@
                         request.setError(PackageManagerException.ofInternalError(
                                 "Failed to obtain the responsible installer info",
                                 INTERNAL_ERROR_ARCHIVE_NO_INSTALLER_TITLE));
-                        return;
+                        return false;
                     }
                     request.setResponsibleInstallerTitles(responsibleInstallerTitles);
                 }
             }
+        }
+        return true;
+    }
 
-            List<ReconciledPackage> reconciledPackages;
+    private List<ReconciledPackage> reconcileInstallPackages(List<InstallRequest> requests,
+            Map<String, Settings.VersionInfo> versionInfos) {
+        try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) {
             synchronized (mPm.mLock) {
                 try {
                     Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages");
-                    reconciledPackages = ReconcilePackageUtils.reconcilePackages(
+                    return ReconcilePackageUtils.reconcilePackages(
                             requests, Collections.unmodifiableMap(mPm.mPackages),
                             versionInfos, mSharedLibraries, mPm.mSettings.getKeySetManagerService(),
                             mPm.mSettings, mPm.mInjector.getSystemConfig());
@@ -1117,70 +1140,80 @@
                     for (InstallRequest request : requests) {
                         request.setError("Reconciliation failed...", e);
                     }
-                    return;
+                    return null;
                 } finally {
                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                 }
-                if (Flags.improveInstallFreeze()) {
-                    // Postpone freezer until after reconcile
-                    for (ReconciledPackage reconciledPkg : reconciledPackages) {
-                        InstallRequest installRequest = reconciledPkg.mInstallRequest;
-                        String packageName = installRequest.getParsedPackage().getPackageName();
-                        PackageFreezer freezer = freezePackageForInstall(packageName,
-                                UserHandle.USER_ALL, installRequest.getInstallFlags(),
-                                "installPackageLI", ApplicationExitInfo.REASON_PACKAGE_UPDATED,
-                                installRequest);
-                        installRequest.setFreezer(freezer);
-                    }
+            }
+        }
+    }
+
+
+    private boolean commitInstallPackages(List<ReconciledPackage> reconciledPackages) {
+        try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) {
+            if (Flags.improveInstallFreeze()) {
+                // Postpone freezer until after reconcile
+                for (ReconciledPackage reconciledPkg : reconciledPackages) {
+                    InstallRequest installRequest = reconciledPkg.mInstallRequest;
+                    String packageName = installRequest.getParsedPackage().getPackageName();
+                    PackageFreezer freezer = freezePackageForInstall(packageName,
+                            UserHandle.USER_ALL, installRequest.getInstallFlags(),
+                            "installPackageLI", ApplicationExitInfo.REASON_PACKAGE_UPDATED,
+                            installRequest);
+                    installRequest.setFreezer(freezer);
                 }
+            }
+            synchronized (mPm.mLock) {
                 try {
                     Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "commitPackages");
                     commitPackagesLocked(reconciledPackages, mPm.mUserManager.getUserIds());
-                    success = true;
                 } finally {
                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                 }
             }
             executePostCommitStepsLIF(reconciledPackages);
-        } finally {
-            if (success) {
-                for (InstallRequest request : requests) {
-                    if (request.getDataLoaderType() != DataLoaderType.INCREMENTAL) {
-                        continue;
-                    }
-                    if (request.getSignatureSchemeVersion() != SIGNING_BLOCK_V4) {
-                        continue;
-                    }
-                    // For incremental installs, we bypass the verifier prior to install. Now
-                    // that we know the package is valid, send a notice to the verifier with
-                    // the root hash of the base.apk.
-                    final String baseCodePath = request.getPkg().getBaseApkPath();
-                    final String[] splitCodePaths = request.getPkg().getSplitCodePaths();
-                    final Uri originUri = request.getOriginUri();
-                    final int verificationId = mPm.mPendingVerificationToken++;
-                    final String rootHashString = PackageManagerServiceUtils
-                            .buildVerificationRootHashString(baseCodePath, splitCodePaths);
-                    VerificationUtils.broadcastPackageVerified(verificationId, originUri,
-                            PackageManager.VERIFICATION_ALLOW, rootHashString,
-                            request.getDataLoaderType(), request.getUser(), mContext);
+        }
+        return true;
+    }
+
+    private void completeInstallProcess(List<InstallRequest> requests,
+            Map<String, Boolean> createdAppId, boolean success) {
+        if (success) {
+            for (InstallRequest request : requests) {
+                if (request.getDataLoaderType() != DataLoaderType.INCREMENTAL) {
+                    continue;
                 }
-            } else {
-                for (InstallRequest installRequest : requests) {
-                    if (installRequest.getParsedPackage() != null && createdAppId.getOrDefault(
-                            installRequest.getParsedPackage().getPackageName(), false)) {
-                        cleanUpAppIdCreation(installRequest);
-                    }
+                if (request.getSignatureSchemeVersion() != SIGNING_BLOCK_V4) {
+                    continue;
                 }
-                // TODO(b/194319951): create a more descriptive reason than unknown
-                // mark all non-failure installs as UNKNOWN so we do not treat them as success
-                for (InstallRequest request : requests) {
-                    request.closeFreezer();
-                    if (request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED) {
-                        request.setReturnCode(PackageManager.INSTALL_UNKNOWN);
-                    }
+                // For incremental installs, we bypass the verifier prior to install. Now
+                // that we know the package is valid, send a notice to the verifier with
+                // the root hash of the base.apk.
+                final String baseCodePath = request.getPkg().getBaseApkPath();
+                final String[] splitCodePaths = request.getPkg().getSplitCodePaths();
+                final Uri originUri = request.getOriginUri();
+                final int verificationId = mPm.mPendingVerificationToken++;
+                final String rootHashString = PackageManagerServiceUtils
+                        .buildVerificationRootHashString(baseCodePath, splitCodePaths);
+                VerificationUtils.broadcastPackageVerified(verificationId, originUri,
+                        PackageManager.VERIFICATION_ALLOW, rootHashString,
+                        request.getDataLoaderType(), request.getUser(), mContext);
+            }
+        } else {
+            for (InstallRequest installRequest : requests) {
+                if (installRequest.getParsedPackage() != null && createdAppId.getOrDefault(
+                        installRequest.getParsedPackage().getPackageName(), false)) {
+                    cleanUpAppIdCreation(installRequest);
                 }
             }
-            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+            // TODO(b/194319951): create a more descriptive reason than unknown
+            // mark all non-failure installs as UNKNOWN so we do not treat them as success
+            for (InstallRequest request : requests) {
+                request.closeFreezer();
+                if (request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED) {
+                    request.setReturnCode(PackageManager.INSTALL_UNKNOWN);
+                }
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 46e6546..df9f7fb 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -26,7 +26,6 @@
 import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.AppOpsManager.MODE_ERRORED;
 import static android.app.AppOpsManager.MODE_IGNORED;
-import static android.app.AppOpsManager.OP_BLUETOOTH_CONNECT;
 import static android.content.pm.ApplicationInfo.AUTO_REVOKE_DISALLOWED;
 import static android.content.pm.ApplicationInfo.AUTO_REVOKE_DISCOURAGED;
 import static android.permission.flags.Flags.serverSideAttributionRegistration;
@@ -1640,22 +1639,7 @@
                         throw new SecurityException(msg + ":" + e.getMessage());
                     }
                 }
-                int result = Math.max(checkedOpResult, notedOpResult);
-                // TODO(b/302609140): Remove extra logging after this issue is diagnosed.
-                if (op == OP_BLUETOOTH_CONNECT && result == MODE_ERRORED) {
-                    if (result == checkedOpResult) {
-                        Slog.e(LOG_TAG, "BLUETOOTH_CONNECT permission hard denied as"
-                                + " checkOp for resolvedAttributionSource "
-                                + resolvedAttributionSource + " and op " + op
-                                + " returned MODE_ERRORED");
-                    } else {
-                        Slog.e(LOG_TAG, "BLUETOOTH_CONNECT permission hard denied as"
-                                + " noteOp for resolvedAttributionSource "
-                                + resolvedAttributionSource + " and op " + notedOp
-                                + " returned MODE_ERRORED");
-                    }
-                }
-                return result;
+                return Math.max(checkedOpResult, notedOpResult);
             }
         }
 
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index f96706e..749025b 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -16,6 +16,7 @@
 
 package com.android.server.policy;
 
+import static android.Manifest.permission.CREATE_VIRTUAL_DEVICE;
 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
 import static android.Manifest.permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW;
 import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
@@ -59,13 +60,18 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
 import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
 import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
 import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
+import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
 import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD;
@@ -3058,7 +3064,7 @@
     /** {@inheritDoc} */
     @Override
     public int checkAddPermission(int type, boolean isRoundedCornerOverlay, String packageName,
-            int[] outAppOp) {
+            int[] outAppOp, int displayId) {
         if (isRoundedCornerOverlay && mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW)
                 != PERMISSION_GRANTED) {
             return ADD_PERMISSION_DENIED;
@@ -3098,6 +3104,12 @@
                 case TYPE_VOICE_INTERACTION:
                 case TYPE_QS_DIALOG:
                 case TYPE_NAVIGATION_BAR_PANEL:
+                case TYPE_STATUS_BAR:
+                case TYPE_NOTIFICATION_SHADE:
+                case TYPE_NAVIGATION_BAR:
+                case TYPE_STATUS_BAR_ADDITIONAL:
+                case TYPE_STATUS_BAR_SUB_PANEL:
+                case TYPE_VOICE_INTERACTION_STARTING:
                     // The window manager will check these.
                     return ADD_OKAY;
             }
@@ -3141,6 +3153,13 @@
             return ADD_OKAY;
         }
 
+        // Allow virtual device owners to add overlays on the displays they own.
+        if (mWindowManagerFuncs.isCallerVirtualDeviceOwner(displayId, callingUid)
+                && mContext.checkCallingOrSelfPermission(CREATE_VIRTUAL_DEVICE)
+                == PERMISSION_GRANTED) {
+            return ADD_OKAY;
+        }
+
         // check if user has enabled this operation. SecurityException will be thrown if this app
         // has not been allowed by the user. The reason to use "noteOp" (instead of checkOp) is to
         // make sure the usage is logged.
@@ -3581,18 +3600,6 @@
                 if (down) {
                     int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;
 
-                    // Disable autobrightness if it's on
-                    int auto = Settings.System.getIntForUser(
-                            mContext.getContentResolver(),
-                            Settings.System.SCREEN_BRIGHTNESS_MODE,
-                            Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
-                            UserHandle.USER_CURRENT_OR_SELF);
-                    if (auto != 0) {
-                        Settings.System.putIntForUser(mContext.getContentResolver(),
-                                Settings.System.SCREEN_BRIGHTNESS_MODE,
-                                Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
-                                UserHandle.USER_CURRENT_OR_SELF);
-                    }
                     int screenDisplayId = displayId < 0 ? DEFAULT_DISPLAY : displayId;
 
                     float minLinearBrightness = mPowerManager.getBrightnessConstraint(
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 989c8a8..892af6b 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -362,6 +362,12 @@
          * Invoked when a screenshot is taken of the given display to notify registered listeners.
          */
         List<ComponentName> notifyScreenshotListeners(int displayId);
+
+        /**
+         * Returns whether the given UID is the owner of a virtual device, which the given display
+         * belongs to.
+         */
+        boolean isCallerVirtualDeviceOwner(int displayId, int callingUid);
     }
 
     /**
@@ -421,6 +427,7 @@
      * @param packageName package name
      * @param outAppOp First element will be filled with the app op corresponding to
      *                 this window, or OP_NONE.
+     * @param displayId The display on which this window is being added.
      *
      * @return {@link WindowManagerGlobal#ADD_OKAY} if the add can proceed;
      *      else an error code, usually
@@ -429,7 +436,7 @@
      * @see WindowManager.LayoutParams#PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY
      */
     int checkAddPermission(int type, boolean isRoundedCornerOverlay, String packageName,
-            int[] outAppOp);
+            int[] outAppOp, int displayId);
 
     /**
      * After the window manager has computed the current configuration based
diff --git a/services/core/java/com/android/server/power/ThermalManagerService.java b/services/core/java/com/android/server/power/ThermalManagerService.java
index 822ec2e..6847a5c 100644
--- a/services/core/java/com/android/server/power/ThermalManagerService.java
+++ b/services/core/java/com/android/server/power/ThermalManagerService.java
@@ -54,6 +54,7 @@
 import android.os.ShellCommand;
 import android.os.SystemClock;
 import android.os.Temperature;
+import android.os.Trace;
 import android.util.ArrayMap;
 import android.util.EventLog;
 import android.util.Slog;
@@ -247,6 +248,7 @@
 
     private void setStatusLocked(int newStatus) {
         if (newStatus != mStatus) {
+            Trace.traceCounter(Trace.TRACE_TAG_POWER, "ThermalManagerService.status", newStatus);
             mStatus = newStatus;
             notifyStatusListenersLocked();
         }
diff --git a/services/core/java/com/android/server/power/stats/AggregatedPowerStatsSection.java b/services/core/java/com/android/server/power/stats/AggregatedPowerStatsSection.java
deleted file mode 100644
index 7ba4330..0000000
--- a/services/core/java/com/android/server/power/stats/AggregatedPowerStatsSection.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2023 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.power.stats;
-
-import android.util.IndentingPrintWriter;
-
-import com.android.modules.utils.TypedXmlSerializer;
-
-import java.io.IOException;
-
-class AggregatedPowerStatsSection extends PowerStatsSpan.Section {
-    public static final String TYPE = "aggregated-power-stats";
-
-    private final AggregatedPowerStats mAggregatedPowerStats;
-
-    AggregatedPowerStatsSection(AggregatedPowerStats aggregatedPowerStats) {
-        super(TYPE);
-        mAggregatedPowerStats = aggregatedPowerStats;
-    }
-
-    public AggregatedPowerStats getAggregatedPowerStats() {
-        return mAggregatedPowerStats;
-    }
-
-    @Override
-    void write(TypedXmlSerializer serializer) throws IOException {
-        mAggregatedPowerStats.writeXml(serializer);
-    }
-
-    @Override
-    public void dump(IndentingPrintWriter ipw) {
-        mAggregatedPowerStats.dump(ipw);
-    }
-}
diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
index 385561d..680b1ac 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -23,8 +23,6 @@
 import static android.os.BatteryStatsManager.NUM_WIFI_STATES;
 import static android.os.BatteryStatsManager.NUM_WIFI_SUPPL_STATES;
 
-import static com.android.server.power.stats.MobileRadioPowerStatsCollector.mapRadioAccessNetworkTypeToRadioAccessTechnology;
-
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -149,6 +147,7 @@
 import com.android.server.LocalServices;
 import com.android.server.power.optimization.Flags;
 import com.android.server.power.stats.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
+import com.android.server.power.stats.format.MobileRadioPowerStatsLayout;
 
 import libcore.util.EmptyArray;
 
@@ -180,7 +179,6 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.ReentrantLock;
-import java.util.function.IntSupplier;
 import java.util.function.LongSupplier;
 import java.util.function.Supplier;
 
@@ -2028,7 +2026,7 @@
         void setContext(Context context) {
             mPackageManager = context.getPackageManager();
             mConsumedEnergyRetriever = new PowerStatsCollector.ConsumedEnergyRetrieverImpl(
-                    LocalServices.getService(PowerStatsInternal.class));
+                    LocalServices.getService(PowerStatsInternal.class), () -> mBatteryVoltageMv);
             mNetworkStatsManager = context.getSystemService(NetworkStatsManager.class);
             mTelephonyManager =
                     (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
@@ -2083,11 +2081,6 @@
         }
 
         @Override
-        public IntSupplier getVoltageSupplier() {
-            return () -> mBatteryVoltageMv;
-        }
-
-        @Override
         public ScreenPowerStatsCollector.ScreenUsageTimeRetriever getScreenUsageTimeRetriever() {
             return mScreenUsageTimeRetriever;
         }
@@ -13191,7 +13184,8 @@
                 final int freq = deltaInfo.getSpecificInfoFrequencyRange(index);
 
                 // Map RadioAccessNetworkType to course grain RadioAccessTechnology.
-                final int ratBucket = mapRadioAccessNetworkTypeToRadioAccessTechnology(rat);
+                final int ratBucket = MobileRadioPowerStatsLayout
+                        .mapRadioAccessNetworkTypeToRadioAccessTechnology(rat);
                 final RadioAccessTechnologyBatteryStats ratStats = getRatBatteryStatsLocked(
                         ratBucket);
 
diff --git a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
index d51cfea..87a3e5e 100644
--- a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
+++ b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
@@ -16,6 +16,7 @@
 
 package com.android.server.power.stats;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.hardware.SensorManager;
 import android.os.BatteryConsumer;
@@ -27,7 +28,6 @@
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
-import android.util.SparseBooleanArray;
 
 import com.android.internal.os.Clock;
 import com.android.internal.os.CpuScalingPolicies;
@@ -44,8 +44,7 @@
 public class BatteryUsageStatsProvider {
     private static final String TAG = "BatteryUsageStatsProv";
     private final Context mContext;
-    private final SparseBooleanArray mPowerStatsExporterEnabled = new SparseBooleanArray();
-    private final PowerStatsExporter mPowerStatsExporter;
+    private final PowerAttributor mPowerAttributor;
     private final PowerStatsStore mPowerStatsStore;
     private final PowerProfile mPowerProfile;
     private final CpuScalingPolicies mCpuScalingPolicies;
@@ -53,16 +52,18 @@
     private final Object mLock = new Object();
     private List<PowerCalculator> mPowerCalculators;
 
-    public BatteryUsageStatsProvider(Context context,
-            PowerStatsExporter powerStatsExporter,
-            PowerProfile powerProfile, CpuScalingPolicies cpuScalingPolicies,
-            PowerStatsStore powerStatsStore, Clock clock) {
+    public BatteryUsageStatsProvider(@NonNull Context context,
+            @NonNull PowerAttributor powerAttributor,
+            @NonNull PowerProfile powerProfile, @NonNull CpuScalingPolicies cpuScalingPolicies,
+            @NonNull PowerStatsStore powerStatsStore, @NonNull Clock clock) {
         mContext = context;
-        mPowerStatsExporter = powerStatsExporter;
+        mPowerAttributor = powerAttributor;
         mPowerStatsStore = powerStatsStore;
         mPowerProfile = powerProfile;
         mCpuScalingPolicies = cpuScalingPolicies;
         mClock = clock;
+
+        mPowerStatsStore.addSectionReader(new BatteryUsageStatsSection.Reader());
     }
 
     private List<PowerCalculator> getPowerCalculators() {
@@ -72,55 +73,67 @@
 
                 // Power calculators are applied in the order of registration
                 mPowerCalculators.add(new BatteryChargeCalculator());
-                if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)) {
+                if (!mPowerAttributor.isPowerComponentSupported(
+                        BatteryConsumer.POWER_COMPONENT_CPU)) {
                     mPowerCalculators.add(
                             new CpuPowerCalculator(mCpuScalingPolicies, mPowerProfile));
                 }
                 mPowerCalculators.add(new MemoryPowerCalculator(mPowerProfile));
                 mPowerCalculators.add(new WakelockPowerCalculator(mPowerProfile));
                 if (!BatteryStats.checkWifiOnly(mContext)) {
-                    if (!mPowerStatsExporterEnabled.get(
+                    if (!mPowerAttributor.isPowerComponentSupported(
                             BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)) {
                         mPowerCalculators.add(new MobileRadioPowerCalculator(mPowerProfile));
                     }
-                    if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_PHONE)) {
+                    if (!mPowerAttributor.isPowerComponentSupported(
+                            BatteryConsumer.POWER_COMPONENT_PHONE)) {
                         mPowerCalculators.add(new PhonePowerCalculator(mPowerProfile));
                     }
                 }
-                if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_WIFI)) {
+                if (!mPowerAttributor.isPowerComponentSupported(
+                        BatteryConsumer.POWER_COMPONENT_WIFI)) {
                     mPowerCalculators.add(new WifiPowerCalculator(mPowerProfile));
                 }
-                if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_BLUETOOTH)) {
+                if (!mPowerAttributor.isPowerComponentSupported(
+                        BatteryConsumer.POWER_COMPONENT_BLUETOOTH)) {
                     mPowerCalculators.add(new BluetoothPowerCalculator(mPowerProfile));
                 }
-                if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_SENSORS)) {
+                if (!mPowerAttributor.isPowerComponentSupported(
+                        BatteryConsumer.POWER_COMPONENT_SENSORS)) {
                     mPowerCalculators.add(new SensorPowerCalculator(
                             mContext.getSystemService(SensorManager.class)));
                 }
-                if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_GNSS)) {
+                if (!mPowerAttributor.isPowerComponentSupported(
+                        BatteryConsumer.POWER_COMPONENT_GNSS)) {
                     mPowerCalculators.add(new GnssPowerCalculator(mPowerProfile));
                 }
-                if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_CAMERA)) {
+                if (!mPowerAttributor.isPowerComponentSupported(
+                        BatteryConsumer.POWER_COMPONENT_CAMERA)) {
                     mPowerCalculators.add(new CameraPowerCalculator(mPowerProfile));
                 }
-                if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT)) {
+                if (!mPowerAttributor.isPowerComponentSupported(
+                        BatteryConsumer.POWER_COMPONENT_FLASHLIGHT)) {
                     mPowerCalculators.add(new FlashlightPowerCalculator(mPowerProfile));
                 }
-                if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_AUDIO)) {
+                if (!mPowerAttributor.isPowerComponentSupported(
+                        BatteryConsumer.POWER_COMPONENT_AUDIO)) {
                     mPowerCalculators.add(new AudioPowerCalculator(mPowerProfile));
                 }
-                if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_VIDEO)) {
+                if (!mPowerAttributor.isPowerComponentSupported(
+                        BatteryConsumer.POWER_COMPONENT_VIDEO)) {
                     mPowerCalculators.add(new VideoPowerCalculator(mPowerProfile));
                 }
-                if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_SCREEN)) {
+                if (!mPowerAttributor.isPowerComponentSupported(
+                        BatteryConsumer.POWER_COMPONENT_SCREEN)) {
                     mPowerCalculators.add(new ScreenPowerCalculator(mPowerProfile));
                 }
-                if (!mPowerStatsExporterEnabled.get(
+                if (!mPowerAttributor.isPowerComponentSupported(
                         BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY)) {
                     mPowerCalculators.add(new AmbientDisplayPowerCalculator(mPowerProfile));
                 }
                 mPowerCalculators.add(new IdlePowerCalculator(mPowerProfile));
-                if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_ANY)) {
+                if (!mPowerAttributor.isPowerComponentSupported(
+                        BatteryConsumer.POWER_COMPONENT_ANY)) {
                     mPowerCalculators.add(new CustomEnergyConsumerPowerCalculator(mPowerProfile));
                 }
                 mPowerCalculators.add(new UserPowerCalculator());
@@ -196,7 +209,7 @@
         final boolean includeProcessStateData = ((query.getFlags()
                 & BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_PROCESS_STATE_DATA) != 0)
                 && stats.isProcessStateDataAvailable();
-        final boolean includeVirtualUids =  ((query.getFlags()
+        final boolean includeVirtualUids = ((query.getFlags()
                 & BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_VIRTUAL_UIDS) != 0);
         final double minConsumedPowerThreshold = query.getMinConsumedPowerThreshold();
 
@@ -258,10 +271,8 @@
             }
         }
 
-        if (mPowerStatsExporterEnabled.indexOfValue(true) >= 0) {
-            mPowerStatsExporter.exportAggregatedPowerStats(batteryUsageStatsBuilder,
-                    monotonicStartTime, monotonicEndTime);
-        }
+        mPowerAttributor.estimatePowerConsumption(batteryUsageStatsBuilder, stats.getHistory(),
+                monotonicStartTime, monotonicEndTime);
 
         BatteryUsageStats batteryUsageStats = batteryUsageStatsBuilder.build();
         if (includeProcessStateData) {
@@ -272,6 +283,7 @@
 
     // STOPSHIP(b/229906525): remove verification before shipping
     private static boolean sErrorReported;
+
     private void verify(BatteryUsageStats stats) {
         if (sErrorReported) {
             return;
@@ -390,7 +402,7 @@
             // while the "to" timestamp is *inclusive*.
             boolean isInRange =
                     (query.getFromTimestamp() == 0 || minTime > query.getFromTimestamp())
-                    && (query.getToTimestamp() == 0 || maxTime <= query.getToTimestamp());
+                            && (query.getToTimestamp() == 0 || maxTime <= query.getToTimestamp());
             if (!isInRange) {
                 continue;
             }
@@ -422,12 +434,4 @@
         }
         return builder.build();
     }
-
-    /**
-     * Specify whether PowerStats based attribution is supported for the specified component.
-     */
-    public void setPowerStatsExporterEnabled(int powerComponentId, boolean enabled) {
-        mPowerStatsExporterEnabled.put(powerComponentId, enabled);
-        mPowerStatsExporter.setPowerComponentEnabled(powerComponentId, enabled);
-    }
 }
diff --git a/services/core/java/com/android/server/power/stats/BatteryUsageStatsSection.java b/services/core/java/com/android/server/power/stats/BatteryUsageStatsSection.java
index b95faac..af36524 100644
--- a/services/core/java/com/android/server/power/stats/BatteryUsageStatsSection.java
+++ b/services/core/java/com/android/server/power/stats/BatteryUsageStatsSection.java
@@ -19,8 +19,11 @@
 import android.os.BatteryUsageStats;
 import android.util.IndentingPrintWriter;
 
+import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
 
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.IOException;
 
 class BatteryUsageStatsSection extends PowerStatsSpan.Section {
@@ -38,7 +41,7 @@
     }
 
     @Override
-    void write(TypedXmlSerializer serializer) throws IOException {
+    public void write(TypedXmlSerializer serializer) throws IOException {
         mBatteryUsageStats.writeXml(serializer);
     }
 
@@ -46,4 +49,17 @@
     public void dump(IndentingPrintWriter ipw) {
         mBatteryUsageStats.dump(ipw, "");
     }
+
+    static class Reader implements PowerStatsSpan.SectionReader {
+        @Override
+        public String getType() {
+            return TYPE;
+        }
+
+        @Override
+        public PowerStatsSpan.Section read(String sectionType, TypedXmlPullParser parser)
+                throws IOException, XmlPullParserException {
+            return new BatteryUsageStatsSection(BatteryUsageStats.createFromXml(parser));
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/power/stats/BluetoothPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/BluetoothPowerStatsCollector.java
index 8a5085b..539c415 100644
--- a/services/core/java/com/android/server/power/stats/BluetoothPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/BluetoothPowerStatsCollector.java
@@ -28,13 +28,12 @@
 
 import com.android.internal.os.Clock;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.BluetoothPowerStatsLayout;
 
-import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
-import java.util.function.IntSupplier;
 
 public class BluetoothPowerStatsCollector extends PowerStatsCollector {
     private static final String TAG = "BluetoothPowerStatsCollector";
@@ -43,7 +42,7 @@
 
     private static final long ENERGY_UNSPECIFIED = -1;
 
-    interface BluetoothStatsRetriever {
+    public interface BluetoothStatsRetriever {
         interface Callback {
             void onBluetoothScanTime(int uid, long scanTimeMs);
         }
@@ -54,29 +53,25 @@
                 BluetoothAdapter.OnBluetoothActivityEnergyInfoCallback callback);
     }
 
-    interface Injector {
+    public interface Injector {
         Handler getHandler();
         Clock getClock();
         PowerStatsUidResolver getUidResolver();
         long getPowerStatsCollectionThrottlePeriod(String powerComponentName);
         PackageManager getPackageManager();
         ConsumedEnergyRetriever getConsumedEnergyRetriever();
-        IntSupplier getVoltageSupplier();
         BluetoothStatsRetriever getBluetoothStatsRetriever();
     }
 
     private final Injector mInjector;
 
-    private BluetoothPowerStatsLayout mLayout;
+    private com.android.server.power.stats.format.BluetoothPowerStatsLayout mLayout;
     private boolean mIsInitialized;
     private PowerStats mPowerStats;
     private long[] mDeviceStats;
     private BluetoothStatsRetriever mBluetoothStatsRetriever;
     private ConsumedEnergyRetriever mConsumedEnergyRetriever;
-    private IntSupplier mVoltageSupplier;
-    private int[] mEnergyConsumerIds = new int[0];
-    private long[] mLastConsumedEnergyUws;
-    private int mLastVoltageMv;
+    private ConsumedEnergyHelper mConsumedEnergyHelper;
 
     private long mLastRxTime;
     private long mLastTxTime;
@@ -93,7 +88,7 @@
 
     private final SparseArray<UidStats> mUidStats = new SparseArray<>();
 
-    BluetoothPowerStatsCollector(Injector injector) {
+    public BluetoothPowerStatsCollector(Injector injector) {
         super(injector.getHandler(),  injector.getPowerStatsCollectionThrottlePeriod(
                         BatteryConsumer.powerComponentIdToString(
                                 BatteryConsumer.POWER_COMPONENT_BLUETOOTH)),
@@ -122,21 +117,11 @@
             return false;
         }
 
-        mConsumedEnergyRetriever = mInjector.getConsumedEnergyRetriever();
-        mVoltageSupplier = mInjector.getVoltageSupplier();
         mBluetoothStatsRetriever = mInjector.getBluetoothStatsRetriever();
-        mEnergyConsumerIds =
-                mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.BLUETOOTH);
-        mLastConsumedEnergyUws = new long[mEnergyConsumerIds.length];
-        Arrays.fill(mLastConsumedEnergyUws, ENERGY_UNSPECIFIED);
-
-        mLayout = new BluetoothPowerStatsLayout();
-        mLayout.addDeviceBluetoothControllerActivity();
-        mLayout.addDeviceSectionEnergyConsumers(mEnergyConsumerIds.length);
-        mLayout.addDeviceSectionUsageDuration();
-        mLayout.addDeviceSectionPowerEstimate();
-        mLayout.addUidTrafficStats();
-        mLayout.addUidSectionPowerEstimate();
+        mConsumedEnergyRetriever = mInjector.getConsumedEnergyRetriever();
+        mConsumedEnergyHelper = new ConsumedEnergyHelper(mConsumedEnergyRetriever,
+                EnergyConsumerType.BLUETOOTH);
+        mLayout = new BluetoothPowerStatsLayout(mConsumedEnergyHelper.getEnergyConsumerCount());
 
         PersistableBundle extras = new PersistableBundle();
         mLayout.toExtras(extras);
@@ -152,7 +137,7 @@
     }
 
     @Override
-    protected PowerStats collectStats() {
+    public PowerStats collectStats() {
         if (!ensureInitialized()) {
             return null;
         }
@@ -162,9 +147,7 @@
         collectBluetoothActivityInfo();
         collectBluetoothScanStats();
 
-        if (mEnergyConsumerIds.length != 0) {
-            collectEnergyConsumers();
-        }
+        mConsumedEnergyHelper.collectConsumedEnergy(mPowerStats, mLayout);
 
         return mPowerStats;
     }
@@ -296,34 +279,6 @@
         mLayout.setDeviceScanTime(mDeviceStats, totalScanTime);
     }
 
-    private void collectEnergyConsumers() {
-        int voltageMv = mVoltageSupplier.getAsInt();
-        if (voltageMv <= 0) {
-            Slog.wtf(TAG, "Unexpected battery voltage (" + voltageMv
-                    + " mV) when querying energy consumers");
-            return;
-        }
-
-        int averageVoltage = mLastVoltageMv != 0 ? (mLastVoltageMv + voltageMv) / 2 : voltageMv;
-        mLastVoltageMv = voltageMv;
-
-        long[] energyUws = mConsumedEnergyRetriever.getConsumedEnergyUws(mEnergyConsumerIds);
-        if (energyUws == null) {
-            return;
-        }
-
-        for (int i = energyUws.length - 1; i >= 0; i--) {
-            long energyDelta = mLastConsumedEnergyUws[i] != ENERGY_UNSPECIFIED
-                    ? energyUws[i] - mLastConsumedEnergyUws[i] : 0;
-            if (energyDelta < 0) {
-                // Likely, restart of powerstats HAL
-                energyDelta = 0;
-            }
-            mLayout.setConsumedEnergy(mPowerStats.stats, i, uJtoUc(energyDelta, averageVoltage));
-            mLastConsumedEnergyUws[i] = energyUws[i];
-        }
-    }
-
     @Override
     protected void onUidRemoved(int uid) {
         super.onUidRemoved(uid);
diff --git a/services/core/java/com/android/server/power/stats/CameraPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/CameraPowerStatsCollector.java
index 8705bd5..0f70064 100644
--- a/services/core/java/com/android/server/power/stats/CameraPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/CameraPowerStatsCollector.java
@@ -19,12 +19,13 @@
 import android.hardware.power.stats.EnergyConsumerType;
 import android.os.BatteryConsumer;
 
+import com.android.server.power.stats.format.BinaryStatePowerStatsLayout;
+
 public class CameraPowerStatsCollector extends EnergyConsumerPowerStatsCollector {
 
-    CameraPowerStatsCollector(Injector injector) {
+    public CameraPowerStatsCollector(Injector injector) {
         super(injector, BatteryConsumer.POWER_COMPONENT_CAMERA,
                 BatteryConsumer.powerComponentIdToString(BatteryConsumer.POWER_COMPONENT_CAMERA),
-                EnergyConsumerType.CAMERA, /* energy consumer name */ null,
-                new BinaryStatePowerStatsLayout());
+                EnergyConsumerType.CAMERA, new BinaryStatePowerStatsLayout());
     }
 }
diff --git a/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java
index b5ef67b..128f14a 100644
--- a/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java
@@ -31,11 +31,10 @@
 import com.android.internal.os.CpuScalingPolicies;
 import com.android.internal.os.PowerProfile;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.CpuPowerStatsLayout;
 
 import java.io.PrintWriter;
-import java.util.Arrays;
 import java.util.Locale;
-import java.util.function.IntSupplier;
 
 /**
  * Collects snapshots of power-related system statistics.
@@ -46,7 +45,6 @@
 public class CpuPowerStatsCollector extends PowerStatsCollector {
     private static final String TAG = "CpuPowerStatsCollector";
     private static final long NANOS_PER_MILLIS = 1000000;
-    private static final long ENERGY_UNSPECIFIED = -1;
     private static final int DEFAULT_CPU_POWER_BRACKETS = 3;
     private static final int DEFAULT_CPU_POWER_BRACKETS_PER_ENERGY_CONSUMER = 2;
 
@@ -58,7 +56,6 @@
         PowerProfile getPowerProfile();
         KernelCpuStatsReader getKernelCpuStatsReader();
         ConsumedEnergyRetriever getConsumedEnergyRetriever();
-        IntSupplier getVoltageSupplier();
         long getPowerStatsCollectionThrottlePeriod(String powerComponentName);
 
         default int getDefaultCpuPowerBrackets() {
@@ -76,8 +73,7 @@
     private CpuScalingPolicies mCpuScalingPolicies;
     private PowerProfile mPowerProfile;
     private KernelCpuStatsReader mKernelCpuStatsReader;
-    private ConsumedEnergyRetriever mConsumedEnergyRetriever;
-    private IntSupplier mVoltageSupplier;
+    private ConsumedEnergyHelper mConsumedEnergyHelper;
     private int mDefaultCpuPowerBrackets;
     private int mDefaultCpuPowerBracketsPerEnergyConsumer;
     private long[] mCpuTimeByScalingStep;
@@ -85,15 +81,12 @@
     private long[] mTempUidStats;
     private final SparseArray<UidStats> mUidStats = new SparseArray<>();
     private boolean mIsPerUidTimeInStateSupported;
-    private int[] mCpuEnergyConsumerIds = new int[0];
     private PowerStats.Descriptor mPowerStatsDescriptor;
     // Reusable instance
     private PowerStats mCpuPowerStats;
     private CpuPowerStatsLayout mLayout;
     private long mLastUpdateTimestampNanos;
     private long mLastUpdateUptimeMillis;
-    private int mLastVoltageMv;
-    private long[] mLastConsumedEnergyUws;
 
     CpuPowerStatsCollector(Injector injector) {
         super(injector.getHandler(), injector.getPowerStatsCollectionThrottlePeriod(
@@ -115,31 +108,22 @@
         mCpuScalingPolicies = mInjector.getCpuScalingPolicies();
         mPowerProfile = mInjector.getPowerProfile();
         mKernelCpuStatsReader = mInjector.getKernelCpuStatsReader();
-        mConsumedEnergyRetriever = mInjector.getConsumedEnergyRetriever();
-        mVoltageSupplier = mInjector.getVoltageSupplier();
         mDefaultCpuPowerBrackets = mInjector.getDefaultCpuPowerBrackets();
         mDefaultCpuPowerBracketsPerEnergyConsumer =
                 mInjector.getDefaultCpuPowerBracketsPerEnergyConsumer();
 
         mIsPerUidTimeInStateSupported = mKernelCpuStatsReader.isSupportedFeature();
-        mCpuEnergyConsumerIds =
-                mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.CPU_CLUSTER);
-        mLastConsumedEnergyUws = new long[mCpuEnergyConsumerIds.length];
-        Arrays.fill(mLastConsumedEnergyUws, ENERGY_UNSPECIFIED);
+
+        mConsumedEnergyHelper = new ConsumedEnergyHelper(mInjector.getConsumedEnergyRetriever(),
+                EnergyConsumerType.CPU_CLUSTER);
 
         int cpuScalingStepCount = mCpuScalingPolicies.getScalingStepCount();
         mCpuTimeByScalingStep = new long[cpuScalingStepCount];
         mTempCpuTimeByScalingStep = new long[cpuScalingStepCount];
         int[] scalingStepToPowerBracketMap = initPowerBrackets();
 
-        mLayout = new CpuPowerStatsLayout();
-        mLayout.addDeviceSectionCpuTimeByScalingStep(cpuScalingStepCount);
-        mLayout.addDeviceSectionCpuTimeByCluster(mCpuScalingPolicies.getPolicies().length);
-        mLayout.addDeviceSectionUsageDuration();
-        mLayout.addDeviceSectionEnergyConsumers(mCpuEnergyConsumerIds.length);
-        mLayout.addDeviceSectionPowerEstimate();
-        mLayout.addUidSectionCpuTimeByPowerBracket(scalingStepToPowerBracketMap);
-        mLayout.addUidSectionPowerEstimate();
+        mLayout = new CpuPowerStatsLayout(mConsumedEnergyHelper.getEnergyConsumerCount(),
+                mCpuScalingPolicies.getPolicies().length, scalingStepToPowerBracketMap);
 
         PersistableBundle extras = new PersistableBundle();
         mLayout.toExtras(extras);
@@ -158,16 +142,18 @@
     private int[] initPowerBrackets() {
         if (mPowerProfile.getCpuPowerBracketCount() != PowerProfile.POWER_BRACKETS_UNSPECIFIED) {
             return initPowerBracketsFromPowerProfile();
-        } else if (mCpuEnergyConsumerIds.length == 0 || mCpuEnergyConsumerIds.length == 1) {
+        } else if (mConsumedEnergyHelper.getEnergyConsumerCount() == 0
+                || mConsumedEnergyHelper.getEnergyConsumerCount() == 1) {
             return initDefaultPowerBrackets(mDefaultCpuPowerBrackets);
-        } else if (mCpuScalingPolicies.getPolicies().length == mCpuEnergyConsumerIds.length) {
+        } else if (mCpuScalingPolicies.getPolicies().length
+                == mConsumedEnergyHelper.getEnergyConsumerCount()) {
             return initPowerBracketsByCluster(mDefaultCpuPowerBracketsPerEnergyConsumer);
         } else {
             Slog.i(TAG, "Assigning a single power brackets to each CPU_CLUSTER energy consumer."
                         + " Number of CPU clusters ("
                         + mCpuScalingPolicies.getPolicies().length
                         + ") does not match the number of energy consumers ("
-                        + mCpuEnergyConsumerIds.length + "). "
+                        + mConsumedEnergyHelper.getEnergyConsumerCount() + "). "
                         + " Using default power bucket assignment.");
             return initDefaultPowerBrackets(mDefaultCpuPowerBrackets);
         }
@@ -368,41 +354,11 @@
         }
         mLayout.setUsageDuration(mCpuPowerStats.stats, uptimeDelta);
 
-        if (mCpuEnergyConsumerIds.length != 0) {
-            collectEnergyConsumers();
-        }
+        mConsumedEnergyHelper.collectConsumedEnergy(mCpuPowerStats, mLayout);
 
         return mCpuPowerStats;
     }
 
-    private void collectEnergyConsumers() {
-        int voltageMv = mVoltageSupplier.getAsInt();
-        if (voltageMv <= 0) {
-            Slog.wtf(TAG, "Unexpected battery voltage (" + voltageMv
-                          + " mV) when querying energy consumers");
-            return;
-        }
-
-        int averageVoltage = mLastVoltageMv != 0 ? (mLastVoltageMv + voltageMv) / 2 : voltageMv;
-        mLastVoltageMv = voltageMv;
-
-        long[] energyUws = mConsumedEnergyRetriever.getConsumedEnergyUws(mCpuEnergyConsumerIds);
-        if (energyUws == null) {
-            return;
-        }
-
-        for (int i = energyUws.length - 1; i >= 0; i--) {
-            long energyDelta = mLastConsumedEnergyUws[i] != ENERGY_UNSPECIFIED
-                    ? energyUws[i] - mLastConsumedEnergyUws[i] : 0;
-            if (energyDelta < 0) {
-                // Likely, restart of powerstats HAL
-                energyDelta = 0;
-            }
-            mLayout.setConsumedEnergy(mCpuPowerStats.stats, i, uJtoUc(energyDelta, averageVoltage));
-            mLastConsumedEnergyUws[i] = energyUws[i];
-        }
-    }
-
     @VisibleForNative
     interface KernelCpuStatsCallback {
         @Keep // Called from native
diff --git a/services/core/java/com/android/server/power/stats/CustomEnergyConsumerPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/CustomEnergyConsumerPowerStatsCollector.java
index 4bfe442..c1c7e12 100644
--- a/services/core/java/com/android/server/power/stats/CustomEnergyConsumerPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/CustomEnergyConsumerPowerStatsCollector.java
@@ -19,6 +19,8 @@
 import android.hardware.power.stats.EnergyConsumerType;
 import android.os.BatteryConsumer;
 
+import com.android.server.power.stats.format.EnergyConsumerPowerStatsLayout;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
@@ -29,7 +31,8 @@
     private final EnergyConsumerPowerStatsCollector.Injector mInjector;
     private List<EnergyConsumerPowerStatsCollector> mCollectors;
 
-    CustomEnergyConsumerPowerStatsCollector(EnergyConsumerPowerStatsCollector.Injector injector) {
+    public CustomEnergyConsumerPowerStatsCollector(
+            EnergyConsumerPowerStatsCollector.Injector injector) {
         super(injector.getHandler(), 0, injector.getUidResolver(), injector.getClock());
         mInjector = injector;
     }
@@ -46,7 +49,8 @@
         for (int i = 0; i < energyConsumerIds.length; i++) {
             String name = retriever.getEnergyConsumerName(energyConsumerIds[i]);
             EnergyConsumerPowerStatsCollector collector = new EnergyConsumerPowerStatsCollector(
-                    mInjector, powerComponentId++, name, energyConsumerIds[i], sLayout);
+                    mInjector, powerComponentId++, name, EnergyConsumerType.OTHER,
+                    energyConsumerIds[i], sLayout);
             collector.setEnabled(true);
             collector.addConsumer(this::deliverStats);
             mCollectors.add(collector);
diff --git a/services/core/java/com/android/server/power/stats/EnergyConsumerPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/EnergyConsumerPowerStatsCollector.java
index 79fbe8e..1d2e388 100644
--- a/services/core/java/com/android/server/power/stats/EnergyConsumerPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/EnergyConsumerPowerStatsCollector.java
@@ -16,78 +16,57 @@
 
 package com.android.server.power.stats;
 
-import android.hardware.power.stats.EnergyConsumerAttribution;
-import android.hardware.power.stats.EnergyConsumerResult;
 import android.hardware.power.stats.EnergyConsumerType;
 import android.os.Handler;
 import android.os.PersistableBundle;
-import android.util.Slog;
-import android.util.SparseLongArray;
 
 import com.android.internal.os.Clock;
 import com.android.internal.os.PowerStats;
-
-import java.util.function.IntSupplier;
+import com.android.server.power.stats.format.EnergyConsumerPowerStatsLayout;
 
 public class EnergyConsumerPowerStatsCollector extends PowerStatsCollector {
-    private static final String TAG = "EnergyConsumerPowerStatsCollector";
 
-    private static final long ENERGY_UNSPECIFIED = -1;
-
-    interface Injector {
+    public interface Injector {
         Handler getHandler();
         Clock getClock();
         PowerStatsUidResolver getUidResolver();
         long getPowerStatsCollectionThrottlePeriod(String powerComponentName);
         ConsumedEnergyRetriever getConsumedEnergyRetriever();
-        IntSupplier getVoltageSupplier();
     }
 
+    private static final int UNSPECIFIED = -1;
+
     private final Injector mInjector;
     private final int mPowerComponentId;
     private final String mPowerComponentName;
+    private final int mEnergyConsumerId;
     private final int mEnergyConsumerType;
-    private final String mEnergyConsumerName;
 
     private final EnergyConsumerPowerStatsLayout mLayout;
     private boolean mIsInitialized;
 
     private PowerStats mPowerStats;
-    private ConsumedEnergyRetriever mConsumedEnergyRetriever;
-    private IntSupplier mVoltageSupplier;
-    private int[] mEnergyConsumerIds;
-    private long mLastConsumedEnergyUws = ENERGY_UNSPECIFIED;
-    private SparseLongArray mLastConsumerEnergyPerUid = new SparseLongArray();
-    private int mLastVoltageMv;
+    private ConsumedEnergyHelper mConsumedEnergyHelper;
     private long mLastUpdateTimestamp;
-    private boolean mFirstCollection = true;
 
     EnergyConsumerPowerStatsCollector(Injector injector, int powerComponentId,
             String powerComponentName, @EnergyConsumerType int energyConsumerType,
-            String energyConsumerName, EnergyConsumerPowerStatsLayout statsLayout) {
-        super(injector.getHandler(),
-                injector.getPowerStatsCollectionThrottlePeriod(powerComponentName),
-                injector.getUidResolver(), injector.getClock());
-        mInjector = injector;
-        mPowerComponentId = powerComponentId;
-        mPowerComponentName = powerComponentName;
-        mEnergyConsumerType = energyConsumerType;
-        mEnergyConsumerName = energyConsumerName;
-        mLayout = statsLayout;
+            EnergyConsumerPowerStatsLayout statsLayout) {
+        this(injector, powerComponentId, powerComponentName, energyConsumerType, UNSPECIFIED,
+                statsLayout);
     }
 
     EnergyConsumerPowerStatsCollector(Injector injector, int powerComponentId,
-            String powerComponentName, int energyConsumerId,
-            EnergyConsumerPowerStatsLayout statsLayout) {
+            String powerComponentName, @EnergyConsumerType int energyConsumerType,
+            int energyConsumerId, EnergyConsumerPowerStatsLayout statsLayout) {
         super(injector.getHandler(),
                 injector.getPowerStatsCollectionThrottlePeriod(powerComponentName),
                 injector.getUidResolver(), injector.getClock());
         mInjector = injector;
         mPowerComponentId = powerComponentId;
         mPowerComponentName = powerComponentName;
-        mEnergyConsumerIds = new int[]{energyConsumerId};
-        mEnergyConsumerType = EnergyConsumerType.OTHER;
-        mEnergyConsumerName = null;
+        mEnergyConsumerId = energyConsumerId;
+        mEnergyConsumerType = energyConsumerType;
         mLayout = statsLayout;
     }
 
@@ -100,12 +79,14 @@
             return false;
         }
 
-        mConsumedEnergyRetriever = mInjector.getConsumedEnergyRetriever();
-        mVoltageSupplier = mInjector.getVoltageSupplier();
-        if (mEnergyConsumerIds == null) {
-            mEnergyConsumerIds = mConsumedEnergyRetriever.getEnergyConsumerIds(mEnergyConsumerType,
-                    mEnergyConsumerName);
+        if (mEnergyConsumerId != UNSPECIFIED) {
+            mConsumedEnergyHelper = new ConsumedEnergyHelper(mInjector.getConsumedEnergyRetriever(),
+                    mEnergyConsumerId, true /* perUidAttribution */);
+        } else {
+            mConsumedEnergyHelper = new ConsumedEnergyHelper(mInjector.getConsumedEnergyRetriever(),
+                    mEnergyConsumerType);
         }
+
         PersistableBundle extras = new PersistableBundle();
         mLayout.toExtras(extras);
         PowerStats.Descriptor powerStatsDescriptor = new PowerStats.Descriptor(
@@ -124,85 +105,15 @@
             return null;
         }
 
-        if (mEnergyConsumerIds.length == 0) {
-            return null;
-        }
-
-        int voltageMv = mVoltageSupplier.getAsInt();
-        int averageVoltage = mLastVoltageMv != 0 ? (mLastVoltageMv + voltageMv) / 2 : voltageMv;
-        if (averageVoltage <= 0) {
-            Slog.wtf(TAG, "Unexpected battery voltage (" + voltageMv
-                    + " mV) when querying energy consumers");
-            return null;
-        }
-
-        mLastVoltageMv = voltageMv;
-
-        EnergyConsumerResult[] energy =
-                    mConsumedEnergyRetriever.getConsumedEnergy(mEnergyConsumerIds);
-        long consumedEnergy = 0;
-        if (energy != null) {
-            for (int i = energy.length - 1; i >= 0; i--) {
-                if (energy[i].energyUWs != ENERGY_UNSPECIFIED) {
-                    consumedEnergy += energy[i].energyUWs;
-                }
-            }
-        }
-
-        long energyDelta = mLastConsumedEnergyUws != ENERGY_UNSPECIFIED
-                ? consumedEnergy - mLastConsumedEnergyUws : 0;
-        mLastConsumedEnergyUws = consumedEnergy;
-        if (energyDelta < 0) {
-            // Likely, restart of powerstats HAL
-            energyDelta = 0;
-        }
-
-        if (energyDelta == 0 && !mFirstCollection) {
-            return null;
-        }
-
-        mLayout.setConsumedEnergy(mPowerStats.stats, 0, uJtoUc(energyDelta, averageVoltage));
-
         mPowerStats.uidStats.clear();
-        if (energy != null) {
-            for (int i = energy.length - 1; i >= 0; i--) {
-                EnergyConsumerAttribution[] perUid = energy[i].attribution;
-                if (perUid == null) {
-                    continue;
-                }
 
-                for (EnergyConsumerAttribution attribution : perUid) {
-                    int uid = mUidResolver.mapUid(attribution.uid);
-                    long lastEnergy = mLastConsumerEnergyPerUid.get(uid, ENERGY_UNSPECIFIED);
-                    mLastConsumerEnergyPerUid.put(uid, attribution.energyUWs);
-                    if (lastEnergy == ENERGY_UNSPECIFIED) {
-                        continue;
-                    }
-                    long deltaEnergy = attribution.energyUWs - lastEnergy;
-                    if (deltaEnergy <= 0) {
-                        continue;
-                    }
-                    long[] uidStats = mPowerStats.uidStats.get(uid);
-                    if (uidStats == null) {
-                        uidStats = new long[mLayout.getUidStatsArrayLength()];
-                        mPowerStats.uidStats.put(uid, uidStats);
-                    }
-
-                    mLayout.setUidConsumedEnergy(uidStats, 0,
-                            mLayout.getUidConsumedEnergy(uidStats, 0)
-                                    + uJtoUc(deltaEnergy, averageVoltage));
-                }
-            }
+        if (!mConsumedEnergyHelper.collectConsumedEnergy(mPowerStats, mLayout)) {
+            return null;
         }
+
         long timestamp = mClock.elapsedRealtime();
         mPowerStats.durationMs = timestamp - mLastUpdateTimestamp;
         mLastUpdateTimestamp = timestamp;
-        mFirstCollection = false;
         return mPowerStats;
     }
-
-    @Override
-    protected void onUidRemoved(int uid) {
-        mLastConsumerEnergyPerUid.delete(uid);
-    }
 }
diff --git a/services/core/java/com/android/server/power/stats/GnssPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/GnssPowerStatsCollector.java
index 168a874..c1b4c31 100644
--- a/services/core/java/com/android/server/power/stats/GnssPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/GnssPowerStatsCollector.java
@@ -19,12 +19,13 @@
 import android.hardware.power.stats.EnergyConsumerType;
 import android.os.BatteryConsumer;
 
+import com.android.server.power.stats.format.GnssPowerStatsLayout;
+
 public class GnssPowerStatsCollector extends EnergyConsumerPowerStatsCollector {
 
-    GnssPowerStatsCollector(Injector injector) {
+    public GnssPowerStatsCollector(Injector injector) {
         super(injector, BatteryConsumer.POWER_COMPONENT_GNSS,
                 BatteryConsumer.powerComponentIdToString(BatteryConsumer.POWER_COMPONENT_GNSS),
-                EnergyConsumerType.GNSS, /* energy consumer name */ null,
-                new GnssPowerStatsLayout());
+                EnergyConsumerType.GNSS, new GnssPowerStatsLayout());
     }
 }
diff --git a/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsCollector.java
index c88e1b0..cbd6fab 100644
--- a/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsCollector.java
@@ -35,12 +35,12 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.Clock;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.MobileRadioPowerStatsLayout;
 
 import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
-import java.util.function.IntSupplier;
 import java.util.function.LongSupplier;
 import java.util.function.Supplier;
 
@@ -56,8 +56,6 @@
 
     private static final long MODEM_ACTIVITY_REQUEST_TIMEOUT = 20000;
 
-    private static final long ENERGY_UNSPECIFIED = -1;
-
     @VisibleForTesting
     @AccessNetworkConstants.RadioAccessNetworkType
     static final int[] NETWORK_TYPES = {
@@ -77,14 +75,13 @@
                 long elapsedRealtimeMs, long uptimeMs);
     }
 
-    interface Injector {
+    public interface Injector {
         Handler getHandler();
         Clock getClock();
         PowerStatsUidResolver getUidResolver();
         long getPowerStatsCollectionThrottlePeriod(String powerComponentName);
         PackageManager getPackageManager();
         ConsumedEnergyRetriever getConsumedEnergyRetriever();
-        IntSupplier getVoltageSupplier();
         Supplier<NetworkStats> getMobileNetworkStatsSupplier();
         TelephonyManager getTelephonyManager();
         LongSupplier getCallDurationSupplier();
@@ -103,18 +100,14 @@
     private LongSupplier mCallDurationSupplier;
     private LongSupplier mScanDurationSupplier;
     private volatile Supplier<NetworkStats> mNetworkStatsSupplier;
-    private ConsumedEnergyRetriever mConsumedEnergyRetriever;
-    private IntSupplier mVoltageSupplier;
-    private int[] mEnergyConsumerIds = new int[0];
+    private ConsumedEnergyHelper mConsumedEnergyHelper;
     private long mLastUpdateTimestampMillis;
     private ModemActivityInfo mLastModemActivityInfo;
     private NetworkStats mLastNetworkStats;
-    private long[] mLastConsumedEnergyUws;
-    private int mLastVoltageMv;
     private long mLastCallDuration;
     private long mLastScanDuration;
 
-    MobileRadioPowerStatsCollector(Injector injector, Observer observer) {
+    public MobileRadioPowerStatsCollector(Injector injector, Observer observer) {
         super(injector.getHandler(), injector.getPowerStatsCollectionThrottlePeriod(
                         BatteryConsumer.powerComponentIdToString(
                                 BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)),
@@ -144,34 +137,22 @@
             return false;
         }
 
-        mConsumedEnergyRetriever = mInjector.getConsumedEnergyRetriever();
-        mVoltageSupplier = mInjector.getVoltageSupplier();
-
         mTelephonyManager = mInjector.getTelephonyManager();
         mNetworkStatsSupplier = mInjector.getMobileNetworkStatsSupplier();
         mCallDurationSupplier = mInjector.getCallDurationSupplier();
         mScanDurationSupplier = mInjector.getPhoneSignalScanDurationSupplier();
 
-        mEnergyConsumerIds = mConsumedEnergyRetriever.getEnergyConsumerIds(
+        mConsumedEnergyHelper = new ConsumedEnergyHelper(mInjector.getConsumedEnergyRetriever(),
                 EnergyConsumerType.MOBILE_RADIO);
-        mLastConsumedEnergyUws = new long[mEnergyConsumerIds.length];
-        Arrays.fill(mLastConsumedEnergyUws, ENERGY_UNSPECIFIED);
 
-        mLayout = new MobileRadioPowerStatsLayout();
-        mLayout.addDeviceMobileActivity();
-        mLayout.addDeviceSectionEnergyConsumers(mEnergyConsumerIds.length);
-        mLayout.addStateStats();
-        mLayout.addUidNetworkStats();
-        mLayout.addDeviceSectionUsageDuration();
-        mLayout.addDeviceSectionPowerEstimate();
-        mLayout.addUidSectionPowerEstimate();
+        mLayout = new MobileRadioPowerStatsLayout(mConsumedEnergyHelper.getEnergyConsumerCount());
 
         SparseArray<String> stateLabels = new SparseArray<>();
         for (int rat = 0; rat < BatteryStats.RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
             final int freqCount = rat == BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR
                     ? ServiceState.FREQUENCY_RANGE_COUNT : 1;
             for (int freq = 0; freq < freqCount; freq++) {
-                int stateKey = makeStateKey(rat, freq);
+                int stateKey = MobileRadioPowerStatsLayout.makeStateKey(rat, freq);
                 StringBuilder sb = new StringBuilder();
                 if (rat != BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER) {
                     sb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
@@ -200,7 +181,7 @@
     }
 
     @Override
-    protected PowerStats collectStats() {
+    public PowerStats collectStats() {
         if (!ensureInitialized()) {
             return null;
         }
@@ -210,9 +191,8 @@
 
         ModemActivityInfo modemActivityDelta = collectModemActivityInfo();
         List<BatteryStatsImpl.NetworkStatsDelta> networkStatsDeltas = collectNetworkStats();
-        if (mEnergyConsumerIds.length != 0) {
-            collectEnergyConsumers();
-        }
+
+        mConsumedEnergyHelper.collectConsumedEnergy(mPowerStats, mLayout);
 
         if (mPowerStats.durationMs == 0) {
             setTimestamp(mClock.elapsedRealtime());
@@ -346,65 +326,8 @@
         return delta;
     }
 
-    private void collectEnergyConsumers() {
-        int voltageMv = mVoltageSupplier.getAsInt();
-        if (voltageMv <= 0) {
-            Slog.wtf(TAG, "Unexpected battery voltage (" + voltageMv
-                    + " mV) when querying energy consumers");
-            return;
-        }
-
-        int averageVoltage = mLastVoltageMv != 0 ? (mLastVoltageMv + voltageMv) / 2 : voltageMv;
-        mLastVoltageMv = voltageMv;
-
-        long[] energyUws = mConsumedEnergyRetriever.getConsumedEnergyUws(mEnergyConsumerIds);
-        if (energyUws == null) {
-            return;
-        }
-
-        for (int i = energyUws.length - 1; i >= 0; i--) {
-            long energyDelta = mLastConsumedEnergyUws[i] != ENERGY_UNSPECIFIED
-                    ? energyUws[i] - mLastConsumedEnergyUws[i] : 0;
-            if (energyDelta < 0) {
-                // Likely, restart of powerstats HAL
-                energyDelta = 0;
-            }
-            mLayout.setConsumedEnergy(mPowerStats.stats, i, uJtoUc(energyDelta, averageVoltage));
-            mLastConsumedEnergyUws[i] = energyUws[i];
-        }
-    }
-
-    static int makeStateKey(int rat, int freqRange) {
-        if (rat == BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR) {
-            return rat | (freqRange << 8);
-        } else {
-            return rat;
-        }
-    }
-
     private void setTimestamp(long timestamp) {
         mPowerStats.durationMs = Math.max(timestamp - mLastUpdateTimestampMillis, 0);
         mLastUpdateTimestampMillis = timestamp;
     }
-
-    @BatteryStats.RadioAccessTechnology
-    static int mapRadioAccessNetworkTypeToRadioAccessTechnology(
-            @AccessNetworkConstants.RadioAccessNetworkType int networkType) {
-        switch (networkType) {
-            case AccessNetworkConstants.AccessNetworkType.NGRAN:
-                return BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR;
-            case AccessNetworkConstants.AccessNetworkType.EUTRAN:
-                return BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE;
-            case AccessNetworkConstants.AccessNetworkType.UNKNOWN: //fallthrough
-            case AccessNetworkConstants.AccessNetworkType.GERAN: //fallthrough
-            case AccessNetworkConstants.AccessNetworkType.UTRAN: //fallthrough
-            case AccessNetworkConstants.AccessNetworkType.CDMA2000: //fallthrough
-            case AccessNetworkConstants.AccessNetworkType.IWLAN:
-                return BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER;
-            default:
-                Slog.w(TAG,
-                        "Unhandled RadioAccessNetworkType (" + networkType + "), mapping to OTHER");
-                return BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER;
-        }
-    }
 }
diff --git a/services/core/java/com/android/server/power/stats/PowerAttributor.java b/services/core/java/com/android/server/power/stats/PowerAttributor.java
new file mode 100644
index 0000000..d1f8564
--- /dev/null
+++ b/services/core/java/com/android/server/power/stats/PowerAttributor.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2024 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.power.stats;
+
+import android.os.BatteryConsumer;
+import android.os.BatteryUsageStats;
+import android.util.IndentingPrintWriter;
+
+import com.android.internal.os.BatteryStatsHistory;
+
+public interface PowerAttributor {
+
+    /**
+     * Returns true if the specified power component can be handled by this PowerAttributor
+     */
+    boolean isPowerComponentSupported(@BatteryConsumer.PowerComponentId int powerComponentId);
+
+    /**
+     * Performs the power attribution calculations and returns the results by populating the
+     * supplied BatteryUsageStats.Builder
+     */
+    void estimatePowerConsumption(BatteryUsageStats.Builder batteryUsageStatsBuilder,
+            BatteryStatsHistory batteryHistory, long monotonicStartTime, long monotonicEndTime);
+
+    /**
+     * Computes estimated power consumption attribution for the specified time range and stores
+     * it in PowerStatsStore for potential accumulation.
+     *
+     * Returns the monotonic timestamp of the last processed history item.
+     */
+    long storeEstimatedPowerConsumption(BatteryStatsHistory batteryStatsHistory, long startTime,
+            long endTimeMs);
+
+    /**
+     * Returns the monotonic timestamp of the last processed history item, stored in
+     * PowerStatsStore.
+     */
+    long getLastSavedEstimatesPowerConsumptionTimestamp();
+
+    /**
+     * Performs the power attribution calculation and prints the results.
+     */
+    void dumpEstimatedPowerConsumption(IndentingPrintWriter ipw,
+            BatteryStatsHistory batteryStatsHistory, long startTime, long endTime);
+}
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsCollector.java b/services/core/java/com/android/server/power/stats/PowerStatsCollector.java
index f5b0005..291f0e3 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsCollector.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.hardware.power.stats.EnergyConsumer;
+import android.hardware.power.stats.EnergyConsumerAttribution;
 import android.hardware.power.stats.EnergyConsumerResult;
 import android.hardware.power.stats.EnergyConsumerType;
 import android.os.ConditionVariable;
@@ -26,13 +27,16 @@
 import android.power.PowerStatsInternal;
 import android.util.IndentingPrintWriter;
 import android.util.Slog;
+import android.util.SparseLongArray;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.Clock;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.PowerStatsLayout;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
@@ -41,6 +45,7 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.function.Consumer;
+import java.util.function.IntSupplier;
 
 /**
  * Collects snapshots of power-related system statistics.
@@ -53,6 +58,8 @@
     private static final String TAG = "PowerStatsCollector";
     private static final int MILLIVOLTS_PER_VOLT = 1000;
     private static final long POWER_STATS_ENERGY_CONSUMERS_TIMEOUT = 20000;
+    private static final long ENERGY_UNSPECIFIED = -1;
+
     private final Handler mHandler;
     protected final PowerStatsUidResolver mUidResolver;
     protected final Clock mClock;
@@ -235,46 +242,31 @@
         return (deltaEnergyUj * MILLIVOLTS_PER_VOLT + (avgVoltageMv / 2)) / avgVoltageMv;
     }
 
-    interface ConsumedEnergyRetriever {
+    public interface ConsumedEnergyRetriever {
+
         @NonNull
-        int[] getEnergyConsumerIds(@EnergyConsumerType int energyConsumerType, String name);
+        int[] getEnergyConsumerIds(@EnergyConsumerType int energyConsumerType);
 
         String getEnergyConsumerName(int energyConsumerId);
 
         @Nullable
         EnergyConsumerResult[] getConsumedEnergy(int[] energyConsumerIds);
 
-        @Nullable
-        default long[] getConsumedEnergyUws(int[] energyConsumerIds) {
-            EnergyConsumerResult[] results = getConsumedEnergy(energyConsumerIds);
-            if (results == null) {
-                return null;
-            }
-
-            long[] energy = new long[energyConsumerIds.length];
-            for (int i = 0; i < energyConsumerIds.length; i++) {
-                int id = energyConsumerIds[i];
-                for (EnergyConsumerResult result : results) {
-                    if (result.id == id) {
-                        energy[i] = result.energyUWs;
-                        break;
-                    }
-                }
-            }
-            return energy;
-        }
-
-        default int[] getEnergyConsumerIds(@EnergyConsumerType int energyConsumerType) {
-            return getEnergyConsumerIds(energyConsumerType, null);
-        }
+        /**
+         * Returns the last known battery/charger voltage in milli-volts.
+         */
+        int getVoltageMv();
     }
 
     static class ConsumedEnergyRetrieverImpl implements ConsumedEnergyRetriever {
         private final PowerStatsInternal mPowerStatsInternal;
+        private final IntSupplier mVoltageSupplier;
         private EnergyConsumer[] mEnergyConsumers;
 
-        ConsumedEnergyRetrieverImpl(PowerStatsInternal powerStatsInternal) {
+        ConsumedEnergyRetrieverImpl(PowerStatsInternal powerStatsInternal,
+                IntSupplier voltageSupplier) {
             mPowerStatsInternal = powerStatsInternal;
+            mVoltageSupplier = voltageSupplier;
         }
 
         private void ensureEnergyConsumers() {
@@ -293,8 +285,9 @@
             }
         }
 
+        @NonNull
         @Override
-        public int[] getEnergyConsumerIds(int energyConsumerType, String name) {
+        public int[] getEnergyConsumerIds(int energyConsumerType) {
             ensureEnergyConsumers();
 
             if (mEnergyConsumers.length == 0) {
@@ -303,8 +296,7 @@
 
             List<EnergyConsumer> energyConsumers = new ArrayList<>();
             for (EnergyConsumer energyConsumer : mEnergyConsumers) {
-                if (energyConsumer.type == energyConsumerType
-                        && (name == null || name.equals(energyConsumer.name))) {
+                if (energyConsumer.type == energyConsumerType) {
                     energyConsumers.add(energyConsumer);
                 }
             }
@@ -335,6 +327,11 @@
         }
 
         @Override
+        public int getVoltageMv() {
+            return mVoltageSupplier.getAsInt();
+        }
+
+        @Override
         public String getEnergyConsumerName(int energyConsumerId) {
             ensureEnergyConsumers();
 
@@ -368,4 +365,152 @@
             return sb.toString();
         }
     }
+
+    class ConsumedEnergyHelper implements PowerStatsUidResolver.Listener {
+        private final ConsumedEnergyRetriever mConsumedEnergyRetriever;
+        private final @EnergyConsumerType int mEnergyConsumerType;
+        private final boolean mPerUidAttributionSupported;
+
+        private boolean mIsInitialized;
+        private boolean mFirstCollection = true;
+        private int[] mEnergyConsumerIds;
+        private long[] mLastConsumedEnergyUws;
+        private final SparseLongArray mLastConsumerEnergyPerUid;
+        private int mLastVoltageMv;
+
+        ConsumedEnergyHelper(ConsumedEnergyRetriever consumedEnergyRetriever,
+                @EnergyConsumerType int energyConsumerType) {
+            mConsumedEnergyRetriever = consumedEnergyRetriever;
+            mEnergyConsumerType = energyConsumerType;
+            mPerUidAttributionSupported = false;
+            mLastConsumerEnergyPerUid = null;
+        }
+
+        ConsumedEnergyHelper(ConsumedEnergyRetriever consumedEnergyRetriever,
+                int energyConsumerId, boolean perUidAttributionSupported) {
+            mConsumedEnergyRetriever = consumedEnergyRetriever;
+            mEnergyConsumerType = EnergyConsumerType.OTHER;
+            mEnergyConsumerIds = new int[]{energyConsumerId};
+            mPerUidAttributionSupported = perUidAttributionSupported;
+            mLastConsumerEnergyPerUid = mPerUidAttributionSupported ? new SparseLongArray() : null;
+        }
+
+        private void ensureInitialized() {
+            if (!mIsInitialized) {
+                if (mEnergyConsumerIds == null) {
+                    mEnergyConsumerIds = mConsumedEnergyRetriever.getEnergyConsumerIds(
+                            mEnergyConsumerType);
+                }
+                mLastConsumedEnergyUws = new long[mEnergyConsumerIds.length];
+                Arrays.fill(mLastConsumedEnergyUws, ENERGY_UNSPECIFIED);
+                mUidResolver.addListener(this);
+                mIsInitialized = true;
+            }
+        }
+
+        int getEnergyConsumerCount() {
+            ensureInitialized();
+            return mEnergyConsumerIds.length;
+        }
+
+        boolean collectConsumedEnergy(PowerStats powerStats, PowerStatsLayout layout) {
+            ensureInitialized();
+
+            if (mEnergyConsumerIds.length == 0) {
+                return false;
+            }
+
+            int voltageMv = mConsumedEnergyRetriever.getVoltageMv();
+            int averageVoltage = mLastVoltageMv != 0 ? (mLastVoltageMv + voltageMv) / 2 : voltageMv;
+            if (averageVoltage <= 0) {
+                Slog.wtf(TAG, "Unexpected battery voltage (" + voltageMv
+                        + " mV) when querying energy consumers");
+                return false;
+            }
+
+            mLastVoltageMv = voltageMv;
+
+            EnergyConsumerResult[] energy =
+                    mConsumedEnergyRetriever.getConsumedEnergy(mEnergyConsumerIds);
+            System.out.println("mEnergyConsumerIds = " + Arrays.toString(mEnergyConsumerIds) + " "
+                    + "energy = "
+                    + Arrays.toString(energy));
+            if (energy == null) {
+                return false;
+            }
+
+            for (int i = 0; i < mEnergyConsumerIds.length; i++) {
+                populatePowerStats(powerStats, layout, energy, i, averageVoltage);
+            }
+            mFirstCollection = false;
+            return true;
+        }
+
+        private void populatePowerStats(PowerStats powerStats, PowerStatsLayout layout,
+                @NonNull EnergyConsumerResult[] energy, int energyConsumerIndex,
+                int averageVoltage) {
+            long consumedEnergy = energy[energyConsumerIndex].energyUWs;
+            long energyDelta = mLastConsumedEnergyUws[energyConsumerIndex] != ENERGY_UNSPECIFIED
+                    ? consumedEnergy - mLastConsumedEnergyUws[energyConsumerIndex] : 0;
+            mLastConsumedEnergyUws[energyConsumerIndex] = consumedEnergy;
+            if (energyDelta < 0) {
+                // Likely, restart of powerstats HAL
+                energyDelta = 0;
+            }
+
+            if (energyDelta == 0 && !mFirstCollection) {
+                return;
+            }
+
+            layout.setConsumedEnergy(powerStats.stats, energyConsumerIndex,
+                    uJtoUc(energyDelta, averageVoltage));
+
+            if (!mPerUidAttributionSupported) {
+                return;
+            }
+
+            EnergyConsumerAttribution[] perUid = energy[energyConsumerIndex].attribution;
+            if (perUid == null) {
+                return;
+            }
+
+            for (EnergyConsumerAttribution attribution : perUid) {
+                int uid = mUidResolver.mapUid(attribution.uid);
+                long lastEnergy = mLastConsumerEnergyPerUid.get(uid, ENERGY_UNSPECIFIED);
+                mLastConsumerEnergyPerUid.put(uid, attribution.energyUWs);
+                if (lastEnergy == ENERGY_UNSPECIFIED) {
+                    continue;
+                }
+                long deltaEnergy = attribution.energyUWs - lastEnergy;
+                if (deltaEnergy <= 0) {
+                    continue;
+                }
+
+                long[] uidStats = powerStats.uidStats.get(uid);
+                if (uidStats == null) {
+                    uidStats = new long[layout.getUidStatsArrayLength()];
+                    powerStats.uidStats.put(uid, uidStats);
+                }
+
+                layout.setUidConsumedEnergy(uidStats, energyConsumerIndex,
+                        layout.getUidConsumedEnergy(uidStats, energyConsumerIndex)
+                                + uJtoUc(deltaEnergy, averageVoltage));
+            }
+        }
+
+        @Override
+        public void onAfterIsolatedUidRemoved(int isolatedUid, int parentUid) {
+            if (mLastConsumerEnergyPerUid != null) {
+                mHandler.post(() -> mLastConsumerEnergyPerUid.delete(isolatedUid));
+            }
+        }
+
+        @Override
+        public void onIsolatedUidAdded(int isolatedUid, int parentUid) {
+        }
+
+        @Override
+        public void onBeforeIsolatedUidRemoved(int isolatedUid, int parentUid) {
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsScheduler.java b/services/core/java/com/android/server/power/stats/PowerStatsScheduler.java
index abe4c0c..38ca087 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsScheduler.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsScheduler.java
@@ -23,6 +23,7 @@
 import android.util.IndentingPrintWriter;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BatteryStatsHistory;
 import com.android.internal.os.Clock;
 import com.android.internal.os.MonotonicClock;
 
@@ -51,7 +52,8 @@
     private final Handler mHandler;
     private final Runnable mPowerStatsCollector;
     private final Supplier<Long> mEarliestAvailableBatteryHistoryTimeMs;
-    private final PowerStatsAggregator mPowerStatsAggregator;
+    private final BatteryStatsHistory mBatteryStatsHistory;
+    private final PowerAttributor mPowerAttributor;
     private long mLastSavedSpanEndMonotonicTime;
 
     /**
@@ -66,12 +68,13 @@
     }
 
     public PowerStatsScheduler(Runnable powerStatsCollector,
-            PowerStatsAggregator powerStatsAggregator,
+            BatteryStatsHistory batteryStatsHistory, PowerAttributor powerAttributor,
             @DurationMillisLong long aggregatedPowerStatsSpanDuration,
             @DurationMillisLong long powerStatsAggregationPeriod, PowerStatsStore powerStatsStore,
             AlarmScheduler alarmScheduler, Clock clock, MonotonicClock monotonicClock,
             Supplier<Long> earliestAvailableBatteryHistoryTimeMs, Handler handler) {
-        mPowerStatsAggregator = powerStatsAggregator;
+        mBatteryStatsHistory = batteryStatsHistory;
+        mPowerAttributor = powerAttributor;
         mAggregatedPowerStatsSpanDuration = aggregatedPowerStatsSpanDuration;
         mPowerStatsAggregationPeriod = powerStatsAggregationPeriod;
         mPowerStatsStore = powerStatsStore;
@@ -123,12 +126,8 @@
         long endTimeMs = alignToWallClock(startTime + mAggregatedPowerStatsSpanDuration,
                 mAggregatedPowerStatsSpanDuration, currentMonotonicTime, currentTimeMillis);
         while (endTimeMs <= currentMonotonicTime) {
-            mPowerStatsAggregator.aggregatePowerStats(startTime, endTimeMs,
-                    stats -> {
-                        storeAggregatedPowerStats(stats);
-                        mLastSavedSpanEndMonotonicTime = stats.getStartTime() + stats.getDuration();
-                    });
-
+            mLastSavedSpanEndMonotonicTime = mPowerAttributor.storeEstimatedPowerConsumption(
+                    mBatteryStatsHistory, startTime, endTimeMs);
             startTime = endTimeMs;
             endTimeMs += mAggregatedPowerStatsSpanDuration;
         }
@@ -153,15 +152,8 @@
             mPowerStatsStore.dump(ipw);
             // Aggregate the remainder of power stats and dump the results without storing them yet.
             long powerStoreEndMonotonicTime = getLastSavedSpanEndMonotonicTime();
-            mPowerStatsAggregator.aggregatePowerStats(powerStoreEndMonotonicTime,
-                    MonotonicClock.UNDEFINED,
-                    stats -> {
-                        // Create a PowerStatsSpan for consistency of the textual output
-                        PowerStatsSpan span = PowerStatsStore.createPowerStatsSpan(stats);
-                        if (span != null) {
-                            span.dump(ipw);
-                        }
-                    });
+            mPowerAttributor.dumpEstimatedPowerConsumption(ipw, mBatteryStatsHistory,
+                    powerStoreEndMonotonicTime, MonotonicClock.UNDEFINED);
         });
 
         awaitCompletion();
@@ -223,28 +215,13 @@
     }
 
     private long getLastSavedSpanEndMonotonicTime() {
-        if (mLastSavedSpanEndMonotonicTime != 0) {
-            return mLastSavedSpanEndMonotonicTime;
-        }
-
-        mLastSavedSpanEndMonotonicTime = -1;
-        for (PowerStatsSpan.Metadata metadata : mPowerStatsStore.getTableOfContents()) {
-            if (metadata.getSections().contains(AggregatedPowerStatsSection.TYPE)) {
-                for (PowerStatsSpan.TimeFrame timeFrame : metadata.getTimeFrames()) {
-                    long endMonotonicTime = timeFrame.startMonotonicTime + timeFrame.duration;
-                    if (endMonotonicTime > mLastSavedSpanEndMonotonicTime) {
-                        mLastSavedSpanEndMonotonicTime = endMonotonicTime;
-                    }
-                }
-            }
+        if (mLastSavedSpanEndMonotonicTime == 0) {
+            mLastSavedSpanEndMonotonicTime =
+                    mPowerAttributor.getLastSavedEstimatesPowerConsumptionTimestamp();
         }
         return mLastSavedSpanEndMonotonicTime;
     }
 
-    private void storeAggregatedPowerStats(AggregatedPowerStats stats) {
-        mPowerStatsStore.storeAggregatedPowerStats(stats);
-    }
-
     private void awaitCompletion() {
         ConditionVariable done = new ConditionVariable();
         mHandler.post(done::open);
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsSpan.java b/services/core/java/com/android/server/power/stats/PowerStatsSpan.java
index 4df919d..fc0611f 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsSpan.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsSpan.java
@@ -44,6 +44,7 @@
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -72,7 +73,7 @@
     private static final DateTimeFormatter DATE_FORMAT =
             DateTimeFormatter.ofPattern("MM-dd HH:mm:ss.SSS").withZone(ZoneId.systemDefault());
 
-    static class TimeFrame {
+    public static class TimeFrame {
         public final long startMonotonicTime;
         @CurrentTimeMillisLong
         public final long startTime;
@@ -119,7 +120,7 @@
         }
     }
 
-    static class Metadata {
+    public static class Metadata {
         static final Comparator<Metadata> COMPARATOR = Comparator.comparing(Metadata::getId);
 
         private final long mId;
@@ -262,7 +263,7 @@
     public abstract static class Section {
         private final String mType;
 
-        Section(String type) {
+        protected Section(String type) {
             mType = type;
         }
 
@@ -274,7 +275,10 @@
             return mType;
         }
 
-        abstract void write(TypedXmlSerializer serializer) throws IOException;
+        /**
+         * Adds the contents of this section to the XML doc.
+         */
+        public abstract void write(TypedXmlSerializer serializer) throws IOException;
 
         /**
          * Prints the section type.
@@ -290,6 +294,11 @@
      */
     public interface SectionReader {
         /**
+         * Returns the unique type of content handled by this reader.
+         */
+        String getType();
+
+        /**
          * Reads the contents of the section using the parser. The type of the object
          * read and the corresponding XML format are determined by the section type.
          */
@@ -316,12 +325,18 @@
         return mMetadata.mId;
     }
 
-    void addTimeFrame(long monotonicTime, @CurrentTimeMillisLong long wallClockTime,
+    /**
+     * Adds a time frame covered by this PowerStats span
+     */
+    public void addTimeFrame(long monotonicTime, @CurrentTimeMillisLong long wallClockTime,
             @DurationMillisLong long duration) {
         mMetadata.mTimeFrames.add(new TimeFrame(monotonicTime, wallClockTime, duration));
     }
 
-    void addSection(Section section) {
+    /**
+     * Adds the supplied section to the span.
+     */
+    public void addSection(Section section) {
         mMetadata.addSection(section.getType());
         mSections.add(section);
     }
@@ -354,7 +369,7 @@
 
     @Nullable
     static PowerStatsSpan read(InputStream in, TypedXmlPullParser parser,
-            SectionReader sectionReader, String... sectionTypes)
+            Map<String, SectionReader> sectionReaders, String... sectionTypes)
             throws IOException, XmlPullParserException {
         Set<String> neededSections = Sets.newArraySet(sectionTypes);
         boolean selectSections = !neededSections.isEmpty();
@@ -386,7 +401,11 @@
                 if (tag.equals(XML_TAG_SECTION)) {
                     String sectionType = parser.getAttributeValue(null, XML_ATTR_SECTION_TYPE);
                     if (!selectSections || neededSections.contains(sectionType)) {
-                        Section section = sectionReader.read(sectionType, parser);
+                        Section section = null;
+                        SectionReader sectionReader = sectionReaders.get(sectionType);
+                        if (sectionReader != null) {
+                            section = sectionReader.read(sectionType, parser);
+                        }
                         if (section == null) {
                             if (selectSections) {
                                 throw new XmlPullParserException(
@@ -396,11 +415,11 @@
                                     @Override
                                     public void dump(IndentingPrintWriter ipw) {
                                         ipw.println("Unsupported PowerStatsStore section type: "
-                                                    + sectionType);
+                                                + sectionType);
                                     }
 
                                     @Override
-                                    void write(TypedXmlSerializer serializer) {
+                                    public void write(TypedXmlSerializer serializer) {
                                     }
                                 };
                             }
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsStore.java b/services/core/java/com/android/server/power/stats/PowerStatsStore.java
index 7bcdc71..a875c30 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsStore.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsStore.java
@@ -42,6 +42,7 @@
 import java.nio.file.StandardOpenOption;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -66,28 +67,31 @@
     private FileLock mJvmLock;
     private final long mMaxStorageBytes;
     private final Handler mHandler;
-    private final PowerStatsSpan.SectionReader mSectionReader;
+    private final Map<String, PowerStatsSpan.SectionReader> mSectionReaders = new HashMap<>();
     private volatile List<PowerStatsSpan.Metadata> mTableOfContents;
 
-    public PowerStatsStore(@NonNull File systemDir, Handler handler,
-            AggregatedPowerStatsConfig aggregatedPowerStatsConfig) {
-        this(systemDir, MAX_POWER_STATS_SPAN_STORAGE_BYTES, handler,
-                new DefaultSectionReader(aggregatedPowerStatsConfig));
+    public PowerStatsStore(@NonNull File systemDir, Handler handler) {
+        this(systemDir, MAX_POWER_STATS_SPAN_STORAGE_BYTES, handler);
     }
 
     @VisibleForTesting
-    public PowerStatsStore(@NonNull File systemDir, long maxStorageBytes, Handler handler,
-            @NonNull PowerStatsSpan.SectionReader sectionReader) {
+    public PowerStatsStore(@NonNull File systemDir, long maxStorageBytes, Handler handler) {
         mSystemDir = systemDir;
         mStoreDir = new File(systemDir, POWER_STATS_DIR);
         mLockFile = new File(mStoreDir, DIR_LOCK_FILENAME);
         mHandler = handler;
         mMaxStorageBytes = maxStorageBytes;
-        mSectionReader = sectionReader;
         mHandler.post(this::maybeClearLegacyStore);
     }
 
     /**
+     * Registers a Reader for a section type, which is determined by `sectionReader.getType()`
+     */
+    public void addSectionReader(PowerStatsSpan.SectionReader sectionReader) {
+        mSectionReaders.put(sectionReader.getType(), sectionReader);
+    }
+
+    /**
      * Returns the metadata for all {@link PowerStatsSpan}'s contained in the store.
      */
     @NonNull
@@ -169,7 +173,7 @@
         try {
             File file = makePowerStatsSpanFilename(id);
             try (InputStream inputStream = new BufferedInputStream(new FileInputStream(file))) {
-                return PowerStatsSpan.read(inputStream, parser, mSectionReader, sectionTypes);
+                return PowerStatsSpan.read(inputStream, parser, mSectionReaders, sectionTypes);
             } catch (IOException | XmlPullParserException e) {
                 Slog.wtf(TAG, "Cannot read PowerStatsSpan file: " + file, e);
             }
@@ -179,41 +183,6 @@
         return null;
     }
 
-    void storeAggregatedPowerStats(AggregatedPowerStats stats) {
-        PowerStatsSpan span = createPowerStatsSpan(stats);
-        if (span == null) {
-            return;
-        }
-        storePowerStatsSpan(span);
-    }
-
-    static PowerStatsSpan createPowerStatsSpan(AggregatedPowerStats stats) {
-        List<AggregatedPowerStats.ClockUpdate> clockUpdates = stats.getClockUpdates();
-        if (clockUpdates.isEmpty()) {
-            Slog.w(TAG, "No clock updates in aggregated power stats " + stats);
-            return null;
-        }
-
-        long monotonicTime = clockUpdates.get(0).monotonicTime;
-        long durationSum = 0;
-        PowerStatsSpan span = new PowerStatsSpan(monotonicTime);
-        for (int i = 0; i < clockUpdates.size(); i++) {
-            AggregatedPowerStats.ClockUpdate clockUpdate = clockUpdates.get(i);
-            long duration;
-            if (i == clockUpdates.size() - 1) {
-                duration = stats.getDuration() - durationSum;
-            } else {
-                duration = clockUpdate.monotonicTime - monotonicTime;
-            }
-            span.addTimeFrame(clockUpdate.monotonicTime, clockUpdate.currentTime, duration);
-            monotonicTime = clockUpdate.monotonicTime;
-            durationSum += duration;
-        }
-
-        span.addSection(new AggregatedPowerStatsSection(stats));
-        return span;
-    }
-
     /**
      * Stores a {@link PowerStatsSpan} containing a single section for the supplied
      * battery usage stats.
@@ -344,28 +313,4 @@
         }
         ipw.decreaseIndent();
     }
-
-    private static class DefaultSectionReader implements PowerStatsSpan.SectionReader {
-        private final AggregatedPowerStatsConfig mAggregatedPowerStatsConfig;
-
-        DefaultSectionReader(AggregatedPowerStatsConfig aggregatedPowerStatsConfig) {
-            mAggregatedPowerStatsConfig = aggregatedPowerStatsConfig;
-        }
-
-        @Override
-        public PowerStatsSpan.Section read(String sectionType, TypedXmlPullParser parser)
-                throws IOException, XmlPullParserException {
-            switch (sectionType) {
-                case AggregatedPowerStatsSection.TYPE:
-                    return new AggregatedPowerStatsSection(
-                            AggregatedPowerStats.createFromXml(parser,
-                                    mAggregatedPowerStatsConfig));
-                case BatteryUsageStatsSection.TYPE:
-                    return new BatteryUsageStatsSection(
-                            BatteryUsageStats.createFromXml(parser));
-                default:
-                    return null;
-            }
-        }
-    }
 }
diff --git a/services/core/java/com/android/server/power/stats/ScreenPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/ScreenPowerStatsCollector.java
index 291f289..8371e66 100644
--- a/services/core/java/com/android/server/power/stats/ScreenPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/ScreenPowerStatsCollector.java
@@ -21,19 +21,16 @@
 import android.os.BatteryStats;
 import android.os.Handler;
 import android.os.PersistableBundle;
-import android.util.Slog;
 import android.util.SparseLongArray;
 
 import com.android.internal.os.Clock;
 import com.android.internal.os.PowerStats;
-
-import java.util.Arrays;
-import java.util.function.IntSupplier;
+import com.android.server.power.stats.format.ScreenPowerStatsLayout;
 
 public class ScreenPowerStatsCollector extends PowerStatsCollector {
     private static final String TAG = "ScreenPowerStatsCollector";
 
-    interface ScreenUsageTimeRetriever {
+    public interface ScreenUsageTimeRetriever {
         interface Callback {
             void onUidTopActivityTime(int uid, long topActivityTimeMs);
         }
@@ -45,30 +42,23 @@
         long getScreenDozeTimeMs(int display);
     }
 
-    interface Injector {
+    public interface Injector {
         Handler getHandler();
         Clock getClock();
         PowerStatsUidResolver getUidResolver();
         long getPowerStatsCollectionThrottlePeriod(String powerComponentName);
         ConsumedEnergyRetriever getConsumedEnergyRetriever();
-        IntSupplier getVoltageSupplier();
         ScreenUsageTimeRetriever getScreenUsageTimeRetriever();
         int getDisplayCount();
     }
 
-    private static final long ENERGY_UNSPECIFIED = -1;
-
     private final Injector mInjector;
     private boolean mIsInitialized;
     private ScreenPowerStatsLayout mLayout;
     private int mDisplayCount;
     private PowerStats mPowerStats;
-    private ConsumedEnergyRetriever mConsumedEnergyRetriever;
-    private IntSupplier mVoltageSupplier;
+    private ConsumedEnergyHelper mConsumedEnergyHelper;
     private ScreenUsageTimeRetriever mScreenUsageTimeRetriever;
-    private int[] mEnergyConsumerIds = new int[0];
-    private long[] mLastConsumedEnergyUws;
-    private int mLastVoltageMv;
     private boolean mFirstSample = true;
     private long[] mLastScreenOnTime;
     private long[][] mLastBrightnessLevelTime;
@@ -76,7 +66,7 @@
     private final SparseLongArray mLastTopActivityTime = new SparseLongArray();
     private long mLastCollectionTime;
 
-    ScreenPowerStatsCollector(Injector injector) {
+    public ScreenPowerStatsCollector(Injector injector) {
         super(injector.getHandler(),
                 injector.getPowerStatsCollectionThrottlePeriod(
                         BatteryConsumer.powerComponentIdToString(
@@ -95,21 +85,12 @@
         }
 
         mDisplayCount = mInjector.getDisplayCount();
-        mConsumedEnergyRetriever = mInjector.getConsumedEnergyRetriever();
-        mVoltageSupplier = mInjector.getVoltageSupplier();
         mScreenUsageTimeRetriever = mInjector.getScreenUsageTimeRetriever();
-        mEnergyConsumerIds = mConsumedEnergyRetriever.getEnergyConsumerIds(
-                EnergyConsumerType.DISPLAY);
-        mLastConsumedEnergyUws = new long[mEnergyConsumerIds.length];
-        Arrays.fill(mLastConsumedEnergyUws, ENERGY_UNSPECIFIED);
 
-        mLayout = new ScreenPowerStatsLayout();
-        mLayout.addDeviceScreenUsageDurationSection(mInjector.getDisplayCount());
-        mLayout.addDeviceSectionEnergyConsumers(mEnergyConsumerIds.length);
-        mLayout.addDeviceSectionUsageDuration();
-        mLayout.addDeviceSectionPowerEstimate();
-        mLayout.addUidTopActivitiyDuration();
-        mLayout.addUidSectionPowerEstimate();
+        mConsumedEnergyHelper = new ConsumedEnergyHelper(mInjector.getConsumedEnergyRetriever(),
+                EnergyConsumerType.DISPLAY);
+        mLayout = new ScreenPowerStatsLayout(mConsumedEnergyHelper.getEnergyConsumerCount(),
+                mInjector.getDisplayCount());
 
         PersistableBundle extras = new PersistableBundle();
         mLayout.toExtras(extras);
@@ -129,14 +110,12 @@
     }
 
     @Override
-    protected PowerStats collectStats() {
+    public PowerStats collectStats() {
         if (!ensureInitialized()) {
             return null;
         }
 
-        if (mEnergyConsumerIds.length != 0) {
-            collectEnergyConsumers();
-        }
+        mConsumedEnergyHelper.collectConsumedEnergy(mPowerStats, mLayout);
 
         for (int display = 0; display < mDisplayCount; display++) {
             long screenOnTimeMs = mScreenUsageTimeRetriever.getScreenOnTimeMs(display);
@@ -192,34 +171,6 @@
         return mPowerStats;
     }
 
-    private void collectEnergyConsumers() {
-        int voltageMv = mVoltageSupplier.getAsInt();
-        if (voltageMv <= 0) {
-            Slog.wtf(TAG, "Unexpected battery voltage (" + voltageMv
-                    + " mV) when querying energy consumers");
-            return;
-        }
-
-        int averageVoltage = mLastVoltageMv != 0 ? (mLastVoltageMv + voltageMv) / 2 : voltageMv;
-        mLastVoltageMv = voltageMv;
-
-        long[] energyUws = mConsumedEnergyRetriever.getConsumedEnergyUws(mEnergyConsumerIds);
-        if (energyUws == null) {
-            return;
-        }
-
-        for (int i = energyUws.length - 1; i >= 0; i--) {
-            long energyDelta = mLastConsumedEnergyUws[i] != ENERGY_UNSPECIFIED
-                    ? energyUws[i] - mLastConsumedEnergyUws[i] : 0;
-            if (energyDelta < 0) {
-                // Likely, restart of powerstats HAL
-                energyDelta = 0;
-            }
-            mLayout.setConsumedEnergy(mPowerStats.stats, i, uJtoUc(energyDelta, averageVoltage));
-            mLastConsumedEnergyUws[i] = energyUws[i];
-        }
-    }
-
     @Override
     protected void onUidRemoved(int uid) {
         mLastTopActivityTime.delete(uid);
diff --git a/services/core/java/com/android/server/power/stats/WifiPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/WifiPowerStatsCollector.java
index 90981ada..7a84b05 100644
--- a/services/core/java/com/android/server/power/stats/WifiPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/WifiPowerStatsCollector.java
@@ -28,12 +28,11 @@
 
 import com.android.internal.os.Clock;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.WifiPowerStatsLayout;
 
-import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
-import java.util.function.IntSupplier;
 import java.util.function.Supplier;
 
 public class WifiPowerStatsCollector extends PowerStatsCollector {
@@ -41,15 +40,13 @@
 
     private static final long WIFI_ACTIVITY_REQUEST_TIMEOUT = 20000;
 
-    private static final long ENERGY_UNSPECIFIED = -1;
-
     interface Observer {
         void onWifiPowerStatsRetrieved(WifiActivityEnergyInfo info,
                 List<BatteryStatsImpl.NetworkStatsDelta> delta, long elapsedRealtimeMs,
                 long uptimeMs);
     }
 
-    interface WifiStatsRetriever {
+    public interface WifiStatsRetriever {
         interface Callback {
             void onWifiScanTime(int uid, long scanTimeMs, long batchScanTimeMs);
         }
@@ -58,14 +55,13 @@
         long getWifiActiveDuration();
     }
 
-    interface Injector {
+    public interface Injector {
         Handler getHandler();
         Clock getClock();
         PowerStatsUidResolver getUidResolver();
         long getPowerStatsCollectionThrottlePeriod(String powerComponentName);
         PackageManager getPackageManager();
         ConsumedEnergyRetriever getConsumedEnergyRetriever();
-        IntSupplier getVoltageSupplier();
         Supplier<NetworkStats> getWifiNetworkStatsSupplier();
         WifiManager getWifiManager();
         WifiStatsRetriever getWifiStatsRetriever();
@@ -83,13 +79,9 @@
     private volatile WifiManager mWifiManager;
     private volatile Supplier<NetworkStats> mNetworkStatsSupplier;
     private volatile WifiStatsRetriever mWifiStatsRetriever;
-    private ConsumedEnergyRetriever mConsumedEnergyRetriever;
-    private IntSupplier mVoltageSupplier;
-    private int[] mEnergyConsumerIds = new int[0];
+    private ConsumedEnergyHelper mConsumedEnergyHelper;
     private WifiActivityEnergyInfo mLastWifiActivityInfo;
     private NetworkStats mLastNetworkStats;
-    private long[] mLastConsumedEnergyUws;
-    private int mLastVoltageMv;
 
     private static class WifiScanTimes {
         public long basicScanTimeMs;
@@ -99,7 +91,7 @@
     private final SparseArray<WifiScanTimes> mLastScanTimes = new SparseArray<>();
     private long mLastWifiActiveDuration;
 
-    WifiPowerStatsCollector(Injector injector, Observer observer) {
+    public WifiPowerStatsCollector(Injector injector, Observer observer) {
         super(injector.getHandler(), injector.getPowerStatsCollectionThrottlePeriod(
                         BatteryConsumer.powerComponentIdToString(
                                 BatteryConsumer.POWER_COMPONENT_WIFI)),
@@ -128,25 +120,17 @@
             return false;
         }
 
-        mConsumedEnergyRetriever = mInjector.getConsumedEnergyRetriever();
-        mVoltageSupplier = mInjector.getVoltageSupplier();
         mWifiManager = mInjector.getWifiManager();
         mNetworkStatsSupplier = mInjector.getWifiNetworkStatsSupplier();
         mWifiStatsRetriever = mInjector.getWifiStatsRetriever();
         mPowerReportingSupported =
                 mWifiManager != null && mWifiManager.isEnhancedPowerReportingSupported();
 
-        mEnergyConsumerIds = mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.WIFI);
-        mLastConsumedEnergyUws = new long[mEnergyConsumerIds.length];
-        Arrays.fill(mLastConsumedEnergyUws, ENERGY_UNSPECIFIED);
+        mConsumedEnergyHelper = new ConsumedEnergyHelper(mInjector.getConsumedEnergyRetriever(),
+                EnergyConsumerType.WIFI);
 
-        mLayout = new WifiPowerStatsLayout();
-        mLayout.addDeviceWifiActivity(mPowerReportingSupported);
-        mLayout.addDeviceSectionEnergyConsumers(mEnergyConsumerIds.length);
-        mLayout.addUidNetworkStats();
-        mLayout.addDeviceSectionUsageDuration();
-        mLayout.addDeviceSectionPowerEstimate();
-        mLayout.addUidSectionPowerEstimate();
+        mLayout = new WifiPowerStatsLayout(mConsumedEnergyHelper.getEnergyConsumerCount(),
+                mPowerReportingSupported);
 
         PersistableBundle extras = new PersistableBundle();
         mLayout.toExtras(extras);
@@ -162,7 +146,7 @@
     }
 
     @Override
-    protected PowerStats collectStats() {
+    public PowerStats collectStats() {
         if (!ensureInitialized()) {
             return null;
         }
@@ -176,9 +160,7 @@
         List<BatteryStatsImpl.NetworkStatsDelta> networkStatsDeltas = collectNetworkStats();
         collectWifiScanTime();
 
-        if (mEnergyConsumerIds.length != 0) {
-            collectEnergyConsumers();
-        }
+        mConsumedEnergyHelper.collectConsumedEnergy(mPowerStats, mLayout);
 
         if (mObserver != null) {
             mObserver.onWifiPowerStatsRetrieved(activityInfo, networkStatsDeltas,
@@ -318,34 +300,6 @@
         mLayout.setDeviceBatchedScanTime(mDeviceStats, mScanTimes.batchedScanTimeMs);
     }
 
-    private void collectEnergyConsumers() {
-        int voltageMv = mVoltageSupplier.getAsInt();
-        if (voltageMv <= 0) {
-            Slog.wtf(TAG, "Unexpected battery voltage (" + voltageMv
-                    + " mV) when querying energy consumers");
-            return;
-        }
-
-        int averageVoltage = mLastVoltageMv != 0 ? (mLastVoltageMv + voltageMv) / 2 : voltageMv;
-        mLastVoltageMv = voltageMv;
-
-        long[] energyUws = mConsumedEnergyRetriever.getConsumedEnergyUws(mEnergyConsumerIds);
-        if (energyUws == null) {
-            return;
-        }
-
-        for (int i = energyUws.length - 1; i >= 0; i--) {
-            long energyDelta = mLastConsumedEnergyUws[i] != ENERGY_UNSPECIFIED
-                    ? energyUws[i] - mLastConsumedEnergyUws[i] : 0;
-            if (energyDelta < 0) {
-                // Likely, restart of powerstats HAL
-                energyDelta = 0;
-            }
-            mLayout.setConsumedEnergy(mPowerStats.stats, i, uJtoUc(energyDelta, averageVoltage));
-            mLastConsumedEnergyUws[i] = energyUws[i];
-        }
-    }
-
     @Override
     protected void onUidRemoved(int uid) {
         super.onUidRemoved(uid);
diff --git a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/AmbientDisplayPowerStatsLayout.java
similarity index 72%
copy from services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java
copy to services/core/java/com/android/server/power/stats/format/AmbientDisplayPowerStatsLayout.java
index 502337c..1b99b0d 100644
--- a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/AmbientDisplayPowerStatsLayout.java
@@ -13,12 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.server.power.stats.format;
 
-package com.android.server.power.stats;
-
-class BinaryStatePowerStatsLayout extends EnergyConsumerPowerStatsLayout {
-    BinaryStatePowerStatsLayout() {
-        addDeviceSectionUsageDuration();
-        addUidSectionUsageDuration();
+public class AmbientDisplayPowerStatsLayout extends PowerStatsLayout {
+    public AmbientDisplayPowerStatsLayout() {
+        addDeviceSectionPowerEstimate();
     }
 }
diff --git a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/BinaryStatePowerStatsLayout.java
similarity index 68%
copy from services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java
copy to services/core/java/com/android/server/power/stats/format/BinaryStatePowerStatsLayout.java
index 502337c..4a26d83 100644
--- a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/BinaryStatePowerStatsLayout.java
@@ -14,11 +14,17 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.format;
 
-class BinaryStatePowerStatsLayout extends EnergyConsumerPowerStatsLayout {
-    BinaryStatePowerStatsLayout() {
+import com.android.internal.os.PowerStats;
+
+public class BinaryStatePowerStatsLayout extends EnergyConsumerPowerStatsLayout {
+    public BinaryStatePowerStatsLayout() {
         addDeviceSectionUsageDuration();
         addUidSectionUsageDuration();
     }
+
+    public BinaryStatePowerStatsLayout(PowerStats.Descriptor descriptor) {
+        super(descriptor);
+    }
 }
diff --git a/services/core/java/com/android/server/power/stats/BluetoothPowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/BluetoothPowerStatsLayout.java
similarity index 88%
rename from services/core/java/com/android/server/power/stats/BluetoothPowerStatsLayout.java
rename to services/core/java/com/android/server/power/stats/format/BluetoothPowerStatsLayout.java
index 9358b5e..534a9f7 100644
--- a/services/core/java/com/android/server/power/stats/BluetoothPowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/BluetoothPowerStatsLayout.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.server.power.stats;
+package com.android.server.power.stats.format;
 
 import android.annotation.NonNull;
 import android.os.PersistableBundle;
@@ -37,21 +37,49 @@
     private int mUidTxBytesPosition;
     private int mUidScanTimePosition;
 
-    BluetoothPowerStatsLayout() {
+    public BluetoothPowerStatsLayout(int energyConsumerCount) {
+        addDeviceBluetoothControllerActivity();
+        addDeviceSectionEnergyConsumers(energyConsumerCount);
+        addDeviceSectionUsageDuration();
+        addDeviceSectionPowerEstimate();
+        addUidTrafficStats();
+        addUidSectionPowerEstimate();
     }
 
-    BluetoothPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) {
+    public BluetoothPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) {
         super(descriptor);
+        PersistableBundle extras = descriptor.extras;
+        mDeviceRxTimePosition = extras.getInt(EXTRA_DEVICE_RX_TIME_POSITION);
+        mDeviceTxTimePosition = extras.getInt(EXTRA_DEVICE_TX_TIME_POSITION);
+        mDeviceIdleTimePosition = extras.getInt(EXTRA_DEVICE_IDLE_TIME_POSITION);
+        mDeviceScanTimePosition = extras.getInt(EXTRA_DEVICE_SCAN_TIME_POSITION);
+        mUidRxBytesPosition = extras.getInt(EXTRA_UID_RX_BYTES_POSITION);
+        mUidTxBytesPosition = extras.getInt(EXTRA_UID_TX_BYTES_POSITION);
+        mUidScanTimePosition = extras.getInt(EXTRA_UID_SCAN_TIME_POSITION);
     }
 
-    void addDeviceBluetoothControllerActivity() {
+    /**
+     * Copies the elements of the stats array layout into <code>extras</code>
+     */
+    public void toExtras(PersistableBundle extras) {
+        super.toExtras(extras);
+        extras.putInt(EXTRA_DEVICE_RX_TIME_POSITION, mDeviceRxTimePosition);
+        extras.putInt(EXTRA_DEVICE_TX_TIME_POSITION, mDeviceTxTimePosition);
+        extras.putInt(EXTRA_DEVICE_IDLE_TIME_POSITION, mDeviceIdleTimePosition);
+        extras.putInt(EXTRA_DEVICE_SCAN_TIME_POSITION, mDeviceScanTimePosition);
+        extras.putInt(EXTRA_UID_RX_BYTES_POSITION, mUidRxBytesPosition);
+        extras.putInt(EXTRA_UID_TX_BYTES_POSITION, mUidTxBytesPosition);
+        extras.putInt(EXTRA_UID_SCAN_TIME_POSITION, mUidScanTimePosition);
+    }
+
+    private void addDeviceBluetoothControllerActivity() {
         mDeviceRxTimePosition = addDeviceSection(1, "rx");
         mDeviceTxTimePosition = addDeviceSection(1, "tx");
         mDeviceIdleTimePosition = addDeviceSection(1, "idle");
         mDeviceScanTimePosition = addDeviceSection(1, "scan", FLAG_OPTIONAL);
     }
 
-    void addUidTrafficStats() {
+    private void addUidTrafficStats() {
         mUidRxBytesPosition = addUidSection(1, "rx-B");
         mUidTxBytesPosition = addUidSection(1, "tx-B");
         mUidScanTimePosition = addUidSection(1, "scan", FLAG_OPTIONAL);
@@ -112,32 +140,4 @@
     public long getUidScanTime(long[] stats) {
         return stats[mUidScanTimePosition];
     }
-
-    /**
-     * Copies the elements of the stats array layout into <code>extras</code>
-     */
-    public void toExtras(PersistableBundle extras) {
-        super.toExtras(extras);
-        extras.putInt(EXTRA_DEVICE_RX_TIME_POSITION, mDeviceRxTimePosition);
-        extras.putInt(EXTRA_DEVICE_TX_TIME_POSITION, mDeviceTxTimePosition);
-        extras.putInt(EXTRA_DEVICE_IDLE_TIME_POSITION, mDeviceIdleTimePosition);
-        extras.putInt(EXTRA_DEVICE_SCAN_TIME_POSITION, mDeviceScanTimePosition);
-        extras.putInt(EXTRA_UID_RX_BYTES_POSITION, mUidRxBytesPosition);
-        extras.putInt(EXTRA_UID_TX_BYTES_POSITION, mUidTxBytesPosition);
-        extras.putInt(EXTRA_UID_SCAN_TIME_POSITION, mUidScanTimePosition);
-    }
-
-    /**
-     * Retrieves elements of the stats array layout from <code>extras</code>
-     */
-    public void fromExtras(PersistableBundle extras) {
-        super.fromExtras(extras);
-        mDeviceRxTimePosition = extras.getInt(EXTRA_DEVICE_RX_TIME_POSITION);
-        mDeviceTxTimePosition = extras.getInt(EXTRA_DEVICE_TX_TIME_POSITION);
-        mDeviceIdleTimePosition = extras.getInt(EXTRA_DEVICE_IDLE_TIME_POSITION);
-        mDeviceScanTimePosition = extras.getInt(EXTRA_DEVICE_SCAN_TIME_POSITION);
-        mUidRxBytesPosition = extras.getInt(EXTRA_UID_RX_BYTES_POSITION);
-        mUidTxBytesPosition = extras.getInt(EXTRA_UID_TX_BYTES_POSITION);
-        mUidScanTimePosition = extras.getInt(EXTRA_UID_SCAN_TIME_POSITION);
-    }
 }
diff --git a/services/core/java/com/android/server/power/stats/CpuPowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/CpuPowerStatsLayout.java
similarity index 85%
rename from services/core/java/com/android/server/power/stats/CpuPowerStatsLayout.java
rename to services/core/java/com/android/server/power/stats/format/CpuPowerStatsLayout.java
index 2a02bd0..3186d7d 100644
--- a/services/core/java/com/android/server/power/stats/CpuPowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/CpuPowerStatsLayout.java
@@ -14,10 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.format;
 
+import android.annotation.NonNull;
 import android.os.PersistableBundle;
 
+import com.android.internal.os.PowerStats;
+
 /**
  * Captures the positions and lengths of sections of the stats array, such as time-in-state,
  * power usage estimates etc.
@@ -40,10 +43,59 @@
 
     private int[] mScalingStepToPowerBracketMap;
 
+    public CpuPowerStatsLayout(int energyConsumerCount, int cpuScalingPolicyCount,
+            int[] scalingStepToPowerBracketMap) {
+        addDeviceSectionCpuTimeByScalingStep(scalingStepToPowerBracketMap.length);
+        addDeviceSectionCpuTimeByCluster(cpuScalingPolicyCount);
+        addDeviceSectionUsageDuration();
+        addDeviceSectionEnergyConsumers(energyConsumerCount);
+        addDeviceSectionPowerEstimate();
+        addUidSectionCpuTimeByPowerBracket(scalingStepToPowerBracketMap);
+        addUidSectionPowerEstimate();
+    }
+
+    public CpuPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) {
+        super(descriptor);
+        PersistableBundle extras = descriptor.extras;
+        mDeviceCpuTimeByScalingStepPosition =
+                extras.getInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_POSITION);
+        mDeviceCpuTimeByScalingStepCount =
+                extras.getInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_COUNT);
+        mDeviceCpuTimeByClusterPosition =
+                extras.getInt(EXTRA_DEVICE_TIME_BY_CLUSTER_POSITION);
+        mDeviceCpuTimeByClusterCount =
+                extras.getInt(EXTRA_DEVICE_TIME_BY_CLUSTER_COUNT);
+        mUidPowerBracketsPosition = extras.getInt(EXTRA_UID_BRACKETS_POSITION);
+        mScalingStepToPowerBracketMap =
+                getIntArray(extras, EXTRA_UID_STATS_SCALING_STEP_TO_POWER_BRACKET);
+        if (mScalingStepToPowerBracketMap == null) {
+            mScalingStepToPowerBracketMap = new int[mDeviceCpuTimeByScalingStepCount];
+        }
+        updatePowerBracketCount();
+    }
+
+    /**
+     * Copies the elements of the stats array layout into <code>extras</code>
+     */
+    public void toExtras(PersistableBundle extras) {
+        super.toExtras(extras);
+        extras.putInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_POSITION,
+                mDeviceCpuTimeByScalingStepPosition);
+        extras.putInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_COUNT,
+                mDeviceCpuTimeByScalingStepCount);
+        extras.putInt(EXTRA_DEVICE_TIME_BY_CLUSTER_POSITION,
+                mDeviceCpuTimeByClusterPosition);
+        extras.putInt(EXTRA_DEVICE_TIME_BY_CLUSTER_COUNT,
+                mDeviceCpuTimeByClusterCount);
+        extras.putInt(EXTRA_UID_BRACKETS_POSITION, mUidPowerBracketsPosition);
+        putIntArray(extras, EXTRA_UID_STATS_SCALING_STEP_TO_POWER_BRACKET,
+                mScalingStepToPowerBracketMap);
+    }
+
     /**
      * Declare that the stats array has a section capturing CPU time per scaling step
      */
-    public void addDeviceSectionCpuTimeByScalingStep(int scalingStepCount) {
+    private void addDeviceSectionCpuTimeByScalingStep(int scalingStepCount) {
         mDeviceCpuTimeByScalingStepPosition = addDeviceSection(scalingStepCount, "steps");
         mDeviceCpuTimeByScalingStepCount = scalingStepCount;
     }
@@ -71,7 +123,7 @@
     /**
      * Declare that the stats array has a section capturing CPU time in each cluster
      */
-    public void addDeviceSectionCpuTimeByCluster(int clusterCount) {
+    private void addDeviceSectionCpuTimeByCluster(int clusterCount) {
         mDeviceCpuTimeByClusterPosition = addDeviceSection(clusterCount, "clusters");
         mDeviceCpuTimeByClusterCount = clusterCount;
     }
@@ -99,7 +151,7 @@
     /**
      * Declare that the UID stats array has a section capturing CPU time per power bracket.
      */
-    public void addUidSectionCpuTimeByPowerBracket(int[] scalingStepToPowerBracketMap) {
+    private void addUidSectionCpuTimeByPowerBracket(int[] scalingStepToPowerBracketMap) {
         mScalingStepToPowerBracketMap = scalingStepToPowerBracketMap;
         updatePowerBracketCount();
         mUidPowerBracketsPosition = addUidSection(mUidPowerBracketCount, "time");
@@ -135,44 +187,4 @@
     public long getUidTimeByPowerBracket(long[] stats, int bracket) {
         return stats[mUidPowerBracketsPosition + bracket];
     }
-
-    /**
-     * Copies the elements of the stats array layout into <code>extras</code>
-     */
-    public void toExtras(PersistableBundle extras) {
-        super.toExtras(extras);
-        extras.putInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_POSITION,
-                mDeviceCpuTimeByScalingStepPosition);
-        extras.putInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_COUNT,
-                mDeviceCpuTimeByScalingStepCount);
-        extras.putInt(EXTRA_DEVICE_TIME_BY_CLUSTER_POSITION,
-                mDeviceCpuTimeByClusterPosition);
-        extras.putInt(EXTRA_DEVICE_TIME_BY_CLUSTER_COUNT,
-                mDeviceCpuTimeByClusterCount);
-        extras.putInt(EXTRA_UID_BRACKETS_POSITION, mUidPowerBracketsPosition);
-        putIntArray(extras, EXTRA_UID_STATS_SCALING_STEP_TO_POWER_BRACKET,
-                mScalingStepToPowerBracketMap);
-    }
-
-    /**
-     * Retrieves elements of the stats array layout from <code>extras</code>
-     */
-    public void fromExtras(PersistableBundle extras) {
-        super.fromExtras(extras);
-        mDeviceCpuTimeByScalingStepPosition =
-                extras.getInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_POSITION);
-        mDeviceCpuTimeByScalingStepCount =
-                extras.getInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_COUNT);
-        mDeviceCpuTimeByClusterPosition =
-                extras.getInt(EXTRA_DEVICE_TIME_BY_CLUSTER_POSITION);
-        mDeviceCpuTimeByClusterCount =
-                extras.getInt(EXTRA_DEVICE_TIME_BY_CLUSTER_COUNT);
-        mUidPowerBracketsPosition = extras.getInt(EXTRA_UID_BRACKETS_POSITION);
-        mScalingStepToPowerBracketMap =
-                getIntArray(extras, EXTRA_UID_STATS_SCALING_STEP_TO_POWER_BRACKET);
-        if (mScalingStepToPowerBracketMap == null) {
-            mScalingStepToPowerBracketMap = new int[mDeviceCpuTimeByScalingStepCount];
-        }
-        updatePowerBracketCount();
-    }
 }
diff --git a/services/core/java/com/android/server/power/stats/EnergyConsumerPowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/EnergyConsumerPowerStatsLayout.java
similarity index 80%
rename from services/core/java/com/android/server/power/stats/EnergyConsumerPowerStatsLayout.java
rename to services/core/java/com/android/server/power/stats/format/EnergyConsumerPowerStatsLayout.java
index 8430f56..e7a4822 100644
--- a/services/core/java/com/android/server/power/stats/EnergyConsumerPowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/EnergyConsumerPowerStatsLayout.java
@@ -14,10 +14,12 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.format;
 
-class EnergyConsumerPowerStatsLayout extends PowerStatsLayout {
-    EnergyConsumerPowerStatsLayout() {
+import com.android.internal.os.PowerStats;
+
+public class EnergyConsumerPowerStatsLayout extends PowerStatsLayout {
+    public EnergyConsumerPowerStatsLayout() {
         // Add a section for consumed energy, even if the specific device does not
         // have support EnergyConsumers.  This is done to guarantee format compatibility between
         // PowerStats created by a PowerStatsCollector and those produced by a PowerStatsProcessor.
@@ -30,4 +32,8 @@
         addUidSectionEnergyConsumers(1);
         addUidSectionPowerEstimate();
     }
+
+    public EnergyConsumerPowerStatsLayout(PowerStats.Descriptor descriptor) {
+        super(descriptor);
+    }
 }
diff --git a/services/core/java/com/android/server/power/stats/GnssPowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/GnssPowerStatsLayout.java
similarity index 81%
rename from services/core/java/com/android/server/power/stats/GnssPowerStatsLayout.java
rename to services/core/java/com/android/server/power/stats/format/GnssPowerStatsLayout.java
index 9a1317d..b70b173 100644
--- a/services/core/java/com/android/server/power/stats/GnssPowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/GnssPowerStatsLayout.java
@@ -14,28 +14,31 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.format;
 
+import android.annotation.NonNull;
 import android.location.GnssSignalQuality;
 import android.os.PersistableBundle;
 
-class GnssPowerStatsLayout extends BinaryStatePowerStatsLayout {
+import com.android.internal.os.PowerStats;
+
+public class GnssPowerStatsLayout extends BinaryStatePowerStatsLayout {
     private static final String EXTRA_DEVICE_TIME_SIGNAL_LEVEL_POSITION = "dt-sig";
     private static final String EXTRA_UID_TIME_SIGNAL_LEVEL_POSITION = "ut-sig";
 
-    private int mDeviceSignalLevelTimePosition;
-    private int mUidSignalLevelTimePosition;
+    private final int mDeviceSignalLevelTimePosition;
+    private final int mUidSignalLevelTimePosition;
 
-    GnssPowerStatsLayout() {
+    public GnssPowerStatsLayout() {
         mDeviceSignalLevelTimePosition = addDeviceSection(
                 GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS, "level");
         mUidSignalLevelTimePosition = addUidSection(
                 GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS, "level");
     }
 
-    @Override
-    public void fromExtras(PersistableBundle extras) {
-        super.fromExtras(extras);
+    public GnssPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) {
+        super(descriptor);
+        PersistableBundle extras = descriptor.extras;
         mDeviceSignalLevelTimePosition = extras.getInt(EXTRA_DEVICE_TIME_SIGNAL_LEVEL_POSITION);
         mUidSignalLevelTimePosition = extras.getInt(EXTRA_UID_TIME_SIGNAL_LEVEL_POSITION);
     }
diff --git a/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/MobileRadioPowerStatsLayout.java
similarity index 79%
rename from services/core/java/com/android/server/power/stats/MobileRadioPowerStatsLayout.java
rename to services/core/java/com/android/server/power/stats/format/MobileRadioPowerStatsLayout.java
index 07d78f8..da6fc41 100644
--- a/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/MobileRadioPowerStatsLayout.java
@@ -14,10 +14,12 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.format;
 
 import android.annotation.NonNull;
+import android.os.BatteryStats;
 import android.os.PersistableBundle;
+import android.telephony.AccessNetworkConstants;
 import android.telephony.ModemActivityInfo;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -28,7 +30,7 @@
  * Captures the positions and lengths of sections of the stats array, such as time-in-state,
  * power usage estimates etc.
  */
-class MobileRadioPowerStatsLayout extends PowerStatsLayout {
+public class MobileRadioPowerStatsLayout extends PowerStatsLayout {
     private static final String TAG = "MobileRadioPowerStatsLayout";
     private static final String EXTRA_DEVICE_SLEEP_TIME_POSITION = "dt-sleep";
     private static final String EXTRA_DEVICE_IDLE_TIME_POSITION = "dt-idle";
@@ -56,27 +58,95 @@
     private int mUidRxPacketsPosition;
     private int mUidTxPacketsPosition;
 
-    MobileRadioPowerStatsLayout() {
+    public MobileRadioPowerStatsLayout(int energyConsumerCount) {
+        addDeviceMobileActivity();
+        addDeviceSectionEnergyConsumers(energyConsumerCount);
+        addStateStats();
+        addUidNetworkStats();
+        addDeviceSectionUsageDuration();
+        addDeviceSectionPowerEstimate();
+        addUidSectionPowerEstimate();
     }
 
-    MobileRadioPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) {
+    public MobileRadioPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) {
         super(descriptor);
+        PersistableBundle extras = descriptor.extras;
+        mDeviceSleepTimePosition = extras.getInt(EXTRA_DEVICE_SLEEP_TIME_POSITION);
+        mDeviceIdleTimePosition = extras.getInt(EXTRA_DEVICE_IDLE_TIME_POSITION);
+        mDeviceScanTimePosition = extras.getInt(EXTRA_DEVICE_SCAN_TIME_POSITION);
+        mDeviceCallTimePosition = extras.getInt(EXTRA_DEVICE_CALL_TIME_POSITION);
+        mDeviceCallPowerPosition = extras.getInt(EXTRA_DEVICE_CALL_POWER_POSITION);
+        mStateRxTimePosition = extras.getInt(EXTRA_STATE_RX_TIME_POSITION);
+        mStateTxTimesPosition = extras.getInt(EXTRA_STATE_TX_TIMES_POSITION);
+        mStateTxTimesCount = extras.getInt(EXTRA_STATE_TX_TIMES_COUNT);
+        mUidRxBytesPosition = extras.getInt(EXTRA_UID_RX_BYTES_POSITION);
+        mUidTxBytesPosition = extras.getInt(EXTRA_UID_TX_BYTES_POSITION);
+        mUidRxPacketsPosition = extras.getInt(EXTRA_UID_RX_PACKETS_POSITION);
+        mUidTxPacketsPosition = extras.getInt(EXTRA_UID_TX_PACKETS_POSITION);
     }
 
-    void addDeviceMobileActivity() {
+    /**
+     * Copies the elements of the stats array layout into <code>extras</code>
+     */
+    public void toExtras(PersistableBundle extras) {
+        super.toExtras(extras);
+        extras.putInt(EXTRA_DEVICE_SLEEP_TIME_POSITION, mDeviceSleepTimePosition);
+        extras.putInt(EXTRA_DEVICE_IDLE_TIME_POSITION, mDeviceIdleTimePosition);
+        extras.putInt(EXTRA_DEVICE_SCAN_TIME_POSITION, mDeviceScanTimePosition);
+        extras.putInt(EXTRA_DEVICE_CALL_TIME_POSITION, mDeviceCallTimePosition);
+        extras.putInt(EXTRA_DEVICE_CALL_POWER_POSITION, mDeviceCallPowerPosition);
+        extras.putInt(EXTRA_STATE_RX_TIME_POSITION, mStateRxTimePosition);
+        extras.putInt(EXTRA_STATE_TX_TIMES_POSITION, mStateTxTimesPosition);
+        extras.putInt(EXTRA_STATE_TX_TIMES_COUNT, mStateTxTimesCount);
+        extras.putInt(EXTRA_UID_RX_BYTES_POSITION, mUidRxBytesPosition);
+        extras.putInt(EXTRA_UID_TX_BYTES_POSITION, mUidTxBytesPosition);
+        extras.putInt(EXTRA_UID_RX_PACKETS_POSITION, mUidRxPacketsPosition);
+        extras.putInt(EXTRA_UID_TX_PACKETS_POSITION, mUidTxPacketsPosition);
+    }
+
+    public static int makeStateKey(int rat, int freqRange) {
+        if (rat == BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR) {
+            return rat | (freqRange << 8);
+        } else {
+            return rat;
+        }
+    }
+
+    @BatteryStats.RadioAccessTechnology
+    public static int mapRadioAccessNetworkTypeToRadioAccessTechnology(
+            @AccessNetworkConstants.RadioAccessNetworkType int networkType) {
+        switch (networkType) {
+            case AccessNetworkConstants.AccessNetworkType.NGRAN:
+                return BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR;
+            case AccessNetworkConstants.AccessNetworkType.EUTRAN:
+                return BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE;
+            case AccessNetworkConstants.AccessNetworkType.UNKNOWN: //fallthrough
+            case AccessNetworkConstants.AccessNetworkType.GERAN: //fallthrough
+            case AccessNetworkConstants.AccessNetworkType.UTRAN: //fallthrough
+            case AccessNetworkConstants.AccessNetworkType.CDMA2000: //fallthrough
+            case AccessNetworkConstants.AccessNetworkType.IWLAN:
+                return BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER;
+            default:
+                Slog.w(TAG,
+                        "Unhandled RadioAccessNetworkType (" + networkType + "), mapping to OTHER");
+                return BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER;
+        }
+    }
+
+    private void addDeviceMobileActivity() {
         mDeviceSleepTimePosition = addDeviceSection(1, "sleep");
         mDeviceIdleTimePosition = addDeviceSection(1, "idle");
         mDeviceScanTimePosition = addDeviceSection(1, "scan");
         mDeviceCallTimePosition = addDeviceSection(1, "call", FLAG_OPTIONAL);
     }
 
-    void addStateStats() {
+    private void addStateStats() {
         mStateRxTimePosition = addStateSection(1, "rx");
         mStateTxTimesCount = ModemActivityInfo.getNumTxPowerLevels();
         mStateTxTimesPosition = addStateSection(mStateTxTimesCount, "tx");
     }
 
-    void addUidNetworkStats() {
+    private void addUidNetworkStats() {
         mUidRxPacketsPosition = addUidSection(1, "rx-pkts");
         mUidRxBytesPosition = addUidSection(1, "rx-B");
         mUidTxPacketsPosition = addUidSection(1, "tx-pkts");
@@ -84,7 +154,7 @@
     }
 
     @Override
-    public void addDeviceSectionPowerEstimate() {
+    protected void addDeviceSectionPowerEstimate() {
         super.addDeviceSectionPowerEstimate();
         // Printed as part of the PhoneCallPowerStatsProcessor
         mDeviceCallPowerPosition = addDeviceSection(1, "call-power", FLAG_HIDDEN);
@@ -178,44 +248,6 @@
         return stats[mUidTxPacketsPosition];
     }
 
-    /**
-     * Copies the elements of the stats array layout into <code>extras</code>
-     */
-    public void toExtras(PersistableBundle extras) {
-        super.toExtras(extras);
-        extras.putInt(EXTRA_DEVICE_SLEEP_TIME_POSITION, mDeviceSleepTimePosition);
-        extras.putInt(EXTRA_DEVICE_IDLE_TIME_POSITION, mDeviceIdleTimePosition);
-        extras.putInt(EXTRA_DEVICE_SCAN_TIME_POSITION, mDeviceScanTimePosition);
-        extras.putInt(EXTRA_DEVICE_CALL_TIME_POSITION, mDeviceCallTimePosition);
-        extras.putInt(EXTRA_DEVICE_CALL_POWER_POSITION, mDeviceCallPowerPosition);
-        extras.putInt(EXTRA_STATE_RX_TIME_POSITION, mStateRxTimePosition);
-        extras.putInt(EXTRA_STATE_TX_TIMES_POSITION, mStateTxTimesPosition);
-        extras.putInt(EXTRA_STATE_TX_TIMES_COUNT, mStateTxTimesCount);
-        extras.putInt(EXTRA_UID_RX_BYTES_POSITION, mUidRxBytesPosition);
-        extras.putInt(EXTRA_UID_TX_BYTES_POSITION, mUidTxBytesPosition);
-        extras.putInt(EXTRA_UID_RX_PACKETS_POSITION, mUidRxPacketsPosition);
-        extras.putInt(EXTRA_UID_TX_PACKETS_POSITION, mUidTxPacketsPosition);
-    }
-
-    /**
-     * Retrieves elements of the stats array layout from <code>extras</code>
-     */
-    public void fromExtras(PersistableBundle extras) {
-        super.fromExtras(extras);
-        mDeviceSleepTimePosition = extras.getInt(EXTRA_DEVICE_SLEEP_TIME_POSITION);
-        mDeviceIdleTimePosition = extras.getInt(EXTRA_DEVICE_IDLE_TIME_POSITION);
-        mDeviceScanTimePosition = extras.getInt(EXTRA_DEVICE_SCAN_TIME_POSITION);
-        mDeviceCallTimePosition = extras.getInt(EXTRA_DEVICE_CALL_TIME_POSITION);
-        mDeviceCallPowerPosition = extras.getInt(EXTRA_DEVICE_CALL_POWER_POSITION);
-        mStateRxTimePosition = extras.getInt(EXTRA_STATE_RX_TIME_POSITION);
-        mStateTxTimesPosition = extras.getInt(EXTRA_STATE_TX_TIMES_POSITION);
-        mStateTxTimesCount = extras.getInt(EXTRA_STATE_TX_TIMES_COUNT);
-        mUidRxBytesPosition = extras.getInt(EXTRA_UID_RX_BYTES_POSITION);
-        mUidTxBytesPosition = extras.getInt(EXTRA_UID_TX_BYTES_POSITION);
-        mUidRxPacketsPosition = extras.getInt(EXTRA_UID_RX_PACKETS_POSITION);
-        mUidTxPacketsPosition = extras.getInt(EXTRA_UID_TX_PACKETS_POSITION);
-    }
-
     public void addRxTxTimesForRat(SparseArray<long[]> stateStats, int networkType, int freqRange,
             long rxTime, int[] txTime) {
         if (txTime.length != mStateTxTimesCount) {
@@ -239,9 +271,8 @@
             return;
         }
 
-        int rat = MobileRadioPowerStatsCollector.mapRadioAccessNetworkTypeToRadioAccessTechnology(
-                networkType);
-        int stateKey = MobileRadioPowerStatsCollector.makeStateKey(rat, freqRange);
+        int rat = mapRadioAccessNetworkTypeToRadioAccessTechnology(networkType);
+        int stateKey = makeStateKey(rat, freqRange);
         long[] stats = stateStats.get(stateKey);
         if (stats == null) {
             stats = new long[getStateStatsArrayLength()];
diff --git a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/PhoneCallPowerStatsLayout.java
similarity index 72%
rename from services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java
rename to services/core/java/com/android/server/power/stats/format/PhoneCallPowerStatsLayout.java
index 502337c..5a34148 100644
--- a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/PhoneCallPowerStatsLayout.java
@@ -13,12 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.server.power.stats.format;
 
-package com.android.server.power.stats;
-
-class BinaryStatePowerStatsLayout extends EnergyConsumerPowerStatsLayout {
-    BinaryStatePowerStatsLayout() {
-        addDeviceSectionUsageDuration();
-        addUidSectionUsageDuration();
+public class PhoneCallPowerStatsLayout extends PowerStatsLayout {
+    public PhoneCallPowerStatsLayout() {
+        addDeviceSectionPowerEstimate();
     }
 }
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/PowerStatsLayout.java
similarity index 91%
rename from services/core/java/com/android/server/power/stats/PowerStatsLayout.java
rename to services/core/java/com/android/server/power/stats/format/PowerStatsLayout.java
index 62abfc6..d070919 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/PowerStatsLayout.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.format;
 
 import android.os.PersistableBundle;
 import android.util.Slog;
@@ -36,7 +36,7 @@
     private static final String EXTRA_UID_ENERGY_CONSUMERS_COUNT = "uec";
     private static final String EXTRA_UID_POWER_POSITION = "up";
 
-    protected static final int UNSUPPORTED = -1;
+    public static final int UNSUPPORTED = -1;
     protected static final double MILLI_TO_NANO_MULTIPLIER = 1000000.0;
     protected static final int FLAG_OPTIONAL = 1;
     protected static final int FLAG_HIDDEN = 2;
@@ -46,9 +46,9 @@
     private int mStateStatsArrayLength;
     private int mUidStatsArrayLength;
 
-    private StringBuilder mDeviceFormat = new StringBuilder();
-    private StringBuilder mStateFormat = new StringBuilder();
-    private StringBuilder mUidFormat = new StringBuilder();
+    private final StringBuilder mDeviceFormat = new StringBuilder();
+    private final StringBuilder mStateFormat = new StringBuilder();
+    private final StringBuilder mUidFormat = new StringBuilder();
 
     protected int mDeviceDurationPosition = UNSUPPORTED;
     private int mDeviceEnergyConsumerPosition;
@@ -63,7 +63,32 @@
     }
 
     public PowerStatsLayout(PowerStats.Descriptor descriptor) {
-        fromExtras(descriptor.extras);
+        PersistableBundle extras = descriptor.extras;
+        mDeviceDurationPosition = extras.getInt(EXTRA_DEVICE_DURATION_POSITION);
+        mDeviceEnergyConsumerPosition = extras.getInt(EXTRA_DEVICE_ENERGY_CONSUMERS_POSITION);
+        mDeviceEnergyConsumerCount = extras.getInt(EXTRA_DEVICE_ENERGY_CONSUMERS_COUNT);
+        mDevicePowerEstimatePosition = extras.getInt(EXTRA_DEVICE_POWER_POSITION);
+        mUidDurationPosition = extras.getInt(EXTRA_UID_DURATION_POSITION);
+        mUidEnergyConsumerPosition = extras.getInt(EXTRA_UID_ENERGY_CONSUMERS_POSITION);
+        mUidEnergyConsumerCount = extras.getInt(EXTRA_UID_ENERGY_CONSUMERS_COUNT);
+        mUidPowerEstimatePosition = extras.getInt(EXTRA_UID_POWER_POSITION);
+    }
+
+    /**
+     * Copies the elements of the stats array layout into <code>extras</code>
+     */
+    public void toExtras(PersistableBundle extras) {
+        extras.putInt(EXTRA_DEVICE_DURATION_POSITION, mDeviceDurationPosition);
+        extras.putInt(EXTRA_DEVICE_ENERGY_CONSUMERS_POSITION, mDeviceEnergyConsumerPosition);
+        extras.putInt(EXTRA_DEVICE_ENERGY_CONSUMERS_COUNT, mDeviceEnergyConsumerCount);
+        extras.putInt(EXTRA_DEVICE_POWER_POSITION, mDevicePowerEstimatePosition);
+        extras.putInt(EXTRA_UID_DURATION_POSITION, mUidDurationPosition);
+        extras.putInt(EXTRA_UID_ENERGY_CONSUMERS_POSITION, mUidEnergyConsumerPosition);
+        extras.putInt(EXTRA_UID_ENERGY_CONSUMERS_COUNT, mUidEnergyConsumerCount);
+        extras.putInt(EXTRA_UID_POWER_POSITION, mUidPowerEstimatePosition);
+        extras.putString(PowerStats.Descriptor.EXTRA_DEVICE_STATS_FORMAT, mDeviceFormat.toString());
+        extras.putString(PowerStats.Descriptor.EXTRA_STATE_STATS_FORMAT, mStateFormat.toString());
+        extras.putString(PowerStats.Descriptor.EXTRA_UID_STATS_FORMAT, mUidFormat.toString());
     }
 
     public int getDeviceStatsArrayLength() {
@@ -141,7 +166,7 @@
     /**
      * Declare that the stats array has a section capturing usage duration
      */
-    public void addDeviceSectionUsageDuration() {
+    protected void addDeviceSectionUsageDuration() {
         mDeviceDurationPosition = addDeviceSection(1, "usage", FLAG_OPTIONAL);
     }
 
@@ -163,7 +188,7 @@
      * Declares that the stats array has a section capturing EnergyConsumer data from
      * PowerStatsService.
      */
-    public void addDeviceSectionEnergyConsumers(int energyConsumerCount) {
+    protected void addDeviceSectionEnergyConsumers(int energyConsumerCount) {
         mDeviceEnergyConsumerPosition = addDeviceSection(energyConsumerCount, "energy",
                 FLAG_OPTIONAL);
         mDeviceEnergyConsumerCount = energyConsumerCount;
@@ -192,7 +217,7 @@
     /**
      * Declare that the stats array has a section capturing a power estimate
      */
-    public void addDeviceSectionPowerEstimate() {
+    protected void addDeviceSectionPowerEstimate() {
         mDevicePowerEstimatePosition = addDeviceSection(1, "power",
                 FLAG_FORMAT_AS_POWER | FLAG_OPTIONAL);
     }
@@ -215,14 +240,14 @@
     /**
      * Declare that the UID stats array has a section capturing usage duration
      */
-    public void addUidSectionUsageDuration() {
+    protected void addUidSectionUsageDuration() {
         mUidDurationPosition = addUidSection(1, "time");
     }
 
     /**
      * Declare that the UID stats array has a section capturing a power estimate
      */
-    public void addUidSectionPowerEstimate() {
+    protected void addUidSectionPowerEstimate() {
         mUidPowerEstimatePosition = addUidSection(1, "power", FLAG_FORMAT_AS_POWER | FLAG_OPTIONAL);
     }
 
@@ -251,7 +276,7 @@
      * Declares that the UID stats array has a section capturing EnergyConsumer data from
      * PowerStatsService.
      */
-    public void addUidSectionEnergyConsumers(int energyConsumerCount) {
+    protected void addUidSectionEnergyConsumers(int energyConsumerCount) {
         mUidEnergyConsumerPosition = addUidSection(energyConsumerCount, "energy",
                 FLAG_OPTIONAL);
         mUidEnergyConsumerCount = energyConsumerCount;
@@ -292,39 +317,6 @@
         return stats[mUidPowerEstimatePosition] / MILLI_TO_NANO_MULTIPLIER;
     }
 
-    /**
-     * Copies the elements of the stats array layout into <code>extras</code>
-     */
-    public void toExtras(PersistableBundle extras) {
-        extras.putInt(EXTRA_DEVICE_DURATION_POSITION, mDeviceDurationPosition);
-        extras.putInt(EXTRA_DEVICE_ENERGY_CONSUMERS_POSITION,
-                mDeviceEnergyConsumerPosition);
-        extras.putInt(EXTRA_DEVICE_ENERGY_CONSUMERS_COUNT,
-                mDeviceEnergyConsumerCount);
-        extras.putInt(EXTRA_DEVICE_POWER_POSITION, mDevicePowerEstimatePosition);
-        extras.putInt(EXTRA_UID_DURATION_POSITION, mUidDurationPosition);
-        extras.putInt(EXTRA_UID_ENERGY_CONSUMERS_POSITION, mUidEnergyConsumerPosition);
-        extras.putInt(EXTRA_UID_ENERGY_CONSUMERS_COUNT, mUidEnergyConsumerCount);
-        extras.putInt(EXTRA_UID_POWER_POSITION, mUidPowerEstimatePosition);
-        extras.putString(PowerStats.Descriptor.EXTRA_DEVICE_STATS_FORMAT, mDeviceFormat.toString());
-        extras.putString(PowerStats.Descriptor.EXTRA_STATE_STATS_FORMAT, mStateFormat.toString());
-        extras.putString(PowerStats.Descriptor.EXTRA_UID_STATS_FORMAT, mUidFormat.toString());
-    }
-
-    /**
-     * Retrieves elements of the stats array layout from <code>extras</code>
-     */
-    public void fromExtras(PersistableBundle extras) {
-        mDeviceDurationPosition = extras.getInt(EXTRA_DEVICE_DURATION_POSITION);
-        mDeviceEnergyConsumerPosition = extras.getInt(EXTRA_DEVICE_ENERGY_CONSUMERS_POSITION);
-        mDeviceEnergyConsumerCount = extras.getInt(EXTRA_DEVICE_ENERGY_CONSUMERS_COUNT);
-        mDevicePowerEstimatePosition = extras.getInt(EXTRA_DEVICE_POWER_POSITION);
-        mUidDurationPosition = extras.getInt(EXTRA_UID_DURATION_POSITION);
-        mUidEnergyConsumerPosition = extras.getInt(EXTRA_UID_ENERGY_CONSUMERS_POSITION);
-        mUidEnergyConsumerCount = extras.getInt(EXTRA_UID_ENERGY_CONSUMERS_COUNT);
-        mUidPowerEstimatePosition = extras.getInt(EXTRA_UID_POWER_POSITION);
-    }
-
     protected void putIntArray(PersistableBundle extras, String key, int[] array) {
         if (array == null) {
             return;
diff --git a/services/core/java/com/android/server/power/stats/ScreenPowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/ScreenPowerStatsLayout.java
similarity index 89%
rename from services/core/java/com/android/server/power/stats/ScreenPowerStatsLayout.java
rename to services/core/java/com/android/server/power/stats/format/ScreenPowerStatsLayout.java
index f134aa8..6f6a7ff 100644
--- a/services/core/java/com/android/server/power/stats/ScreenPowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/ScreenPowerStatsLayout.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.format;
 
 import android.annotation.NonNull;
 import android.os.BatteryStats;
@@ -41,14 +41,40 @@
     private int mDeviceScreenDozePowerPosition;
     private int mUidTopActivityTimePosition;
 
-    ScreenPowerStatsLayout() {
+    public ScreenPowerStatsLayout(int energyConsumerCount, int displayCount) {
+        addDeviceScreenUsageDurationSection(displayCount);
+        addDeviceSectionEnergyConsumers(energyConsumerCount);
+        addDeviceSectionUsageDuration();
+        addDeviceSectionPowerEstimate();
+        addUidTopActivitiyDuration();
+        addUidSectionPowerEstimate();
     }
 
-    ScreenPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) {
+    public ScreenPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) {
         super(descriptor);
+        PersistableBundle extras = descriptor.extras;
+        mDisplayCount = extras.getInt(EXTRA_DEVICE_SCREEN_COUNT, 1);
+        mDeviceScreenOnDurationPosition = extras.getInt(EXTRA_DEVICE_SCREEN_ON_DURATION_POSITION);
+        mDeviceBrightnessDurationPositions = extras.getIntArray(
+                EXTRA_DEVICE_BRIGHTNESS_DURATION_POSITIONS);
+        mDeviceScreenDozeDurationPosition = extras.getInt(EXTRA_DEVICE_DOZE_DURATION_POSITION);
+        mDeviceScreenDozePowerPosition = extras.getInt(EXTRA_DEVICE_DOZE_POWER_POSITION);
+        mUidTopActivityTimePosition = extras.getInt(EXTRA_UID_FOREGROUND_DURATION);
     }
 
-    void addDeviceScreenUsageDurationSection(int displayCount) {
+    @Override
+    public void toExtras(PersistableBundle extras) {
+        super.toExtras(extras);
+        extras.putInt(EXTRA_DEVICE_SCREEN_COUNT, mDisplayCount);
+        extras.putInt(EXTRA_DEVICE_SCREEN_ON_DURATION_POSITION, mDeviceScreenOnDurationPosition);
+        extras.putIntArray(EXTRA_DEVICE_BRIGHTNESS_DURATION_POSITIONS,
+                mDeviceBrightnessDurationPositions);
+        extras.putInt(EXTRA_DEVICE_DOZE_DURATION_POSITION, mDeviceScreenDozeDurationPosition);
+        extras.putInt(EXTRA_DEVICE_DOZE_POWER_POSITION, mDeviceScreenDozePowerPosition);
+        extras.putInt(EXTRA_UID_FOREGROUND_DURATION, mUidTopActivityTimePosition);
+    }
+
+    private void addDeviceScreenUsageDurationSection(int displayCount) {
         mDisplayCount = displayCount;
         mDeviceScreenOnDurationPosition = addDeviceSection(displayCount, "on");
         mDeviceBrightnessDurationPositions = new int[BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS];
@@ -60,7 +86,7 @@
     }
 
     @Override
-    public void addDeviceSectionPowerEstimate() {
+    protected void addDeviceSectionPowerEstimate() {
         super.addDeviceSectionPowerEstimate();
         // Used by AmbientDisplayPowerStatsProcessor
         mDeviceScreenDozePowerPosition = addDeviceSection(1, "doze-power", FLAG_HIDDEN);
@@ -127,7 +153,7 @@
         return stats[mDeviceScreenDozePowerPosition] / MILLI_TO_NANO_MULTIPLIER;
     }
 
-    void addUidTopActivitiyDuration() {
+    private void addUidTopActivitiyDuration() {
         mUidTopActivityTimePosition = addUidSection(1, "top");
     }
 
@@ -144,28 +170,4 @@
     public long getUidTopActivityDuration(long[] stats) {
         return stats[mUidTopActivityTimePosition];
     }
-
-    @Override
-    public void toExtras(PersistableBundle extras) {
-        super.toExtras(extras);
-        extras.putInt(EXTRA_DEVICE_SCREEN_COUNT, mDisplayCount);
-        extras.putInt(EXTRA_DEVICE_SCREEN_ON_DURATION_POSITION, mDeviceScreenOnDurationPosition);
-        extras.putIntArray(EXTRA_DEVICE_BRIGHTNESS_DURATION_POSITIONS,
-                mDeviceBrightnessDurationPositions);
-        extras.putInt(EXTRA_DEVICE_DOZE_DURATION_POSITION, mDeviceScreenDozeDurationPosition);
-        extras.putInt(EXTRA_DEVICE_DOZE_POWER_POSITION, mDeviceScreenDozePowerPosition);
-        extras.putInt(EXTRA_UID_FOREGROUND_DURATION, mUidTopActivityTimePosition);
-    }
-
-    @Override
-    public void fromExtras(PersistableBundle extras) {
-        super.fromExtras(extras);
-        mDisplayCount = extras.getInt(EXTRA_DEVICE_SCREEN_COUNT, 1);
-        mDeviceScreenOnDurationPosition = extras.getInt(EXTRA_DEVICE_SCREEN_ON_DURATION_POSITION);
-        mDeviceBrightnessDurationPositions = extras.getIntArray(
-                EXTRA_DEVICE_BRIGHTNESS_DURATION_POSITIONS);
-        mDeviceScreenDozeDurationPosition = extras.getInt(EXTRA_DEVICE_DOZE_DURATION_POSITION);
-        mDeviceScreenDozePowerPosition = extras.getInt(EXTRA_DEVICE_DOZE_POWER_POSITION);
-        mUidTopActivityTimePosition = extras.getInt(EXTRA_UID_FOREGROUND_DURATION);
-    }
 }
diff --git a/services/core/java/com/android/server/power/stats/SensorPowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/SensorPowerStatsLayout.java
similarity index 72%
rename from services/core/java/com/android/server/power/stats/SensorPowerStatsLayout.java
rename to services/core/java/com/android/server/power/stats/format/SensorPowerStatsLayout.java
index e66cd39..e8df3dd 100644
--- a/services/core/java/com/android/server/power/stats/SensorPowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/SensorPowerStatsLayout.java
@@ -14,12 +14,17 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.format;
 
 import android.os.PersistableBundle;
 import android.util.Slog;
 import android.util.SparseIntArray;
 
+import com.android.internal.os.PowerStats;
+
+import java.util.Arrays;
+import java.util.Map;
+
 public class SensorPowerStatsLayout extends PowerStatsLayout {
     private static final String TAG = "SensorPowerStatsLayout";
     private static final String EXTRA_DEVICE_SENSOR_HANDLES = "dsh";
@@ -27,7 +32,48 @@
 
     private final SparseIntArray mSensorPositions = new SparseIntArray();
 
-    void addUidSensorSection(int handle, String label) {
+    public SensorPowerStatsLayout(Map<Integer, String> idToLabelMap) {
+        Integer[] keys = new Integer[idToLabelMap.size()];
+        idToLabelMap.keySet().toArray(keys);
+        Arrays.sort(keys);
+        for (int i = 0; i < keys.length; i++) {
+            addUidSensorSection(keys[i], idToLabelMap.get(keys[i]));
+        }
+        addUidSectionPowerEstimate();
+        addDeviceSectionPowerEstimate();
+    }
+
+    public SensorPowerStatsLayout(PowerStats.Descriptor descriptor) {
+        super(descriptor);
+
+        PersistableBundle extras = descriptor.extras;
+        int[] handlers = extras.getIntArray(EXTRA_DEVICE_SENSOR_HANDLES);
+        int[] uidDurationPositions = extras.getIntArray(EXTRA_UID_SENSOR_POSITIONS);
+
+        if (handlers != null && uidDurationPositions != null) {
+            for (int i = 0; i < handlers.length; i++) {
+                mSensorPositions.put(handlers[i], uidDurationPositions[i]);
+            }
+        }
+    }
+
+    @Override
+    public void toExtras(PersistableBundle extras) {
+        super.toExtras(extras);
+
+        int[] handlers = new int[mSensorPositions.size()];
+        int[] uidDurationPositions = new int[mSensorPositions.size()];
+
+        for (int i = 0; i < mSensorPositions.size(); i++) {
+            handlers[i] = mSensorPositions.keyAt(i);
+            uidDurationPositions[i] = mSensorPositions.valueAt(i);
+        }
+
+        extras.putIntArray(EXTRA_DEVICE_SENSOR_HANDLES, handlers);
+        extras.putIntArray(EXTRA_UID_SENSOR_POSITIONS, uidDurationPositions);
+    }
+
+    private void addUidSensorSection(int handle, String label) {
         mSensorPositions.put(handle, addUidSection(1, label, FLAG_OPTIONAL));
     }
 
@@ -50,32 +96,4 @@
         }
         stats[position] += durationMs;
     }
-
-    @Override
-    public void toExtras(PersistableBundle extras) {
-        super.toExtras(extras);
-
-        int[] handlers = new int[mSensorPositions.size()];
-        int[] uidDurationPositions = new int[mSensorPositions.size()];
-
-        for (int i = 0; i < mSensorPositions.size(); i++) {
-            handlers[i] = mSensorPositions.keyAt(i);
-            uidDurationPositions[i] = mSensorPositions.valueAt(i);
-        }
-
-        extras.putIntArray(EXTRA_DEVICE_SENSOR_HANDLES, handlers);
-        extras.putIntArray(EXTRA_UID_SENSOR_POSITIONS, uidDurationPositions);
-    }
-
-    @Override
-    public void fromExtras(PersistableBundle extras) {
-        super.fromExtras(extras);
-
-        int[] handlers = extras.getIntArray(EXTRA_DEVICE_SENSOR_HANDLES);
-        int[] uidDurationPositions = extras.getIntArray(EXTRA_UID_SENSOR_POSITIONS);
-
-        for (int i = 0; i < handlers.length; i++) {
-            mSensorPositions.put(handlers[i], uidDurationPositions[i]);
-        }
-    }
 }
diff --git a/services/core/java/com/android/server/power/stats/WifiPowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/WifiPowerStatsLayout.java
similarity index 93%
rename from services/core/java/com/android/server/power/stats/WifiPowerStatsLayout.java
rename to services/core/java/com/android/server/power/stats/format/WifiPowerStatsLayout.java
index e2e8226..ce7ef12 100644
--- a/services/core/java/com/android/server/power/stats/WifiPowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/WifiPowerStatsLayout.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.format;
 
 import android.annotation.NonNull;
 import android.os.PersistableBundle;
@@ -22,7 +22,6 @@
 import com.android.internal.os.PowerStats;
 
 public class WifiPowerStatsLayout extends PowerStatsLayout {
-    private static final String TAG = "WifiPowerStatsLayout";
     private static final int UNSPECIFIED = -1;
     private static final String EXTRA_POWER_REPORTING_SUPPORTED = "prs";
     private static final String EXTRA_DEVICE_RX_TIME_POSITION = "dt-rx";
@@ -54,14 +53,56 @@
     private int mUidScanTimePosition;
     private int mUidBatchScanTimePosition;
 
-    WifiPowerStatsLayout() {
+    public WifiPowerStatsLayout(int energyConsumerCount, boolean powerReportingSupported) {
+        addDeviceWifiActivity(powerReportingSupported);
+        addDeviceSectionEnergyConsumers(energyConsumerCount);
+        addUidNetworkStats();
+        addDeviceSectionUsageDuration();
+        addDeviceSectionPowerEstimate();
+        addUidSectionPowerEstimate();
     }
 
-    WifiPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) {
+    public WifiPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) {
         super(descriptor);
+        PersistableBundle extras = descriptor.extras;
+        mPowerReportingSupported = extras.getBoolean(EXTRA_POWER_REPORTING_SUPPORTED);
+        mDeviceRxTimePosition = extras.getInt(EXTRA_DEVICE_RX_TIME_POSITION);
+        mDeviceTxTimePosition = extras.getInt(EXTRA_DEVICE_TX_TIME_POSITION);
+        mDeviceScanTimePosition = extras.getInt(EXTRA_DEVICE_SCAN_TIME_POSITION);
+        mDeviceBasicScanTimePosition = extras.getInt(EXTRA_DEVICE_BASIC_SCAN_TIME_POSITION);
+        mDeviceBatchedScanTimePosition = extras.getInt(EXTRA_DEVICE_BATCHED_SCAN_TIME_POSITION);
+        mDeviceIdleTimePosition = extras.getInt(EXTRA_DEVICE_IDLE_TIME_POSITION);
+        mDeviceActiveTimePosition = extras.getInt(EXTRA_DEVICE_ACTIVE_TIME_POSITION);
+        mUidRxBytesPosition = extras.getInt(EXTRA_UID_RX_BYTES_POSITION);
+        mUidTxBytesPosition = extras.getInt(EXTRA_UID_TX_BYTES_POSITION);
+        mUidRxPacketsPosition = extras.getInt(EXTRA_UID_RX_PACKETS_POSITION);
+        mUidTxPacketsPosition = extras.getInt(EXTRA_UID_TX_PACKETS_POSITION);
+        mUidScanTimePosition = extras.getInt(EXTRA_UID_SCAN_TIME_POSITION);
+        mUidBatchScanTimePosition = extras.getInt(EXTRA_UID_BATCH_SCAN_TIME_POSITION);
     }
 
-    void addDeviceWifiActivity(boolean powerReportingSupported) {
+    /**
+     * Copies the elements of the stats array layout into <code>extras</code>
+     */
+    public void toExtras(PersistableBundle extras) {
+        super.toExtras(extras);
+        extras.putBoolean(EXTRA_POWER_REPORTING_SUPPORTED, mPowerReportingSupported);
+        extras.putInt(EXTRA_DEVICE_RX_TIME_POSITION, mDeviceRxTimePosition);
+        extras.putInt(EXTRA_DEVICE_TX_TIME_POSITION, mDeviceTxTimePosition);
+        extras.putInt(EXTRA_DEVICE_SCAN_TIME_POSITION, mDeviceScanTimePosition);
+        extras.putInt(EXTRA_DEVICE_BASIC_SCAN_TIME_POSITION, mDeviceBasicScanTimePosition);
+        extras.putInt(EXTRA_DEVICE_BATCHED_SCAN_TIME_POSITION, mDeviceBatchedScanTimePosition);
+        extras.putInt(EXTRA_DEVICE_IDLE_TIME_POSITION, mDeviceIdleTimePosition);
+        extras.putInt(EXTRA_DEVICE_ACTIVE_TIME_POSITION, mDeviceActiveTimePosition);
+        extras.putInt(EXTRA_UID_RX_BYTES_POSITION, mUidRxBytesPosition);
+        extras.putInt(EXTRA_UID_TX_BYTES_POSITION, mUidTxBytesPosition);
+        extras.putInt(EXTRA_UID_RX_PACKETS_POSITION, mUidRxPacketsPosition);
+        extras.putInt(EXTRA_UID_TX_PACKETS_POSITION, mUidTxPacketsPosition);
+        extras.putInt(EXTRA_UID_SCAN_TIME_POSITION, mUidScanTimePosition);
+        extras.putInt(EXTRA_UID_BATCH_SCAN_TIME_POSITION, mUidBatchScanTimePosition);
+    }
+
+    private void addDeviceWifiActivity(boolean powerReportingSupported) {
         mPowerReportingSupported = powerReportingSupported;
         if (mPowerReportingSupported) {
             mDeviceActiveTimePosition = UNSPECIFIED;
@@ -80,7 +121,7 @@
         mDeviceBatchedScanTimePosition = addDeviceSection(1, "batched-scan", FLAG_OPTIONAL);
     }
 
-    void addUidNetworkStats() {
+    private void addUidNetworkStats() {
         mUidRxPacketsPosition = addUidSection(1, "rx-pkts");
         mUidRxBytesPosition = addUidSection(1, "rx-B");
         mUidTxPacketsPosition = addUidSection(1, "tx-pkts");
@@ -196,46 +237,4 @@
     public long getUidBatchedScanTime(long[] stats) {
         return stats[mUidBatchScanTimePosition];
     }
-
-    /**
-     * Copies the elements of the stats array layout into <code>extras</code>
-     */
-    public void toExtras(PersistableBundle extras) {
-        super.toExtras(extras);
-        extras.putBoolean(EXTRA_POWER_REPORTING_SUPPORTED, mPowerReportingSupported);
-        extras.putInt(EXTRA_DEVICE_RX_TIME_POSITION, mDeviceRxTimePosition);
-        extras.putInt(EXTRA_DEVICE_TX_TIME_POSITION, mDeviceTxTimePosition);
-        extras.putInt(EXTRA_DEVICE_SCAN_TIME_POSITION, mDeviceScanTimePosition);
-        extras.putInt(EXTRA_DEVICE_BASIC_SCAN_TIME_POSITION, mDeviceBasicScanTimePosition);
-        extras.putInt(EXTRA_DEVICE_BATCHED_SCAN_TIME_POSITION, mDeviceBatchedScanTimePosition);
-        extras.putInt(EXTRA_DEVICE_IDLE_TIME_POSITION, mDeviceIdleTimePosition);
-        extras.putInt(EXTRA_DEVICE_ACTIVE_TIME_POSITION, mDeviceActiveTimePosition);
-        extras.putInt(EXTRA_UID_RX_BYTES_POSITION, mUidRxBytesPosition);
-        extras.putInt(EXTRA_UID_TX_BYTES_POSITION, mUidTxBytesPosition);
-        extras.putInt(EXTRA_UID_RX_PACKETS_POSITION, mUidRxPacketsPosition);
-        extras.putInt(EXTRA_UID_TX_PACKETS_POSITION, mUidTxPacketsPosition);
-        extras.putInt(EXTRA_UID_SCAN_TIME_POSITION, mUidScanTimePosition);
-        extras.putInt(EXTRA_UID_BATCH_SCAN_TIME_POSITION, mUidBatchScanTimePosition);
-    }
-
-    /**
-     * Retrieves elements of the stats array layout from <code>extras</code>
-     */
-    public void fromExtras(PersistableBundle extras) {
-        super.fromExtras(extras);
-        mPowerReportingSupported = extras.getBoolean(EXTRA_POWER_REPORTING_SUPPORTED);
-        mDeviceRxTimePosition = extras.getInt(EXTRA_DEVICE_RX_TIME_POSITION);
-        mDeviceTxTimePosition = extras.getInt(EXTRA_DEVICE_TX_TIME_POSITION);
-        mDeviceScanTimePosition = extras.getInt(EXTRA_DEVICE_SCAN_TIME_POSITION);
-        mDeviceBasicScanTimePosition = extras.getInt(EXTRA_DEVICE_BASIC_SCAN_TIME_POSITION);
-        mDeviceBatchedScanTimePosition = extras.getInt(EXTRA_DEVICE_BATCHED_SCAN_TIME_POSITION);
-        mDeviceIdleTimePosition = extras.getInt(EXTRA_DEVICE_IDLE_TIME_POSITION);
-        mDeviceActiveTimePosition = extras.getInt(EXTRA_DEVICE_ACTIVE_TIME_POSITION);
-        mUidRxBytesPosition = extras.getInt(EXTRA_UID_RX_BYTES_POSITION);
-        mUidTxBytesPosition = extras.getInt(EXTRA_UID_TX_BYTES_POSITION);
-        mUidRxPacketsPosition = extras.getInt(EXTRA_UID_RX_PACKETS_POSITION);
-        mUidTxPacketsPosition = extras.getInt(EXTRA_UID_TX_PACKETS_POSITION);
-        mUidScanTimePosition = extras.getInt(EXTRA_UID_SCAN_TIME_POSITION);
-        mUidBatchScanTimePosition = extras.getInt(EXTRA_UID_BATCH_SCAN_TIME_POSITION);
-    }
 }
diff --git a/services/core/java/com/android/server/power/stats/AggregatedPowerStats.java b/services/core/java/com/android/server/power/stats/processor/AggregatedPowerStats.java
similarity index 97%
rename from services/core/java/com/android/server/power/stats/AggregatedPowerStats.java
rename to services/core/java/com/android/server/power/stats/processor/AggregatedPowerStats.java
index 674b4bc..a4758dd 100644
--- a/services/core/java/com/android/server/power/stats/AggregatedPowerStats.java
+++ b/services/core/java/com/android/server/power/stats/processor/AggregatedPowerStats.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import android.annotation.CurrentTimeMillisLong;
 import android.annotation.DurationMillisLong;
@@ -33,7 +33,7 @@
 import com.android.internal.os.PowerStats;
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
-import com.android.server.power.stats.AggregatedPowerStatsConfig.PowerComponent;
+import com.android.server.power.stats.processor.AggregatedPowerStatsConfig.PowerComponent;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -143,7 +143,8 @@
         }
     }
 
-    List<ClockUpdate> getClockUpdates() {
+    // TODO - DO NOT SUBMIT public
+    public List<ClockUpdate> getClockUpdates() {
         return mClockUpdates;
     }
 
@@ -274,7 +275,8 @@
                         int powerComponentId = parser.getAttributeInt(null,
                                 PowerComponentAggregatedPowerStats.XML_ATTR_ID);
 
-                        PowerComponentAggregatedPowerStats powerComponentStats =
+                        PowerComponentAggregatedPowerStats
+                                powerComponentStats =
                                 stats.getPowerComponentStats(powerComponentId);
                         if (powerComponentStats == null) {
                             PowerComponent powerComponent =
diff --git a/services/core/java/com/android/server/power/stats/AggregatedPowerStatsConfig.java b/services/core/java/com/android/server/power/stats/processor/AggregatedPowerStatsConfig.java
similarity index 95%
rename from services/core/java/com/android/server/power/stats/AggregatedPowerStatsConfig.java
rename to services/core/java/com/android/server/power/stats/processor/AggregatedPowerStatsConfig.java
index ec12228..eaeda43 100644
--- a/services/core/java/com/android/server/power/stats/AggregatedPowerStatsConfig.java
+++ b/services/core/java/com/android/server/power/stats/processor/AggregatedPowerStatsConfig.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -32,7 +32,7 @@
  * WiFi, etc).  Also, it determines which states are tracked globally and which ones on a per-UID
  * basis.
  */
-public class AggregatedPowerStatsConfig {
+class AggregatedPowerStatsConfig {
     public static final int STATE_POWER = 0;
     public static final int STATE_SCREEN = 1;
     public static final int STATE_PROCESS_STATE = 2;
@@ -70,7 +70,7 @@
     /**
      * Configuration for a give power component (CPU, WiFi, etc)
      */
-    public static class PowerComponent {
+    static class PowerComponent {
         private final int mPowerComponentId;
         private @TrackedState int[] mTrackedDeviceStates;
         private @TrackedState int[] mTrackedUidStates;
@@ -174,7 +174,7 @@
      * standard power component IDs, e.g. {@link BatteryConsumer#POWER_COMPONENT_CPU}, or
      * a custom power component.
      */
-    public PowerComponent trackPowerComponent(int powerComponentId) {
+    PowerComponent trackPowerComponent(int powerComponentId) {
         PowerComponent builder = new PowerComponent(powerComponentId);
         mPowerComponents.add(builder);
         return builder;
@@ -185,7 +185,7 @@
      * of a different power component.  The tracked states will be the same as the parent
      * component's.
      */
-    public PowerComponent trackPowerComponent(int powerComponentId,
+    PowerComponent trackPowerComponent(int powerComponentId,
             int parentPowerComponentId) {
         PowerComponent parent = null;
         for (int i = 0; i < mPowerComponents.size(); i++) {
@@ -211,7 +211,7 @@
      * Creates a configuration for custom power components, which are yet to be discovered
      * dynamically through the integration with PowerStatsService.
      */
-    public PowerComponent trackCustomPowerComponents(
+    PowerComponent trackCustomPowerComponents(
             Supplier<PowerStatsProcessor> processorFactory) {
         mCustomPowerStatsProcessorFactory = processorFactory;
         mCustomPowerComponent = new PowerComponent(BatteryConsumer.POWER_COMPONENT_ANY);
@@ -221,7 +221,7 @@
     /**
      * Returns configurations for all registered or dynamically discovered power components.
      */
-    public List<PowerComponent> getPowerComponentsAggregatedStatsConfigs() {
+    List<PowerComponent> getPowerComponentsAggregatedStatsConfigs() {
         return mPowerComponents;
     }
 
@@ -230,7 +230,7 @@
      * integration with PowerStatsService.
      */
     @Nullable
-    public PowerComponent createPowerComponent(int powerComponentId) {
+    PowerComponent createPowerComponent(int powerComponentId) {
         if (mCustomPowerComponent == null) {
             return null;
         }
diff --git a/services/core/java/com/android/server/power/stats/processor/AggregatedPowerStatsSection.java b/services/core/java/com/android/server/power/stats/processor/AggregatedPowerStatsSection.java
new file mode 100644
index 0000000..4a9730c
--- /dev/null
+++ b/services/core/java/com/android/server/power/stats/processor/AggregatedPowerStatsSection.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2023 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.power.stats.processor;
+
+import android.util.IndentingPrintWriter;
+
+import com.android.modules.utils.TypedXmlPullParser;
+import com.android.modules.utils.TypedXmlSerializer;
+import com.android.server.power.stats.PowerStatsSpan;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+class AggregatedPowerStatsSection extends PowerStatsSpan.Section {
+    public static final String TYPE = "aggregated-power-stats";
+
+    private final AggregatedPowerStats mAggregatedPowerStats;
+
+    AggregatedPowerStatsSection(AggregatedPowerStats aggregatedPowerStats) {
+        super(TYPE);
+        mAggregatedPowerStats = aggregatedPowerStats;
+    }
+
+    public AggregatedPowerStats getAggregatedPowerStats() {
+        return mAggregatedPowerStats;
+    }
+
+    @Override
+    public void write(TypedXmlSerializer serializer) throws IOException {
+        mAggregatedPowerStats.writeXml(serializer);
+    }
+
+    @Override
+    public void dump(IndentingPrintWriter ipw) {
+        mAggregatedPowerStats.dump(ipw);
+    }
+
+    static class Reader implements PowerStatsSpan.SectionReader {
+        private final AggregatedPowerStatsConfig mAggregatedPowerStatsConfig;
+
+        Reader(AggregatedPowerStatsConfig config) {
+            mAggregatedPowerStatsConfig = config;
+        }
+
+        @Override
+        public String getType() {
+            return TYPE;
+        }
+
+        @Override
+        public PowerStatsSpan.Section read(String sectionType, TypedXmlPullParser parser)
+                throws IOException, XmlPullParserException {
+            return new AggregatedPowerStatsSection(
+                    AggregatedPowerStats.createFromXml(parser, mAggregatedPowerStatsConfig));
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/power/stats/AmbientDisplayPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessor.java
similarity index 86%
rename from services/core/java/com/android/server/power/stats/AmbientDisplayPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessor.java
index a42929f..32dfdf9 100644
--- a/services/core/java/com/android/server/power/stats/AmbientDisplayPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessor.java
@@ -13,24 +13,25 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import android.os.BatteryConsumer;
 import android.os.PersistableBundle;
 
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.AmbientDisplayPowerStatsLayout;
+import com.android.server.power.stats.format.ScreenPowerStatsLayout;
 
-public class AmbientDisplayPowerStatsProcessor extends PowerStatsProcessor {
-    private final PowerStatsLayout mStatsLayout;
+class AmbientDisplayPowerStatsProcessor extends PowerStatsProcessor {
+    private final AmbientDisplayPowerStatsLayout mStatsLayout;
     private final PowerStats.Descriptor mDescriptor;
     private final long[] mTmpDeviceStats;
     private PowerStats.Descriptor mScreenPowerStatsDescriptor;
     private ScreenPowerStatsLayout mScreenPowerStatsLayout;
     private long[] mTmpScreenStats;
 
-    public AmbientDisplayPowerStatsProcessor() {
-        mStatsLayout = new PowerStatsLayout();
-        mStatsLayout.addDeviceSectionPowerEstimate();
+    AmbientDisplayPowerStatsProcessor() {
+        mStatsLayout = new AmbientDisplayPowerStatsLayout();
         PersistableBundle extras = new PersistableBundle();
         mStatsLayout.toExtras(extras);
         mDescriptor = new PowerStats.Descriptor(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY,
diff --git a/services/core/java/com/android/server/power/stats/AudioPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/AudioPowerStatsProcessor.java
similarity index 82%
rename from services/core/java/com/android/server/power/stats/AudioPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/AudioPowerStatsProcessor.java
index a48f162..ad1b4a7 100644
--- a/services/core/java/com/android/server/power/stats/AudioPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/AudioPowerStatsProcessor.java
@@ -14,15 +14,16 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import android.os.BatteryConsumer;
 import android.os.BatteryStats;
 
 import com.android.internal.os.PowerProfile;
+import com.android.server.power.stats.PowerStatsUidResolver;
 
-public class AudioPowerStatsProcessor extends BinaryStatePowerStatsProcessor {
-    public AudioPowerStatsProcessor(PowerProfile powerProfile,
+class AudioPowerStatsProcessor extends BinaryStatePowerStatsProcessor {
+    AudioPowerStatsProcessor(PowerProfile powerProfile,
             PowerStatsUidResolver uidResolver) {
         super(BatteryConsumer.POWER_COMPONENT_AUDIO, uidResolver,
                 powerProfile.getAveragePower(PowerProfile.POWER_AUDIO));
diff --git a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessor.java
similarity index 97%
rename from services/core/java/com/android/server/power/stats/BinaryStatePowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessor.java
index 03df46a..e45a707 100644
--- a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessor.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import android.annotation.IntDef;
 import android.os.BatteryStats;
@@ -22,6 +22,9 @@
 import android.os.Process;
 
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.UsageBasedPowerEstimator;
+import com.android.server.power.stats.format.BinaryStatePowerStatsLayout;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/services/core/java/com/android/server/power/stats/BluetoothPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/BluetoothPowerStatsProcessor.java
similarity index 97%
rename from services/core/java/com/android/server/power/stats/BluetoothPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/BluetoothPowerStatsProcessor.java
index 077b057..4c1a0db 100644
--- a/services/core/java/com/android/server/power/stats/BluetoothPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/BluetoothPowerStatsProcessor.java
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import com.android.internal.os.PowerProfile;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.UsageBasedPowerEstimator;
+import com.android.server.power.stats.format.BluetoothPowerStatsLayout;
 
 import java.util.ArrayList;
 import java.util.List;
 
-public class BluetoothPowerStatsProcessor extends PowerStatsProcessor {
-    private static final String TAG = "BluetoothPowerStatsProcessor";
-
+class BluetoothPowerStatsProcessor extends PowerStatsProcessor {
     private final UsageBasedPowerEstimator mRxPowerEstimator;
     private final UsageBasedPowerEstimator mTxPowerEstimator;
     private final UsageBasedPowerEstimator mIdlePowerEstimator;
@@ -37,7 +37,7 @@
     private long[] mTmpDeviceStatsArray;
     private long[] mTmpUidStatsArray;
 
-    public BluetoothPowerStatsProcessor(PowerProfile powerProfile) {
+    BluetoothPowerStatsProcessor(PowerProfile powerProfile) {
         mRxPowerEstimator = new UsageBasedPowerEstimator(
                 powerProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_RX));
         mTxPowerEstimator = new UsageBasedPowerEstimator(
diff --git a/services/core/java/com/android/server/power/stats/CameraPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/CameraPowerStatsProcessor.java
similarity index 82%
rename from services/core/java/com/android/server/power/stats/CameraPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/CameraPowerStatsProcessor.java
index 15c3eb8..8309061 100644
--- a/services/core/java/com/android/server/power/stats/CameraPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/CameraPowerStatsProcessor.java
@@ -14,15 +14,16 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import android.os.BatteryConsumer;
 import android.os.BatteryStats;
 
 import com.android.internal.os.PowerProfile;
+import com.android.server.power.stats.PowerStatsUidResolver;
 
-public class CameraPowerStatsProcessor extends BinaryStatePowerStatsProcessor {
-    public CameraPowerStatsProcessor(PowerProfile powerProfile,
+class CameraPowerStatsProcessor extends BinaryStatePowerStatsProcessor {
+    CameraPowerStatsProcessor(PowerProfile powerProfile,
             PowerStatsUidResolver uidResolver) {
         super(BatteryConsumer.POWER_COMPONENT_CAMERA, uidResolver,
                 powerProfile.getAveragePower(PowerProfile.POWER_CAMERA));
diff --git a/services/core/java/com/android/server/power/stats/CpuPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/CpuPowerStatsProcessor.java
similarity index 97%
rename from services/core/java/com/android/server/power/stats/CpuPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/CpuPowerStatsProcessor.java
index 6da0a8f..5f7a3da 100644
--- a/services/core/java/com/android/server/power/stats/CpuPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/CpuPowerStatsProcessor.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import android.util.ArraySet;
 import android.util.Log;
@@ -22,13 +22,14 @@
 import com.android.internal.os.CpuScalingPolicies;
 import com.android.internal.os.PowerProfile;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.CpuPowerStatsLayout;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 
-public class CpuPowerStatsProcessor extends PowerStatsProcessor {
+class CpuPowerStatsProcessor extends PowerStatsProcessor {
     private static final String TAG = "CpuPowerStatsProcessor";
 
     private static final double HOUR_IN_MILLIS = TimeUnit.HOURS.toMillis(1);
@@ -72,7 +73,7 @@
     // Temp array for retrieval of UID power stats, to avoid repeated allocations
     private long[] mTmpUidStatsArray;
 
-    public CpuPowerStatsProcessor(PowerProfile powerProfile, CpuScalingPolicies scalingPolicies) {
+    CpuPowerStatsProcessor(PowerProfile powerProfile, CpuScalingPolicies scalingPolicies) {
         mCpuScalingPolicies = scalingPolicies;
         mCpuScalingStepCount = scalingPolicies.getScalingStepCount();
         mScalingStepToCluster = new int[mCpuScalingStepCount];
@@ -104,8 +105,7 @@
         }
 
         mLastUsedDescriptor = descriptor;
-        mStatsLayout = new CpuPowerStatsLayout();
-        mStatsLayout.fromExtras(descriptor.extras);
+        mStatsLayout = new CpuPowerStatsLayout(descriptor);
 
         mTmpDeviceStatsArray = new long[descriptor.statsArrayLength];
         mTmpUidStatsArray = new long[descriptor.uidStatsArrayLength];
@@ -138,7 +138,7 @@
     }
 
     @Override
-    public void finish(PowerComponentAggregatedPowerStats stats, long timestampMs) {
+    void finish(PowerComponentAggregatedPowerStats stats, long timestampMs) {
         if (stats.getPowerStatsDescriptor() == null) {
             return;
         }
diff --git a/services/core/java/com/android/server/power/stats/CustomEnergyConsumerPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsProcessor.java
similarity index 94%
rename from services/core/java/com/android/server/power/stats/CustomEnergyConsumerPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsProcessor.java
index a86242a..76adc47 100644
--- a/services/core/java/com/android/server/power/stats/CustomEnergyConsumerPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsProcessor.java
@@ -14,14 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.EnergyConsumerPowerStatsLayout;
 
 import java.util.ArrayList;
 import java.util.List;
 
-public class CustomEnergyConsumerPowerStatsProcessor extends PowerStatsProcessor {
+class CustomEnergyConsumerPowerStatsProcessor extends PowerStatsProcessor {
     private static final EnergyConsumerPowerStatsLayout sLayout =
             new EnergyConsumerPowerStatsLayout();
     private long[] mTmpDeviceStatsArray;
diff --git a/services/core/java/com/android/server/power/stats/FlashlightPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/FlashlightPowerStatsProcessor.java
similarity index 82%
rename from services/core/java/com/android/server/power/stats/FlashlightPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/FlashlightPowerStatsProcessor.java
index f7216c9..b0bef69 100644
--- a/services/core/java/com/android/server/power/stats/FlashlightPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/FlashlightPowerStatsProcessor.java
@@ -14,15 +14,16 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import android.os.BatteryConsumer;
 import android.os.BatteryStats;
 
 import com.android.internal.os.PowerProfile;
+import com.android.server.power.stats.PowerStatsUidResolver;
 
-public class FlashlightPowerStatsProcessor extends BinaryStatePowerStatsProcessor {
-    public FlashlightPowerStatsProcessor(PowerProfile powerProfile,
+class FlashlightPowerStatsProcessor extends BinaryStatePowerStatsProcessor {
+    FlashlightPowerStatsProcessor(PowerProfile powerProfile,
             PowerStatsUidResolver uidResolver) {
         super(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT, uidResolver,
                 powerProfile.getAveragePower(PowerProfile.POWER_FLASHLIGHT));
diff --git a/services/core/java/com/android/server/power/stats/GnssPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/GnssPowerStatsProcessor.java
similarity index 94%
rename from services/core/java/com/android/server/power/stats/GnssPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/GnssPowerStatsProcessor.java
index 0b28710..f1e3e90 100644
--- a/services/core/java/com/android/server/power/stats/GnssPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/GnssPowerStatsProcessor.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import android.location.GnssSignalQuality;
 import android.os.BatteryConsumer;
@@ -23,10 +23,13 @@
 
 import com.android.internal.os.PowerProfile;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.UsageBasedPowerEstimator;
+import com.android.server.power.stats.format.GnssPowerStatsLayout;
 
 import java.util.Arrays;
 
-public class GnssPowerStatsProcessor extends BinaryStatePowerStatsProcessor {
+class GnssPowerStatsProcessor extends BinaryStatePowerStatsProcessor {
     private static final GnssPowerStatsLayout sStatsLayout = new GnssPowerStatsLayout();
     private final UsageBasedPowerEstimator[] mSignalLevelEstimators =
             new UsageBasedPowerEstimator[GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS];
@@ -37,7 +40,7 @@
     private final long[] mGnssSignalDurations =
             new long[GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS];
 
-    public GnssPowerStatsProcessor(PowerProfile powerProfile, PowerStatsUidResolver uidResolver) {
+    GnssPowerStatsProcessor(PowerProfile powerProfile, PowerStatsUidResolver uidResolver) {
         super(BatteryConsumer.POWER_COMPONENT_GNSS, uidResolver,
                 powerProfile.getAveragePower(PowerProfile.POWER_GPS_ON),
                 sStatsLayout);
diff --git a/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessor.java
similarity index 96%
rename from services/core/java/com/android/server/power/stats/MobileRadioPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessor.java
index dcce562..b4c40de8 100644
--- a/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessor.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import android.os.BatteryStats;
 import android.telephony.CellSignalStrength;
@@ -26,13 +26,15 @@
 import com.android.internal.os.PowerProfile;
 import com.android.internal.os.PowerStats;
 import com.android.internal.power.ModemPowerProfile;
+import com.android.server.power.stats.UsageBasedPowerEstimator;
+import com.android.server.power.stats.format.MobileRadioPowerStatsLayout;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-public class MobileRadioPowerStatsProcessor extends PowerStatsProcessor {
-    private static final String TAG = "MobileRadioPowerStatsProcessor";
+class MobileRadioPowerStatsProcessor extends PowerStatsProcessor {
+    private static final String TAG = "MobileRadioPowerStats";
     private static final boolean DEBUG = false;
 
     private static final int NUM_SIGNAL_STRENGTH_LEVELS =
@@ -61,7 +63,7 @@
     private long[] mTmpStateStatsArray;
     private long[] mTmpUidStatsArray;
 
-    public MobileRadioPowerStatsProcessor(PowerProfile powerProfile) {
+    MobileRadioPowerStatsProcessor(PowerProfile powerProfile) {
         final double sleepDrainRateMa = powerProfile.getAverageBatteryDrainOrDefaultMa(
                 PowerProfile.SUBSYSTEM_MODEM | ModemPowerProfile.MODEM_DRAIN_TYPE_SLEEP,
                 Double.NaN);
@@ -101,7 +103,7 @@
                     ? ServiceState.FREQUENCY_RANGE_COUNT : 1;
             for (int freqRange = 0; freqRange < freqCount; freqRange++) {
                 mRxTxPowerEstimators.put(
-                        MobileRadioPowerStatsCollector.makeStateKey(rat, freqRange),
+                        MobileRadioPowerStatsLayout.makeStateKey(rat, freqRange),
                         buildRxTxPowerEstimators(powerProfile, rat, freqRange));
             }
         }
@@ -114,8 +116,7 @@
                 ModemPowerProfile.MODEM_DRAIN_TYPE_RX, rat, freqRange, IGNORE);
         double rxDrainRateMa = powerProfile.getAverageBatteryDrainOrDefaultMa(rxKey, Double.NaN);
         if (Double.isNaN(rxDrainRateMa)) {
-            Log.w(TAG, "Unavailable Power Profile constant for key 0x"
-                    + Long.toHexString(rxKey));
+            Log.w(TAG, "Unavailable Power Profile constant for key 0x" + Long.toHexString(rxKey));
             rxDrainRateMa = 0;
         }
         estimators.mRxPowerEstimator = new UsageBasedPowerEstimator(rxDrainRateMa);
diff --git a/services/core/java/com/android/server/power/stats/processor/MultiStatePowerAttributor.java b/services/core/java/com/android/server/power/stats/processor/MultiStatePowerAttributor.java
new file mode 100644
index 0000000..2ba4a52
--- /dev/null
+++ b/services/core/java/com/android/server/power/stats/processor/MultiStatePowerAttributor.java
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2024 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.power.stats.processor;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.hardware.SensorManager;
+import android.os.BatteryConsumer;
+import android.os.BatteryUsageStats;
+import android.util.IndentingPrintWriter;
+import android.util.Slog;
+import android.util.SparseBooleanArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BatteryStatsHistory;
+import com.android.internal.os.CpuScalingPolicies;
+import com.android.internal.os.PowerProfile;
+import com.android.server.power.stats.PowerAttributor;
+import com.android.server.power.stats.PowerStatsSpan;
+import com.android.server.power.stats.PowerStatsStore;
+import com.android.server.power.stats.PowerStatsUidResolver;
+
+import java.util.List;
+
+public class MultiStatePowerAttributor implements PowerAttributor {
+    private static final String TAG = "MultiStatePowerAttributor";
+
+    private final PowerStatsStore mPowerStatsStore;
+    private final PowerStatsExporter mPowerStatsExporter;
+    private final PowerStatsAggregator mPowerStatsAggregator;
+    private final SparseBooleanArray mPowerStatsExporterEnabled = new SparseBooleanArray();
+
+    // TODO(b/346371828): remove dependency on PowerStatsUidResolver. At the time of power
+    // attribution isolates UIDs are supposed to be long forgotten.
+    public MultiStatePowerAttributor(Context context, PowerStatsStore powerStatsStore,
+            @NonNull PowerProfile powerProfile, @NonNull CpuScalingPolicies cpuScalingPolicies,
+            @NonNull PowerStatsUidResolver powerStatsUidResolver) {
+        this(powerStatsStore, new PowerStatsAggregator(
+                createAggregatedPowerStatsConfig(context, powerProfile, cpuScalingPolicies,
+                        powerStatsUidResolver)));
+    }
+
+    @VisibleForTesting
+    MultiStatePowerAttributor(PowerStatsStore powerStatsStore,
+            PowerStatsAggregator powerStatsAggregator) {
+        mPowerStatsStore = powerStatsStore;
+        mPowerStatsAggregator = powerStatsAggregator;
+        mPowerStatsStore.addSectionReader(
+                new AggregatedPowerStatsSection.Reader(mPowerStatsAggregator.getConfig()));
+        mPowerStatsExporter = new PowerStatsExporter(mPowerStatsStore, mPowerStatsAggregator);
+    }
+
+    private static AggregatedPowerStatsConfig createAggregatedPowerStatsConfig(Context context,
+            PowerProfile powerProfile, CpuScalingPolicies cpuScalingPolicies,
+            PowerStatsUidResolver powerStatsUidResolver) {
+        AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig();
+        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_CPU)
+                .trackDeviceStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN)
+                .trackUidStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN,
+                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
+                .setProcessorSupplier(
+                        () -> new CpuPowerStatsProcessor(powerProfile, cpuScalingPolicies));
+
+        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_SCREEN)
+                .trackDeviceStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN)
+                .trackUidStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN)
+                .setProcessorSupplier(
+                        () -> new ScreenPowerStatsProcessor(powerProfile));
+
+        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY,
+                        BatteryConsumer.POWER_COMPONENT_SCREEN)
+                .setProcessorSupplier(AmbientDisplayPowerStatsProcessor::new);
+
+        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
+                .trackDeviceStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN)
+                .trackUidStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN,
+                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
+                .setProcessorSupplier(
+                        () -> new MobileRadioPowerStatsProcessor(powerProfile));
+
+        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_PHONE,
+                        BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
+                .setProcessorSupplier(PhoneCallPowerStatsProcessor::new);
+
+        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_WIFI)
+                .trackDeviceStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN)
+                .trackUidStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN,
+                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
+                .setProcessorSupplier(
+                        () -> new WifiPowerStatsProcessor(powerProfile));
+
+        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_BLUETOOTH)
+                .trackDeviceStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN)
+                .trackUidStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN,
+                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
+                .setProcessorSupplier(
+                        () -> new BluetoothPowerStatsProcessor(powerProfile));
+
+        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_AUDIO)
+                .trackDeviceStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN)
+                .trackUidStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN,
+                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
+                .setProcessorSupplier(
+                        () -> new AudioPowerStatsProcessor(powerProfile, powerStatsUidResolver));
+
+        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_VIDEO)
+                .trackDeviceStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN)
+                .trackUidStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN,
+                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
+                .setProcessorSupplier(
+                        () -> new VideoPowerStatsProcessor(powerProfile, powerStatsUidResolver));
+
+        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT)
+                .trackDeviceStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN)
+                .trackUidStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN,
+                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
+                .setProcessorSupplier(
+                        () -> new FlashlightPowerStatsProcessor(powerProfile,
+                                powerStatsUidResolver));
+
+        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_CAMERA)
+                .trackDeviceStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN)
+                .trackUidStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN,
+                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
+                .setProcessorSupplier(
+                        () -> new CameraPowerStatsProcessor(powerProfile, powerStatsUidResolver));
+
+        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_GNSS)
+                .trackDeviceStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN)
+                .trackUidStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN,
+                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
+                .setProcessorSupplier(
+                        () -> new GnssPowerStatsProcessor(powerProfile, powerStatsUidResolver));
+
+        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_SENSORS)
+                .trackDeviceStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN)
+                .trackUidStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN,
+                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
+                .setProcessorSupplier(() -> new SensorPowerStatsProcessor(
+                        () -> context.getSystemService(SensorManager.class)));
+
+        config.trackCustomPowerComponents(CustomEnergyConsumerPowerStatsProcessor::new)
+                .trackDeviceStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN)
+                .trackUidStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN,
+                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE);
+        return config;
+    }
+
+    /**
+     * Marks the specified power component as supported by this PowerAttributor
+     */
+    public void setPowerComponentSupported(@BatteryConsumer.PowerComponentId int powerComponentId,
+            boolean enabled) {
+        mPowerStatsExporterEnabled.put(powerComponentId, enabled);
+        mPowerStatsExporter.setPowerComponentEnabled(powerComponentId, enabled);
+    }
+
+    @Override
+    public boolean isPowerComponentSupported(
+            @BatteryConsumer.PowerComponentId int powerComponentId) {
+        return mPowerStatsExporterEnabled.get(powerComponentId);
+    }
+
+    @Override
+    public void estimatePowerConsumption(BatteryUsageStats.Builder batteryUsageStatsBuilder,
+            BatteryStatsHistory batteryHistory, long monotonicStartTime, long monotonicEndTime) {
+        mPowerStatsExporter.exportAggregatedPowerStats(batteryUsageStatsBuilder, batteryHistory,
+                monotonicStartTime, monotonicEndTime);
+    }
+
+    @Override
+    public void dumpEstimatedPowerConsumption(IndentingPrintWriter ipw,
+            BatteryStatsHistory batteryStatsHistory,
+            long startTime, long endTime) {
+        mPowerStatsAggregator.aggregatePowerStats(batteryStatsHistory, startTime, endTime,
+                stats -> {
+                    // Create a PowerStatsSpan for consistency of the textual output
+                    PowerStatsSpan span = createPowerStatsSpan(stats);
+                    if (span != null) {
+                        span.dump(ipw);
+                    }
+                });
+    }
+
+    @Override
+    public long storeEstimatedPowerConsumption(BatteryStatsHistory batteryStatsHistory,
+            long startTime, long endTimeMs) {
+        long[] lastSavedMonotonicTime = new long[1];
+        mPowerStatsAggregator.aggregatePowerStats(batteryStatsHistory, startTime, endTimeMs,
+                stats -> {
+                    storeAggregatedPowerStats(stats);
+                    lastSavedMonotonicTime[0] = stats.getStartTime() + stats.getDuration();
+                });
+        return lastSavedMonotonicTime[0];
+    }
+
+    @VisibleForTesting
+    void storeAggregatedPowerStats(AggregatedPowerStats stats) {
+        PowerStatsSpan span = createPowerStatsSpan(stats);
+        if (span == null) {
+            return;
+        }
+        mPowerStatsStore.storePowerStatsSpan(span);
+    }
+
+    private static PowerStatsSpan createPowerStatsSpan(AggregatedPowerStats stats) {
+        List<AggregatedPowerStats.ClockUpdate> clockUpdates = stats.getClockUpdates();
+        if (clockUpdates.isEmpty()) {
+            Slog.w(TAG, "No clock updates in aggregated power stats " + stats);
+            return null;
+        }
+
+        long monotonicTime = clockUpdates.get(0).monotonicTime;
+        long durationSum = 0;
+        PowerStatsSpan span = new PowerStatsSpan(monotonicTime);
+        for (int i = 0; i < clockUpdates.size(); i++) {
+            AggregatedPowerStats.ClockUpdate clockUpdate = clockUpdates.get(i);
+            long duration;
+            if (i == clockUpdates.size() - 1) {
+                duration = stats.getDuration() - durationSum;
+            } else {
+                duration = clockUpdate.monotonicTime - monotonicTime;
+            }
+            span.addTimeFrame(clockUpdate.monotonicTime, clockUpdate.currentTime, duration);
+            monotonicTime = clockUpdate.monotonicTime;
+            durationSum += duration;
+        }
+
+        span.addSection(new AggregatedPowerStatsSection(stats));
+        return span;
+    }
+
+    @Override
+    public long getLastSavedEstimatesPowerConsumptionTimestamp() {
+        long timestamp = -1;
+        for (PowerStatsSpan.Metadata metadata : mPowerStatsStore.getTableOfContents()) {
+            if (metadata.getSections().contains(AggregatedPowerStatsSection.TYPE)) {
+                for (PowerStatsSpan.TimeFrame timeFrame : metadata.getTimeFrames()) {
+                    long endMonotonicTime = timeFrame.startMonotonicTime + timeFrame.duration;
+                    if (endMonotonicTime > timestamp) {
+                        timestamp = endMonotonicTime;
+                    }
+                }
+            }
+        }
+        return timestamp;
+    }
+}
diff --git a/services/core/java/com/android/server/power/stats/MultiStateStats.java b/services/core/java/com/android/server/power/stats/processor/MultiStateStats.java
similarity index 94%
rename from services/core/java/com/android/server/power/stats/MultiStateStats.java
rename to services/core/java/com/android/server/power/stats/processor/MultiStateStats.java
index c3a0aeb..28474a5 100644
--- a/services/core/java/com/android/server/power/stats/MultiStateStats.java
+++ b/services/core/java/com/android/server/power/stats/processor/MultiStateStats.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import android.util.Slog;
 
@@ -37,7 +37,7 @@
  * CPU residency, Network packet counts etc.  All metrics must be represented as <code>long</code>
  * values;
  */
-public class MultiStateStats {
+class MultiStateStats {
     private static final String TAG = "MultiStateStats";
 
     private static final String XML_TAG_STATS = "stats";
@@ -47,12 +47,12 @@
      * A set of states, e.g. on-battery, screen-on, procstate.  The state values are integers
      * from 0 to States.mLabels.length
      */
-    public static class States {
+    static class States {
         final String mName;
         final boolean mTracked;
         final String[] mLabels;
 
-        public States(String name, boolean tracked, String... labels) {
+        States(String name, boolean tracked, String... labels) {
             mName = name;
             mTracked = tracked;
             mLabels = labels;
@@ -121,7 +121,7 @@
      * Factory for MultiStateStats containers. All generated containers retain their connection
      * to the Factory and the corresponding configuration.
      */
-    public static class Factory {
+    static class Factory {
         private static final int INVALID_SERIAL_STATE = -1;
         final int mDimensionCount;
         final States[] mStates;
@@ -147,7 +147,7 @@
         final int[] mCompositeToSerialState;
         final int mSerialStateCount;
 
-        public Factory(int dimensionCount, States... states) {
+        Factory(int dimensionCount, States... states) {
             mDimensionCount = dimensionCount;
             mStates = states;
 
@@ -250,7 +250,7 @@
         /**
          * Allocates a new stats container using this Factory's configuration.
          */
-        public MultiStateStats create() {
+        MultiStateStats create() {
             return new MultiStateStats(this, mDimensionCount);
         }
 
@@ -293,16 +293,16 @@
     private int mCompositeState;
     private boolean mTracking;
 
-    public MultiStateStats(Factory factory, int dimensionCount) {
+    MultiStateStats(Factory factory, int dimensionCount) {
         this.mFactory = factory;
         mCounter = new LongArrayMultiStateCounter(factory.mSerialStateCount, dimensionCount);
     }
 
-    public int getDimensionCount() {
+    int getDimensionCount() {
         return mFactory.mDimensionCount;
     }
 
-    public States[] getStates() {
+    States[] getStates() {
         return mFactory.mStates;
     }
 
@@ -310,7 +310,7 @@
      * Copies time-in-state and timestamps from the supplied prototype. Does not
      * copy accumulated counts.
      */
-    public void copyStatesFrom(MultiStateStats otherStats) {
+    void copyStatesFrom(MultiStateStats otherStats) {
         mCounter.copyStatesFrom(otherStats.mCounter);
     }
 
@@ -322,7 +322,7 @@
      * @param state       The new value of the state (e.g. 0 or 1 for "on-battery")
      * @param timestampMs The time when the state change occurred
      */
-    public void setState(int stateIndex, int state, long timestampMs) {
+    void setState(int stateIndex, int state, long timestampMs) {
         if (!mTracking) {
             mCounter.updateValues(new long[mCounter.getArrayLength()], timestampMs);
             mTracking = true;
@@ -335,7 +335,7 @@
      * Adds the delta to the metrics.  The number of values must correspond to the dimension count
      * supplied to the Factory constructor
      */
-    public void increment(long[] values, long timestampMs) {
+    void increment(long[] values, long timestampMs) {
         mCounter.incrementValues(values, timestampMs);
         mTracking = true;
     }
@@ -343,21 +343,21 @@
     /**
      * Returns accumulated stats for the specified composite state.
      */
-    public void getStats(long[] outValues, int[] states) {
+    void getStats(long[] outValues, int[] states) {
         mCounter.getCounts(outValues, mFactory.getSerialState(states));
     }
 
     /**
      * Updates the stats values for the provided combination of states.
      */
-    public void setStats(int[] states, long[] values) {
+    void setStats(int[] states, long[] values) {
         mCounter.setValues(mFactory.getSerialState(states), values);
     }
 
     /**
      * Resets the counters.
      */
-    public void reset() {
+    void reset() {
         mCounter.reset();
         mTracking = false;
     }
@@ -365,7 +365,7 @@
     /**
      * Stores contents in an XML doc.
      */
-    public void writeXml(TypedXmlSerializer serializer) throws IOException {
+    void writeXml(TypedXmlSerializer serializer) throws IOException {
         long[] tmpArray = new long[mCounter.getArrayLength()];
 
         try {
@@ -420,8 +420,7 @@
      * Populates the object with contents in an XML doc. The parser is expected to be
      * positioned on the opening tag of the corresponding element.
      */
-    public boolean readFromXml(TypedXmlPullParser parser) throws XmlPullParserException,
-            IOException {
+    boolean readFromXml(TypedXmlPullParser parser) throws XmlPullParserException, IOException {
         String outerTag = parser.getName();
         long[] tmpArray = new long[mCounter.getArrayLength()];
         int eventType = parser.getEventType();
diff --git a/services/core/java/com/android/server/power/stats/PhoneCallPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/PhoneCallPowerStatsProcessor.java
similarity index 88%
rename from services/core/java/com/android/server/power/stats/PhoneCallPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/PhoneCallPowerStatsProcessor.java
index ec23fa0..3957ae0 100644
--- a/services/core/java/com/android/server/power/stats/PhoneCallPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/PhoneCallPowerStatsProcessor.java
@@ -13,24 +13,25 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import android.os.BatteryConsumer;
 import android.os.PersistableBundle;
 
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.MobileRadioPowerStatsLayout;
+import com.android.server.power.stats.format.PhoneCallPowerStatsLayout;
 
-public class PhoneCallPowerStatsProcessor extends PowerStatsProcessor {
-    private final PowerStatsLayout mStatsLayout;
+class PhoneCallPowerStatsProcessor extends PowerStatsProcessor {
+    private final PhoneCallPowerStatsLayout mStatsLayout;
     private final PowerStats.Descriptor mDescriptor;
     private final long[] mTmpDeviceStats;
     private PowerStats.Descriptor mMobileRadioStatsDescriptor;
     private MobileRadioPowerStatsLayout mMobileRadioStatsLayout;
     private long[] mTmpMobileRadioDeviceStats;
 
-    public PhoneCallPowerStatsProcessor() {
-        mStatsLayout = new PowerStatsLayout();
-        mStatsLayout.addDeviceSectionPowerEstimate();
+    PhoneCallPowerStatsProcessor() {
+        mStatsLayout = new PhoneCallPowerStatsLayout();
         PersistableBundle extras = new PersistableBundle();
         mStatsLayout.toExtras(extras);
         mDescriptor = new PowerStats.Descriptor(BatteryConsumer.POWER_COMPONENT_PHONE,
diff --git a/services/core/java/com/android/server/power/stats/PowerComponentAggregatedPowerStats.java b/services/core/java/com/android/server/power/stats/processor/PowerComponentAggregatedPowerStats.java
similarity index 98%
rename from services/core/java/com/android/server/power/stats/PowerComponentAggregatedPowerStats.java
rename to services/core/java/com/android/server/power/stats/processor/PowerComponentAggregatedPowerStats.java
index a92a6fd3..d04c5ba 100644
--- a/services/core/java/com/android/server/power/stats/PowerComponentAggregatedPowerStats.java
+++ b/services/core/java/com/android/server/power/stats/processor/PowerComponentAggregatedPowerStats.java
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
-
-import static com.android.server.power.stats.MultiStateStats.STATE_DOES_NOT_EXIST;
+package com.android.server.power.stats.processor;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -147,7 +145,8 @@
 
         int uidStateId = MultiStateStats.States
                 .findTrackedStateByName(mUidStateConfig, mDeviceStateConfig[stateId].getName());
-        if (uidStateId != STATE_DOES_NOT_EXIST && mUidStateConfig[uidStateId].isTracked()) {
+        if (uidStateId != MultiStateStats.STATE_DOES_NOT_EXIST
+                && mUidStateConfig[uidStateId].isTracked()) {
             for (int i = mUidStats.size() - 1; i >= 0; i--) {
                 PowerComponentAggregatedPowerStats.UidStats uidStats = mUidStats.valueAt(i);
                 if (uidStats.stats == null) {
@@ -271,7 +270,7 @@
                 if (mUidStateConfig[stateId].isTracked()) {
                     int deviceStateId = MultiStateStats.States.findTrackedStateByName(
                             mDeviceStateConfig, mUidStateConfig[stateId].getName());
-                    if (deviceStateId != STATE_DOES_NOT_EXIST
+                    if (deviceStateId != MultiStateStats.STATE_DOES_NOT_EXIST
                             && mDeviceStateConfig[deviceStateId].isTracked()) {
                         uidStats.states[stateId] = mDeviceStates[deviceStateId];
                     }
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java b/services/core/java/com/android/server/power/stats/processor/PowerStatsAggregator.java
similarity index 92%
rename from services/core/java/com/android/server/power/stats/PowerStatsAggregator.java
rename to services/core/java/com/android/server/power/stats/processor/PowerStatsAggregator.java
index c734f68..32c1056 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java
+++ b/services/core/java/com/android/server/power/stats/processor/PowerStatsAggregator.java
@@ -13,13 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import android.annotation.NonNull;
 import android.os.BatteryConsumer;
 import android.os.BatteryStats;
 import android.util.SparseBooleanArray;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.BatteryStatsHistory;
 import com.android.internal.os.BatteryStatsHistoryIterator;
 
@@ -33,20 +34,22 @@
 public class PowerStatsAggregator {
     private static final long UNINITIALIZED = -1;
     private final AggregatedPowerStatsConfig mAggregatedPowerStatsConfig;
-    private final BatteryStatsHistory mHistory;
     private final SparseBooleanArray mEnabledComponents =
             new SparseBooleanArray(BatteryConsumer.POWER_COMPONENT_COUNT + 10);
     private AggregatedPowerStats mStats;
     private int mCurrentBatteryState = AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
     private int mCurrentScreenState = AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
 
-    public PowerStatsAggregator(@NonNull AggregatedPowerStatsConfig aggregatedPowerStatsConfig,
-            @NonNull BatteryStatsHistory history) {
-        mAggregatedPowerStatsConfig = aggregatedPowerStatsConfig;
-        mHistory = history;
+    @VisibleForTesting
+    public PowerStatsAggregator() {
+        this(new AggregatedPowerStatsConfig());
     }
 
-    public AggregatedPowerStatsConfig getConfig() {
+    PowerStatsAggregator(@NonNull AggregatedPowerStatsConfig aggregatedPowerStatsConfig) {
+        mAggregatedPowerStatsConfig = aggregatedPowerStatsConfig;
+    }
+
+    AggregatedPowerStatsConfig getConfig() {
         return mAggregatedPowerStatsConfig;
     }
 
@@ -71,7 +74,7 @@
      * Note: the AggregatedPowerStats object is reused, so the consumer should fully consume
      * the stats in the <code>accept</code> method and never cache it.
      */
-    public void aggregatePowerStats(long startTimeMs, long endTimeMs,
+    public void aggregatePowerStats(BatteryStatsHistory history, long startTimeMs, long endTimeMs,
             Consumer<AggregatedPowerStats> consumer) {
         synchronized (this) {
             if (mStats == null) {
@@ -85,7 +88,7 @@
             long lastTime = 0;
             int lastStates = 0xFFFFFFFF;
             int lastStates2 = 0xFFFFFFFF;
-            try (BatteryStatsHistoryIterator iterator = mHistory.iterate(startTimeMs, endTimeMs)) {
+            try (BatteryStatsHistoryIterator iterator = history.iterate(startTimeMs, endTimeMs)) {
                 while (iterator.hasNext()) {
                     BatteryStats.HistoryItem item = iterator.next();
 
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsExporter.java b/services/core/java/com/android/server/power/stats/processor/PowerStatsExporter.java
similarity index 94%
rename from services/core/java/com/android/server/power/stats/PowerStatsExporter.java
rename to services/core/java/com/android/server/power/stats/processor/PowerStatsExporter.java
index c5bed24..fab87d6 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsExporter.java
+++ b/services/core/java/com/android/server/power/stats/processor/PowerStatsExporter.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import android.annotation.Nullable;
 import android.os.AggregateBatteryConsumer;
@@ -24,7 +24,11 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BatteryStatsHistory;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.PowerStatsSpan;
+import com.android.server.power.stats.PowerStatsStore;
+import com.android.server.power.stats.format.PowerStatsLayout;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -35,19 +39,18 @@
  * Given a time range, converts accumulated PowerStats to BatteryUsageStats.  Combines
  * stores spans of PowerStats with the yet-unprocessed tail of battery history.
  */
-public class PowerStatsExporter {
+class PowerStatsExporter {
     private static final String TAG = "PowerStatsExporter";
     private final PowerStatsStore mPowerStatsStore;
     private final PowerStatsAggregator mPowerStatsAggregator;
     private final long mBatterySessionTimeSpanSlackMillis;
     private static final long BATTERY_SESSION_TIME_SPAN_SLACK_MILLIS = TimeUnit.MINUTES.toMillis(2);
 
-    public PowerStatsExporter(PowerStatsStore powerStatsStore,
-            PowerStatsAggregator powerStatsAggregator) {
+    PowerStatsExporter(PowerStatsStore powerStatsStore, PowerStatsAggregator powerStatsAggregator) {
         this(powerStatsStore, powerStatsAggregator, BATTERY_SESSION_TIME_SPAN_SLACK_MILLIS);
     }
 
-    public PowerStatsExporter(PowerStatsStore powerStatsStore,
+    PowerStatsExporter(PowerStatsStore powerStatsStore,
             PowerStatsAggregator powerStatsAggregator,
             long batterySessionTimeSpanSlackMillis) {
         mPowerStatsStore = powerStatsStore;
@@ -59,8 +62,8 @@
      * Populates the provided BatteryUsageStats.Builder with power estimates from the accumulated
      * PowerStats, both stored in PowerStatsStore and not-yet processed.
      */
-    public void exportAggregatedPowerStats(BatteryUsageStats.Builder batteryUsageStatsBuilder,
-            long monotonicStartTime, long monotonicEndTime) {
+    void exportAggregatedPowerStats(BatteryUsageStats.Builder batteryUsageStatsBuilder,
+            BatteryStatsHistory history, long monotonicStartTime, long monotonicEndTime) {
         synchronized (mPowerStatsAggregator) {
             boolean hasStoredSpans = false;
             long maxEndTime = monotonicStartTime;
@@ -111,7 +114,7 @@
 
             if (!hasStoredSpans
                     || maxEndTime < monotonicEndTime - mBatterySessionTimeSpanSlackMillis) {
-                mPowerStatsAggregator.aggregatePowerStats(maxEndTime, monotonicEndTime,
+                mPowerStatsAggregator.aggregatePowerStats(history, maxEndTime, monotonicEndTime,
                         stats -> populateBatteryUsageStatsBuilder(batteryUsageStatsBuilder, stats));
             }
             mPowerStatsAggregator.reset();
@@ -140,9 +143,7 @@
             return;
         }
 
-        PowerStatsLayout layout = new PowerStatsLayout();
-        layout.fromExtras(descriptor.extras);
-
+        PowerStatsLayout layout = new PowerStatsLayout(descriptor);
         long[] deviceStats = new long[descriptor.statsArrayLength];
         for (int screenState = 0; screenState < BatteryConsumer.SCREEN_STATE_COUNT; screenState++) {
             if (batteryUsageStatsBuilder.isScreenStateDataNeeded()) {
@@ -328,8 +329,8 @@
         BatteryConsumer.Key key = getKeyForPartialTotal(batteryUsageStatsBuilder, allAppsScope,
                 powerComponentId, screenState, powerState);
         if (key != null) {
-                allAppsScope.addConsumedPower(key, powerAllApps,
-                        BatteryConsumer.POWER_MODEL_UNDEFINED);
+            allAppsScope.addConsumedPower(key, powerAllApps,
+                    BatteryConsumer.POWER_MODEL_UNDEFINED);
         }
         allAppsScope.addConsumedPower(powerComponentId, powerAllApps,
                 BatteryConsumer.POWER_MODEL_UNDEFINED);
@@ -393,7 +394,7 @@
         return true;
     }
 
-    void setPowerComponentEnabled(int powerComponentId, boolean enabled) {
+    public void setPowerComponentEnabled(int powerComponentId, boolean enabled) {
         mPowerStatsAggregator.setPowerComponentEnabled(powerComponentId, enabled);
     }
 }
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/PowerStatsProcessor.java
similarity index 97%
rename from services/core/java/com/android/server/power/stats/PowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/PowerStatsProcessor.java
index 6a8c6b12..838fc62 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/PowerStatsProcessor.java
@@ -13,10 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
-import static com.android.server.power.stats.MultiStateStats.STATE_DOES_NOT_EXIST;
-import static com.android.server.power.stats.MultiStateStats.States.findTrackedStateByName;
+import static com.android.server.power.stats.processor.MultiStateStats.STATE_DOES_NOT_EXIST;
+import static com.android.server.power.stats.processor.MultiStateStats.States.findTrackedStateByName;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -43,7 +43,7 @@
  * 2. For each UID, compute the proportion of the combined estimates in each state
  * and attribute the corresponding portion of the total power estimate in that state to the UID.
  */
-public abstract class PowerStatsProcessor {
+abstract class PowerStatsProcessor {
     private static final String TAG = "PowerStatsProcessor";
 
     private static final double MILLIAMPHOUR_PER_MICROCOULOMB = 1.0 / 1000.0 / 60.0 / 60.0;
diff --git a/services/core/java/com/android/server/power/stats/ScreenPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java
similarity index 93%
rename from services/core/java/com/android/server/power/stats/ScreenPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java
index 8fb1fd6..b295e30 100644
--- a/services/core/java/com/android/server/power/stats/ScreenPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java
@@ -14,28 +14,30 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import static android.os.BatteryConsumer.PROCESS_STATE_UNSPECIFIED;
 
 import static com.android.internal.os.PowerProfile.POWER_GROUP_DISPLAY_AMBIENT;
 import static com.android.internal.os.PowerProfile.POWER_GROUP_DISPLAY_SCREEN_FULL;
 import static com.android.internal.os.PowerProfile.POWER_GROUP_DISPLAY_SCREEN_ON;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_POWER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_SCREEN;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
 
 import android.os.BatteryStats;
 import android.util.Slog;
 
 import com.android.internal.os.PowerProfile;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.UsageBasedPowerEstimator;
+import com.android.server.power.stats.format.ScreenPowerStatsLayout;
 
 import java.util.ArrayList;
 import java.util.List;
 
-public class ScreenPowerStatsProcessor extends PowerStatsProcessor {
+class ScreenPowerStatsProcessor extends PowerStatsProcessor {
     private static final String TAG = "ScreenPowerStatsProcessor";
     private final int mDisplayCount;
     private final UsageBasedPowerEstimator[] mScreenOnPowerEstimators;
@@ -51,7 +53,7 @@
         public double power;
     }
 
-    public ScreenPowerStatsProcessor(PowerProfile powerProfile) {
+    ScreenPowerStatsProcessor(PowerProfile powerProfile) {
         mDisplayCount = powerProfile.getNumDisplays();
         mScreenOnPowerEstimators = new UsageBasedPowerEstimator[mDisplayCount];
         mScreenDozePowerEstimators = new UsageBasedPowerEstimator[mDisplayCount];
diff --git a/services/core/java/com/android/server/power/stats/SensorPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/SensorPowerStatsProcessor.java
similarity index 90%
rename from services/core/java/com/android/server/power/stats/SensorPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/SensorPowerStatsProcessor.java
index 79d8076..67013ea 100644
--- a/services/core/java/com/android/server/power/stats/SensorPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/SensorPowerStatsProcessor.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import android.hardware.Sensor;
 import android.hardware.SensorManager;
@@ -25,14 +25,16 @@
 import android.util.SparseArray;
 
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.PowerStatsLayout;
+import com.android.server.power.stats.format.SensorPowerStatsLayout;
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Comparator;
 import java.util.List;
 import java.util.function.Supplier;
+import java.util.stream.Collectors;
 
-public class SensorPowerStatsProcessor extends PowerStatsProcessor {
+class SensorPowerStatsProcessor extends PowerStatsProcessor {
     private static final String TAG = "SensorPowerStatsProcessor";
     private static final String ANDROID_SENSOR_TYPE_PREFIX = "android.sensor.";
 
@@ -64,7 +66,7 @@
     private long[] mTmpDeviceStatsArray;
     private long[] mTmpUidStatsArray;
 
-    public SensorPowerStatsProcessor(Supplier<SensorManager> sensorManagerSupplier) {
+    SensorPowerStatsProcessor(Supplier<SensorManager> sensorManagerSupplier) {
         mSensorManagerSupplier = sensorManagerSupplier;
     }
 
@@ -78,16 +80,9 @@
             return false;
         }
 
-        mStatsLayout = new SensorPowerStatsLayout();
-        List<Sensor> sensorList = new ArrayList<>(mSensorManager.getSensorList(Sensor.TYPE_ALL));
-        sensorList.sort(Comparator.comparingInt(Sensor::getId));
-        for (int i = 0; i < sensorList.size(); i++) {
-            Sensor sensor = sensorList.get(i);
-            String label = makeLabel(sensor, sensorList);
-            mStatsLayout.addUidSensorSection(sensor.getHandle(), label);
-        }
-        mStatsLayout.addUidSectionPowerEstimate();
-        mStatsLayout.addDeviceSectionPowerEstimate();
+        List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
+        mStatsLayout = new SensorPowerStatsLayout(sensorList.stream().collect(
+                Collectors.toMap(Sensor::getHandle, sensor -> makeLabel(sensor, sensorList))));
 
         PersistableBundle extras = new PersistableBundle();
         mStatsLayout.toExtras(extras);
@@ -231,7 +226,8 @@
         sensorState.startTime = time;
     }
 
-    private void flushPowerStats(PowerComponentAggregatedPowerStats stats, long timestamp) {
+    private void flushPowerStats(
+            PowerComponentAggregatedPowerStats stats, long timestamp) {
         mPowerStats.durationMs = timestamp - mLastUpdateTimestamp;
         stats.addProcessedPowerStats(mPowerStats, timestamp);
 
@@ -240,7 +236,8 @@
         mLastUpdateTimestamp = timestamp;
     }
 
-    private void computeUidPowerEstimates(PowerComponentAggregatedPowerStats stats,
+    private void computeUidPowerEstimates(
+            PowerComponentAggregatedPowerStats stats,
             List<Integer> uids) {
         List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
         int[] uidSensorDurationPositions = new int[sensorList.size()];
@@ -292,7 +289,8 @@
         }
     }
 
-    private void computeDevicePowerEstimates(PowerComponentAggregatedPowerStats stats) {
+    private void computeDevicePowerEstimates(
+            PowerComponentAggregatedPowerStats stats) {
         for (int i = mPlan.combinedDeviceStateEstimations.size() - 1; i >= 0; i--) {
             CombinedDeviceStateEstimate estimation =
                     mPlan.combinedDeviceStateEstimations.get(i);
diff --git a/services/core/java/com/android/server/power/stats/VideoPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/VideoPowerStatsProcessor.java
similarity index 80%
rename from services/core/java/com/android/server/power/stats/VideoPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/VideoPowerStatsProcessor.java
index 48dac8a..a6c3807 100644
--- a/services/core/java/com/android/server/power/stats/VideoPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/VideoPowerStatsProcessor.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import android.os.BatteryConsumer;
 import android.os.BatteryStats;
 
 import com.android.internal.os.PowerProfile;
+import com.android.server.power.stats.PowerStatsUidResolver;
 
-public class VideoPowerStatsProcessor extends BinaryStatePowerStatsProcessor {
-    public VideoPowerStatsProcessor(PowerProfile powerProfile,
-            PowerStatsUidResolver uidResolver) {
+class VideoPowerStatsProcessor extends BinaryStatePowerStatsProcessor {
+    VideoPowerStatsProcessor(PowerProfile powerProfile, PowerStatsUidResolver uidResolver) {
         super(BatteryConsumer.POWER_COMPONENT_VIDEO, uidResolver,
                 powerProfile.getAveragePower(PowerProfile.POWER_VIDEO));
     }
diff --git a/services/core/java/com/android/server/power/stats/WifiPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/WifiPowerStatsProcessor.java
similarity index 98%
rename from services/core/java/com/android/server/power/stats/WifiPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/WifiPowerStatsProcessor.java
index 4e035c3..0df01cf 100644
--- a/services/core/java/com/android/server/power/stats/WifiPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/WifiPowerStatsProcessor.java
@@ -14,18 +14,20 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import android.util.Slog;
 
 import com.android.internal.os.PowerProfile;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.UsageBasedPowerEstimator;
+import com.android.server.power.stats.format.WifiPowerStatsLayout;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-public class WifiPowerStatsProcessor extends PowerStatsProcessor {
+class WifiPowerStatsProcessor extends PowerStatsProcessor {
     private static final String TAG = "WifiPowerStatsProcessor";
     private static final boolean DEBUG = false;
 
@@ -46,7 +48,7 @@
     private long[] mTmpUidStatsArray;
     private boolean mHasWifiPowerController;
 
-    public WifiPowerStatsProcessor(PowerProfile powerProfile) {
+    WifiPowerStatsProcessor(PowerProfile powerProfile) {
         mRxPowerEstimator = new UsageBasedPowerEstimator(
                 powerProfile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_RX));
         mTxPowerEstimator = new UsageBasedPowerEstimator(
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index 1660ca9..35ec5ad 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -424,13 +424,19 @@
                 Intent intent = intents[i];
                 NeededUriGrants intentGrants = null;
 
-                intent.prepareToEnterSystemServer();
+                // Refuse possible leaked file descriptors.
+                if (intent.hasFileDescriptors()) {
+                    throw new IllegalArgumentException("File descriptors passed in Intent");
+                }
 
                 // Get the flag earlier because the intent may be modified in resolveActivity below.
                 final boolean componentSpecified = intent.getComponent() != null;
                 // Don't modify the client's object!
                 intent = new Intent(intent);
 
+                // Remove existing mismatch flag so it can be properly updated later
+                intent.removeExtendedFlags(Intent.EXTENDED_FLAG_FILTER_MISMATCH);
+
                 // Collect information about the target of the Intent.
                 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i],
                         0 /* startFlags */, null /* profilerInfo */, userId, filterCallingUid,
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index bf18a43..1822a80 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -721,7 +721,13 @@
             onExecutionStarted();
 
             if (mRequest.intent != null) {
-                mRequest.intent.prepareToEnterSystemServer();
+                // Refuse possible leaked file descriptors
+                if (mRequest.intent.hasFileDescriptors()) {
+                    throw new IllegalArgumentException("File descriptors passed in Intent");
+                }
+
+                // Remove existing mismatch flag so it can be properly updated later
+                mRequest.intent.removeExtendedFlags(Intent.EXTENDED_FLAG_FILTER_MISMATCH);
             }
 
             final LaunchingState launchingState;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index f5476f2..3cfb9a07 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -1317,7 +1317,12 @@
             String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle bOptions) {
         enforceNotIsolatedCaller("startActivityIntentSender");
         if (fillInIntent != null) {
-            fillInIntent.prepareToEnterSystemServer();
+            // Refuse possible leaked file descriptors
+            if (fillInIntent.hasFileDescriptors()) {
+                throw new IllegalArgumentException("File descriptors passed in Intent");
+            }
+            // Remove existing mismatch flag so it can be properly updated later
+            fillInIntent.removeExtendedFlags(Intent.EXTENDED_FLAG_FILTER_MISMATCH);
         }
 
         if (!(target instanceof PendingIntentRecord)) {
@@ -1343,10 +1348,10 @@
     @Override
     public boolean startNextMatchingActivity(IBinder callingActivity, Intent intent,
             Bundle bOptions) {
-        if (intent != null) {
-            intent.prepareToEnterSystemServer();
+        // Refuse possible leaked file descriptors
+        if (intent != null && intent.hasFileDescriptors()) {
+            throw new IllegalArgumentException("File descriptors passed in Intent");
         }
-
         SafeActivityOptions options = SafeActivityOptions.fromBundle(bOptions);
 
         synchronized (mGlobalLock) {
@@ -1361,6 +1366,8 @@
                 return false;
             }
             intent = new Intent(intent);
+            // Remove existing mismatch flag so it can be properly updated later
+            intent.removeExtendedFlags(Intent.EXTENDED_FLAG_FILTER_MISMATCH);
             // The caller is not allowed to change the data.
             intent.setDataAndType(r.intent.getData(), r.intent.getType());
             // And we are resetting to find the next component...
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index e90a2c9..9a3ad2d 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -107,7 +107,6 @@
 import android.app.servertransaction.PauseActivityItem;
 import android.app.servertransaction.ResumeActivityItem;
 import android.app.servertransaction.StopActivityItem;
-import android.companion.virtual.VirtualDeviceManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -158,6 +157,7 @@
 import com.android.server.am.ActivityManagerService;
 import com.android.server.am.HostingRecord;
 import com.android.server.am.UserState;
+import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
 import com.android.server.pm.SaferIntentUtils;
 import com.android.server.utils.Slogf;
 import com.android.server.wm.ActivityMetricsLogger.LaunchingState;
@@ -285,7 +285,7 @@
     private WindowManagerService mWindowManager;
 
     private AppOpsManager mAppOpsManager;
-    private VirtualDeviceManager mVirtualDeviceManager;
+    private VirtualDeviceManagerInternal mVirtualDeviceManagerInternal;
 
     /** Common synchronization logic used to save things to disks. */
     PersisterQueue mPersisterQueue;
@@ -1298,16 +1298,24 @@
         if (displayId == DEFAULT_DISPLAY || displayId == INVALID_DISPLAY)  {
             return Context.DEVICE_ID_DEFAULT;
         }
-        if (mVirtualDeviceManager == null) {
+        if (mVirtualDeviceManagerInternal == null) {
             if (mService.mHasCompanionDeviceSetupFeature) {
-                mVirtualDeviceManager =
-                        mService.mContext.getSystemService(VirtualDeviceManager.class);
+                mVirtualDeviceManagerInternal =
+                        LocalServices.getService(VirtualDeviceManagerInternal.class);
             }
-            if (mVirtualDeviceManager == null) {
+            if (mVirtualDeviceManagerInternal == null) {
                 return Context.DEVICE_ID_DEFAULT;
             }
         }
-        return mVirtualDeviceManager.getDeviceIdForDisplayId(displayId);
+        return mVirtualDeviceManagerInternal.getDeviceIdForDisplayId(displayId);
+    }
+
+    boolean isDeviceOwnerUid(int displayId, int callingUid) {
+        final int deviceId = getDeviceIdForDisplayId(displayId);
+        if (deviceId == Context.DEVICE_ID_DEFAULT || deviceId == Context.DEVICE_ID_INVALID) {
+            return false;
+        }
+        return mVirtualDeviceManagerInternal.getDeviceOwnerUid(deviceId) == callingUid;
     }
 
     private AppOpsManager getAppOpsManager() {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 34bbe6a..d495acb 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -235,7 +235,6 @@
 import android.view.Surface.Rotation;
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Transaction;
-import android.view.SurfaceSession;
 import android.view.WindowInsets;
 import android.view.WindowInsets.Type.InsetsType;
 import android.view.WindowManager;
@@ -572,8 +571,6 @@
 
     boolean mWallpaperMayChange = false;
 
-    private final SurfaceSession mSession = new SurfaceSession();
-
     /**
      * A perf hint session which will boost the refresh rate for the display and change sf duration
      * to handle larger workloads.
@@ -1284,7 +1281,7 @@
      * @param transaction as part of which to perform the configuration
      */
     private void configureSurfaces(Transaction transaction) {
-        final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(mSession)
+        final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder()
                 .setOpaque(true)
                 .setContainerLayer()
                 .setCallsite("DisplayContent");
@@ -4597,7 +4594,7 @@
         // removed on the task.
         removeImeSurfaceImmediately();
         mImeScreenshot = new ImeScreenshot(
-                mWmService.mSurfaceControlFactory.apply(null), imeTarget);
+                mWmService.mSurfaceControlFactory.get(), imeTarget);
         // If the caller requests to hide IME, then allow to show IME snapshot for any target task.
         // So IME won't look like suddenly disappeared. It usually happens when turning off screen.
         mImeScreenshot.attachAndShow(t, hideImeWindow /* anyTargetTask */);
@@ -5430,14 +5427,8 @@
     }
 
     @Override
-    SurfaceSession getSession() {
-        return mSession;
-    }
-
-    @Override
     SurfaceControl.Builder makeChildSurface(WindowContainer child) {
-        SurfaceSession s = child != null ? child.getSession() : getSession();
-        final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(s).setContainerLayer();
+        final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder().setContainerLayer();
         if (child == null) {
             return b;
         }
@@ -5453,12 +5444,12 @@
      * and other potpourii.
      */
     SurfaceControl.Builder makeOverlay() {
-        return mWmService.makeSurfaceBuilder(mSession).setParent(getOverlayLayer());
+        return mWmService.makeSurfaceBuilder().setParent(getOverlayLayer());
     }
 
     @Override
     public SurfaceControl.Builder makeAnimationLeash() {
-        return mWmService.makeSurfaceBuilder(mSession).setParent(mSurfaceControl)
+        return mWmService.makeSurfaceBuilder().setParent(mSurfaceControl)
                 .setContainerLayer();
     }
 
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 745b792..5c62120 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -1036,7 +1036,7 @@
     /**
      * Check if a window can be added to the system.
      *
-     * Currently enforces that two window types are singletons per display:
+     * Currently enforces that these window types are singletons per display:
      * <ul>
      * <li>{@link WindowManager.LayoutParams#TYPE_STATUS_BAR}</li>
      * <li>{@link WindowManager.LayoutParams#TYPE_NOTIFICATION_SHADE}</li>
@@ -1058,41 +1058,39 @@
             ActivityTaskManagerService.enforceTaskPermission("DisplayPolicy");
         }
 
+        final String systemUiPermission =
+                mService.isCallerVirtualDeviceOwner(mDisplayContent.getDisplayId(), callingUid)
+                        // Allow virtual device owners to add system windows on their displays.
+                        ? android.Manifest.permission.CREATE_VIRTUAL_DEVICE
+                        : android.Manifest.permission.STATUS_BAR_SERVICE;
+
         switch (attrs.type) {
             case TYPE_STATUS_BAR:
-                mContext.enforcePermission(
-                        android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
+                mContext.enforcePermission(systemUiPermission, callingPid, callingUid,
                         "DisplayPolicy");
                 if (mStatusBar != null && mStatusBar.isAlive()) {
                     return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
                 }
                 break;
             case TYPE_NOTIFICATION_SHADE:
-                mContext.enforcePermission(
-                        android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
+                mContext.enforcePermission(systemUiPermission, callingPid, callingUid,
                         "DisplayPolicy");
-                if (mNotificationShade != null) {
-                    if (mNotificationShade.isAlive()) {
-                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
-                    }
+                if (mNotificationShade != null && mNotificationShade.isAlive()) {
+                    return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
                 }
                 break;
             case TYPE_NAVIGATION_BAR:
-                mContext.enforcePermission(android.Manifest.permission.STATUS_BAR_SERVICE,
-                        callingPid, callingUid, "DisplayPolicy");
+                mContext.enforcePermission(systemUiPermission, callingPid, callingUid,
+                        "DisplayPolicy");
                 if (mNavigationBar != null && mNavigationBar.isAlive()) {
                     return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
                 }
                 break;
             case TYPE_NAVIGATION_BAR_PANEL:
-                mContext.enforcePermission(android.Manifest.permission.STATUS_BAR_SERVICE,
-                        callingPid, callingUid, "DisplayPolicy");
-                break;
             case TYPE_STATUS_BAR_ADDITIONAL:
             case TYPE_STATUS_BAR_SUB_PANEL:
             case TYPE_VOICE_INTERACTION_STARTING:
-                mContext.enforcePermission(
-                        android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
+                mContext.enforcePermission(systemUiPermission, callingPid, callingUid,
                         "DisplayPolicy");
                 break;
             case TYPE_STATUS_BAR_PANEL:
@@ -1102,8 +1100,7 @@
         if (attrs.providedInsets != null) {
             // Recents component is allowed to add inset types.
             if (!mService.mAtmService.isCallerRecents(callingUid)) {
-                mContext.enforcePermission(
-                        android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
+                mContext.enforcePermission(systemUiPermission, callingPid, callingUid,
                         "DisplayPolicy");
             }
         }
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 59435b8..b09d63f 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -175,7 +175,7 @@
      */
     private CompletableFuture<Void> showInputSurface() {
         if (mInputSurface == null) {
-            mInputSurface = mService.makeSurfaceBuilder(mDisplayContent.getSession())
+            mInputSurface = mService.makeSurfaceBuilder()
                     .setContainerLayer()
                     .setName("Drag and Drop Input Consumer")
                     .setCallsite("DragState.showInputSurface")
diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java
index 4204670..a288cc7 100644
--- a/services/core/java/com/android/server/wm/InputConsumerImpl.java
+++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java
@@ -77,8 +77,7 @@
         mWindowHandle.scaleFactor = 1.0f;
         mWindowHandle.inputConfig = InputConfig.NOT_FOCUSABLE;
 
-        mInputSurface = mService.makeSurfaceBuilder(
-                        mService.mRoot.getDisplayContent(displayId).getSession())
+        mInputSurface = mService.makeSurfaceBuilder()
                 .setContainerLayer()
                 .setName("Input Consumer " + name)
                 .setCallsite("InputConsumerImpl")
diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java
index 1e7de2b..232c3b6 100644
--- a/services/core/java/com/android/server/wm/InputManagerCallback.java
+++ b/services/core/java/com/android/server/wm/InputManagerCallback.java
@@ -281,7 +281,7 @@
                         + " - Input overlay layer is not initialized.");
                 return null;
             }
-            return mService.makeSurfaceBuilder(dc.getSession())
+            return mService.makeSurfaceBuilder()
                     .setContainerLayer()
                     .setName(name)
                     .setCallsite("createSurfaceForGestureMonitor")
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 7c875c1..2ea2aeb 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -38,7 +38,6 @@
 import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
-import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
@@ -72,7 +71,6 @@
 import android.view.InsetsSourceControl;
 import android.view.InsetsState;
 import android.view.SurfaceControl;
-import android.view.SurfaceSession;
 import android.view.View;
 import android.view.View.FocusDirection;
 import android.view.WindowInsets;
@@ -108,7 +106,6 @@
     @NonNull
     final WindowProcessController mProcess;
     private final String mStringName;
-    SurfaceSession mSurfaceSession;
     private final ArrayList<WindowState> mAddedWindows = new ArrayList<>();
     /** Set of visible alert/app-overlay windows connected to this session. */
     private final ArraySet<WindowState> mAlertWindows = new ArraySet<>();
@@ -719,12 +716,10 @@
             mPackageName = mProcess.mInfo.packageName;
             mRelayoutTag = "relayoutWindow: " + mPackageName;
         }
-        if (mSurfaceSession == null) {
+        if (mProcess.mWindowSession == null) {
             if (DEBUG) {
-                Slog.v(TAG_WM, "First window added to " + this + ", creating SurfaceSession");
+                Slog.v(TAG_WM, "First window added to " + mProcess);
             }
-            mSurfaceSession = new SurfaceSession();
-            ProtoLog.i(WM_SHOW_TRANSACTIONS, "  NEW SURFACE SESSION %s", mSurfaceSession);
             mService.mSessions.add(this);
             if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
                 mService.dispatchNewAnimatorScaleLocked(this);
@@ -821,18 +816,11 @@
         }
 
         mService.mSessions.remove(this);
-        if (mSurfaceSession == null) {
+        if (mProcess.mWindowSession == null) {
             return;
         }
 
-        ProtoLog.i(WM_SHOW_TRANSACTIONS, "  KILL SURFACE SESSION %s", mSurfaceSession);
-        try {
-            mSurfaceSession.kill();
-        } catch (Exception e) {
-            Slog.w(TAG_WM, "Exception thrown when killing surface session " + mSurfaceSession
-                    + " in session " + this + ": " + e.toString());
-        }
-        mSurfaceSession = null;
+        mProcess.mWindowSession = null;
         mAddedWindows.clear();
         mAlertWindows.clear();
         setHasOverlayUi(false);
@@ -857,7 +845,6 @@
                 pw.print(" mCanAddInternalSystemWindow="); pw.print(mCanAddInternalSystemWindow);
                 pw.print(" mAlertWindows="); pw.print(mAlertWindows);
                 pw.print(" mClientDead="); pw.print(mClientDead);
-                pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
         pw.print(prefix); pw.print("mPackageName="); pw.println(mPackageName);
         if (isSatellitePointingUiPackage()) {
             pw.print(prefix); pw.println("mIsSatellitePointingUiPackage=true");
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 21be0fc..8c93b4fe 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3507,7 +3507,7 @@
      * {@link android.window.TaskFragmentOrganizer}
      */
     TaskFragmentParentInfo getTaskFragmentParentInfo() {
-        return new TaskFragmentParentInfo(getConfiguration(), getDisplayId(),
+        return new TaskFragmentParentInfo(getConfiguration(), getDisplayId(), mTaskId,
                 shouldBeVisible(null /* starting */), hasNonFinishingDirectActivity(),
                 getDecorSurface());
     }
diff --git a/services/core/java/com/android/server/wm/TrustedOverlayHost.java b/services/core/java/com/android/server/wm/TrustedOverlayHost.java
index 5f3c558..030e848 100644
--- a/services/core/java/com/android/server/wm/TrustedOverlayHost.java
+++ b/services/core/java/com/android/server/wm/TrustedOverlayHost.java
@@ -51,7 +51,7 @@
 
     void requireOverlaySurfaceControl() {
         if (mSurfaceControl == null) {
-            final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(null)
+            final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder()
                 .setContainerLayer()
                 .setHidden(true)
                 .setCallsite("TrustedOverlayHost.requireOverlaySurfaceControl")
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 790ca1b..1eeb3ec 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -100,7 +100,6 @@
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Builder;
 import android.view.SurfaceControlViewHost;
-import android.view.SurfaceSession;
 import android.view.WindowManager;
 import android.view.WindowManager.TransitionOldType;
 import android.view.animation.Animation;
@@ -706,7 +705,7 @@
         mLastSurfacePosition.set(0, 0);
         mLastDeltaRotation = Surface.ROTATION_0;
 
-        final Builder b = mWmService.makeSurfaceBuilder(null)
+        final Builder b = mWmService.makeSurfaceBuilder()
                 .setContainerLayer()
                 .setName(getName());
 
@@ -2662,13 +2661,6 @@
         return true;
     }
 
-    SurfaceSession getSession() {
-        if (getParent() != null) {
-            return getParent().getSession();
-        }
-        return null;
-    }
-
     void assignLayer(Transaction t, int layer) {
         // Don't assign layers while a transition animation is playing
         // TODO(b/173528115): establish robust best-practices around z-order fighting.
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 29ab4dd..6b7ba66 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -288,7 +288,6 @@
 import android.view.Surface;
 import android.view.SurfaceControl;
 import android.view.SurfaceControlViewHost;
-import android.view.SurfaceSession;
 import android.view.View;
 import android.view.View.FocusDirection;
 import android.view.ViewDebug;
@@ -386,7 +385,6 @@
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
-import java.util.function.Function;
 import java.util.function.Supplier;
 
 /** {@hide} */
@@ -1111,7 +1109,7 @@
     static WindowManagerThreadPriorityBooster sThreadPriorityBooster =
             new WindowManagerThreadPriorityBooster();
 
-    Function<SurfaceSession, SurfaceControl.Builder> mSurfaceControlFactory;
+    Supplier<SurfaceControl.Builder> mSurfaceControlFactory;
     Supplier<SurfaceControl.Transaction> mTransactionFactory;
 
     private final SurfaceControl.Transaction mTransaction;
@@ -1202,7 +1200,7 @@
             final boolean showBootMsgs, WindowManagerPolicy policy, ActivityTaskManagerService atm,
             DisplayWindowSettingsProvider displayWindowSettingsProvider,
             Supplier<SurfaceControl.Transaction> transactionFactory,
-            Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
+            Supplier<SurfaceControl.Builder> surfaceControlFactory) {
         final WindowManagerService[] wms = new WindowManagerService[1];
         DisplayThread.getHandler().runWithScissors(() ->
                 wms[0] = new WindowManagerService(context, im, showBootMsgs, policy, atm,
@@ -1231,7 +1229,7 @@
             boolean showBootMsgs, WindowManagerPolicy policy, ActivityTaskManagerService atm,
             DisplayWindowSettingsProvider displayWindowSettingsProvider,
             Supplier<SurfaceControl.Transaction> transactionFactory,
-            Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
+            Supplier<SurfaceControl.Builder> surfaceControlFactory) {
         installLock(this, INDEX_WINDOW);
         mGlobalLock = atm.getGlobalLock();
         mAtmService = atm;
@@ -1526,7 +1524,7 @@
         final boolean isRoundedCornerOverlay = (attrs.privateFlags
                 & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0;
         int res = mPolicy.checkAddPermission(attrs.type, isRoundedCornerOverlay, attrs.packageName,
-                appOp);
+                appOp, displayId);
         if (res != ADD_OKAY) {
             return res;
         }
@@ -8521,7 +8519,7 @@
                     return null;
                 }
                 // TODO(b/210039666): Use a method like add/removeDisplayOverlay if available.
-                return makeSurfaceBuilder(dc.getSession())
+                return makeSurfaceBuilder()
                         .setContainerLayer()
                         .setName("IME Handwriting Surface")
                         .setCallsite("getHandwritingSurfaceForDisplay")
@@ -8829,8 +8827,8 @@
         }
     }
 
-    SurfaceControl.Builder makeSurfaceBuilder(SurfaceSession s) {
-        return mSurfaceControlFactory.apply(s);
+    SurfaceControl.Builder makeSurfaceBuilder() {
+        return mSurfaceControlFactory.get();
     }
 
     /**
@@ -10123,6 +10121,23 @@
         }
     }
 
+    /**
+     * Returns whether the given UID is the owner of a virtual device, which the given display
+     * belongs to.
+     */
+    @Override
+    public boolean isCallerVirtualDeviceOwner(int displayId, int callingUid) {
+        if (!android.companion.virtualdevice.flags.Flags.statusBarAndInsets()) {
+            return false;
+        }
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return mAtmService.mTaskSupervisor.isDeviceOwnerUid(displayId, callingUid);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
     @RequiresPermission(ACCESS_SURFACE_FLINGER)
     @Override
     public boolean replaceContentOnDisplay(int displayId, SurfaceControl sc) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 7c05c29..256d0c6 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -233,7 +233,6 @@
 import android.view.Surface;
 import android.view.Surface.Rotation;
 import android.view.SurfaceControl;
-import android.view.SurfaceSession;
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewTreeObserver;
@@ -5162,15 +5161,6 @@
     }
 
     @Override
-    SurfaceSession getSession() {
-        if (mSession.mSurfaceSession != null) {
-            return mSession.mSurfaceSession;
-        } else {
-            return getParent().getSession();
-        }
-    }
-
-    @Override
     boolean needsZBoost() {
         final InsetsControlTarget target = getDisplayContent().getImeTarget(IME_TARGET_LAYERING);
         if (mIsImWindow && target != null) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index b40cf56..82fa9d4 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -321,8 +321,7 @@
         }
 
         if (DEBUG_VISIBILITY) {
-            Slog.v(TAG, "Creating surface in session "
-                    + mSession.mSurfaceSession + " window " + this
+            Slog.v(TAG, "Creating surface " + this
                     + " format=" + attrs.format + " flags=" + flags);
         }
 
@@ -358,9 +357,8 @@
             w.mInputWindowHandle.forceChange();
 
             ProtoLog.i(WM_SHOW_SURFACE_ALLOC,
-                        "  CREATE SURFACE %s IN SESSION %s: pid=%d format=%d flags=0x%x / %s",
-                    mSurfaceControl, mSession.mSurfaceSession, mSession.mPid, attrs.format,
-                        flags, this);
+                    "  CREATE SURFACE %s: pid=%d format=%d flags=0x%x / %s",
+                    mSurfaceControl, mSession.mPid, attrs.format, flags, this);
         } catch (OutOfResourcesException e) {
             Slog.w(TAG, "OutOfResourcesException creating surface");
             mService.mRoot.reclaimSomeSurfaceMemory(this, "create", true);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index fc61967..2b7e9f9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -11858,7 +11858,7 @@
             }
             setBackwardsCompatibleAppRestrictions(
                     caller, packageName, restrictions, caller.getUserHandle());
-        } else if (Flags.dmrhSetAppRestrictions()) {
+        } else {
             final boolean isRoleHolder;
             if (who != null) {
                 // DO or PO
@@ -11905,15 +11905,6 @@
                             caller.getUserHandle());
                 });
             }
-        } else {
-            Preconditions.checkCallAuthorization((caller.hasAdminComponent()
-                    && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
-                    || (caller.hasPackage() && isCallerDelegate(caller,
-                    DELEGATION_APP_RESTRICTIONS)));
-            mInjector.binderWithCleanCallingIdentity(() -> {
-                mUserManager.setApplicationRestrictions(packageName, restrictions,
-                        caller.getUserHandle());
-            });
         }
 
         DevicePolicyEventLogger
@@ -13244,7 +13235,7 @@
                 return Bundle.EMPTY;
             }
             return policies.get(enforcingAdmin).getValue();
-        } else if (Flags.dmrhSetAppRestrictions()) {
+        } else {
             final boolean isRoleHolder;
             if (who != null) {
                 // Caller is DO or PO. They cannot call this on parent
@@ -13287,19 +13278,6 @@
                     return bundle != null ? bundle : Bundle.EMPTY;
                 });
             }
-
-        } else {
-            Preconditions.checkCallAuthorization((caller.hasAdminComponent()
-                    && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
-                    || (caller.hasPackage() && isCallerDelegate(caller,
-                    DELEGATION_APP_RESTRICTIONS)));
-            return mInjector.binderWithCleanCallingIdentity(() -> {
-                Bundle bundle = mUserManager.getApplicationRestrictions(packageName,
-                        caller.getUserHandle());
-                // if no restrictions were saved, mUserManager.getApplicationRestrictions
-                // returns null, but DPM method should return an empty Bundle as per JavaDoc
-                return bundle != null ? bundle : Bundle.EMPTY;
-            });
         }
     }
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 13c436d..ab459df 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -2467,8 +2467,8 @@
                 reportWtf("starting RuntimeService", e);
             }
             t.traceEnd();
-
-            if (!isWatch && !disableNetworkTime) {
+            if (!disableNetworkTime && (!isWatch || (isWatch
+                    && android.server.Flags.allowNetworkTimeUpdateService()))) {
                 t.traceBegin("StartNetworkTimeUpdateService");
                 try {
                     networkTimeUpdater = new NetworkTimeUpdateService(context);
diff --git a/services/java/com/android/server/flags.aconfig b/services/java/com/android/server/flags.aconfig
index 29f3871..ec74ef19 100644
--- a/services/java/com/android/server/flags.aconfig
+++ b/services/java/com/android/server/flags.aconfig
@@ -28,4 +28,11 @@
      namespace: "wear_frameworks"
      description: "Allow removing VpnManagerService"
      bug: "340928692"
+}
+
+flag {
+    name: "allow_network_time_update_service"
+    namespace: "wear_systems"
+    description: "Allow NetworkTimeUpdateService on Wear"
+    bug: "327508176"
 }
\ No newline at end of file
diff --git a/services/tests/displayservicetests/src/com/android/server/display/BrightnessRangeControllerTest.kt b/services/tests/displayservicetests/src/com/android/server/display/BrightnessRangeControllerTest.kt
index 1f3184d..f589a2c 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/BrightnessRangeControllerTest.kt
+++ b/services/tests/displayservicetests/src/com/android/server/display/BrightnessRangeControllerTest.kt
@@ -42,31 +42,31 @@
     private val mockToken = mock<IBinder>()
 
     @Test
-    fun `returns HBC max brightness if HBM supported and ON`() {
+    fun testMaxBrightness_HbmSupportedAndOn() {
         val controller = createController()
         assertThat(controller.currentBrightnessMax).isEqualTo(MAX_BRIGHTNESS)
     }
 
     @Test
-    fun `returns NBC max brightness if device does not support HBM`() {
+    fun testMaxBrightness_HbmNotSupported() {
         val controller = createController(hbmSupported = false)
         assertThat(controller.currentBrightnessMax).isEqualTo(NORMAL_BRIGHTNESS_LOW)
     }
 
     @Test
-    fun `returns NBC max brightness if HBM not allowed`() {
+    fun testMaxBrightness_HbmNotAllowed() {
         val controller = createController(hbmAllowed = false)
         assertThat(controller.currentBrightnessMax).isEqualTo(NORMAL_BRIGHTNESS_LOW)
     }
 
     @Test
-    fun `returns HBC max brightness if NBM is disabled`() {
+    fun testMaxBrightness_HbmDisabledAndNotAllowed() {
         val controller = createController(nbmEnabled = false, hbmAllowed = false)
         assertThat(controller.currentBrightnessMax).isEqualTo(MAX_BRIGHTNESS)
     }
 
     @Test
-    fun `returns HBC max brightness if lower than NBC max brightness`() {
+    fun testMaxBrightness_transitionPointLessThanCurrentNbmLimit() {
         val controller = createController(
             hbmAllowed = false,
             hbmMaxBrightness = TRANSITION_POINT,
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayOffloadSessionImplTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayOffloadSessionImplTest.java
index 30c384a..5e868a3 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayOffloadSessionImplTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayOffloadSessionImplTest.java
@@ -38,7 +38,7 @@
     private DisplayManagerInternal.DisplayOffloader mDisplayOffloader;
 
     @Mock
-    private DisplayPowerControllerInterface mDisplayPowerController;
+    private DisplayPowerController mDisplayPowerController;
 
     private DisplayOffloadSessionImpl mSession;
 
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerStateTest.kt b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerStateTest.kt
index 33d3020..a684fdb 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerStateTest.kt
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerStateTest.kt
@@ -60,7 +60,7 @@
     }
 
     @Test
-    fun `destroys ColorFade on stop`() {
+    fun destroysColorFadeOnStop() {
         displayPowerState.stop()
         val runnableCaptor = argumentCaptor<Runnable>()
 
@@ -71,13 +71,13 @@
     }
 
     @Test
-    fun `GIVEN not prepared WHEN draw runnable is called THEN colorFade not drawn`() {
+    fun testColorFadeDraw_notPrepared() {
         displayPowerState.mColorFadeDrawRunnable.run()
 
         verify(mockColorFade, never()).draw(anyFloat())
     }
     @Test
-    fun `GIVEN prepared WHEN draw runnable is called THEN colorFade is drawn`() {
+    fun testColorFadeDraw_prepared() {
         displayPowerState.prepareColorFade(mockContext, ColorFade.MODE_FADE)
         clearInvocations(mockColorFade)
 
@@ -87,7 +87,7 @@
     }
 
     @Test
-    fun `GIVEN prepared AND stopped WHEN draw runnable is called THEN colorFade is not drawn`() {
+    fun testColorFadeDraw_preparedAndStopped() {
         displayPowerState.prepareColorFade(mockContext, ColorFade.MODE_FADE)
         clearInvocations(mockColorFade)
         displayPowerState.stop()
diff --git a/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java
index a7e0ebd..120cc84 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -118,7 +118,7 @@
     @Mock
     private DisplayManagerFlags mFlags;
     @Mock
-    private DisplayPowerControllerInterface mMockedDisplayPowerController;
+    private DisplayPowerController mMockedDisplayPowerController;
 
     private Handler mHandler;
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 51aa528..3b284a2 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -90,7 +90,6 @@
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.app.ApplicationExitInfo;
-import android.app.IApplicationThread;
 import android.app.IServiceConnection;
 import android.content.ComponentName;
 import android.content.Context;
@@ -164,6 +163,10 @@
 
     private static int sFirstCachedAdj = ProcessList.CACHED_APP_MIN_ADJ
             + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
+    private static int sFirstUiCachedAdj = ProcessList.CACHED_APP_MIN_ADJ + 10;
+    private static int sFirstNonUiCachedAdj = ProcessList.CACHED_APP_MIN_ADJ + 20;
+    private static int sUiTierSize = 5;
+
     private Context mContext;
     private PackageManagerInternal mPackageManagerInternal;
     private ActivityManagerService mService;
@@ -232,9 +235,6 @@
                         mInjector);
         mService.mOomAdjuster.mAdjSeq = 10000;
         mService.mWakefulness = new AtomicInteger(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        if (mService.mConstants.USE_TIERED_CACHED_ADJ) {
-            sFirstCachedAdj = ProcessList.CACHED_APP_MIN_ADJ + 10;
-        }
         mSetFlagsRule.enableFlags(Flags.FLAG_NEW_FGS_RESTRICTION_LOGIC);
     }
 
@@ -473,7 +473,8 @@
         mService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(app);
 
-        final int expectedAdj = sFirstCachedAdj;
+        final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+                ? sFirstUiCachedAdj : sFirstCachedAdj;
         assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, expectedAdj,
                 SCHED_GROUP_BACKGROUND);
     }
@@ -701,7 +702,9 @@
             mInjector.jumpUptimeAheadTo(followUpTimeCaptor.getValue());
             mService.mOomAdjuster.updateOomAdjFollowUpTargetsLocked();
 
-            assertEquals(sFirstCachedAdj, app.mState.getSetAdj());
+            final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+                    ? sFirstUiCachedAdj : sFirstCachedAdj;
+            assertEquals(expectedAdj, app.mState.getSetAdj());
             // Follow up should not have been called again.
             verify(mService.mHandler).sendEmptyMessageAtTime(eq(FOLLOW_UP_OOMADJUSTER_UPDATE_MSG),
                     followUpTimeCaptor.capture());
@@ -836,7 +839,9 @@
         mInjector.jumpUptimeAheadTo(followUpTimeCaptor.getValue());
         mService.mOomAdjuster.updateOomAdjFollowUpTargetsLocked();
 
-        assertProcStates(app, PROCESS_STATE_LAST_ACTIVITY, CACHED_APP_MIN_ADJ,
+        int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+                ? sFirstUiCachedAdj : CACHED_APP_MIN_ADJ;
+        assertProcStates(app, PROCESS_STATE_LAST_ACTIVITY, expectedAdj,
                 SCHED_GROUP_BACKGROUND, "previous-expired");
         // Follow up should not have been called again.
         verify(mService.mHandler).sendEmptyMessageAtTime(eq(FOLLOW_UP_OOMADJUSTER_UPDATE_MSG),
@@ -877,9 +882,15 @@
 
         for (int i = 0; i < numberOfApps; i++) {
             final int mruIndex = numberOfApps - i - 1;
-            int expectedAdj = CACHED_APP_MIN_ADJ + (mruIndex * 2 * CACHED_APP_IMPORTANCE_LEVELS);
-            if (expectedAdj > CACHED_APP_MAX_ADJ) {
-                expectedAdj = CACHED_APP_MAX_ADJ;
+            int expectedAdj;
+            if (mService.mConstants.USE_TIERED_CACHED_ADJ) {
+                expectedAdj = (i < numberOfApps - sUiTierSize)
+                        ? sFirstNonUiCachedAdj : sFirstUiCachedAdj + mruIndex;
+            } else {
+                expectedAdj = CACHED_APP_MIN_ADJ + (mruIndex * 2 * CACHED_APP_IMPORTANCE_LEVELS);
+                if (expectedAdj > CACHED_APP_MAX_ADJ) {
+                    expectedAdj = CACHED_APP_MAX_ADJ;
+                }
             }
             assertProcStates(apps[i], PROCESS_STATE_LAST_ACTIVITY, expectedAdj,
                     SCHED_GROUP_BACKGROUND, "previous-expired");
@@ -1003,7 +1014,9 @@
         updateOomAdj(client, app);
         doReturn(null).when(mService).getTopApp();
 
-        assertProcStates(app, PROCESS_STATE_SERVICE, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
+        final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+                ? sFirstUiCachedAdj : sFirstCachedAdj;
+        assertProcStates(app, PROCESS_STATE_SERVICE, expectedAdj, SCHED_GROUP_BACKGROUND);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1053,7 +1066,9 @@
         mService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(app);
 
-        assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
+        final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+                ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+        assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1469,7 +1484,9 @@
         bindProvider(app, app, null, null, false);
         updateOomAdj(app);
 
-        assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
+        final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+                ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+        assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1484,7 +1501,9 @@
         mService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(app, client);
 
-        assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
+        final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+                ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+        assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1592,7 +1611,9 @@
         mInjector.jumpUptimeAheadTo(followUpTimeCaptor.getValue());
         mService.mOomAdjuster.updateOomAdjFollowUpTargetsLocked();
 
-        assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND,
+        final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+                ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+        assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND,
                 "cch-empty");
         // Follow up should not have been called again.
         verify(mService.mHandler).sendEmptyMessageAtTime(eq(FOLLOW_UP_OOMADJUSTER_UPDATE_MSG),
@@ -2623,12 +2644,11 @@
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
         final int userOwner = 0;
         final int userOther = 1;
-        final int cachedAdj1 = mService.mConstants.USE_TIERED_CACHED_ADJ
-                ? CACHED_APP_MIN_ADJ + 10
-                : CACHED_APP_MIN_ADJ + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
-        final int cachedAdj2 = mService.mConstants.USE_TIERED_CACHED_ADJ
-                ? CACHED_APP_MIN_ADJ + 10
-                : cachedAdj1 + ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
+
+        // cachedAdj1 and cachedAdj2 will be read if USE_TIERED_CACHED_ADJ is disabled. Otherwise,
+        // sFirstUiCachedAdj and sFirstNonUiCachedAdj are used instead.
+        final int cachedAdj1 = CACHED_APP_MIN_ADJ + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
+        final int cachedAdj2 = cachedAdj1 + ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
         doReturn(userOwner).when(mService.mUserController).getCurrentUserId();
 
         final ArrayList<ProcessRecord> lru = mService.mProcessList.getLruProcessesLOSP();
@@ -2669,8 +2689,12 @@
         mService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj();
 
-        assertProcStates(app, true, PROCESS_STATE_SERVICE, cachedAdj1, "cch-started-ui-services");
-        assertProcStates(app2, true, PROCESS_STATE_SERVICE, cachedAdj2, "cch-started-services");
+        assertProcStates(app, true, PROCESS_STATE_SERVICE,
+                mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstUiCachedAdj : cachedAdj1,
+                "cch-started-ui-services");
+        assertProcStates(app2, true, PROCESS_STATE_SERVICE,
+                mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstNonUiCachedAdj : cachedAdj2,
+                "cch-started-services");
 
         app.mState.setSetProcState(PROCESS_STATE_NONEXISTENT);
         app.mState.setAdjType(null);
@@ -2686,7 +2710,10 @@
         s.lastActivity = now - mService.mConstants.MAX_SERVICE_INACTIVITY - 1;
         updateOomAdj();
 
-        assertProcStates(app, true, PROCESS_STATE_SERVICE, cachedAdj1, "cch-started-services");
+        // hasShownUi was set to false for 'app', so 920 is expected for USE_TIERED_CACHED_ADJ.
+        assertProcStates(app, true, PROCESS_STATE_SERVICE,
+                mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstNonUiCachedAdj : cachedAdj1,
+                "cch-started-services");
 
         app.mServices.stopService(s);
         app.mState.setSetProcState(PROCESS_STATE_NONEXISTENT);
@@ -2705,7 +2732,9 @@
         updateOomAdj();
 
         assertProcStates(app, false, PROCESS_STATE_SERVICE, SERVICE_ADJ, "started-services");
-        assertProcStates(app2, true, PROCESS_STATE_SERVICE, cachedAdj1, "cch-started-services");
+        assertProcStates(app2, true, PROCESS_STATE_SERVICE,
+                mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstNonUiCachedAdj : cachedAdj1,
+                "cch-started-services");
 
         app.mState.setSetProcState(PROCESS_STATE_NONEXISTENT);
         app.mState.setAdjType(null);
@@ -2715,13 +2744,17 @@
         updateOomAdj();
 
         assertProcStates(app, false, PROCESS_STATE_SERVICE, SERVICE_ADJ, "started-services");
-        assertProcStates(app2, true, PROCESS_STATE_SERVICE, cachedAdj1, "cch-started-services");
+        assertProcStates(app2, true, PROCESS_STATE_SERVICE,
+                mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstNonUiCachedAdj : cachedAdj1,
+                "cch-started-services");
 
         doReturn(userOther).when(mService.mUserController).getCurrentUserId();
         mService.mOomAdjuster.handleUserSwitchedLocked();
 
         updateOomAdj();
-        assertProcStates(app, true, PROCESS_STATE_SERVICE, cachedAdj1, "cch-started-services");
+        assertProcStates(app, true, PROCESS_STATE_SERVICE,
+                mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstNonUiCachedAdj : cachedAdj1,
+                "cch-started-services");
         assertProcStates(app2, false, PROCESS_STATE_SERVICE, SERVICE_ADJ, "started-services");
     }
 
@@ -2998,7 +3031,9 @@
         mInjector.jumpUptimeAheadTo(followUpTimeCaptor.getValue());
         mService.mOomAdjuster.updateOomAdjFollowUpTargetsLocked();
 
-        assertProcStates(app, PROCESS_STATE_SERVICE, sFirstCachedAdj, SCHED_GROUP_BACKGROUND,
+        final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+                ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+        assertProcStates(app, PROCESS_STATE_SERVICE, expectedAdj, SCHED_GROUP_BACKGROUND,
                 "cch-started-services");
         // Follow up should not have been called again.
         verify(mService.mHandler).sendEmptyMessageAtTime(eq(FOLLOW_UP_OOMADJUSTER_UPDATE_MSG),
@@ -3031,14 +3066,16 @@
         mInjector.jumpUptimeAheadTo(followUpTimeCaptor.getValue());
         mService.mOomAdjuster.updateOomAdjFollowUpTargetsLocked();
 
-        assertProcStates(app1, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND,
+        final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+                ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+        assertProcStates(app1, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND,
                 "cch-empty");
 
         verify(mService.mHandler, atLeastOnce()).sendEmptyMessageAtTime(
                 eq(FOLLOW_UP_OOMADJUSTER_UPDATE_MSG), followUpTimeCaptor.capture());
         mInjector.jumpUptimeAheadTo(followUpTimeCaptor.getValue());
         mService.mOomAdjuster.updateOomAdjFollowUpTargetsLocked();
-        assertProcStates(app2, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND,
+        assertProcStates(app2, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND,
                 "cch-empty");
     }
 
diff --git a/services/tests/powerstatstests/Android.bp b/services/tests/powerstatstests/Android.bp
index b2a5b02..91c62be 100644
--- a/services/tests/powerstatstests/Android.bp
+++ b/services/tests/powerstatstests/Android.bp
@@ -71,6 +71,8 @@
     ],
     srcs: [
         "src/com/android/server/power/stats/*.java",
+        "src/com/android/server/power/stats/format/*.java",
+        "src/com/android/server/power/stats/processor/*.java",
     ],
     java_resources: [
         "res/xml/power_profile*.xml",
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java
index a1101cd..1d20538 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java
@@ -117,7 +117,7 @@
     private PowerStatsStore mPowerStatsStore;
     private BatteryUsageStatsProvider mBatteryUsageStatsProvider;
     @Mock
-    private PowerStatsExporter mPowerStatsExporter;
+    private PowerAttributor mPowerAttributor;
 
     @Before
     public void setUp() throws IOException {
@@ -149,9 +149,8 @@
         } else {
             context = InstrumentationRegistry.getContext();
         }
-        mPowerStatsStore = new PowerStatsStore(systemDir, mHandler,
-                new AggregatedPowerStatsConfig());
-        mBatteryUsageStatsProvider = new BatteryUsageStatsProvider(context, mPowerStatsExporter,
+        mPowerStatsStore = new PowerStatsStore(systemDir, mHandler);
+        mBatteryUsageStatsProvider = new BatteryUsageStatsProvider(context, mPowerAttributor,
                 mPowerProfile, mBatteryStatsImpl.getCpuScalingPolicies(), mPowerStatsStore,
                 mMockClock);
     }
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java
index 17c7efa..fde84e9 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java
@@ -94,8 +94,9 @@
     public void test_getBatteryUsageStats() {
         BatteryStatsImpl batteryStats = prepareBatteryStats();
 
-        BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext, null,
-                mStatsRule.getPowerProfile(), mStatsRule.getCpuScalingPolicies(), null, mMockClock);
+        BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext,
+                mock(PowerAttributor.class), mStatsRule.getPowerProfile(),
+                mStatsRule.getCpuScalingPolicies(), mock(PowerStatsStore.class), mMockClock);
 
         final BatteryUsageStats batteryUsageStats =
                 provider.getBatteryUsageStats(batteryStats, BatteryUsageStatsQuery.DEFAULT);
@@ -130,8 +131,9 @@
     public void test_selectPowerComponents() {
         BatteryStatsImpl batteryStats = prepareBatteryStats();
 
-        BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext, null,
-                mStatsRule.getPowerProfile(), mStatsRule.getCpuScalingPolicies(), null, mMockClock);
+        BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext,
+                mock(PowerAttributor.class), mStatsRule.getPowerProfile(),
+                mStatsRule.getCpuScalingPolicies(), mock(PowerStatsStore.class), mMockClock);
 
         final BatteryUsageStats batteryUsageStats =
                 provider.getBatteryUsageStats(batteryStats,
@@ -235,8 +237,9 @@
             batteryStats.noteAlarmFinishLocked("foo", null, APP_UID, 3_001_000, 2_001_000);
         }
 
-        BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext, null,
-                mStatsRule.getPowerProfile(), mStatsRule.getCpuScalingPolicies(), null, mMockClock);
+        BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext,
+                mock(PowerAttributor.class), mStatsRule.getPowerProfile(),
+                mStatsRule.getCpuScalingPolicies(), mock(PowerStatsStore.class), mMockClock);
 
         final BatteryUsageStats batteryUsageStats =
                 provider.getBatteryUsageStats(batteryStats,
@@ -323,8 +326,9 @@
             }
         }
 
-        BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext, null,
-                mStatsRule.getPowerProfile(), mStatsRule.getCpuScalingPolicies(), null, mMockClock);
+        BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext,
+                mock(PowerAttributor.class), mStatsRule.getPowerProfile(),
+                mStatsRule.getCpuScalingPolicies(), mock(PowerStatsStore.class), mMockClock);
 
         final BatteryUsageStats batteryUsageStats =
                 provider.getBatteryUsageStats(batteryStats,
@@ -408,12 +412,12 @@
 
         PowerStatsStore powerStatsStore = new PowerStatsStore(
                 new File(mStatsRule.getHistoryDir(), "powerstatsstore"),
-                mStatsRule.getHandler(), null);
+                mStatsRule.getHandler());
         powerStatsStore.reset();
 
-        BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext, null,
-                mStatsRule.getPowerProfile(), mStatsRule.getCpuScalingPolicies(), powerStatsStore,
-                mMockClock);
+        BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext,
+                mock(PowerAttributor.class), mStatsRule.getPowerProfile(),
+                mStatsRule.getCpuScalingPolicies(), powerStatsStore, mMockClock);
 
         batteryStats.saveBatteryUsageStatsOnReset(provider, powerStatsStore);
         synchronized (batteryStats) {
@@ -522,8 +526,9 @@
             batteryStats.updateCustomEnergyConsumerStatsLocked(1, 200_000_000, uidEnergies);
         }
 
-        BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext, null,
-                mStatsRule.getPowerProfile(), mStatsRule.getCpuScalingPolicies(), null, mMockClock);
+        BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext,
+                mock(PowerAttributor.class), mStatsRule.getPowerProfile(),
+                mStatsRule.getCpuScalingPolicies(), mock(PowerStatsStore.class), mMockClock);
 
         PowerStatsStore powerStatsStore = mock(PowerStatsStore.class);
         doAnswer(invocation -> {
@@ -584,9 +589,9 @@
         when(powerStatsStore.loadPowerStatsSpan(1, BatteryUsageStatsSection.TYPE))
                 .thenReturn(span1);
 
-        BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext, null,
-                mStatsRule.getPowerProfile(), mStatsRule.getCpuScalingPolicies(), powerStatsStore,
-                mMockClock);
+        BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext,
+                mock(PowerAttributor.class), mStatsRule.getPowerProfile(),
+                mStatsRule.getCpuScalingPolicies(), powerStatsStore, mMockClock);
 
         BatteryUsageStatsQuery query = new BatteryUsageStatsQuery.Builder()
                 .aggregateSnapshots(0, 3000)
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BluetoothPowerStatsCollectorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BluetoothPowerStatsCollectorTest.java
index 02c7b74..e392c5d 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BluetoothPowerStatsCollectorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BluetoothPowerStatsCollectorTest.java
@@ -27,6 +27,7 @@
 import android.bluetooth.UidTraffic;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.hardware.power.stats.EnergyConsumerResult;
 import android.hardware.power.stats.EnergyConsumerType;
 import android.os.BatteryConsumer;
 import android.os.Handler;
@@ -37,6 +38,7 @@
 
 import com.android.internal.os.Clock;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.BluetoothPowerStatsLayout;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -48,7 +50,6 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.Executor;
-import java.util.function.IntSupplier;
 
 public class BluetoothPowerStatsCollectorTest {
     private static final int APP_UID1 = 42;
@@ -132,11 +133,6 @@
                 }
 
                 @Override
-                public IntSupplier getVoltageSupplier() {
-                    return () -> 3500;
-                }
-
-                @Override
                 public BluetoothPowerStatsCollector.BluetoothStatsRetriever
                         getBluetoothStatsRetriever() {
                     return mBluetoothStatsRetriever;
@@ -232,6 +228,7 @@
         BluetoothPowerStatsCollector collector = new BluetoothPowerStatsCollector(mInjector);
         collector.setEnabled(true);
 
+        when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(3500);
         when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.BLUETOOTH))
                 .thenReturn(new int[]{777});
 
@@ -242,8 +239,7 @@
 
         mUidScanTimes.put(APP_UID1, 100);
 
-        when(mConsumedEnergyRetriever.getConsumedEnergyUws(eq(new int[]{777})))
-                .thenReturn(new long[]{10000});
+        mockConsumedEnergy(777, 10000);
 
         // Establish a baseline
         collector.collectStats();
@@ -258,13 +254,19 @@
         mUidScanTimes.put(APP_UID2, 300);
         mUidScanTimes.put(ISOLATED_UID, 400);
 
-        when(mConsumedEnergyRetriever.getConsumedEnergyUws(eq(new int[]{777})))
-                .thenReturn(new long[]{64321});
+        mockConsumedEnergy(777, 64321);
 
         mStatsRule.setTime(20000, 20000);
         return collector.collectStats();
     }
 
+    private void mockConsumedEnergy(int consumerId, long energyUWs) {
+        EnergyConsumerResult ecr = new EnergyConsumerResult();
+        ecr.energyUWs = energyUWs;
+        when(mConsumedEnergyRetriever.getConsumedEnergy(eq(new int[]{consumerId})))
+                .thenReturn(new EnergyConsumerResult[]{ecr});
+    }
+
     private BluetoothActivityEnergyInfo mockBluetoothActivityEnergyInfo(long timestamp,
             long rxTimeMs, long txTimeMs, long idleTimeMs, UidTraffic... uidTraffic) {
         if (RavenwoodRule.isOnRavenwood()) {
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorTest.java
index d1105a4..1fea462 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorTest.java
@@ -26,6 +26,7 @@
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.when;
 
+import android.hardware.power.stats.EnergyConsumerResult;
 import android.hardware.power.stats.EnergyConsumerType;
 import android.os.BatteryConsumer;
 import android.os.ConditionVariable;
@@ -42,6 +43,7 @@
 import com.android.internal.os.CpuScalingPolicies;
 import com.android.internal.os.PowerProfile;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.CpuPowerStatsLayout;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -53,7 +55,6 @@
 
 import java.io.IOException;
 import java.io.StringWriter;
-import java.util.function.IntSupplier;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
@@ -124,11 +125,6 @@
         }
 
         @Override
-        public IntSupplier getVoltageSupplier() {
-            return () -> 3500;
-        }
-
-        @Override
         public long getPowerStatsCollectionThrottlePeriod(String powerComponentName) {
             return 0;
         }
@@ -150,7 +146,9 @@
         mHandlerThread.start();
         mHandler = mHandlerThread.getThreadHandler();
         when(mMockKernelCpuStatsReader.isSupportedFeature()).thenReturn(true);
-        when(mConsumedEnergyRetriever.getEnergyConsumerIds(anyInt())).thenReturn(new int[0]);
+        when(mConsumedEnergyRetriever.getEnergyConsumerIds(anyInt()))
+                .thenReturn(new int[0]);
+        when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(3500);
         mUidResolver.noteIsolatedUidAdded(ISOLATED_UID, UID_2);
     }
 
@@ -228,9 +226,7 @@
         assertThat(descriptor.name).isEqualTo("cpu");
         assertThat(descriptor.statsArrayLength).isEqualTo(13);
         assertThat(descriptor.uidStatsArrayLength).isEqualTo(5);
-        CpuPowerStatsLayout layout =
-                new CpuPowerStatsLayout();
-        layout.fromExtras(descriptor.extras);
+        CpuPowerStatsLayout layout = new CpuPowerStatsLayout(descriptor);
 
         long[] deviceStats = new long[descriptor.statsArrayLength];
         layout.setTimeByScalingStep(deviceStats, 2, 42);
@@ -267,8 +263,7 @@
         mockEnergyConsumers();
 
         CpuPowerStatsCollector collector = createCollector(8, 0);
-        CpuPowerStatsLayout layout = new CpuPowerStatsLayout();
-        layout.fromExtras(collector.getPowerStatsDescriptor().extras);
+        CpuPowerStatsLayout layout = new CpuPowerStatsLayout(collector.getPowerStatsDescriptor());
 
         mockKernelCpuStats(new long[]{1111, 2222, 3333},
                 new SparseArray<>() {{
@@ -338,8 +333,7 @@
         mockEnergyConsumers();
 
         CpuPowerStatsCollector collector = createCollector(8, 0);
-        CpuPowerStatsLayout layout = new CpuPowerStatsLayout();
-        layout.fromExtras(collector.getPowerStatsDescriptor().extras);
+        CpuPowerStatsLayout layout = new CpuPowerStatsLayout(collector.getPowerStatsDescriptor());
 
         mockKernelCpuStats(new long[]{1111, 2222, 3333},
                 new SparseArray<>() {{
@@ -462,17 +456,24 @@
 
     private void mockEnergyConsumers() {
         reset(mConsumedEnergyRetriever);
+        when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(3500);
         when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.CPU_CLUSTER))
                 .thenReturn(new int[]{1, 2});
-        when(mConsumedEnergyRetriever.getConsumedEnergyUws(eq(new int[]{1, 2})))
-                .thenReturn(new long[]{1000, 2000})
-                .thenReturn(new long[]{1500, 2700});
+        when(mConsumedEnergyRetriever.getConsumedEnergy(eq(new int[]{1, 2})))
+                .thenReturn(new EnergyConsumerResult[]{
+                        mockEnergyConsumer(1000), mockEnergyConsumer(2000)})
+                .thenReturn(new EnergyConsumerResult[]{
+                        mockEnergyConsumer(1500), mockEnergyConsumer(2700)});
+    }
+
+    private EnergyConsumerResult mockEnergyConsumer(long energyUWs) {
+        EnergyConsumerResult ecr = new EnergyConsumerResult();
+        ecr.energyUWs = energyUWs;
+        return ecr;
     }
 
     private static int[] getScalingStepToPowerBracketMap(CpuPowerStatsCollector collector) {
-        CpuPowerStatsLayout layout =
-                new CpuPowerStatsLayout();
-        layout.fromExtras(collector.getPowerStatsDescriptor().extras);
+        CpuPowerStatsLayout layout = new CpuPowerStatsLayout(collector.getPowerStatsDescriptor());
         return layout.getScalingStepToPowerBracketMap();
     }
 
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerStatsCollectorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerStatsCollectorTest.java
index ef20946..00b911b 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerStatsCollectorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerStatsCollectorTest.java
@@ -33,6 +33,7 @@
 import android.annotation.NonNull;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.hardware.power.stats.EnergyConsumerResult;
 import android.hardware.power.stats.EnergyConsumerType;
 import android.net.NetworkStats;
 import android.os.BatteryConsumer;
@@ -51,6 +52,7 @@
 
 import com.android.internal.os.Clock;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.MobileRadioPowerStatsLayout;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -63,7 +65,6 @@
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.function.IntSupplier;
 import java.util.function.LongSupplier;
 import java.util.function.Supplier;
 
@@ -139,11 +140,6 @@
         }
 
         @Override
-        public IntSupplier getVoltageSupplier() {
-            return () -> 3500;
-        }
-
-        @Override
         public Supplier<NetworkStats> getMobileNetworkStatsSupplier() {
             return mNetworkStatsSupplier;
         }
@@ -178,6 +174,7 @@
                 return uid;
             }
         });
+        when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(3500);
         mBatteryStats = mStatsRule.getBatteryStats();
     }
 
@@ -242,8 +239,7 @@
         assertThat(powerStats.durationMs).isEqualTo(100);
 
         PowerStats.Descriptor descriptor = powerStats.descriptor;
-        MobileRadioPowerStatsLayout layout =
-                new MobileRadioPowerStatsLayout(descriptor);
+        MobileRadioPowerStatsLayout layout = new MobileRadioPowerStatsLayout(descriptor);
         assertThat(layout.getDeviceSleepTime(powerStats.stats)).isEqualTo(200);
         assertThat(layout.getDeviceIdleTime(powerStats.stats)).isEqualTo(300);
         assertThat(layout.getDeviceCallTime(powerStats.stats)).isEqualTo(40000);
@@ -252,7 +248,7 @@
                 .isEqualTo((64321 - 10000) * 1000 / 3500);
 
         assertThat(powerStats.stateStats.size()).isEqualTo(2);
-        long[] state1 = powerStats.stateStats.get(MobileRadioPowerStatsCollector.makeStateKey(
+        long[] state1 = powerStats.stateStats.get(MobileRadioPowerStatsLayout.makeStateKey(
                 BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR,
                 ServiceState.FREQUENCY_RANGE_MMWAVE
         ));
@@ -263,7 +259,7 @@
         assertThat(layout.getStateTxTime(state1, 3)).isEqualTo(4000);
         assertThat(layout.getStateTxTime(state1, 4)).isEqualTo(5000);
 
-        long[] state2 = powerStats.stateStats.get(MobileRadioPowerStatsCollector.makeStateKey(
+        long[] state2 = powerStats.stateStats.get(MobileRadioPowerStatsLayout.makeStateKey(
                 BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
                 ServiceState.FREQUENCY_RANGE_LOW
         ));
@@ -298,15 +294,14 @@
         assertThat(powerStats.durationMs).isEqualTo(100);
 
         PowerStats.Descriptor descriptor = powerStats.descriptor;
-        MobileRadioPowerStatsLayout layout =
-                new MobileRadioPowerStatsLayout(descriptor);
+        MobileRadioPowerStatsLayout layout = new MobileRadioPowerStatsLayout(descriptor);
         assertThat(layout.getDeviceSleepTime(powerStats.stats)).isEqualTo(200);
         assertThat(layout.getDeviceIdleTime(powerStats.stats)).isEqualTo(300);
         assertThat(layout.getConsumedEnergy(powerStats.stats, 0))
                 .isEqualTo((64321 - 10000) * 1000 / 3500);
 
         assertThat(powerStats.stateStats.size()).isEqualTo(1);
-        long[] stateStats = powerStats.stateStats.get(MobileRadioPowerStatsCollector.makeStateKey(
+        long[] stateStats = powerStats.stateStats.get(MobileRadioPowerStatsLayout.makeStateKey(
                 AccessNetworkConstants.AccessNetworkType.UNKNOWN,
                 ServiceState.FREQUENCY_RANGE_UNKNOWN
         ));
@@ -416,8 +411,8 @@
                 4321, 321, 1234, 23,
                 4000, 40, 2000, 20);
 
-        when(mConsumedEnergyRetriever.getConsumedEnergyUws(eq(new int[]{777})))
-                .thenReturn(new long[]{10000});
+        when(mConsumedEnergyRetriever.getConsumedEnergy(eq(new int[]{777})))
+                .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(10000)});
 
         when(mCallDurationSupplier.getAsLong()).thenReturn(10000L);
         when(mScanDurationSupplier.getAsLong()).thenReturn(20000L);
@@ -439,8 +434,8 @@
                 5321, 421, 3234, 223,
                 8000, 80, 4000, 40);
 
-        when(mConsumedEnergyRetriever.getConsumedEnergyUws(eq(new int[]{777})))
-                .thenReturn(new long[]{64321});
+        when(mConsumedEnergyRetriever.getConsumedEnergy(eq(new int[]{777})))
+                .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(64321)});
         when(mCallDurationSupplier.getAsLong()).thenReturn(50000L);
         when(mScanDurationSupplier.getAsLong()).thenReturn(80000L);
 
@@ -448,6 +443,12 @@
         return collector.collectStats();
     }
 
+    private EnergyConsumerResult mockEnergyConsumer(long energyUWs) {
+        EnergyConsumerResult ecr = new EnergyConsumerResult();
+        ecr.energyUWs = energyUWs;
+        return ecr;
+    }
+
     private void mockModemActivityInfo(long timestamp, int sleepTimeMs, int idleTimeMs,
             int networkType1, int freqRange1, int rxTimeMs1, @NonNull int[] txTimeMs1,
             int networkType2, int freqRange2, int rxTimeMs2, @NonNull int[] txTimeMs2) {
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsCollectorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsCollectorTest.java
index 89d6c1c..a04f721 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsCollectorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsCollectorTest.java
@@ -114,13 +114,15 @@
         mockEnergyConsumers(powerStatsInternal);
 
         PowerStatsCollector.ConsumedEnergyRetrieverImpl retriever =
-                new PowerStatsCollector.ConsumedEnergyRetrieverImpl(powerStatsInternal);
+                new PowerStatsCollector.ConsumedEnergyRetrieverImpl(powerStatsInternal, ()-> 3500);
         int[] energyConsumerIds = retriever.getEnergyConsumerIds(EnergyConsumerType.CPU_CLUSTER);
         assertThat(energyConsumerIds).isEqualTo(new int[]{1, 2});
-        long[] energy = retriever.getConsumedEnergyUws(energyConsumerIds);
-        assertThat(energy).isEqualTo(new long[]{1000, 2000});
-        energy = retriever.getConsumedEnergyUws(energyConsumerIds);
-        assertThat(energy).isEqualTo(new long[]{1500, 2700});
+        EnergyConsumerResult[] energy = retriever.getConsumedEnergy(energyConsumerIds);
+        assertThat(energy[0].energyUWs).isEqualTo(1000);
+        assertThat(energy[1].energyUWs).isEqualTo(2000);
+        energy = retriever.getConsumedEnergy(energyConsumerIds);
+        assertThat(energy[0].energyUWs).isEqualTo(1500);
+        assertThat(energy[1].energyUWs).isEqualTo(2700);
     }
 
     @SuppressWarnings("unchecked")
@@ -176,4 +178,11 @@
                 .thenReturn(future1)
                 .thenReturn(future2);
     }
+
+    private EnergyConsumerResult mockEnergyConsumerResult(long energyUWs) {
+        EnergyConsumerResult ecr = new EnergyConsumerResult();
+        ecr.energyUWs = energyUWs;
+        return ecr;
+    }
+
 }
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsSchedulerTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsSchedulerTest.java
index beec661..143d046 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsSchedulerTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsSchedulerTest.java
@@ -18,36 +18,18 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.os.ConditionVariable;
-import android.os.Handler;
-import android.os.HandlerThread;
 import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.internal.os.MonotonicClock;
-
-import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.io.IOException;
-import java.nio.file.Files;
 import java.time.Duration;
 import java.time.Instant;
-import java.util.ArrayList;
-import java.util.List;
 import java.util.TimeZone;
 import java.util.concurrent.TimeUnit;
-import java.util.function.Consumer;
 
 @RunWith(AndroidJUnit4.class)
 public class PowerStatsSchedulerTest {
@@ -56,134 +38,10 @@
             .setProvideMainThread(true)
             .build();
 
-    private PowerStatsStore mPowerStatsStore;
-    private Handler mHandler;
-    private MockClock mClock = new MockClock();
-    private MonotonicClock mMonotonicClock = new MonotonicClock(0, mClock);
-    private PowerStatsScheduler mPowerStatsScheduler;
-    private PowerStatsAggregator mPowerStatsAggregator;
-    private AggregatedPowerStatsConfig mAggregatedPowerStatsConfig;
-    private List<Long> mScheduledAlarms = new ArrayList<>();
-    private boolean mPowerStatsCollectionOccurred;
-
-    private static final int START_REALTIME = 7654321;
-
-    @Before
-    @SuppressWarnings("GuardedBy")
-    public void setup() throws IOException {
-        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
-
-        mClock.currentTime = Instant.parse("2023-01-02T03:04:05.00Z").toEpochMilli();
-        mClock.realtime = START_REALTIME;
-
-        HandlerThread bgThread = new HandlerThread("bg thread");
-        bgThread.start();
-        mHandler = new Handler(bgThread.getLooper());
-        mAggregatedPowerStatsConfig = new AggregatedPowerStatsConfig();
-        mPowerStatsStore = new PowerStatsStore(
-                Files.createTempDirectory("PowerStatsSchedulerTest").toFile(),
-                mHandler, mAggregatedPowerStatsConfig);
-        mPowerStatsAggregator = mock(PowerStatsAggregator.class);
-        mPowerStatsScheduler = new PowerStatsScheduler(
-                () -> mPowerStatsCollectionOccurred = true,
-                mPowerStatsAggregator, TimeUnit.MINUTES.toMillis(30), TimeUnit.HOURS.toMillis(1),
-                mPowerStatsStore,
-                ((triggerAtMillis, tag, onAlarmListener, handler) ->
-                        mScheduledAlarms.add(triggerAtMillis)),
-                mClock, mMonotonicClock, () -> 12345L, mHandler);
-    }
-
-    @Test
-    @SuppressWarnings("unchecked")
-    public void storeAggregatePowerStats() {
-        mPowerStatsStore.reset();
-
-        assertThat(mPowerStatsStore.getTableOfContents()).isEmpty();
-
-        mPowerStatsStore.storeAggregatedPowerStats(
-                createAggregatedPowerStats(mMonotonicClock.monotonicTime(), mClock.currentTime,
-                        123));
-
-        long delayBeforeAggregating = TimeUnit.MINUTES.toMillis(90);
-        mClock.realtime += delayBeforeAggregating;
-        mClock.currentTime += delayBeforeAggregating;
-
-        doAnswer(invocation -> {
-            // The first span is longer than 30 min, because the end time is being aligned with
-            // the wall clock.  Subsequent spans should be precisely 30 minutes.
-            long startTime = invocation.getArgument(0);
-            long endTime = invocation.getArgument(1);
-            Consumer<AggregatedPowerStats> consumer = invocation.getArgument(2);
-
-            long startTimeWallClock =
-                    mClock.currentTime - (mMonotonicClock.monotonicTime() - startTime);
-            long endTimeWallClock =
-                    mClock.currentTime - (mMonotonicClock.monotonicTime() - endTime);
-
-            assertThat(startTime).isEqualTo(START_REALTIME + 123);
-            assertThat(endTime - startTime).isAtLeast(TimeUnit.MINUTES.toMillis(30));
-            assertThat(Instant.ofEpochMilli(endTimeWallClock))
-                    .isEqualTo(Instant.parse("2023-01-02T04:00:00Z"));
-
-            consumer.accept(
-                    createAggregatedPowerStats(startTime, startTimeWallClock, endTime - startTime));
-            return null;
-        }).doAnswer(invocation -> {
-            long startTime = invocation.getArgument(0);
-            long endTime = invocation.getArgument(1);
-            Consumer<AggregatedPowerStats> consumer = invocation.getArgument(2);
-
-            long startTimeWallClock =
-                    mClock.currentTime - (mMonotonicClock.monotonicTime() - startTime);
-            long endTimeWallClock =
-                    mClock.currentTime - (mMonotonicClock.monotonicTime() - endTime);
-
-            assertThat(Instant.ofEpochMilli(startTimeWallClock))
-                    .isEqualTo(Instant.parse("2023-01-02T04:00:00Z"));
-            assertThat(Instant.ofEpochMilli(endTimeWallClock))
-                    .isEqualTo(Instant.parse("2023-01-02T04:30:00Z"));
-
-            consumer.accept(
-                    createAggregatedPowerStats(startTime, startTimeWallClock, endTime - startTime));
-            return null;
-        }).when(mPowerStatsAggregator).aggregatePowerStats(anyLong(), anyLong(),
-                any(Consumer.class));
-
-        mPowerStatsScheduler.start(/*enabled*/ true);
-        ConditionVariable done = new ConditionVariable();
-        mHandler.post(done::open);
-        done.block();
-
-        assertThat(mPowerStatsCollectionOccurred).isTrue();
-        assertThat(mScheduledAlarms).containsExactly(
-                START_REALTIME + TimeUnit.MINUTES.toMillis(90) + TimeUnit.HOURS.toMillis(1));
-
-        verify(mPowerStatsAggregator, times(2))
-                .aggregatePowerStats(anyLong(), anyLong(), any(Consumer.class));
-
-        List<PowerStatsSpan.Metadata> contents = mPowerStatsStore.getTableOfContents();
-        assertThat(contents).hasSize(3);
-        // Skip the first entry, which was placed in the store at the beginning of this test
-        PowerStatsSpan.TimeFrame timeFrame1 = contents.get(1).getTimeFrames().get(0);
-        PowerStatsSpan.TimeFrame timeFrame2 = contents.get(2).getTimeFrames().get(0);
-        assertThat(timeFrame1.startMonotonicTime).isEqualTo(START_REALTIME + 123);
-        assertThat(timeFrame2.startMonotonicTime)
-                .isEqualTo(timeFrame1.startMonotonicTime + timeFrame1.duration);
-        assertThat(Instant.ofEpochMilli(timeFrame2.startTime))
-                .isEqualTo(Instant.parse("2023-01-02T04:00:00Z"));
-        assertThat(Duration.ofMillis(timeFrame2.duration)).isEqualTo(Duration.ofMinutes(30));
-    }
-
-    private AggregatedPowerStats createAggregatedPowerStats(long monotonicTime, long currentTime,
-            long duration) {
-        AggregatedPowerStats stats = new AggregatedPowerStats(mAggregatedPowerStatsConfig);
-        stats.addClockUpdate(monotonicTime, currentTime);
-        stats.setDuration(duration);
-        return stats;
-    }
-
     @Test
     public void alignToWallClock() {
+        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+
         // Expect the aligned value to be adjusted by 1 min 30 sec - rounded to the next 15 min
         assertThat(PowerStatsScheduler.alignToWallClock(123, TimeUnit.MINUTES.toMillis(15),
                 123 + TimeUnit.HOURS.toMillis(2),
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsStoreTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsStoreTest.java
index 36d7af5..dc8d920 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsStoreTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsStoreTest.java
@@ -59,14 +59,7 @@
         clearDirectory(mStoreDirectory);
 
         mPowerStatsStore = new PowerStatsStore(mStoreDirectory,
-                MAX_BATTERY_STATS_SNAPSHOT_STORAGE_BYTES,
-                new TestHandler(),
-                (sectionType, parser) -> {
-                    if (sectionType.equals(TestSection.TYPE)) {
-                        return TestSection.readXml(parser);
-                    }
-                    return null;
-                });
+                MAX_BATTERY_STATS_SNAPSHOT_STORAGE_BYTES, new TestHandler());
     }
 
     @Test
@@ -144,7 +137,7 @@
         }
 
         @Override
-        void write(TypedXmlSerializer serializer) throws IOException {
+        public void write(TypedXmlSerializer serializer) throws IOException {
             StringBuilder sb = new StringBuilder();
             for (int i = 0; i < mSize; i++) {
                 sb.append("X");
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/ScreenPowerStatsCollectorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/ScreenPowerStatsCollectorTest.java
index 817fdcb..8c09d1d 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/ScreenPowerStatsCollectorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/ScreenPowerStatsCollectorTest.java
@@ -23,6 +23,7 @@
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.when;
 
+import android.hardware.power.stats.EnergyConsumerResult;
 import android.hardware.power.stats.EnergyConsumerType;
 import android.os.BatteryConsumer;
 import android.os.BatteryStats;
@@ -32,6 +33,7 @@
 import com.android.internal.os.Clock;
 import com.android.internal.os.PowerStats;
 import com.android.server.power.stats.ScreenPowerStatsCollector.Injector;
+import com.android.server.power.stats.format.ScreenPowerStatsLayout;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -39,8 +41,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.util.function.IntSupplier;
-
 public class ScreenPowerStatsCollectorTest {
     private static final int APP_UID1 = 42;
     private static final int APP_UID2 = 24;
@@ -89,11 +89,6 @@
         }
 
         @Override
-        public IntSupplier getVoltageSupplier() {
-            return () -> 3500;
-        }
-
-        @Override
         public int getDisplayCount() {
             return 2;
         }
@@ -115,6 +110,7 @@
                 return uid;
             }
         });
+        when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(3500);
     }
 
     @Test
@@ -125,8 +121,8 @@
         // Establish a baseline
         when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.DISPLAY))
                 .thenReturn(new int[]{77});
-        when(mConsumedEnergyRetriever.getConsumedEnergyUws(new int[]{77}))
-                .thenReturn(new long[]{10_000});
+        when(mConsumedEnergyRetriever.getConsumedEnergy(new int[]{77}))
+                .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(10_000)});
 
         doAnswer(inv -> {
             ScreenPowerStatsCollector.ScreenUsageTimeRetriever.Callback callback =
@@ -139,8 +135,8 @@
 
         collector.collectStats();
 
-        when(mConsumedEnergyRetriever.getConsumedEnergyUws(new int[]{77}))
-                .thenReturn(new long[]{45_000});
+        when(mConsumedEnergyRetriever.getConsumedEnergy(new int[]{77}))
+                .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(45_000)});
         when(mScreenUsageTimeRetriever.getScreenOnTimeMs(0))
                 .thenReturn(60_000L);
         when(mScreenUsageTimeRetriever.getBrightnessLevelTimeMs(0,
@@ -171,8 +167,7 @@
 
         PowerStats powerStats = collector.collectStats();
 
-        ScreenPowerStatsLayout layout = new ScreenPowerStatsLayout();
-        layout.fromExtras(powerStats.descriptor.extras);
+        ScreenPowerStatsLayout layout = new ScreenPowerStatsLayout(powerStats.descriptor);
 
         // (45000 - 10000) / 3500
         assertThat(layout.getConsumedEnergy(powerStats.stats, 0))
@@ -204,4 +199,10 @@
         assertThat(layout.getUidTopActivityDuration(powerStats.uidStats.get(APP_UID2)))
                 .isEqualTo(10000);
     }
+
+    private EnergyConsumerResult mockEnergyConsumer(long energyUWs) {
+        EnergyConsumerResult ecr = new EnergyConsumerResult();
+        ecr.energyUWs = energyUWs;
+        return ecr;
+    }
 }
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsCollectorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsCollectorTest.java
index b13fc53..8b5e6ee 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsCollectorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsCollectorTest.java
@@ -32,6 +32,7 @@
 
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.hardware.power.stats.EnergyConsumerResult;
 import android.hardware.power.stats.EnergyConsumerType;
 import android.net.NetworkStats;
 import android.net.wifi.WifiManager;
@@ -47,6 +48,7 @@
 
 import com.android.internal.os.Clock;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.WifiPowerStatsLayout;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -57,7 +59,6 @@
 import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.function.IntSupplier;
 import java.util.function.Supplier;
 
 public class WifiPowerStatsCollectorTest {
@@ -154,11 +155,6 @@
         }
 
         @Override
-        public IntSupplier getVoltageSupplier() {
-            return () -> 3500;
-        }
-
-        @Override
         public Supplier<NetworkStats> getWifiNetworkStatsSupplier() {
             return mNetworkStatsSupplier;
         }
@@ -368,6 +364,7 @@
         WifiPowerStatsCollector collector = new WifiPowerStatsCollector(mInjector, null);
         collector.setEnabled(true);
 
+        when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(3500);
         when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.WIFI))
                 .thenReturn(new int[]{777});
 
@@ -385,8 +382,8 @@
         mockWifiScanTimes(APP_UID2, 3000, 4000);
         mockWifiScanTimes(ISOLATED_UID, 5000, 6000);
 
-        when(mConsumedEnergyRetriever.getConsumedEnergyUws(eq(new int[]{777})))
-                .thenReturn(new long[]{10000});
+        when(mConsumedEnergyRetriever.getConsumedEnergy(eq(new int[]{777})))
+                .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(10_000)});
 
         collector.collectStats();
 
@@ -404,13 +401,19 @@
         mockWifiScanTimes(APP_UID2, 3100, 4200);
         mockWifiScanTimes(ISOLATED_UID, 5300, 6400);
 
-        when(mConsumedEnergyRetriever.getConsumedEnergyUws(eq(new int[]{777})))
-                .thenReturn(new long[]{64321});
+        when(mConsumedEnergyRetriever.getConsumedEnergy(eq(new int[]{777})))
+                .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(64_321)});
 
         mStatsRule.setTime(20000, 20000);
         return collector.collectStats();
     }
 
+    private EnergyConsumerResult mockEnergyConsumer(long energyUWs) {
+        EnergyConsumerResult ecr = new EnergyConsumerResult();
+        ecr.energyUWs = energyUWs;
+        return ecr;
+    }
+
     private void mockWifiActivityInfo(long timestamp, long rxTimeMs, long txTimeMs, int scanTimeMs,
             int idleTimeMs) {
         int stackState = 0;
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/AggregatedPowerStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/AggregatedPowerStatsTest.java
similarity index 93%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/AggregatedPowerStatsTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/AggregatedPowerStatsTest.java
index 04d53de..0e73329 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/AggregatedPowerStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/AggregatedPowerStatsTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -49,7 +49,8 @@
     private static final int COMPONENT_STATE_1 = 1;
     private static final int COMPONENT_STATE_2 = 2;
 
-    private AggregatedPowerStatsConfig mAggregatedPowerStatsConfig;
+    private AggregatedPowerStatsConfig
+            mAggregatedPowerStatsConfig;
     private PowerStats.Descriptor mPowerComponentDescriptor;
 
     @Before
@@ -67,7 +68,8 @@
         mAggregatedPowerStatsConfig.trackCustomPowerComponents(
                         () -> new PowerStatsProcessor() {
                             @Override
-                            void finish(PowerComponentAggregatedPowerStats stats,
+                            void finish(
+                                    PowerComponentAggregatedPowerStats stats,
                                     long timestampMs) {
                             }
                         })
@@ -103,8 +105,8 @@
 
         TypedXmlPullParser parser = Xml.newFastPullParser();
         parser.setInput(new ByteArrayInputStream(baos.toByteArray()), "UTF-8");
-        AggregatedPowerStats actualStats = AggregatedPowerStats.createFromXml(parser,
-                mAggregatedPowerStatsConfig);
+        AggregatedPowerStats actualStats =
+                AggregatedPowerStats.createFromXml(parser, mAggregatedPowerStatsConfig);
 
         verifyAggregatedPowerStats(actualStats);
     }
@@ -163,7 +165,8 @@
         return stats;
     }
 
-    private void verifyAggregatedPowerStats(AggregatedPowerStats stats) {
+    private void verifyAggregatedPowerStats(
+            AggregatedPowerStats stats) {
         PowerStats.Descriptor descriptor = stats.getPowerComponentStats(TEST_POWER_COMPONENT)
                 .getPowerStatsDescriptor();
         assertThat(descriptor.powerComponentId).isEqualTo(TEST_POWER_COMPONENT);
@@ -277,7 +280,8 @@
                 .isEqualTo(new long[]{250, 300});
     }
 
-    private static long[] getDeviceStats(AggregatedPowerStats stats, int powerComponentId,
+    private static long[] getDeviceStats(
+            AggregatedPowerStats stats, int powerComponentId,
             int... states) {
         PowerComponentAggregatedPowerStats powerComponentStats =
                 stats.getPowerComponentStats(powerComponentId);
@@ -286,7 +290,8 @@
         return out;
     }
 
-    private static long[] getStateStats(AggregatedPowerStats stats, int key, int... states) {
+    private static long[] getStateStats(
+            AggregatedPowerStats stats, int key, int... states) {
         PowerComponentAggregatedPowerStats powerComponentStats =
                 stats.getPowerComponentStats(TEST_POWER_COMPONENT);
         long[] out = new long[powerComponentStats.getPowerStatsDescriptor().stateStatsArrayLength];
@@ -294,7 +299,8 @@
         return out;
     }
 
-    private static long[] getUidDeviceStats(AggregatedPowerStats stats, int powerComponentId,
+    private static long[] getUidDeviceStats(
+            AggregatedPowerStats stats, int powerComponentId,
             int uid, int... states) {
         PowerComponentAggregatedPowerStats powerComponentStats =
                 stats.getPowerComponentStats(powerComponentId);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/AmbientDisplayPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessorTest.java
similarity index 68%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/AmbientDisplayPowerStatsProcessorTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessorTest.java
index a2a7e00..21e615f 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/AmbientDisplayPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessorTest.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_POWER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_SCREEN;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -35,7 +35,12 @@
 import com.android.internal.os.Clock;
 import com.android.internal.os.PowerProfile;
 import com.android.internal.os.PowerStats;
-import com.android.server.power.stats.ScreenPowerStatsCollector.Injector;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.PowerStatsCollector;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.ScreenPowerStatsCollector;
+import com.android.server.power.stats.ScreenPowerStatsCollector.ScreenUsageTimeRetriever;
+import com.android.server.power.stats.format.PowerStatsLayout;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -43,8 +48,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.util.function.IntSupplier;
-
 public class AmbientDisplayPowerStatsProcessorTest {
 
     @Rule(order = 0)
@@ -64,49 +67,45 @@
     @Mock
     private PowerStatsCollector.ConsumedEnergyRetriever mConsumedEnergyRetriever;
     @Mock
-    private ScreenPowerStatsCollector.ScreenUsageTimeRetriever mScreenUsageTimeRetriever;
+    private ScreenUsageTimeRetriever mScreenUsageTimeRetriever;
 
-    private final Injector mInjector = new Injector() {
-        @Override
-        public Handler getHandler() {
-            return mStatsRule.getHandler();
-        }
+    private final ScreenPowerStatsCollector.Injector mInjector =
+            new ScreenPowerStatsCollector.Injector() {
+                @Override
+                public Handler getHandler() {
+                    return mStatsRule.getHandler();
+                }
 
-        @Override
-        public Clock getClock() {
-            return mStatsRule.getMockClock();
-        }
+                @Override
+                public Clock getClock() {
+                    return mStatsRule.getMockClock();
+                }
 
-        @Override
-        public PowerStatsUidResolver getUidResolver() {
-            return new PowerStatsUidResolver();
-        }
+                @Override
+                public PowerStatsUidResolver getUidResolver() {
+                    return new PowerStatsUidResolver();
+                }
 
-        @Override
-        public long getPowerStatsCollectionThrottlePeriod(String powerComponentName) {
-            return 0;
-        }
+                @Override
+                public long getPowerStatsCollectionThrottlePeriod(String powerComponentName) {
+                    return 0;
+                }
 
-        @Override
-        public PowerStatsCollector.ConsumedEnergyRetriever getConsumedEnergyRetriever() {
-            return mConsumedEnergyRetriever;
-        }
+                @Override
+                public PowerStatsCollector.ConsumedEnergyRetriever getConsumedEnergyRetriever() {
+                    return mConsumedEnergyRetriever;
+                }
 
-        @Override
-        public IntSupplier getVoltageSupplier() {
-            return () -> VOLTAGE_MV;
-        }
+                @Override
+                public int getDisplayCount() {
+                    return 2;
+                }
 
-        @Override
-        public int getDisplayCount() {
-            return 2;
-        }
-
-        @Override
-        public ScreenPowerStatsCollector.ScreenUsageTimeRetriever getScreenUsageTimeRetriever() {
-            return mScreenUsageTimeRetriever;
-        }
-    };
+                @Override
+                public ScreenUsageTimeRetriever getScreenUsageTimeRetriever() {
+                    return mScreenUsageTimeRetriever;
+                }
+            };
 
     @Before
     public void setup() {
@@ -167,7 +166,8 @@
         return stats.getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY);
     }
 
-    private void assertPowerEstimate(PowerComponentAggregatedPowerStats aggregatedStats,
+    private void assertPowerEstimate(
+            PowerComponentAggregatedPowerStats aggregatedStats,
             int powerState, int screenState, double expectedPowerEstimate) {
         PowerStats.Descriptor descriptor = aggregatedStats.getPowerStatsDescriptor();
         PowerStatsLayout layout = new PowerStatsLayout(descriptor);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BinaryStatePowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessorTest.java
similarity index 92%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/BinaryStatePowerStatsProcessorTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessorTest.java
index 4b40f68..b412ad6 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BinaryStatePowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessorTest.java
@@ -14,19 +14,19 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import static android.os.BatteryConsumer.PROCESS_STATE_BACKGROUND;
 import static android.os.BatteryConsumer.PROCESS_STATE_CACHED;
 import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND;
 import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE;
 
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_POWER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_SCREEN;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -40,6 +40,9 @@
 
 import com.android.internal.os.MonotonicClock;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.MockClock;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.format.BinaryStatePowerStatsLayout;
 
 import org.junit.Rule;
 import org.junit.Test;
@@ -146,7 +149,8 @@
 
     @Test
     public void energyConsumerModel() {
-        BinaryStatePowerStatsLayout statsLayout = new BinaryStatePowerStatsLayout();
+        BinaryStatePowerStatsLayout
+                statsLayout = new BinaryStatePowerStatsLayout();
         PersistableBundle extras = new PersistableBundle();
         statsLayout.toExtras(extras);
         PowerStats.Descriptor descriptor = new PowerStats.Descriptor(POWER_COMPONENT,
@@ -270,9 +274,8 @@
                 .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
                 .setProcessorSupplier(processorSupplier);
 
-        AggregatedPowerStats aggregatedPowerStats = new AggregatedPowerStats(config);
         PowerComponentAggregatedPowerStats powerComponentStats =
-                aggregatedPowerStats.getPowerComponentStats(POWER_COMPONENT);
+                new AggregatedPowerStats(config).getPowerComponentStats(POWER_COMPONENT);
         powerComponentStats.start(0);
 
         powerComponentStats.setState(STATE_POWER, POWER_STATE_OTHER, 0);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BluetoothPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BluetoothPowerStatsProcessorTest.java
similarity index 91%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/BluetoothPowerStatsProcessorTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/BluetoothPowerStatsProcessorTest.java
index 4a8125f..6dfc220 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BluetoothPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BluetoothPowerStatsProcessorTest.java
@@ -14,19 +14,19 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import static android.os.BatteryConsumer.PROCESS_STATE_BACKGROUND;
 import static android.os.BatteryConsumer.PROCESS_STATE_CACHED;
 import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND;
 import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE;
 
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_POWER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_SCREEN;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -38,6 +38,7 @@
 import android.bluetooth.UidTraffic;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.hardware.power.stats.EnergyConsumerResult;
 import android.hardware.power.stats.EnergyConsumerType;
 import android.os.BatteryConsumer;
 import android.os.Handler;
@@ -48,7 +49,12 @@
 
 import com.android.internal.os.Clock;
 import com.android.internal.os.PowerProfile;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.BluetoothPowerStatsCollector;
 import com.android.server.power.stats.BluetoothPowerStatsCollector.BluetoothStatsRetriever;
+import com.android.server.power.stats.PowerStatsCollector;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.format.BluetoothPowerStatsLayout;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -58,7 +64,6 @@
 
 import java.util.List;
 import java.util.concurrent.Executor;
-import java.util.function.IntSupplier;
 import java.util.function.Supplier;
 
 public class BluetoothPowerStatsProcessorTest {
@@ -143,11 +148,6 @@
                 }
 
                 @Override
-                public IntSupplier getVoltageSupplier() {
-                    return () -> VOLTAGE_MV;
-                }
-
-                @Override
                 public BluetoothStatsRetriever getBluetoothStatsRetriever() {
                     return mBluetoothStatsRetriever;
                 }
@@ -363,7 +363,8 @@
 
     @Test
     public void consumedEnergyModel() {
-        // No power monitoring hardware
+        when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(VOLTAGE_MV);
+        // Power monitoring hardware exists
         when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.BLUETOOTH))
                 .thenReturn(new int[]{BLUETOOTH_ENERGY_CONSUMER_ID});
 
@@ -378,8 +379,8 @@
 
         mUidScanTimes.put(APP_UID1, 100);
 
-        when(mConsumedEnergyRetriever.getConsumedEnergyUws(
-                new int[]{BLUETOOTH_ENERGY_CONSUMER_ID})).thenReturn(new long[]{0});
+        when(mConsumedEnergyRetriever.getConsumedEnergy(new int[]{BLUETOOTH_ENERGY_CONSUMER_ID}))
+                .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(0)});
 
         aggregatedStats.start(0);
 
@@ -404,8 +405,8 @@
 
         // 10 mAh represented as microWattSeconds
         long energyUws = 10 * 3600 * VOLTAGE_MV;
-        when(mConsumedEnergyRetriever.getConsumedEnergyUws(
-                new int[]{BLUETOOTH_ENERGY_CONSUMER_ID})).thenReturn(new long[]{energyUws});
+        when(mConsumedEnergyRetriever.getConsumedEnergy(new int[]{BLUETOOTH_ENERGY_CONSUMER_ID}))
+                .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(energyUws)});
 
         aggregatedStats.addPowerStats(collector.collectStats(), 10_000);
 
@@ -468,16 +469,15 @@
 
     private static PowerComponentAggregatedPowerStats createAggregatedPowerStats(
             Supplier<PowerStatsProcessor> processorSupplier) {
-        AggregatedPowerStatsConfig.PowerComponent config =
-                new AggregatedPowerStatsConfig.PowerComponent(
-                        BatteryConsumer.POWER_COMPONENT_BLUETOOTH)
-                        .trackDeviceStates(STATE_POWER, STATE_SCREEN)
-                        .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
-                        .setProcessorSupplier(processorSupplier);
+        AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig();
+        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_BLUETOOTH)
+                .trackDeviceStates(STATE_POWER, STATE_SCREEN)
+                .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
+                .setProcessorSupplier(processorSupplier);
 
         PowerComponentAggregatedPowerStats aggregatedStats =
-                new PowerComponentAggregatedPowerStats(
-                        new AggregatedPowerStats(mock(AggregatedPowerStatsConfig.class)), config);
+                new AggregatedPowerStats(config).getPowerComponentStats(
+                        BatteryConsumer.POWER_COMPONENT_BLUETOOTH);
 
         aggregatedStats.setState(STATE_POWER, POWER_STATE_OTHER, 0);
         aggregatedStats.setState(STATE_SCREEN, SCREEN_STATE_ON, 0);
@@ -491,6 +491,12 @@
         return states;
     }
 
+    private EnergyConsumerResult mockEnergyConsumer(long energyUWs) {
+        EnergyConsumerResult ecr = new EnergyConsumerResult();
+        ecr.energyUWs = energyUWs;
+        return ecr;
+    }
+
     private BluetoothActivityEnergyInfo mockBluetoothActivityEnergyInfo(long timestamp,
             long rxTimeMs, long txTimeMs, long idleTimeMs, UidTraffic... uidTraffic) {
         if (RavenwoodRule.isOnRavenwood()) {
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/CameraPowerStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CameraPowerStatsTest.java
similarity index 88%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/CameraPowerStatsTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/CameraPowerStatsTest.java
index 88a4f5e..0afcbf1 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/CameraPowerStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CameraPowerStatsTest.java
@@ -14,23 +14,22 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import static android.os.BatteryConsumer.PROCESS_STATE_BACKGROUND;
 import static android.os.BatteryConsumer.PROCESS_STATE_CACHED;
 import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND;
 import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE;
 
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_POWER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_SCREEN;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.when;
 
@@ -46,6 +45,12 @@
 import com.android.internal.os.MonotonicClock;
 import com.android.internal.os.PowerProfile;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.CameraPowerStatsCollector;
+import com.android.server.power.stats.EnergyConsumerPowerStatsCollector;
+import com.android.server.power.stats.PowerStatsCollector;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.format.BinaryStatePowerStatsLayout;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -53,7 +58,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.util.function.IntSupplier;
 import java.util.function.Supplier;
 
 public class CameraPowerStatsTest {
@@ -103,11 +107,6 @@
                 public PowerStatsCollector.ConsumedEnergyRetriever getConsumedEnergyRetriever() {
                     return mConsumedEnergyRetriever;
                 }
-
-                @Override
-                public IntSupplier getVoltageSupplier() {
-                    return () -> VOLTAGE_MV;
-                }
             };
 
     private MonotonicClock mMonotonicClock;
@@ -120,8 +119,9 @@
 
     @Test
     public void energyConsumerModel() {
+        when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(VOLTAGE_MV);
         when(mConsumedEnergyRetriever
-                .getEnergyConsumerIds(eq((int) EnergyConsumerType.CAMERA), any()))
+                .getEnergyConsumerIds(eq((int) EnergyConsumerType.CAMERA)))
                 .thenReturn(new int[]{ENERGY_CONSUMER_ID});
 
         PowerComponentAggregatedPowerStats stats = createAggregatedPowerStats(
@@ -161,8 +161,7 @@
         stats.finish(11_000);
 
         PowerStats.Descriptor descriptor = stats.getPowerStatsDescriptor();
-        BinaryStatePowerStatsLayout statsLayout = new BinaryStatePowerStatsLayout();
-        statsLayout.fromExtras(descriptor.extras);
+        BinaryStatePowerStatsLayout statsLayout = new BinaryStatePowerStatsLayout(descriptor);
 
         // Total estimated power = 3,600,000 uC = 1.0 mAh
         // of which 3,000,000 is distributed:
@@ -243,7 +242,8 @@
 
     private static PowerComponentAggregatedPowerStats createAggregatedPowerStats(
             Supplier<PowerStatsProcessor> processorSupplier) {
-        AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig();
+        AggregatedPowerStatsConfig
+                config = new AggregatedPowerStatsConfig();
         config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_CAMERA)
                 .trackDeviceStates(
                         AggregatedPowerStatsConfig.STATE_POWER,
@@ -254,9 +254,8 @@
                         AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
                 .setProcessorSupplier(processorSupplier);
 
-        AggregatedPowerStats aggregatedPowerStats = new AggregatedPowerStats(config);
-        PowerComponentAggregatedPowerStats powerComponentStats =
-                aggregatedPowerStats.getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_CAMERA);
+        PowerComponentAggregatedPowerStats powerComponentStats = new AggregatedPowerStats(config)
+                .getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_CAMERA);
         powerComponentStats.start(0);
 
         powerComponentStats.setState(STATE_POWER, POWER_STATE_OTHER, 0);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CpuPowerStatsProcessorTest.java
similarity index 86%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsProcessorTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/CpuPowerStatsProcessorTest.java
index ab2e631..6938615 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CpuPowerStatsProcessorTest.java
@@ -13,24 +13,23 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import static android.os.BatteryConsumer.PROCESS_STATE_BACKGROUND;
 import static android.os.BatteryConsumer.PROCESS_STATE_CACHED;
 import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND;
 
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_POWER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_SCREEN;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
 
 import android.os.BatteryConsumer;
 import android.os.PersistableBundle;
@@ -42,6 +41,8 @@
 
 import com.android.internal.os.PowerProfile;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.format.CpuPowerStatsLayout;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -202,26 +203,18 @@
             PowerComponentAggregatedPowerStats {
         private final CpuPowerStatsLayout mStatsLayout;
         private final PowerStats.Descriptor mDescriptor;
-        private HashMap<String, long[]> mDeviceStats = new HashMap<>();
-        private HashMap<String, long[]> mUidStats = new HashMap<>();
-        private HashSet<Integer> mUids = new HashSet<>();
-        private HashMap<String, Double> mExpectedDevicePower = new HashMap<>();
-        private HashMap<String, Double> mExpectedUidPower = new HashMap<>();
+        private final HashMap<String, long[]> mDeviceStats = new HashMap<>();
+        private final HashMap<String, long[]> mUidStats = new HashMap<>();
+        private final HashSet<Integer> mUids = new HashSet<>();
+        private final HashMap<String, Double> mExpectedDevicePower = new HashMap<>();
+        private final HashMap<String, Double> mExpectedUidPower = new HashMap<>();
 
-        MockPowerComponentAggregatedPowerStats(AggregatedPowerStatsConfig.PowerComponent config,
+        MockPowerComponentAggregatedPowerStats(
+                AggregatedPowerStatsConfig.PowerComponent config,
                 boolean useEnergyConsumers) {
-            super(new AggregatedPowerStats(mock(AggregatedPowerStatsConfig.class)), config);
-            mStatsLayout = new CpuPowerStatsLayout();
-            mStatsLayout.addDeviceSectionCpuTimeByScalingStep(3);
-            mStatsLayout.addDeviceSectionCpuTimeByCluster(2);
-            mStatsLayout.addDeviceSectionUsageDuration();
-            if (useEnergyConsumers) {
-                mStatsLayout.addDeviceSectionEnergyConsumers(2);
-            }
-            mStatsLayout.addDeviceSectionPowerEstimate();
-            mStatsLayout.addUidSectionCpuTimeByPowerBracket(new int[]{0, 1, 2});
-            mStatsLayout.addUidSectionPowerEstimate();
-
+            super(new AggregatedPowerStats(new AggregatedPowerStatsConfig()), config);
+            mStatsLayout = new CpuPowerStatsLayout(useEnergyConsumers ? 2 : 0, 2,
+                    new int[]{0, 1, 2});
             PersistableBundle extras = new PersistableBundle();
             mStatsLayout.toExtras(extras);
             mDescriptor = new PowerStats.Descriptor(BatteryConsumer.POWER_COMPONENT_CPU,
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/CustomEnergyConsumerPowerStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsTest.java
similarity index 90%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/CustomEnergyConsumerPowerStatsTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsTest.java
index 8239fdb..42baba7 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/CustomEnergyConsumerPowerStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsTest.java
@@ -14,20 +14,20 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import static android.os.BatteryConsumer.PROCESS_STATE_BACKGROUND;
 import static android.os.BatteryConsumer.PROCESS_STATE_CACHED;
 import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND;
 import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE;
 
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_POWER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_SCREEN;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -42,6 +42,12 @@
 
 import com.android.internal.os.Clock;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.CustomEnergyConsumerPowerStatsCollector;
+import com.android.server.power.stats.EnergyConsumerPowerStatsCollector;
+import com.android.server.power.stats.PowerStatsCollector;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.format.EnergyConsumerPowerStatsLayout;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -54,7 +60,6 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
-import java.util.function.IntSupplier;
 
 public class CustomEnergyConsumerPowerStatsTest {
     @Rule(order = 0)
@@ -105,11 +110,6 @@
                 public PowerStatsCollector.ConsumedEnergyRetriever getConsumedEnergyRetriever() {
                     return mConsumedEnergyRetriever;
                 }
-
-                @Override
-                public IntSupplier getVoltageSupplier() {
-                    return () -> VOLTAGE_MV;
-                }
             };
 
 
@@ -237,6 +237,7 @@
 
     private List<PowerStats> collectPowerStats(long timestamp, int chargeUc1, int chargeUc2,
             EnergyConsumerAttribution... attributions2) throws Exception {
+        when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(VOLTAGE_MV);
         when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.OTHER))
                 .thenReturn(new int[]{ENERGY_CONSUMER_ID1, ENERGY_CONSUMER_ID2});
         when(mConsumedEnergyRetriever.getEnergyConsumerName(ENERGY_CONSUMER_ID1))
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/GnssPowerStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/GnssPowerStatsTest.java
similarity index 93%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/GnssPowerStatsTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/GnssPowerStatsTest.java
index f22279a..e6207d4 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/GnssPowerStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/GnssPowerStatsTest.java
@@ -14,23 +14,22 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import static android.os.BatteryConsumer.PROCESS_STATE_BACKGROUND;
 import static android.os.BatteryConsumer.PROCESS_STATE_CACHED;
 import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND;
 import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE;
 
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_POWER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_SCREEN;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.when;
 
@@ -47,6 +46,12 @@
 import com.android.internal.os.MonotonicClock;
 import com.android.internal.os.PowerProfile;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.EnergyConsumerPowerStatsCollector;
+import com.android.server.power.stats.GnssPowerStatsCollector;
+import com.android.server.power.stats.PowerStatsCollector;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.format.BinaryStatePowerStatsLayout;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -54,7 +59,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.util.function.IntSupplier;
 import java.util.function.Supplier;
 
 public class GnssPowerStatsTest {
@@ -106,11 +110,6 @@
                 public PowerStatsCollector.ConsumedEnergyRetriever getConsumedEnergyRetriever() {
                     return mConsumedEnergyRetriever;
                 }
-
-                @Override
-                public IntSupplier getVoltageSupplier() {
-                    return () -> VOLTAGE_MV;
-                }
             };
 
     private MonotonicClock mMonotonicClock;
@@ -127,7 +126,7 @@
     public void powerProfileModel() {
         // ODPM unsupported
         when(mConsumedEnergyRetriever
-                .getEnergyConsumerIds(eq((int) EnergyConsumerType.GNSS), any()))
+                .getEnergyConsumerIds(eq((int) EnergyConsumerType.GNSS)))
                 .thenReturn(new int[0]);
 
         PowerComponentAggregatedPowerStats stats = createAggregatedPowerStats(
@@ -165,8 +164,7 @@
         stats.finish(START_TIME + 11_000);
 
         PowerStats.Descriptor descriptor = stats.getPowerStatsDescriptor();
-        BinaryStatePowerStatsLayout statsLayout = new BinaryStatePowerStatsLayout();
-        statsLayout.fromExtras(descriptor.extras);
+        BinaryStatePowerStatsLayout statsLayout = new BinaryStatePowerStatsLayout(descriptor);
 
         // scr-on, GNSS-good: 2500 * 100 = 250000 mA-ms = 0.06944 mAh
         // scr-off GNSS=good: 4500 * 100 = 0.12500 mAh
@@ -218,7 +216,7 @@
     public void initialStateGnssOn() {
         // ODPM unsupported
         when(mConsumedEnergyRetriever
-                .getEnergyConsumerIds(eq((int) EnergyConsumerType.GNSS), any()))
+                .getEnergyConsumerIds(eq((int) EnergyConsumerType.GNSS)))
                 .thenReturn(new int[0]);
 
         PowerComponentAggregatedPowerStats stats = createAggregatedPowerStats(
@@ -245,8 +243,7 @@
         stats.finish(START_TIME + 11_000);
 
         PowerStats.Descriptor descriptor = stats.getPowerStatsDescriptor();
-        BinaryStatePowerStatsLayout statsLayout = new BinaryStatePowerStatsLayout();
-        statsLayout.fromExtras(descriptor.extras);
+        BinaryStatePowerStatsLayout statsLayout = new BinaryStatePowerStatsLayout(descriptor);
 
         // scr-on, GNSS-good: 2500 * 100 = 250000 mA-ms = 0.06944 mAh
         // scr-off GNSS=good: 4500 * 100 = 0.12500 mAh
@@ -296,8 +293,9 @@
 
     @Test
     public void energyConsumerModel() {
+        when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(VOLTAGE_MV);
         when(mConsumedEnergyRetriever
-                .getEnergyConsumerIds(eq((int) EnergyConsumerType.GNSS), any()))
+                .getEnergyConsumerIds(eq((int) EnergyConsumerType.GNSS)))
                 .thenReturn(new int[]{ENERGY_CONSUMER_ID});
 
         PowerComponentAggregatedPowerStats stats = createAggregatedPowerStats(
@@ -339,8 +337,7 @@
         stats.finish(START_TIME + 11_000);
 
         PowerStats.Descriptor descriptor = stats.getPowerStatsDescriptor();
-        BinaryStatePowerStatsLayout statsLayout = new BinaryStatePowerStatsLayout();
-        statsLayout.fromExtras(descriptor.extras);
+        BinaryStatePowerStatsLayout statsLayout = new BinaryStatePowerStatsLayout(descriptor);
 
         // Total estimated power = 3,600,000 uC = 1.0 mAh
         // of which 3,000,000 is distributed:
@@ -442,7 +439,8 @@
 
     private static PowerComponentAggregatedPowerStats createAggregatedPowerStats(
             Supplier<PowerStatsProcessor> processorSupplier) {
-        AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig();
+        AggregatedPowerStatsConfig
+                config = new AggregatedPowerStatsConfig();
         config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_GNSS)
                 .trackDeviceStates(
                         AggregatedPowerStatsConfig.STATE_POWER,
@@ -453,9 +451,8 @@
                         AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
                 .setProcessorSupplier(processorSupplier);
 
-        AggregatedPowerStats aggregatedPowerStats = new AggregatedPowerStats(config);
-        PowerComponentAggregatedPowerStats powerComponentStats =
-                aggregatedPowerStats.getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_GNSS);
+        PowerComponentAggregatedPowerStats powerComponentStats = new AggregatedPowerStats(config)
+                .getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_GNSS);
         powerComponentStats.start(START_TIME);
 
         powerComponentStats.setState(STATE_POWER, POWER_STATE_OTHER, START_TIME);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessorTest.java
similarity index 87%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerStatsProcessorTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessorTest.java
index 89d59a9..80358c5 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessorTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
 import static android.net.NetworkStats.METERED_NO;
@@ -23,12 +23,12 @@
 import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND;
 import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE;
 
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_POWER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_SCREEN;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -41,6 +41,7 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.hardware.power.stats.EnergyConsumerResult;
 import android.hardware.power.stats.EnergyConsumerType;
 import android.net.NetworkStats;
 import android.os.BatteryConsumer;
@@ -53,6 +54,11 @@
 
 import com.android.internal.os.Clock;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.MobileRadioPowerStatsCollector;
+import com.android.server.power.stats.PowerStatsCollector;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.format.MobileRadioPowerStatsLayout;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -61,7 +67,6 @@
 import org.mockito.MockitoAnnotations;
 
 import java.util.List;
-import java.util.function.IntSupplier;
 import java.util.function.LongSupplier;
 import java.util.function.Supplier;
 
@@ -129,11 +134,6 @@
                 }
 
                 @Override
-                public IntSupplier getVoltageSupplier() {
-                    return () -> VOLTAGE_MV;
-                }
-
-                @Override
                 public Supplier<NetworkStats> getMobileNetworkStatsSupplier() {
                     return mNetworkStatsSupplier;
                 }
@@ -172,17 +172,15 @@
 
         mStatsRule.setTestPowerProfile("power_profile_test_modem_calculator");
 
-        AggregatedPowerStatsConfig.PowerComponent config =
-                new AggregatedPowerStatsConfig.PowerComponent(
-                        BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
-                        .trackDeviceStates(STATE_POWER, STATE_SCREEN)
-                        .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
-                        .setProcessorSupplier(() -> new MobileRadioPowerStatsProcessor(
-                                mStatsRule.getPowerProfile()));
+        AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig();
+        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
+                .trackDeviceStates(STATE_POWER, STATE_SCREEN)
+                .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
+                .setProcessorSupplier(
+                        () -> new MobileRadioPowerStatsProcessor(mStatsRule.getPowerProfile()));
 
-        PowerComponentAggregatedPowerStats aggregatedStats =
-                new PowerComponentAggregatedPowerStats(
-                        new AggregatedPowerStats(mock(AggregatedPowerStatsConfig.class)), config);
+        PowerComponentAggregatedPowerStats aggregatedStats = new AggregatedPowerStats(config)
+                .getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO);
 
         aggregatedStats.setState(STATE_POWER, POWER_STATE_OTHER, 0);
         aggregatedStats.setState(STATE_SCREEN, SCREEN_STATE_ON, 0);
@@ -232,8 +230,7 @@
         aggregatedStats.finish(10_000);
 
         MobileRadioPowerStatsLayout statsLayout =
-                new MobileRadioPowerStatsLayout(
-                        aggregatedStats.getPowerStatsDescriptor());
+                new MobileRadioPowerStatsLayout(aggregatedStats.getPowerStatsDescriptor());
 
         //    720 mA * 100 ms  (level 0 TX drain rate * level 0 TX duration)
         // + 1080 mA * 200 ms  (level 1 TX drain rate * level 1 TX duration)
@@ -316,8 +313,7 @@
                 prepareAggregatedStats_energyConsumerModel();
 
         MobileRadioPowerStatsLayout statsLayout =
-                new MobileRadioPowerStatsLayout(
-                        aggregatedStats.getPowerStatsDescriptor());
+                new MobileRadioPowerStatsLayout(aggregatedStats.getPowerStatsDescriptor());
 
         // 10_000_000 micro-Coulomb * 1/1000 milli/micro * 1/3600 hour/second = 2.77778 mAh
         double totalPower = 0;
@@ -406,23 +402,22 @@
 
     private PowerComponentAggregatedPowerStats prepareAggregatedStats_energyConsumerModel() {
         // PowerStats hardware is available
+        when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(VOLTAGE_MV);
         when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.MOBILE_RADIO))
                 .thenReturn(new int[] {MOBILE_RADIO_ENERGY_CONSUMER_ID});
 
         mStatsRule.setTestPowerProfile("power_profile_test_legacy_modem")
                 .initMeasuredEnergyStatsLocked();
 
-        AggregatedPowerStatsConfig.PowerComponent config =
-                new AggregatedPowerStatsConfig.PowerComponent(
-                        BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
-                        .trackDeviceStates(STATE_POWER, STATE_SCREEN)
-                        .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
-                        .setProcessorSupplier(() -> new MobileRadioPowerStatsProcessor(
-                                mStatsRule.getPowerProfile()));
+        AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig();
+        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
+                .trackDeviceStates(STATE_POWER, STATE_SCREEN)
+                .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
+                .setProcessorSupplier(
+                        () -> new MobileRadioPowerStatsProcessor(mStatsRule.getPowerProfile()));
 
-        PowerComponentAggregatedPowerStats aggregatedStats =
-                new PowerComponentAggregatedPowerStats(
-                        new AggregatedPowerStats(mock(AggregatedPowerStatsConfig.class)), config);
+        PowerComponentAggregatedPowerStats aggregatedStats = new AggregatedPowerStats(config)
+                .getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO);
 
         aggregatedStats.setState(STATE_POWER, POWER_STATE_OTHER, 0);
         aggregatedStats.setState(STATE_SCREEN, SCREEN_STATE_ON, 0);
@@ -436,9 +431,9 @@
         // Initial empty ModemActivityInfo.
         mockModemActivityInfo(new ModemActivityInfo(0L, 0L, 0L, new int[5], 0L));
 
-        when(mConsumedEnergyRetriever.getConsumedEnergyUws(
+        when(mConsumedEnergyRetriever.getConsumedEnergy(
                 new int[]{MOBILE_RADIO_ENERGY_CONSUMER_ID}))
-                .thenReturn(new long[]{0});
+                .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(0)});
 
         aggregatedStats.start(0);
 
@@ -467,8 +462,8 @@
         mStatsRule.setTime(10_000, 10_000);
 
         long energyUws = 10_000_000L * VOLTAGE_MV / 1000L;
-        when(mConsumedEnergyRetriever.getConsumedEnergyUws(
-                new int[]{MOBILE_RADIO_ENERGY_CONSUMER_ID})).thenReturn(new long[]{energyUws});
+        when(mConsumedEnergyRetriever.getConsumedEnergy(new int[]{MOBILE_RADIO_ENERGY_CONSUMER_ID}))
+                .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(energyUws)});
 
         when(mCallDurationSupplier.getAsLong()).thenReturn(200L);
         when(mScanDurationSupplier.getAsLong()).thenReturn(5555L);
@@ -485,6 +480,12 @@
         return states;
     }
 
+    private EnergyConsumerResult mockEnergyConsumer(long energyUWs) {
+        EnergyConsumerResult ecr = new EnergyConsumerResult();
+        ecr.energyUWs = energyUWs;
+        return ecr;
+    }
+
     private void mockModemActivityInfo(ModemActivityInfo emptyMai) {
         doAnswer(invocation -> {
             OutcomeReceiver<ModemActivityInfo, TelephonyManager.ModemActivityInfoException>
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MultiStatePowerAttributorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MultiStatePowerAttributorTest.java
new file mode 100644
index 0000000..704ee62
--- /dev/null
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MultiStatePowerAttributorTest.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2024 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.power.stats.processor;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.os.ConditionVariable;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import com.android.internal.os.BatteryStatsHistory;
+import com.android.internal.os.MonotonicClock;
+import com.android.server.power.stats.MockClock;
+import com.android.server.power.stats.PowerStatsScheduler;
+import com.android.server.power.stats.PowerStatsSpan;
+import com.android.server.power.stats.PowerStatsStore;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.TimeZone;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
+public class MultiStatePowerAttributorTest {
+
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
+            .setProvideMainThread(true)
+            .build();
+
+    private PowerStatsStore mPowerStatsStore;
+    private Handler mHandler;
+    private final MockClock mClock = new MockClock();
+    private final MonotonicClock mMonotonicClock = new MonotonicClock(0, mClock);
+    private PowerStatsScheduler mPowerStatsScheduler;
+    private PowerStatsAggregator mPowerStatsAggregator;
+    private MultiStatePowerAttributor mPowerAttributor;
+    private final List<Long> mScheduledAlarms = new ArrayList<>();
+    private boolean mPowerStatsCollectionOccurred;
+
+    private static final int START_REALTIME = 7654321;
+
+    @Before
+    public void setup() throws IOException {
+        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+
+        mClock.currentTime = Instant.parse("2023-01-02T03:04:05.00Z").toEpochMilli();
+        mClock.realtime = START_REALTIME;
+
+        HandlerThread bgThread = new HandlerThread("bg thread");
+        bgThread.start();
+        mHandler = new Handler(bgThread.getLooper());
+        mPowerStatsStore = new PowerStatsStore(
+                Files.createTempDirectory("MultiStatePowerAttributorTest").toFile(), mHandler);
+        mPowerStatsAggregator = mock(PowerStatsAggregator.class);
+        mPowerAttributor = new MultiStatePowerAttributor(mPowerStatsStore, mPowerStatsAggregator);
+        mPowerStatsScheduler = new PowerStatsScheduler(
+                () -> mPowerStatsCollectionOccurred = true,
+                mock(BatteryStatsHistory.class),
+                mPowerAttributor, TimeUnit.MINUTES.toMillis(30), TimeUnit.HOURS.toMillis(1),
+                mPowerStatsStore,
+                ((triggerAtMillis, tag, onAlarmListener, handler) ->
+                        mScheduledAlarms.add(triggerAtMillis)),
+                mClock, mMonotonicClock, () -> 12345L, mHandler);
+    }
+
+    @Test
+    public void storeAggregatedPowerStats() {
+        mPowerStatsStore.reset();
+
+        assertThat(mPowerStatsStore.getTableOfContents()).isEmpty();
+
+        mPowerAttributor.storeAggregatedPowerStats(
+                createAggregatedPowerStats(mMonotonicClock.monotonicTime(), mClock.currentTime,
+                        123));
+
+        long delayBeforeAggregating = TimeUnit.MINUTES.toMillis(90);
+        mClock.realtime += delayBeforeAggregating;
+        mClock.currentTime += delayBeforeAggregating;
+
+        doAnswer(invocation -> {
+            // The first span is longer than 30 min, because the end time is being aligned with
+            // the wall clock.  Subsequent spans should be precisely 30 minutes.
+            long startTime = invocation.getArgument(1);
+            long endTime = invocation.getArgument(2);
+            Consumer<AggregatedPowerStats> consumer = invocation.getArgument(3);
+
+            long startTimeWallClock =
+                    mClock.currentTime - (mMonotonicClock.monotonicTime() - startTime);
+            long endTimeWallClock =
+                    mClock.currentTime - (mMonotonicClock.monotonicTime() - endTime);
+
+            assertThat(startTime).isEqualTo(START_REALTIME + 123);
+            assertThat(endTime - startTime).isAtLeast(TimeUnit.MINUTES.toMillis(30));
+            assertThat(Instant.ofEpochMilli(endTimeWallClock))
+                    .isEqualTo(Instant.parse("2023-01-02T04:00:00Z"));
+
+            consumer.accept(
+                    createAggregatedPowerStats(startTime, startTimeWallClock, endTime - startTime));
+            return null;
+        }).doAnswer(invocation -> {
+            long startTime = invocation.getArgument(1);
+            long endTime = invocation.getArgument(2);
+            Consumer<AggregatedPowerStats> consumer = invocation.getArgument(3);
+
+            long startTimeWallClock =
+                    mClock.currentTime - (mMonotonicClock.monotonicTime() - startTime);
+            long endTimeWallClock =
+                    mClock.currentTime - (mMonotonicClock.monotonicTime() - endTime);
+
+            assertThat(Instant.ofEpochMilli(startTimeWallClock))
+                    .isEqualTo(Instant.parse("2023-01-02T04:00:00Z"));
+            assertThat(Instant.ofEpochMilli(endTimeWallClock))
+                    .isEqualTo(Instant.parse("2023-01-02T04:30:00Z"));
+
+            consumer.accept(
+                    createAggregatedPowerStats(startTime, startTimeWallClock, endTime - startTime));
+            return null;
+        }).when(mPowerStatsAggregator).aggregatePowerStats(any(BatteryStatsHistory.class),
+                anyLong(), anyLong(), any(Consumer.class));
+
+        mPowerStatsScheduler.start(/*enabled*/ true);
+        ConditionVariable done = new ConditionVariable();
+        mHandler.post(done::open);
+        done.block();
+
+        assertThat(mPowerStatsCollectionOccurred).isTrue();
+        assertThat(mScheduledAlarms).containsExactly(
+                START_REALTIME + TimeUnit.MINUTES.toMillis(90) + TimeUnit.HOURS.toMillis(1));
+
+        verify(mPowerStatsAggregator, times(2)).aggregatePowerStats(
+                any(BatteryStatsHistory.class), anyLong(), anyLong(), any(Consumer.class));
+
+        List<PowerStatsSpan.Metadata> contents = mPowerStatsStore.getTableOfContents();
+        assertThat(contents).hasSize(3);
+        // Skip the first entry, which was placed in the store at the beginning of this test
+        PowerStatsSpan.TimeFrame timeFrame1 = contents.get(1).getTimeFrames().get(0);
+        PowerStatsSpan.TimeFrame timeFrame2 = contents.get(2).getTimeFrames().get(0);
+        assertThat(timeFrame1.startMonotonicTime).isEqualTo(START_REALTIME + 123);
+        assertThat(timeFrame2.startMonotonicTime)
+                .isEqualTo(timeFrame1.startMonotonicTime + timeFrame1.duration);
+        assertThat(Instant.ofEpochMilli(timeFrame2.startTime))
+                .isEqualTo(Instant.parse("2023-01-02T04:00:00Z"));
+        assertThat(Duration.ofMillis(timeFrame2.duration)).isEqualTo(Duration.ofMinutes(30));
+    }
+
+    private AggregatedPowerStats createAggregatedPowerStats(long monotonicTime, long currentTime,
+            long duration) {
+        AggregatedPowerStats stats = new AggregatedPowerStats(new AggregatedPowerStatsConfig());
+        stats.addClockUpdate(monotonicTime, currentTime);
+        stats.setDuration(duration);
+        return stats;
+    }
+}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/MultiStateStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MultiStateStatsTest.java
similarity index 99%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/MultiStateStatsTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/MultiStateStatsTest.java
index ae258cd3..a232c0c 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/MultiStateStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MultiStateStatsTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
@@ -198,8 +198,7 @@
                 new MultiStateStats.States("scr", trackScreenState, "screen-off", "plugged-in"));
     }
 
-    private FactorySubject assertThatCpuPerformanceStatsFactory(
-            MultiStateStats.Factory factory) {
+    private FactorySubject assertThatCpuPerformanceStatsFactory(MultiStateStats.Factory factory) {
         FactorySubject subject = new FactorySubject();
         subject.mFactory = factory;
         return subject;
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PhoneCallPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/PhoneCallPowerStatsProcessorTest.java
similarity index 84%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/PhoneCallPowerStatsProcessorTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/PhoneCallPowerStatsProcessorTest.java
index cb1bcfe..535f2da 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/PhoneCallPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/PhoneCallPowerStatsProcessorTest.java
@@ -13,14 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_POWER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_SCREEN;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -41,6 +41,11 @@
 import android.telephony.TelephonyManager;
 
 import com.android.internal.os.Clock;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.MobileRadioPowerStatsCollector;
+import com.android.server.power.stats.PowerStatsCollector;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.format.PowerStatsLayout;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -48,7 +53,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.util.function.IntSupplier;
 import java.util.function.LongSupplier;
 import java.util.function.Supplier;
 
@@ -113,11 +117,6 @@
                 }
 
                 @Override
-                public IntSupplier getVoltageSupplier() {
-                    return () -> VOLTAGE_MV;
-                }
-
-                @Override
                 public Supplier<NetworkStats> getMobileNetworkStatsSupplier() {
                     return mNetworkStatsSupplier;
                 }
@@ -156,19 +155,17 @@
 
     @Test
     public void copyEstimatesFromMobileRadioPowerStats() {
-
-        AggregatedPowerStatsConfig aggregatedPowerStatsConfig = new AggregatedPowerStatsConfig();
-        aggregatedPowerStatsConfig.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
+        AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig();
+        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
                 .trackDeviceStates(STATE_POWER, STATE_SCREEN)
                 .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
                 .setProcessorSupplier(
                         () -> new MobileRadioPowerStatsProcessor(mStatsRule.getPowerProfile()));
-        aggregatedPowerStatsConfig.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_PHONE,
+        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_PHONE,
                         BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
                 .setProcessorSupplier(PhoneCallPowerStatsProcessor::new);
 
-        AggregatedPowerStats aggregatedPowerStats =
-                new AggregatedPowerStats(aggregatedPowerStatsConfig);
+        AggregatedPowerStats aggregatedPowerStats = new AggregatedPowerStats(config);
         PowerComponentAggregatedPowerStats mobileRadioStats =
                 aggregatedPowerStats.getPowerComponentStats(
                         BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO);
@@ -208,8 +205,7 @@
                 aggregatedPowerStats.getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_PHONE);
         stats.finish(10_000);
 
-        PowerStatsLayout statsLayout =
-                new PowerStatsLayout(stats.getPowerStatsDescriptor());
+        PowerStatsLayout statsLayout = new PowerStatsLayout(stats.getPowerStatsDescriptor());
 
         long[] deviceStats = new long[stats.getPowerStatsDescriptor().statsArrayLength];
         stats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_ON));
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/PowerStatsAggregatorTest.java
similarity index 95%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/PowerStatsAggregatorTest.java
index 3929137..f312bed 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/PowerStatsAggregatorTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -32,6 +32,7 @@
 import com.android.internal.os.BatteryStatsHistory;
 import com.android.internal.os.MonotonicClock;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.MockClock;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -53,7 +54,7 @@
     private final MockClock mClock = new MockClock();
     private final MonotonicClock mMonotonicClock = new MonotonicClock(START_TIME, mClock);
     private BatteryStatsHistory mHistory;
-    private PowerStatsAggregator mAggregator;
+    private com.android.server.power.stats.processor.PowerStatsAggregator mAggregator;
     private int mAggregatedStatsCount;
 
     @Before
@@ -71,7 +72,7 @@
                         AggregatedPowerStatsConfig.STATE_POWER,
                         AggregatedPowerStatsConfig.STATE_SCREEN,
                         AggregatedPowerStatsConfig.STATE_PROCESS_STATE);
-        mAggregator = new PowerStatsAggregator(config, mHistory);
+        mAggregator = new PowerStatsAggregator(config);
     }
 
     @Test
@@ -119,7 +120,7 @@
         powerStats.uidStats.put(TEST_UID, new long[]{4444});
         mHistory.recordPowerStats(mClock.realtime, mClock.uptime, powerStats);
 
-        mAggregator.aggregatePowerStats(0, MonotonicClock.UNDEFINED, stats -> {
+        mAggregator.aggregatePowerStats(mHistory, 0, MonotonicClock.UNDEFINED, stats -> {
             assertThat(mAggregatedStatsCount++).isEqualTo(0);
             assertThat(stats.getStartTime()).isEqualTo(START_TIME);
 
@@ -138,7 +139,8 @@
 
             long[] values = new long[1];
 
-            PowerComponentAggregatedPowerStats powerComponentStats = stats.getPowerComponentStats(
+            PowerComponentAggregatedPowerStats
+                    powerComponentStats = stats.getPowerComponentStats(
                     TEST_POWER_COMPONENT);
 
             assertThat(powerComponentStats.getDeviceStats(values, new int[]{
@@ -218,7 +220,7 @@
 
         mHistory.recordBatteryState(mClock.realtime, mClock.uptime, 50, /* plugged */ true);
 
-        mAggregator.aggregatePowerStats(0, MonotonicClock.UNDEFINED, stats -> {
+        mAggregator.aggregatePowerStats(mHistory, 0, MonotonicClock.UNDEFINED, stats -> {
             long[] values = new long[1];
 
             PowerComponentAggregatedPowerStats powerComponentStats =
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsExporterTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/PowerStatsExporterTest.java
similarity index 95%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsExporterTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/PowerStatsExporterTest.java
index 96203a5..024743d 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsExporterTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/PowerStatsExporterTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
@@ -22,6 +22,7 @@
 import static org.mockito.Mockito.mock;
 
 import android.annotation.NonNull;
+import android.content.Context;
 import android.os.AggregateBatteryConsumer;
 import android.os.BatteryConsumer;
 import android.os.BatteryStats;
@@ -37,9 +38,16 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.os.BatteryStatsHistory;
+import com.android.internal.os.CpuScalingPolicies;
 import com.android.internal.os.MonotonicClock;
 import com.android.internal.os.PowerProfile;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.MockClock;
+import com.android.server.power.stats.PowerStatsStore;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.format.CpuPowerStatsLayout;
+import com.android.server.power.stats.format.EnergyConsumerPowerStatsLayout;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -76,6 +84,7 @@
     private MonotonicClock mMonotonicClock = new MonotonicClock(0, mClock);
     private PowerStatsStore mPowerStatsStore;
     private PowerStatsAggregator mPowerStatsAggregator;
+    private MultiStatePowerAttributor mPowerAttributor;
     private BatteryStatsHistory mHistory;
     private CpuPowerStatsLayout mCpuStatsArrayLayout;
     private PowerStats.Descriptor mPowerStatsDescriptor;
@@ -108,25 +117,23 @@
                         AggregatedPowerStatsConfig.STATE_SCREEN,
                         AggregatedPowerStatsConfig.STATE_PROCESS_STATE);
 
-        mPowerStatsStore = new PowerStatsStore(storeDirectory, new TestHandler(), config);
+        mPowerStatsStore = new PowerStatsStore(storeDirectory, new TestHandler());
         mHistory = new BatteryStatsHistory(Parcel.obtain(), storeDirectory, 0, 10000,
                 mock(BatteryStatsHistory.HistoryStepDetailsCalculator.class), mClock,
                 mMonotonicClock, null, null);
-        mPowerStatsAggregator = new PowerStatsAggregator(config, mHistory);
+        mPowerStatsAggregator = new PowerStatsAggregator(config);
 
-        mCpuStatsArrayLayout = new CpuPowerStatsLayout();
-        mCpuStatsArrayLayout.addDeviceSectionCpuTimeByScalingStep(1);
-        mCpuStatsArrayLayout.addDeviceSectionCpuTimeByCluster(1);
-        mCpuStatsArrayLayout.addDeviceSectionUsageDuration();
-        mCpuStatsArrayLayout.addDeviceSectionPowerEstimate();
-        mCpuStatsArrayLayout.addUidSectionCpuTimeByPowerBracket(new int[]{0});
-        mCpuStatsArrayLayout.addUidSectionPowerEstimate();
+        mCpuStatsArrayLayout = new CpuPowerStatsLayout(0, 1, new int[]{0});
         PersistableBundle extras = new PersistableBundle();
         mCpuStatsArrayLayout.toExtras(extras);
 
         mPowerStatsDescriptor = new PowerStats.Descriptor(BatteryConsumer.POWER_COMPONENT_CPU,
                 mCpuStatsArrayLayout.getDeviceStatsArrayLength(),
                 null, 0, mCpuStatsArrayLayout.getUidStatsArrayLength(), extras);
+
+        mPowerAttributor = new MultiStatePowerAttributor(mock(Context.class), mPowerStatsStore,
+                mock(PowerProfile.class), mock(CpuScalingPolicies.class),
+                mock(PowerStatsUidResolver.class));
     }
 
     @Test
@@ -329,10 +336,12 @@
                 includeScreenStateData, includesPowerStateData);
     }
 
-    private @NonNull BatteryUsageStats exportToBatteryUsageStats(AggregatedPowerStats aps,
+    private @NonNull BatteryUsageStats exportToBatteryUsageStats(
+            AggregatedPowerStats aps,
             boolean includeProcessStateData, boolean includeScreenStateData,
             boolean includesPowerStateData) {
-        PowerStatsExporter exporter = new PowerStatsExporter(mPowerStatsStore,
+        PowerStatsExporter
+                exporter = new PowerStatsExporter(mPowerStatsStore,
                 mPowerStatsAggregator, /* batterySessionTimeSpanSlackMillis */ 0);
 
         BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder(new String[0], false,
@@ -508,8 +517,8 @@
         mCpuStatsArrayLayout.setUidTimeByPowerBracket(uidStats2, 0, 2469);
         mHistory.recordPowerStats(3000, 3000, powerStats);
 
-        mPowerStatsAggregator.aggregatePowerStats(0, 3500,
-                stats -> mPowerStatsStore.storeAggregatedPowerStats(stats));
+        mPowerStatsAggregator.aggregatePowerStats(mHistory, 0, 3500,
+                stats -> mPowerAttributor.storeAggregatedPowerStats(stats));
 
         mHistory.recordProcessStateChange(4000, 4000, APP_UID1,
                 BatteryConsumer.PROCESS_STATE_BACKGROUND);
@@ -525,9 +534,8 @@
         mEnergyConsumerPowerStatsLayout.setUidConsumedEnergy(customUidStats, 0, 360_000);
         mHistory.recordPowerStats(6010, 6010, customPowerStats);
 
-        mPowerStatsAggregator.aggregatePowerStats(3500, 6500, stats -> {
-            mPowerStatsStore.storeAggregatedPowerStats(stats);
-        });
+        mPowerStatsAggregator.aggregatePowerStats(mHistory, 3500, 6500,
+                stats -> mPowerAttributor.storeAggregatedPowerStats(stats));
 
         mHistory.recordStateStartEvent(7000, 7000, BatteryStats.HistoryItem.STATE_SCREEN_ON_FLAG);
         mHistory.recordProcessStateChange(7000, 7000, APP_UID1,
@@ -548,7 +556,8 @@
         recordBatteryHistory();
         PowerStatsExporter exporter = new PowerStatsExporter(mPowerStatsStore,
                 mPowerStatsAggregator, /* batterySessionTimeSpanSlackMillis */ 0);
-        exporter.exportAggregatedPowerStats(builder, monotonicStartTime, monotonicEndTime);
+        exporter.exportAggregatedPowerStats(builder, mHistory, monotonicStartTime,
+                monotonicEndTime);
     }
 
     private void assertAggregatedPowerEstimate(String message, BatteryUsageStats bus, int scope,
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/PowerStatsProcessorTest.java
similarity index 94%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsProcessorTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/PowerStatsProcessorTest.java
index 02e446a..13e0d9d 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/PowerStatsProcessorTest.java
@@ -13,11 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_POWER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_SCREEN;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
 
 import static com.google.common.truth.Truth.assertThat;
 
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/ScreenPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/ScreenPowerStatsProcessorTest.java
similarity index 83%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/ScreenPowerStatsProcessorTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/ScreenPowerStatsProcessorTest.java
index 94f5662..1852165 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/ScreenPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/ScreenPowerStatsProcessorTest.java
@@ -14,22 +14,22 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_POWER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_SCREEN;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import android.hardware.power.stats.EnergyConsumerResult;
 import android.hardware.power.stats.EnergyConsumerType;
 import android.os.BatteryConsumer;
 import android.os.BatteryStats;
@@ -40,7 +40,12 @@
 import com.android.internal.os.Clock;
 import com.android.internal.os.PowerProfile;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.PowerStatsCollector;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.ScreenPowerStatsCollector;
 import com.android.server.power.stats.ScreenPowerStatsCollector.Injector;
+import com.android.server.power.stats.format.ScreenPowerStatsLayout;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -48,7 +53,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.util.function.IntSupplier;
 import java.util.function.Supplier;
 
 public class ScreenPowerStatsProcessorTest {
@@ -106,11 +110,6 @@
         }
 
         @Override
-        public IntSupplier getVoltageSupplier() {
-            return () -> VOLTAGE_MV;
-        }
-
-        @Override
         public int getDisplayCount() {
             return 2;
         }
@@ -124,6 +123,7 @@
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
+        when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(VOLTAGE_MV);
     }
 
     @Test
@@ -177,8 +177,8 @@
         if (energyConsumer) {
             when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.DISPLAY))
                     .thenReturn(new int[]{77});
-            when(mConsumedEnergyRetriever.getConsumedEnergyUws(new int[]{77}))
-                    .thenReturn(new long[]{10_000});
+            when(mConsumedEnergyRetriever.getConsumedEnergy(new int[]{77}))
+                    .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(10_000)});
         } else {
             when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.DISPLAY))
                     .thenReturn(new int[0]);
@@ -200,8 +200,8 @@
         if (energyConsumer) {
             // 400 mAh represented as microWattSeconds
             long energyUws = 400L * 3600 * VOLTAGE_MV;
-            when(mConsumedEnergyRetriever.getConsumedEnergyUws(new int[]{77}))
-                    .thenReturn(new long[]{10_000 + energyUws});
+            when(mConsumedEnergyRetriever.getConsumedEnergy(new int[]{77}))
+                    .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(10_000 + energyUws)});
         }
 
         when(mScreenUsageTimeRetriever.getScreenOnTimeMs(0))
@@ -243,16 +243,14 @@
 
     private static PowerComponentAggregatedPowerStats createAggregatedPowerStats(
             Supplier<PowerStatsProcessor> processorSupplier) {
-        AggregatedPowerStatsConfig.PowerComponent config =
-                new AggregatedPowerStatsConfig.PowerComponent(
-                        BatteryConsumer.POWER_COMPONENT_SCREEN)
+        AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig();
+        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_SCREEN)
                         .trackDeviceStates(STATE_POWER, STATE_SCREEN)
                         .trackUidStates(STATE_POWER, STATE_SCREEN)
                         .setProcessorSupplier(processorSupplier);
 
-        PowerComponentAggregatedPowerStats aggregatedStats =
-                new PowerComponentAggregatedPowerStats(
-                        new AggregatedPowerStats(mock(AggregatedPowerStatsConfig.class)), config);
+        PowerComponentAggregatedPowerStats aggregatedStats = new AggregatedPowerStats(config)
+                .getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_SCREEN);
 
         aggregatedStats.setState(STATE_POWER, POWER_STATE_OTHER, 0);
         aggregatedStats.setState(STATE_SCREEN, SCREEN_STATE_ON, 0);
@@ -260,7 +258,14 @@
         return aggregatedStats;
     }
 
-    private void assertDevicePowerEstimate(PowerComponentAggregatedPowerStats aggregatedStats,
+    private EnergyConsumerResult mockEnergyConsumer(long energyUWs) {
+        EnergyConsumerResult ecr = new EnergyConsumerResult();
+        ecr.energyUWs = energyUWs;
+        return ecr;
+    }
+
+    private void assertDevicePowerEstimate(
+            PowerComponentAggregatedPowerStats aggregatedStats,
             int powerState, int screenState, double expectedScreenPowerEstimate,
             double expectedDozePowerEstimate) {
         PowerStats.Descriptor descriptor = aggregatedStats.getPowerStatsDescriptor();
@@ -273,7 +278,8 @@
                 .of(expectedDozePowerEstimate);
     }
 
-    private void assertUidPowerEstimate(PowerComponentAggregatedPowerStats aggregatedStats, int uid,
+    private void assertUidPowerEstimate(
+            PowerComponentAggregatedPowerStats aggregatedStats, int uid,
             int powerState, int screenState, double expectedScreenPowerEstimate) {
         PowerStats.Descriptor descriptor = aggregatedStats.getPowerStatsDescriptor();
         ScreenPowerStatsLayout layout = new ScreenPowerStatsLayout(descriptor);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/SensorPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/SensorPowerStatsProcessorTest.java
similarity index 91%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/SensorPowerStatsProcessorTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/SensorPowerStatsProcessorTest.java
index 687d70b..d972604 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/SensorPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/SensorPowerStatsProcessorTest.java
@@ -14,19 +14,19 @@
  * limitations under the License.
  */
 
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import static android.os.BatteryConsumer.PROCESS_STATE_BACKGROUND;
 import static android.os.BatteryConsumer.PROCESS_STATE_CACHED;
 import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND;
 import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE;
 
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_POWER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_SCREEN;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -43,6 +43,8 @@
 
 import com.android.internal.os.MonotonicClock;
 import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.format.SensorPowerStatsLayout;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -109,8 +111,7 @@
         stats.finish(10000);
 
         PowerStats.Descriptor descriptor = stats.getPowerStatsDescriptor();
-        SensorPowerStatsLayout statsLayout = new SensorPowerStatsLayout();
-        statsLayout.fromExtras(descriptor.extras);
+        SensorPowerStatsLayout statsLayout = new SensorPowerStatsLayout(descriptor);
 
         String dump = stats.toString();
         assertThat(dump).contains(" step_counter: ");
@@ -207,10 +208,8 @@
                         AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
                 .setProcessorSupplier(processorSupplier);
 
-        AggregatedPowerStats aggregatedPowerStats = new AggregatedPowerStats(config);
-        PowerComponentAggregatedPowerStats powerComponentStats =
-                aggregatedPowerStats.getPowerComponentStats(
-                        BatteryConsumer.POWER_COMPONENT_SENSORS);
+        PowerComponentAggregatedPowerStats powerComponentStats = new AggregatedPowerStats(config)
+                .getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_SENSORS);
         powerComponentStats.start(0);
 
         powerComponentStats.setState(STATE_POWER, POWER_STATE_OTHER, 0);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/WifiPowerStatsProcessorTest.java
similarity index 91%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsProcessorTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/WifiPowerStatsProcessorTest.java
index 11c09bc..baf468e 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/WifiPowerStatsProcessorTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
 
 import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
 import static android.net.NetworkStats.METERED_NO;
@@ -23,12 +23,12 @@
 import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND;
 import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE;
 
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_POWER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_SCREEN;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -41,6 +41,7 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.hardware.power.stats.EnergyConsumerResult;
 import android.hardware.power.stats.EnergyConsumerType;
 import android.net.NetworkStats;
 import android.net.wifi.WifiManager;
@@ -53,6 +54,13 @@
 
 import com.android.internal.os.Clock;
 import com.android.internal.os.PowerProfile;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.MockBatteryStatsImpl;
+import com.android.server.power.stats.PowerStatsCollector;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.WifiPowerStatsCollector;
+import com.android.server.power.stats.WifiPowerStatsCollector.WifiStatsRetriever;
+import com.android.server.power.stats.format.WifiPowerStatsLayout;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -61,7 +69,6 @@
 import org.mockito.MockitoAnnotations;
 
 import java.util.List;
-import java.util.function.IntSupplier;
 import java.util.function.Supplier;
 
 public class WifiPowerStatsProcessorTest {
@@ -109,8 +116,7 @@
     private final SparseArray<ScanTimes> mScanTimes = new SparseArray<>();
     private long mWifiActiveDuration;
 
-    private final WifiPowerStatsCollector.WifiStatsRetriever mWifiStatsRetriever =
-            new WifiPowerStatsCollector.WifiStatsRetriever() {
+    private final WifiStatsRetriever mWifiStatsRetriever = new WifiStatsRetriever() {
         @Override
         public void retrieveWifiScanTimes(Callback callback) {
             for (int i = 0; i < mScanTimes.size(); i++) {
@@ -159,11 +165,6 @@
                 }
 
                 @Override
-                public IntSupplier getVoltageSupplier() {
-                    return () -> VOLTAGE_MV;
-                }
-
-                @Override
                 public Supplier<NetworkStats> getWifiNetworkStatsSupplier() {
                     return mNetworkStatsSupplier;
                 }
@@ -174,7 +175,7 @@
                 }
 
                 @Override
-                public WifiPowerStatsCollector.WifiStatsRetriever getWifiStatsRetriever() {
+                public WifiStatsRetriever getWifiStatsRetriever() {
                     return mWifiStatsRetriever;
                 }
             };
@@ -308,6 +309,7 @@
         when(mWifiManager.isEnhancedPowerReportingSupported()).thenReturn(true);
 
         // PowerStats hardware is available
+        when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(VOLTAGE_MV);
         when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.WIFI))
                 .thenReturn(new int[] {WIFI_ENERGY_CONSUMER_ID});
 
@@ -321,9 +323,9 @@
         mockWifiActivityEnergyInfo(new WifiActivityEnergyInfo(0L,
                 WifiActivityEnergyInfo.STACK_STATE_INVALID, 0L, 0L, 0L, 0L));
 
-        when(mConsumedEnergyRetriever.getConsumedEnergyUws(
+        when(mConsumedEnergyRetriever.getConsumedEnergy(
                 new int[]{WIFI_ENERGY_CONSUMER_ID}))
-                .thenReturn(new long[]{0});
+                .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(0)});
 
         aggregatedStats.start(0);
 
@@ -354,8 +356,8 @@
 
         // 10 mAh represented as microWattSeconds
         long energyUws = 10 * 3600 * VOLTAGE_MV;
-        when(mConsumedEnergyRetriever.getConsumedEnergyUws(
-                new int[]{WIFI_ENERGY_CONSUMER_ID})).thenReturn(new long[]{energyUws});
+        when(mConsumedEnergyRetriever.getConsumedEnergy(new int[]{WIFI_ENERGY_CONSUMER_ID}))
+                .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(energyUws)});
 
         aggregatedStats.addPowerStats(collector.collectStats(), 10_000);
 
@@ -525,15 +527,14 @@
 
     private static PowerComponentAggregatedPowerStats createAggregatedPowerStats(
             Supplier<PowerStatsProcessor> processorSupplier) {
-        AggregatedPowerStatsConfig.PowerComponent config =
-                new AggregatedPowerStatsConfig.PowerComponent(BatteryConsumer.POWER_COMPONENT_WIFI)
-                        .trackDeviceStates(STATE_POWER, STATE_SCREEN)
-                        .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
-                        .setProcessorSupplier(processorSupplier);
+        AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig();
+        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_WIFI)
+                .trackDeviceStates(STATE_POWER, STATE_SCREEN)
+                .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
+                .setProcessorSupplier(processorSupplier);
 
-        PowerComponentAggregatedPowerStats aggregatedStats =
-                new PowerComponentAggregatedPowerStats(
-                        new AggregatedPowerStats(mock(AggregatedPowerStatsConfig.class)), config);
+        PowerComponentAggregatedPowerStats aggregatedStats = new AggregatedPowerStats(config)
+                .getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_WIFI);
 
         aggregatedStats.setState(STATE_POWER, POWER_STATE_OTHER, 0);
         aggregatedStats.setState(STATE_SCREEN, SCREEN_STATE_ON, 0);
@@ -547,6 +548,12 @@
         return states;
     }
 
+    private EnergyConsumerResult mockEnergyConsumer(long energyUWs) {
+        EnergyConsumerResult ecr = new EnergyConsumerResult();
+        ecr.energyUWs = energyUWs;
+        return ecr;
+    }
+
     private void mockWifiActivityEnergyInfo(WifiActivityEnergyInfo waei) {
         doAnswer(invocation -> {
             WifiManager.OnWifiActivityEnergyInfoListener
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MouseKeysInterceptorTest.kt b/services/tests/servicestests/src/com/android/server/accessibility/MouseKeysInterceptorTest.kt
index 8753b25..019ccf9 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MouseKeysInterceptorTest.kt
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MouseKeysInterceptorTest.kt
@@ -48,6 +48,7 @@
 import java.util.LinkedList
 import java.util.Queue
 import android.util.ArraySet
+import android.view.InputDevice
 
 /**
  * Tests for {@link MouseKeysInterceptor}
@@ -68,6 +69,8 @@
     }
 
     private lateinit var mouseKeysInterceptor: MouseKeysInterceptor
+    private lateinit var inputDevice: InputDevice
+
     private val clock = OffsettableClock()
     private val testLooper = TestLooper { clock.now() }
     private val nextInterceptor = TrackingInterceptor()
@@ -98,6 +101,10 @@
         testSession = InputManagerGlobal.createTestSession(iInputManager)
         mockInputManager = InputManager(context)
 
+        inputDevice = createInputDevice(DEVICE_ID)
+        Mockito.`when`(iInputManager.getInputDevice(DEVICE_ID))
+                .thenReturn(inputDevice)
+
         Mockito.`when`(mockVirtualDeviceManagerInternal.getDeviceIdsForUid(Mockito.anyInt()))
             .thenReturn(ArraySet(setOf(DEVICE_ID)))
         LocalServices.removeServiceForTest(VirtualDeviceManagerInternal::class.java)
@@ -115,7 +122,8 @@
         Mockito.`when`(iInputManager.inputDeviceIds).thenReturn(intArrayOf(DEVICE_ID))
         Mockito.`when`(mockAms.traceManager).thenReturn(mockTraceManager)
 
-        mouseKeysInterceptor = MouseKeysInterceptor(mockAms, testLooper.looper, DISPLAY_ID)
+        mouseKeysInterceptor = MouseKeysInterceptor(mockAms, mockInputManager,
+                testLooper.looper, DISPLAY_ID)
         mouseKeysInterceptor.next = nextInterceptor
     }
 
@@ -281,6 +289,17 @@
         }
     }
 
+    private fun createInputDevice(
+            deviceId: Int,
+            generation: Int = -1
+    ): InputDevice =
+            InputDevice.Builder()
+                    .setId(deviceId)
+                    .setName("Device $deviceId")
+                    .setDescriptor("descriptor $deviceId")
+                    .setGeneration(generation)
+                    .build()
+
     private class TrackingInterceptor : BaseEventStreamTransformation() {
         val events: Queue<KeyEvent> = LinkedList()
 
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index 1db46bf..2a55521 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -55,6 +55,7 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyBoolean;
@@ -145,7 +146,6 @@
  */
 @SmallTest
 @Presubmit
-
 public class UserControllerTest {
     // Use big enough user id to avoid picking up already active user id.
     private static final int TEST_USER_ID = 100;
@@ -593,6 +593,7 @@
     @Test
     public void testScheduleStopOfBackgroundUser_switch() {
         mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_SCHEDULE_STOP_OF_BACKGROUND_USER);
+        assumeFalse(UserManager.isVisibleBackgroundUsersEnabled());
 
         mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
                 /* maxRunningUsers= */ 10, /* delayUserDataLocking= */ false,
@@ -642,6 +643,7 @@
     @Test
     public void testScheduleStopOfBackgroundUser_startInBackground() throws Exception {
         mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_SCHEDULE_STOP_OF_BACKGROUND_USER);
+        assumeFalse(UserManager.isVisibleBackgroundUsersEnabled());
 
         mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
                 /* maxRunningUsers= */ 10, /* delayUserDataLocking= */ false,
@@ -681,6 +683,7 @@
     @Test
     public void testScheduleStopOfBackgroundUser_rescheduleWhenGuest() throws Exception {
         mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_SCHEDULE_STOP_OF_BACKGROUND_USER);
+        assumeFalse(UserManager.isVisibleBackgroundUsersEnabled());
 
         mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
                 /* maxRunningUsers= */ 10, /* delayUserDataLocking= */ false,
@@ -736,6 +739,7 @@
     @Test
     public void testScheduleStopOfBackgroundUser_rescheduleIfAlarm() throws Exception {
         mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_SCHEDULE_STOP_OF_BACKGROUND_USER);
+        assumeFalse(UserManager.isVisibleBackgroundUsersEnabled());
 
         mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
                 /* maxRunningUsers= */ 10, /* delayUserDataLocking= */ false,
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java b/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
index 7933f7a..4a19973 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
@@ -46,6 +46,7 @@
 import android.content.IntentFilter;
 import android.hardware.display.ColorDisplayManager;
 import android.os.PowerManager;
+import android.platform.test.annotations.EnableFlags;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.service.notification.ZenDeviceEffects;
 import android.testing.TestableContext;
@@ -64,6 +65,9 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
 @RunWith(TestParameterInjector.class)
 public class DefaultDeviceEffectsApplierTest {
 
@@ -89,6 +93,8 @@
 
         mApplier = new DefaultDeviceEffectsApplier(mContext);
         verify(mWallpaperManager).isWallpaperSupported();
+
+        ZenLog.clear();
     }
 
     @Test
@@ -110,6 +116,41 @@
     }
 
     @Test
+    @EnableFlags(android.app.Flags.FLAG_MODES_API)
+    public void apply_logsToZenLog() {
+        when(mPowerManager.isInteractive()).thenReturn(true);
+        ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
+                ArgumentCaptor.forClass(BroadcastReceiver.class);
+        ArgumentCaptor<IntentFilter> intentFilterCaptor =
+                ArgumentCaptor.forClass(IntentFilter.class);
+
+        ZenDeviceEffects effects = new ZenDeviceEffects.Builder()
+                .setShouldDisplayGrayscale(true)
+                .setShouldUseNightMode(true)
+                .build();
+        mApplier.apply(effects, ORIGIN_APP);
+
+        String zenLog = getZenLog();
+        assertThat(zenLog).contains("apply_device_effect: displayGrayscale -> true");
+        assertThat(zenLog).contains("schedule_device_effect: nightMode -> true");
+        assertThat(zenLog).doesNotContain("apply_device_effect: nightMode");
+
+        verify(mContext).registerReceiver(broadcastReceiverCaptor.capture(),
+                intentFilterCaptor.capture(), anyInt());
+        BroadcastReceiver screenOffReceiver = broadcastReceiverCaptor.getValue();
+        screenOffReceiver.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF));
+
+        zenLog = getZenLog();
+        assertThat(zenLog).contains("apply_device_effect: nightMode -> true");
+    }
+
+    private static String getZenLog() {
+        StringWriter zenLogWriter = new StringWriter();
+        ZenLog.dump(new PrintWriter(zenLogWriter), "");
+        return zenLogWriter.toString();
+    }
+
+    @Test
     public void apply_removesEffects() {
         mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);
 
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 0a52238..6a1140c 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -14995,7 +14995,6 @@
     }
 
     @Test
-    @EnableFlags(android.app.Flags.FLAG_SECURE_ALLOWLIST_TOKEN)
     public void enqueueNotification_acceptsCorrectToken() throws RemoteException {
         Notification sent = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setContentIntent(createPendingIntent("content"))
@@ -15014,7 +15013,6 @@
     }
 
     @Test
-    @EnableFlags(android.app.Flags.FLAG_SECURE_ALLOWLIST_TOKEN)
     public void enqueueNotification_acceptsNullToken_andPopulatesIt() throws RemoteException {
         Notification receivedWithoutParceling = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setContentIntent(createPendingIntent("content"))
@@ -15031,7 +15029,6 @@
     }
 
     @Test
-    @EnableFlags(android.app.Flags.FLAG_SECURE_ALLOWLIST_TOKEN)
     public void enqueueNotification_directlyThroughRunnable_populatesAllowlistToken() {
         Notification receivedWithoutParceling = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setContentIntent(createPendingIntent("content"))
@@ -15054,7 +15051,6 @@
     }
 
     @Test
-    @EnableFlags(android.app.Flags.FLAG_SECURE_ALLOWLIST_TOKEN)
     public void enqueueNotification_rejectsOtherToken() throws RemoteException {
         Notification sent = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setContentIntent(createPendingIntent("content"))
@@ -15072,7 +15068,6 @@
     }
 
     @Test
-    @EnableFlags(android.app.Flags.FLAG_SECURE_ALLOWLIST_TOKEN)
     public void enqueueNotification_customParcelingWithFakeInnerToken_hasCorrectTokenInIntents()
             throws RemoteException {
         Notification sentFromApp = new Notification.Builder(mContext, TEST_CHANNEL_ID)
@@ -15278,7 +15273,6 @@
 
     @Test
     @SuppressWarnings("unchecked")
-    @EnableFlags(android.app.Flags.FLAG_SECURE_ALLOWLIST_TOKEN)
     public void getActiveNotifications_doesNotLeakAllowlistToken() throws RemoteException {
         Notification sentFromApp = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setContentIntent(createPendingIntent("content"))
diff --git a/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
index 07934ea..e694c0b 100644
--- a/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
@@ -188,7 +188,7 @@
                 .FLAG_CREATE_ACCESSIBILITY_OVERLAY_APP_OP_ENABLED);
         int[] outAppOp = new int[1];
         assertEquals(ADD_OKAY, mPhoneWindowManager.checkAddPermission(TYPE_WALLPAPER,
-                /* isRoundedCornerOverlay= */ false, "test.pkg", outAppOp));
+                /* isRoundedCornerOverlay= */ false, "test.pkg", outAppOp, DEFAULT_DISPLAY));
         assertThat(outAppOp[0]).isEqualTo(AppOpsManager.OP_NONE);
     }
 
@@ -198,7 +198,7 @@
                 .FLAG_CREATE_ACCESSIBILITY_OVERLAY_APP_OP_ENABLED);
         int[] outAppOp = new int[1];
         assertEquals(ADD_OKAY, mPhoneWindowManager.checkAddPermission(TYPE_ACCESSIBILITY_OVERLAY,
-                /* isRoundedCornerOverlay= */ false, "test.pkg", outAppOp));
+                /* isRoundedCornerOverlay= */ false, "test.pkg", outAppOp, DEFAULT_DISPLAY));
         assertThat(outAppOp[0]).isEqualTo(AppOpsManager.OP_CREATE_ACCESSIBILITY_OVERLAY);
     }
 
@@ -208,7 +208,7 @@
                 .FLAG_CREATE_ACCESSIBILITY_OVERLAY_APP_OP_ENABLED);
         int[] outAppOp = new int[1];
         assertEquals(ADD_OKAY, mPhoneWindowManager.checkAddPermission(TYPE_ACCESSIBILITY_OVERLAY,
-                /* isRoundedCornerOverlay= */ false, "test.pkg", outAppOp));
+                /* isRoundedCornerOverlay= */ false, "test.pkg", outAppOp, DEFAULT_DISPLAY));
         assertThat(outAppOp[0]).isEqualTo(AppOpsManager.OP_NONE);
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
index 9981a4d..9967cce 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
@@ -36,7 +36,6 @@
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Builder;
 import android.view.SurfaceControl.Transaction;
-import android.view.SurfaceSession;
 
 import androidx.test.filters.SmallTest;
 
@@ -69,7 +68,6 @@
     @Mock AnimationAdapter mSpec2;
     @Mock Transaction mTransaction;
 
-    private SurfaceSession mSession = new SurfaceSession();
     private MyAnimatable mAnimatable;
     private MyAnimatable mAnimatable2;
     private DeferFinishAnimatable mDeferFinishAnimatable;
@@ -78,9 +76,9 @@
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
 
-        mAnimatable = new MyAnimatable(mWm, mSession, mTransaction);
-        mAnimatable2 = new MyAnimatable(mWm, mSession, mTransaction);
-        mDeferFinishAnimatable = new DeferFinishAnimatable(mWm, mSession, mTransaction);
+        mAnimatable = new MyAnimatable(mWm, mTransaction);
+        mAnimatable2 = new MyAnimatable(mWm, mTransaction);
+        mDeferFinishAnimatable = new DeferFinishAnimatable(mWm, mTransaction);
     }
 
     @After
@@ -88,8 +86,6 @@
         mAnimatable = null;
         mAnimatable2 = null;
         mDeferFinishAnimatable = null;
-        mSession.kill();
-        mSession = null;
     }
 
     @Test
@@ -313,7 +309,6 @@
 
     private static class MyAnimatable implements Animatable {
 
-        private final SurfaceSession mSession;
         private final Transaction mTransaction;
         final SurfaceControl mParent;
         final SurfaceControl mSurface;
@@ -322,13 +317,12 @@
         boolean mFinishedCallbackCalled;
         @AnimationType int mFinishedAnimationType;
 
-        MyAnimatable(WindowManagerService wm, SurfaceSession session, Transaction transaction) {
-            mSession = session;
+        MyAnimatable(WindowManagerService wm, Transaction transaction) {
             mTransaction = transaction;
-            mParent = wm.makeSurfaceBuilder(mSession)
+            mParent = wm.makeSurfaceBuilder()
                     .setName("test surface parent")
                     .build();
-            mSurface = wm.makeSurfaceBuilder(mSession)
+            mSurface = wm.makeSurfaceBuilder()
                     .setName("test surface")
                     .build();
             mFinishedCallbackCalled = false;
@@ -360,7 +354,7 @@
 
         @Override
         public Builder makeAnimationLeash() {
-            return new Builder(mSession) {
+            return new Builder() {
 
                 @Override
                 public SurfaceControl build() {
@@ -406,9 +400,8 @@
 
         Runnable mEndDeferFinishCallback;
 
-        DeferFinishAnimatable(WindowManagerService wm, SurfaceSession session,
-                Transaction transaction) {
-            super(wm, session, transaction);
+        DeferFinishAnimatable(WindowManagerService wm, Transaction transaction) {
+            super(wm, transaction);
         }
 
         @Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 1e39f0b..ae722807 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -394,7 +394,7 @@
         mWmService = WindowManagerService.main(
                 mContext, mImService, false, wmPolicy, mAtmService,
                 testDisplayWindowSettingsProvider, StubTransaction::new,
-                (unused) -> new MockSurfaceControlBuilder());
+                MockSurfaceControlBuilder::new);
         spyOn(mWmService);
         spyOn(mWmService.mRoot);
         // Invoked during {@link ActivityStack} creation.
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
index a71b81e..0cd036f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
@@ -2135,8 +2135,8 @@
     private static void setupMockParent(TaskFragment taskFragment, Task mockParent) {
         doReturn(mockParent).when(taskFragment).getTask();
         doReturn(new TaskFragmentParentInfo(
-                new Configuration(), DEFAULT_DISPLAY, true, true, null /* decorSurface */))
-                .when(mockParent).getTaskFragmentParentInfo();
+                new Configuration(), DEFAULT_DISPLAY, mockParent.mTaskId, true, true,
+                null /* decorSurface */)).when(mockParent).getTaskFragmentParentInfo();
 
         // Task needs to be visible
         mockParent.lastActiveTime = 100;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
index d62c626..eebb487 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -60,7 +60,7 @@
 
     @Override
     public int checkAddPermission(int type, boolean isRoundedCornerOverlay, String packageName,
-            int[] outAppOp) {
+            int[] outAppOp, int displayId) {
         return 0;
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
index 39640fb..916c237 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
@@ -1189,7 +1189,7 @@
         final int displayId = mDisplayContent.mDisplayId;
         // Use real surface, so ViewportWindow's BlastBufferQueue can be created.
         final ArrayList<SurfaceControl> surfaceControls = new ArrayList<>();
-        mWm.mSurfaceControlFactory = s -> new SurfaceControl.Builder() {
+        mWm.mSurfaceControlFactory = () -> new SurfaceControl.Builder() {
             @Override
             public SurfaceControl build() {
                 final SurfaceControl sc = super.build();
diff --git a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
index 88ce3a6..4f60106 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
@@ -51,7 +51,6 @@
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.view.SurfaceControl;
-import android.view.SurfaceSession;
 import android.window.ScreenCapture;
 
 import androidx.test.filters.SmallTest;
@@ -63,7 +62,7 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedList;
-import java.util.function.Function;
+import java.util.function.Supplier;
 
 /**
  * Tests for the {@link DisplayContent#assignChildLayers(SurfaceControl.Transaction)} method.
@@ -126,8 +125,7 @@
         private LayerRecordingTransaction mTransaction;
         private SurfaceControl mPendingParent;
 
-        HierarchyRecorder(SurfaceSession s, LayerRecordingTransaction transaction) {
-            super(s);
+        HierarchyRecorder(LayerRecordingTransaction transaction) {
             mTransaction = transaction;
         }
 
@@ -146,8 +144,8 @@
         }
     }
 
-    private static class HierarchyRecordingBuilderFactory implements Function<SurfaceSession,
-            SurfaceControl.Builder> {
+    private static class HierarchyRecordingBuilderFactory
+            implements Supplier<SurfaceControl.Builder> {
         private LayerRecordingTransaction mTransaction;
 
         HierarchyRecordingBuilderFactory(LayerRecordingTransaction transaction) {
@@ -155,9 +153,8 @@
         }
 
         @Override
-        public SurfaceControl.Builder apply(SurfaceSession s) {
-            final LayerRecordingTransaction transaction = mTransaction;
-            return new HierarchyRecorder(s, transaction);
+        public SurfaceControl.Builder get() {
+            return new HierarchyRecorder(mTransaction);
         }
     }
 
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 13bd5eb..aca0941 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -10098,8 +10098,8 @@
      * The default value is 30 seconds.
      */
     @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
-    public static final String KEY_SATELLITE_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT =
-            "satellite_screen_off_inactivity_timeout_sec_int";
+    public static final String KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT =
+            "satellite_roaming_screen_off_inactivity_timeout_sec_int";
 
     /**
      * An integer key holds the timeout duration in seconds used to determine whether to exit P2P
@@ -10112,8 +10112,8 @@
      * The default value is 180 seconds.
      */
     @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
-    public static final String KEY_SATELLITE_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT =
-            "satellite_p2p_sms_inactivity_timeout_sec_int";
+    public static final String KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT =
+            "satellite_roaming_p2p_sms_inactivity_timeout_sec_int";
 
     /**
      * An integer key holds the timeout duration in seconds used to determine whether to exit ESOS
@@ -10126,8 +10126,8 @@
      * The default value is 600 seconds.
      */
     @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
-    public static final String KEY_SATELLITE_ESOS_INACTIVITY_TIMEOUT_SEC_INT =
-            "satellite_esos_inactivity_timeout_sec_int";
+    public static final String KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT =
+            "satellite_roaming_esos_inactivity_timeout_sec_int";
 
     /**
      * Indicating whether DUN APN should be disabled when the device is roaming. In that case,
@@ -11294,9 +11294,9 @@
         sDefaults.putInt(KEY_CARRIER_ROAMING_NTN_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_INT,
                 SatelliteManager.EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911);
         sDefaults.putInt(KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT, 180);
-        sDefaults.putInt(KEY_SATELLITE_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT, 30);
-        sDefaults.putInt(KEY_SATELLITE_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT, 180);
-        sDefaults.putInt(KEY_SATELLITE_ESOS_INACTIVITY_TIMEOUT_SEC_INT, 600);
+        sDefaults.putInt(KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT, 30);
+        sDefaults.putInt(KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT, 180);
+        sDefaults.putInt(KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT, 600);
         sDefaults.putString(KEY_DEFAULT_PREFERRED_APN_NAME_STRING, "");
         sDefaults.putBoolean(KEY_SUPPORTS_CALL_COMPOSER_BOOL, false);
         sDefaults.putBoolean(KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL, false);
diff --git a/tests/Input/Android.bp b/tests/Input/Android.bp
index 06c2651..65398a2 100644
--- a/tests/Input/Android.bp
+++ b/tests/Input/Android.bp
@@ -40,7 +40,7 @@
         "frameworks-base-testutils",
         "hamcrest-library",
         "kotlin-test",
-        "mockito-target-minus-junit4",
+        "mockito-target-extended-minus-junit4",
         "platform-test-annotations",
         "platform-screenshot-diff-core",
         "services.core.unboosted",
diff --git a/tests/Input/src/com/android/server/input/debug/TouchpadDebugViewTest.java b/tests/Input/src/com/android/server/input/debug/TouchpadDebugViewTest.java
new file mode 100644
index 0000000..ad0ef1b
--- /dev/null
+++ b/tests/Input/src/com/android/server/input/debug/TouchpadDebugViewTest.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2024 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.input.debug;
+
+import static android.view.InputDevice.SOURCE_TOUCHSCREEN;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.testing.TestableContext;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.cts.input.MotionEventBuilder;
+import com.android.cts.input.PointerBuilder;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Build/Install/Run:
+ * atest TouchpadDebugViewTest
+ */
+@RunWith(AndroidJUnit4.class)
+public class TouchpadDebugViewTest {
+    private static final int TOUCHPAD_DEVICE_ID = 6;
+
+    private TouchpadDebugView mTouchpadDebugView;
+    private WindowManager.LayoutParams mWindowLayoutParams;
+
+    @Mock
+    WindowManager mWindowManager;
+
+    Rect mWindowBounds;
+    WindowMetrics mWindowMetrics;
+    TestableContext mTestableContext;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
+        mTestableContext = new TestableContext(context);
+
+        mTestableContext.addMockSystemService(WindowManager.class, mWindowManager);
+
+        mWindowBounds = new Rect(0, 0, 2560, 1600);
+        mWindowMetrics = new WindowMetrics(mWindowBounds, new WindowInsets(mWindowBounds), 1.0f);
+
+        when(mWindowManager.getCurrentWindowMetrics()).thenReturn(mWindowMetrics);
+
+        mTouchpadDebugView = new TouchpadDebugView(mTestableContext, TOUCHPAD_DEVICE_ID);
+
+        mTouchpadDebugView.measure(
+                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
+                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
+        );
+
+        doAnswer(invocation -> {
+            mTouchpadDebugView.layout(0, 0, mTouchpadDebugView.getMeasuredWidth(),
+                    mTouchpadDebugView.getMeasuredHeight());
+            return null;
+        }).when(mWindowManager).addView(any(), any());
+
+        doAnswer(invocation -> {
+            mTouchpadDebugView.layout(0, 0, mTouchpadDebugView.getMeasuredWidth(),
+                    mTouchpadDebugView.getMeasuredHeight());
+            return null;
+        }).when(mWindowManager).updateViewLayout(any(), any());
+
+        mWindowLayoutParams = mTouchpadDebugView.getWindowLayoutParams();
+        mWindowLayoutParams.x = 20;
+        mWindowLayoutParams.y = 20;
+
+        mTouchpadDebugView.layout(0, 0, mTouchpadDebugView.getMeasuredWidth(),
+                mTouchpadDebugView.getMeasuredHeight());
+    }
+
+    @Test
+    public void testDragView() {
+        // Initial view position relative to screen.
+        int initialX = mWindowLayoutParams.x;
+        int initialY = mWindowLayoutParams.y;
+
+        float offsetX = ViewConfiguration.get(mTestableContext).getScaledTouchSlop() + 10;
+        float offsetY = ViewConfiguration.get(mTestableContext).getScaledTouchSlop() + 10;
+
+        // Simulate ACTION_DOWN event (initial touch).
+        MotionEvent actionDown = new MotionEventBuilder(MotionEvent.ACTION_DOWN, SOURCE_TOUCHSCREEN)
+                .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+                        .x(40f)
+                        .y(40f)
+                )
+                .build();
+        mTouchpadDebugView.dispatchTouchEvent(actionDown);
+
+        verify(mWindowManager, times(0)).updateViewLayout(any(), any());
+
+        // Simulate ACTION_MOVE event (dragging to the right).
+        MotionEvent actionMove = new MotionEventBuilder(MotionEvent.ACTION_MOVE, SOURCE_TOUCHSCREEN)
+                .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+                        .x(40f + offsetX)
+                        .y(40f + offsetY)
+                )
+                .build();
+        mTouchpadDebugView.dispatchTouchEvent(actionMove);
+
+        ArgumentCaptor<WindowManager.LayoutParams> mWindowLayoutParamsCaptor =
+                ArgumentCaptor.forClass(WindowManager.LayoutParams.class);
+        verify(mWindowManager).updateViewLayout(any(), mWindowLayoutParamsCaptor.capture());
+
+        // Verify position after ACTION_MOVE
+        assertEquals(initialX + (long) offsetX, mWindowLayoutParamsCaptor.getValue().x);
+        assertEquals(initialY + (long) offsetY, mWindowLayoutParamsCaptor.getValue().y);
+
+        // Simulate ACTION_UP event (release touch).
+        MotionEvent actionUp = new MotionEventBuilder(MotionEvent.ACTION_UP, SOURCE_TOUCHSCREEN)
+                .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+                        .x(40f + offsetX)
+                        .y(40f + offsetY)
+                )
+                .build();
+        mTouchpadDebugView.dispatchTouchEvent(actionUp);
+
+        assertEquals(initialX + (long) offsetX, mWindowLayoutParamsCaptor.getValue().x);
+        assertEquals(initialY + (long) offsetY, mWindowLayoutParamsCaptor.getValue().y);
+    }
+
+    @Test
+    public void testDragViewOutOfBounds() {
+        int initialX = mWindowLayoutParams.x;
+        int initialY = mWindowLayoutParams.y;
+
+        MotionEvent actionDown = new MotionEventBuilder(MotionEvent.ACTION_DOWN, SOURCE_TOUCHSCREEN)
+                .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+                        .x(initialX + 10f)
+                        .y(initialY + 10f)
+                )
+                .build();
+        mTouchpadDebugView.dispatchTouchEvent(actionDown);
+
+        verify(mWindowManager, times(0)).updateViewLayout(any(), any());
+
+        // Simulate ACTION_MOVE event (dragging far to the right and bottom, beyond screen bounds)
+        MotionEvent actionMove = new MotionEventBuilder(MotionEvent.ACTION_MOVE, SOURCE_TOUCHSCREEN)
+                .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+                        .x(mWindowBounds.width() + mTouchpadDebugView.getWidth())
+                        .y(mWindowBounds.height() + mTouchpadDebugView.getHeight())
+                )
+                .build();
+        mTouchpadDebugView.dispatchTouchEvent(actionMove);
+
+        ArgumentCaptor<WindowManager.LayoutParams> mWindowLayoutParamsCaptor =
+                ArgumentCaptor.forClass(WindowManager.LayoutParams.class);
+        verify(mWindowManager).updateViewLayout(any(), mWindowLayoutParamsCaptor.capture());
+
+        // Verify the view has been clamped to the right and bottom edges of the screen
+        assertEquals(mWindowBounds.width() - mTouchpadDebugView.getWidth(),
+                mWindowLayoutParamsCaptor.getValue().x);
+        assertEquals(mWindowBounds.height() - mTouchpadDebugView.getHeight(),
+                mWindowLayoutParamsCaptor.getValue().y);
+
+        MotionEvent actionUp = new MotionEventBuilder(MotionEvent.ACTION_UP, SOURCE_TOUCHSCREEN)
+                .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+                        .x(mWindowBounds.width() + mTouchpadDebugView.getWidth())
+                        .y(mWindowBounds.height() + mTouchpadDebugView.getHeight())
+                )
+                .build();
+        mTouchpadDebugView.dispatchTouchEvent(actionUp);
+
+        // Verify the view has been clamped to the right and bottom edges of the screen
+        assertEquals(mWindowBounds.width() - mTouchpadDebugView.getWidth(),
+                mWindowLayoutParamsCaptor.getValue().x);
+        assertEquals(mWindowBounds.height() - mTouchpadDebugView.getHeight(),
+                mWindowLayoutParamsCaptor.getValue().y);
+    }
+
+    @Test
+    public void testSlopOffset() {
+        int initialX = mWindowLayoutParams.x;
+        int initialY = mWindowLayoutParams.y;
+
+        float offsetX = ViewConfiguration.get(mTestableContext).getScaledTouchSlop() / 2.0f;
+        float offsetY = -(ViewConfiguration.get(mTestableContext).getScaledTouchSlop() / 2.0f);
+
+        MotionEvent actionDown = new MotionEventBuilder(MotionEvent.ACTION_DOWN, SOURCE_TOUCHSCREEN)
+                .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+                        .x(initialX)
+                        .y(initialY)
+                )
+                .build();
+        mTouchpadDebugView.dispatchTouchEvent(actionDown);
+
+        MotionEvent actionMove = new MotionEventBuilder(MotionEvent.ACTION_MOVE, SOURCE_TOUCHSCREEN)
+                .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+                        .x(initialX + offsetX)
+                        .y(initialY + offsetY)
+                )
+                .build();
+        mTouchpadDebugView.dispatchTouchEvent(actionMove);
+
+        MotionEvent actionUp = new MotionEventBuilder(MotionEvent.ACTION_UP, SOURCE_TOUCHSCREEN)
+                .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+                        .x(initialX)
+                        .y(initialY)
+                )
+                .build();
+        mTouchpadDebugView.dispatchTouchEvent(actionUp);
+
+        // In this case the updateViewLayout() method wouldn't be called because the drag
+        // distance hasn't exceeded the slop
+        verify(mWindowManager, times(0)).updateViewLayout(any(), any());
+    }
+
+    @Test
+    public void testViewReturnsToInitialPositionOnCancel() {
+        int initialX = mWindowLayoutParams.x;
+        int initialY = mWindowLayoutParams.y;
+
+        float offsetX = 50;
+        float offsetY = 50;
+
+        MotionEvent actionDown = new MotionEventBuilder(MotionEvent.ACTION_DOWN, SOURCE_TOUCHSCREEN)
+                .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+                        .x(initialX)
+                        .y(initialY)
+                )
+                .build();
+        mTouchpadDebugView.dispatchTouchEvent(actionDown);
+
+        MotionEvent actionMove = new MotionEventBuilder(MotionEvent.ACTION_MOVE, SOURCE_TOUCHSCREEN)
+                .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+                        .x(initialX + offsetX)
+                        .y(initialY + offsetY)
+                )
+                .build();
+        mTouchpadDebugView.dispatchTouchEvent(actionMove);
+
+        ArgumentCaptor<WindowManager.LayoutParams> mWindowLayoutParamsCaptor =
+                ArgumentCaptor.forClass(WindowManager.LayoutParams.class);
+        verify(mWindowManager).updateViewLayout(any(), mWindowLayoutParamsCaptor.capture());
+
+        assertEquals(initialX + (long) offsetX, mWindowLayoutParamsCaptor.getValue().x);
+        assertEquals(initialY + (long) offsetY, mWindowLayoutParamsCaptor.getValue().y);
+
+        // Simulate ACTION_CANCEL event (canceling the touch event stream)
+        MotionEvent actionCancel = new MotionEventBuilder(MotionEvent.ACTION_CANCEL,
+                SOURCE_TOUCHSCREEN)
+                .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+                        .x(initialX + offsetX)
+                        .y(initialY + offsetY)
+                )
+                .build();
+        mTouchpadDebugView.dispatchTouchEvent(actionCancel);
+
+        // Verify the view returns to its initial position
+        verify(mWindowManager, times(2)).updateViewLayout(any(),
+                mWindowLayoutParamsCaptor.capture());
+        assertEquals(initialX, mWindowLayoutParamsCaptor.getValue().x);
+        assertEquals(initialY, mWindowLayoutParamsCaptor.getValue().y);
+    }
+}
diff --git a/tools/hoststubgen/hoststubgen/Android.bp b/tools/hoststubgen/hoststubgen/Android.bp
index 682adbc..ea77b8d 100644
--- a/tools/hoststubgen/hoststubgen/Android.bp
+++ b/tools/hoststubgen/hoststubgen/Android.bp
@@ -118,7 +118,6 @@
 
 java_test_host {
     name: "hoststubgentest",
-    // main_class: "com.android.hoststubgen.Main",
     srcs: ["test/**/*.kt"],
     static_libs: [
         "hoststubgen",
@@ -143,8 +142,7 @@
     // "--policy-override-file $(location framework-policy-override.txt) " +
     "@$(location :hoststubgen-standard-options) " +
 
-    "--out-stub-jar $(location host_stub.jar) " +
-    "--out-impl-jar $(location host_impl.jar) " +
+    "--out-jar $(location host.jar) " +
 
     // "--keep-all-classes " + // Used it for an experiment. See KeepAllClassesFilter.
     "--gen-keep-all-file $(location hoststubgen_keep_all.txt) " +
@@ -159,10 +157,8 @@
     srcs: [
         ":hoststubgen-standard-options",
     ],
-    // Create two jar files.
     out: [
-        "host_stub.jar",
-        "host_impl.jar",
+        "host.jar",
 
         // Following files are created just as FYI.
         "hoststubgen_keep_all.txt",
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestStub.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestStub.java
deleted file mode 100644
index cabdfe0..0000000
--- a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestStub.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2023 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.hosttest.annotation;
-
-import static java.lang.annotation.ElementType.CONSTRUCTOR;
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.TYPE;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
- * QUESTIONS ABOUT IT.
- *
- * Mark a class, field or a method as "Stub", meaning tests can see the APIs.
- * When applied to a class, it will _not_ affect the visibility of its members. They need to be
- * individually marked.
- *
- * <p>In order to expose a class and all its members, use {@link HostSideTestWholeClassStub}
- * instead.
- *
- * @hide
- */
-@Target({TYPE, FIELD, METHOD, CONSTRUCTOR})
-@Retention(RetentionPolicy.CLASS)
-public @interface HostSideTestStub {
-}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassStub.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassStub.java
deleted file mode 100644
index 1824f6f..0000000
--- a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassStub.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2023 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.hosttest.annotation;
-
-import static java.lang.annotation.ElementType.TYPE;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
- * QUESTIONS ABOUT IT.
- *
- * Same as {@link HostSideTestStub} but it'll change the visibility of all its members too.
- *
- * @hide
- */
-@Target({TYPE})
-@Retention(RetentionPolicy.CLASS)
-public @interface HostSideTestWholeClassStub {
-}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenKeptInStub.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenKeptInStub.java
deleted file mode 100644
index 12b9875..0000000
--- a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenKeptInStub.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2023 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.hoststubgen.hosthelper;
-
-import static java.lang.annotation.ElementType.CONSTRUCTOR;
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.TYPE;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation injected to all classes/methods/fields that are kept in the "stub" jar.
- *
- * All items in the stub jar are automatically kept in the impl jar as well, so
- * the items with this annotation will all have {@link HostStubGenKeptInImpl} too.
- */
-@Target({TYPE, METHOD, CONSTRUCTOR, FIELD})
-@Retention(RetentionPolicy.RUNTIME)
-public @interface HostStubGenKeptInStub {
-    String CLASS_INTERNAL_NAME = HostTestUtils.getInternalName(HostStubGenKeptInStub.class);
-    String CLASS_DESCRIPTOR = "L" + CLASS_INTERNAL_NAME + ";";
-}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsIgnore.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsIgnore.java
index cb50404..b017103 100644
--- a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsIgnore.java
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsIgnore.java
@@ -23,8 +23,6 @@
 
 /**
  * Annotation injected to all methods processed as "ignore".
- *
- * (This annotation is only added in the impl jar, but not the stub jar)
  */
 @Target({METHOD})
 @Retention(RetentionPolicy.RUNTIME)
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenKeptInImpl.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsKeep.java
similarity index 92%
rename from tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenKeptInImpl.java
rename to tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsKeep.java
index 2cc500f..18ef1ba 100644
--- a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenKeptInImpl.java
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsKeep.java
@@ -25,11 +25,11 @@
 import java.lang.annotation.Target;
 
 /**
- * Annotation injected to all classes/methods/fields that are kept in the "impl" jar.
+ * Annotation injected to all classes/methods/fields that are kept in the processes jar.
  */
 @Target({TYPE, METHOD, CONSTRUCTOR, FIELD})
 @Retention(RetentionPolicy.RUNTIME)
-public @interface HostStubGenKeptInImpl {
-    String CLASS_INTERNAL_NAME = HostTestUtils.getInternalName(HostStubGenKeptInImpl.class);
+public @interface HostStubGenProcessedAsKeep {
+    String CLASS_INTERNAL_NAME = HostTestUtils.getInternalName(HostStubGenProcessedAsKeep.class);
     String CLASS_DESCRIPTOR = "L" + CLASS_INTERNAL_NAME + ";";
 }
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsSubstitute.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsSubstitute.java
index cfa4896..99e38c0 100644
--- a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsSubstitute.java
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsSubstitute.java
@@ -26,8 +26,6 @@
 
 /**
  * Annotation injected to all methods that are processed as "substitute".
- *
- * (This annotation is only added in the impl jar, but not the stub jar)
  */
 @Target({TYPE, METHOD, CONSTRUCTOR, FIELD})
 @Retention(RetentionPolicy.RUNTIME)
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsThrow.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsThrow.java
index 0d2da11..4933cf8 100644
--- a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsThrow.java
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsThrow.java
@@ -23,8 +23,6 @@
 
 /**
  * Annotation injected to all methods that are processed as "throw".
- *
- * (This annotation is only added in the impl jar, but not the stub jar)
  */
 @Target({METHOD})
 @Retention(RetentionPolicy.RUNTIME)
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java
index 60eb47ee..78fd8f7 100644
--- a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java
@@ -16,12 +16,8 @@
 package com.android.hoststubgen.hosthelper;
 
 import java.io.PrintStream;
-import java.lang.StackWalker.Option;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
-import java.util.HashMap;
-
-import javax.annotation.concurrent.GuardedBy;
 
 /**
  * Utilities used in the host side test environment.
@@ -101,68 +97,6 @@
                 + methodName + methodDescriptor);
     }
 
-    private static final StackWalker sStackWalker =
-            StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE);
-
-    /**
-     * Return a {@link StackWalker} that supports {@link StackWalker#getCallerClass()}.
-     */
-    public static StackWalker getStackWalker() {
-        return sStackWalker;
-    }
-
-    /**
-     * Cache used by {@link #isClassAllowedToCallNonStubMethods}.
-     */
-    @GuardedBy("sAllowedClasses")
-    private static final HashMap<Class, Boolean> sAllowedClasses = new HashMap();
-
-    /**
-     * Return true if a given class is allowed to access non-stub methods -- that is, if the class
-     * is in the hoststubgen generated JARs. (not in the test jar.)
-     */
-    private static boolean isClassAllowedToCallNonStubMethods(Class<?> clazz) {
-        synchronized (sAllowedClasses) {
-            var cached = sAllowedClasses.get(clazz);
-            if (cached != null) {
-                return cached;
-            }
-        }
-        // All processed classes have this annotation.
-        var allowed = clazz.getAnnotation(HostStubGenKeptInImpl.class) != null;
-
-        // Java classes should be able to access any methods. (via callbacks, etc.)
-        if (!allowed) {
-            if (clazz.getPackageName().startsWith("java.")
-                    || clazz.getPackageName().startsWith("javax.")) {
-                allowed = true;
-            }
-        }
-        synchronized (sAllowedClasses) {
-            sAllowedClasses.put(clazz, allowed);
-        }
-        return allowed;
-    }
-
-    /**
-     * Called when non-stub methods are called. We do a host-unsupported method direct call check
-     * in here.
-     */
-    public static void onNonStubMethodCalled(
-            String methodClass,
-            String methodName,
-            String methodDescriptor,
-            Class<?> callerClass) {
-        if (SKIP_NON_STUB_METHOD_CHECK) {
-            return;
-        }
-        if (isClassAllowedToCallNonStubMethods(callerClass)) {
-            return; // Generated class is allowed to call framework class.
-        }
-        logPrintStream.println("! " + methodClass + "." + methodName + methodDescriptor
-                + " called by " + callerClass.getCanonicalName());
-    }
-
     /**
      * Called when any top level class (not nested classes) in the impl jar is loaded.
      *
diff --git a/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt b/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt
index c371b5d..e72c9a4 100644
--- a/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt
+++ b/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt
@@ -3,8 +3,6 @@
 --debug
 
 # Uncomment below lines to enable each feature.
---enable-non-stub-method-check
-# --no-non-stub-method-check
 
 #--default-method-call-hook
 #    com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
@@ -13,15 +11,10 @@
 
 # Standard annotations.
 # Note, each line is a single argument, so we need newlines after each `--xxx-annotation`.
---stub-annotation
-    android.hosttest.annotation.HostSideTestStub
 
 --keep-annotation
     android.hosttest.annotation.HostSideTestKeep
 
---stub-class-annotation
-    android.hosttest.annotation.HostSideTestWholeClassStub
-
 --keep-class-annotation
     android.hosttest.annotation.HostSideTestWholeClassKeep
 
diff --git a/tools/hoststubgen/hoststubgen/invoketest/hoststubgen-invoke-test.sh b/tools/hoststubgen/hoststubgen/invoketest/hoststubgen-invoke-test.sh
index 5c5421a..5f0368a 100755
--- a/tools/hoststubgen/hoststubgen/invoketest/hoststubgen-invoke-test.sh
+++ b/tools/hoststubgen/hoststubgen/invoketest/hoststubgen-invoke-test.sh
@@ -43,9 +43,8 @@
 
 cleanup_temp
 
-JAR=hoststubgen-test-tiny-framework.jar
-STUB=$TEMP/stub.jar
-IMPL=$TEMP/impl.jar
+INJAR=hoststubgen-test-tiny-framework.jar
+OUTJAR=$TEMP/host.jar
 
 ANNOTATION_FILTER=$TEMP/annotation-filter.txt
 
@@ -81,27 +80,18 @@
     cat $ANNOTATION_FILTER
   fi
 
-  local stub_arg=""
-  local impl_arg=""
+  local out_arg=""
 
-  if [[ "$STUB" != "" ]] ; then
-    stub_arg="--out-stub-jar $STUB"
-  fi
-  if [[ "$IMPL" != "" ]] ; then
-    impl_arg="--out-impl-jar $IMPL"
+  if [[ "$OUTJAR" != "" ]] ; then
+    out_arg="--out-jar $OUTJAR"
   fi
 
   hoststubgen \
       --debug \
-      --in-jar $JAR \
-      $stub_arg \
-      $impl_arg \
-      --stub-annotation \
-          android.hosttest.annotation.HostSideTestStub \
+      --in-jar $INJAR \
+      $out_arg \
       --keep-annotation \
           android.hosttest.annotation.HostSideTestKeep \
-      --stub-class-annotation \
-          android.hosttest.annotation.HostSideTestWholeClassStub \
       --keep-class-annotation \
           android.hosttest.annotation.HostSideTestWholeClassKeep \
       --throw-annotation \
@@ -225,11 +215,7 @@
 * # All other classes allowed
 "
 
-STUB="" run_hoststubgen_for_success "No stub generation" ""
-
-IMPL="" run_hoststubgen_for_success "No impl generation" ""
-
-STUB="" IMPL="" run_hoststubgen_for_success "No stub, no impl generation" ""
+OUTJAR="" run_hoststubgen_for_success "No output generation" ""
 
 EXTRA_ARGS="--in-jar abc" run_hoststubgen_for_failure "Duplicate arg" \
     "Duplicate or conflicting argument found: --in-jar" \
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
index 7b08678..0f38fe7 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
@@ -24,19 +24,13 @@
 import com.android.hoststubgen.filters.FilterPolicy
 import com.android.hoststubgen.filters.FilterRemapper
 import com.android.hoststubgen.filters.ImplicitOutputFilter
+import com.android.hoststubgen.filters.NativeFilter
 import com.android.hoststubgen.filters.OutputFilter
-import com.android.hoststubgen.filters.StubIntersectingFilter
 import com.android.hoststubgen.filters.createFilterFromTextPolicyFile
 import com.android.hoststubgen.filters.printAsTextPolicy
 import com.android.hoststubgen.utils.ClassFilter
 import com.android.hoststubgen.visitors.BaseAdapter
 import com.android.hoststubgen.visitors.PackageRedirectRemapper
-import org.objectweb.asm.ClassReader
-import org.objectweb.asm.ClassVisitor
-import org.objectweb.asm.ClassWriter
-import org.objectweb.asm.commons.ClassRemapper
-import org.objectweb.asm.commons.Remapper
-import org.objectweb.asm.util.CheckClassAdapter
 import java.io.BufferedInputStream
 import java.io.BufferedOutputStream
 import java.io.FileOutputStream
@@ -46,6 +40,12 @@
 import java.util.zip.ZipEntry
 import java.util.zip.ZipFile
 import java.util.zip.ZipOutputStream
+import org.objectweb.asm.ClassReader
+import org.objectweb.asm.ClassVisitor
+import org.objectweb.asm.ClassWriter
+import org.objectweb.asm.commons.ClassRemapper
+import org.objectweb.asm.commons.Remapper
+import org.objectweb.asm.util.CheckClassAdapter
 
 /**
  * Actual main class.
@@ -82,17 +82,16 @@
 
         // Transform the jar.
         convert(
-                options.inJar.get,
-                options.outStubJar.get,
-                options.outImplJar.get,
-                filter,
-                options.enableClassChecker.get,
-                allClasses,
-                errors,
-                stats,
-                filterRemapper,
-                options.numShards.get,
-                options.shard.get,
+            options.inJar.get,
+            options.outJar.get,
+            filter,
+            options.enableClassChecker.get,
+            allClasses,
+            errors,
+            stats,
+            filterRemapper,
+            options.numShards.get,
+            options.shard.get,
         )
 
         // Dump statistics, if specified.
@@ -117,10 +116,10 @@
      * jars, and "how". (e.g. with substitution?)
      */
     private fun buildFilter(
-            errors: HostStubGenErrors,
-            allClasses: ClassNodes,
-            options: HostStubGenOptions,
-            ): OutputFilter {
+        errors: HostStubGenErrors,
+        allClasses: ClassNodes,
+        options: HostStubGenOptions,
+    ): OutputFilter {
         // We build a "chain" of multiple filters here.
         //
         // The filters are build in from "inside", meaning the first filter created here is
@@ -134,6 +133,9 @@
         // The first filter is for the default policy from the command line options.
         var filter: OutputFilter = ConstantFilter(options.defaultPolicy.get, "default-by-options")
 
+        // Next, we build a filter that preserves all native methods by default
+        filter = NativeFilter(allClasses, filter)
+
         // Next, we need a filter that resolves "class-wide" policies.
         // This is used when a member (methods, fields, nested classes) don't get any polices
         // from upper filters. e.g. when a method has no annotations, then this filter will apply
@@ -159,9 +161,7 @@
         filter = AnnotationBasedFilter(
             errors,
             allClasses,
-            options.stubAnnotations,
             options.keepAnnotations,
-            options.stubClassAnnotations,
             options.keepClassAnnotations,
             options.throwAnnotations,
             options.removeAnnotations,
@@ -179,15 +179,6 @@
             filter = createFilterFromTextPolicyFile(it, allClasses, filter)
         }
 
-        // If `--intersect-stub-jar` is provided, load from these jar files too.
-        // We use this to restrict stub APIs to public/system/test APIs,
-        // by intersecting with a stub jar file created by metalava.
-        if (options.intersectStubJars.size > 0) {
-            val intersectingJars = loadIntersectingJars(options.intersectStubJars)
-
-            filter = StubIntersectingFilter(errors, intersectingJars, filter)
-        }
-
         // Apply the implicit filter.
         filter = ImplicitOutputFilter(errors, allClasses, filter)
 
@@ -195,34 +186,21 @@
     }
 
     /**
-     * Load jar files specified with "--intersect-stub-jar".
-     */
-    private fun loadIntersectingJars(filenames: Set<String>): Map<String, ClassNodes> {
-        val intersectingJars = mutableMapOf<String, ClassNodes>()
-
-        filenames.forEach { filename ->
-            intersectingJars[filename] = ClassNodes.loadClassStructures(filename)
-        }
-        return intersectingJars
-    }
-
-    /**
      * Convert a JAR file into "stub" and "impl" JAR files.
      */
     private fun convert(
-            inJar: String,
-            outStubJar: String?,
-            outImplJar: String?,
-            filter: OutputFilter,
-            enableChecker: Boolean,
-            classes: ClassNodes,
-            errors: HostStubGenErrors,
-            stats: HostStubGenStats,
-            remapper: Remapper?,
-            numShards: Int,
-            shard: Int,
-            ) {
-        log.i("Converting %s into [stub: %s, impl: %s] ...", inJar, outStubJar, outImplJar)
+        inJar: String,
+        outJar: String?,
+        filter: OutputFilter,
+        enableChecker: Boolean,
+        classes: ClassNodes,
+        errors: HostStubGenErrors,
+        stats: HostStubGenStats,
+        remapper: Remapper?,
+        numShards: Int,
+        shard: Int
+    ) {
+        log.i("Converting %s into %s ...", inJar, outJar)
         log.i("ASM CheckClassAdapter is %s", if (enableChecker) "enabled" else "disabled")
 
         log.iTime("Transforming jar") {
@@ -240,29 +218,26 @@
                     val shardStart = numItems * shard / numShards
                     val shardNextStart = numItems * (shard + 1) / numShards
 
-                    maybeWithZipOutputStream(outStubJar) { stubOutStream ->
-                        maybeWithZipOutputStream(outImplJar) { implOutStream ->
-                            val inEntries = inZip.entries()
-                            while (inEntries.hasMoreElements()) {
-                                val entry = inEntries.nextElement()
-                                val inShard = (shardStart <= itemIndex)
-                                        && (itemIndex < shardNextStart)
-                                itemIndex++
-                                if (!inShard) {
-                                    continue
-                                }
-                                convertSingleEntry(
-                                    inZip, entry, stubOutStream, implOutStream,
-                                    filter, packageRedirector, remapper,
-                                    enableChecker, classes, errors, stats
-                                )
-                                numItemsProcessed++
+                    maybeWithZipOutputStream(outJar) { outStream ->
+                        val inEntries = inZip.entries()
+                        while (inEntries.hasMoreElements()) {
+                            val entry = inEntries.nextElement()
+                            val inShard = (shardStart <= itemIndex)
+                                    && (itemIndex < shardNextStart)
+                            itemIndex++
+                            if (!inShard) {
+                                continue
                             }
-                            log.i("Converted all entries.")
+                            convertSingleEntry(
+                                inZip, entry, outStream, filter,
+                                packageRedirector, remapper, enableChecker,
+                                classes, errors, stats
+                            )
+                            numItemsProcessed++
                         }
+                        log.i("Converted all entries.")
                     }
-                    outStubJar?.let { log.i("Created stub: $it") }
-                    outImplJar?.let { log.i("Created impl: $it") }
+                    outJar?.let { log.i("Created: $it") }
                 }
             }
             log.i("%d / %d item(s) processed.", numItemsProcessed, numItems)
@@ -280,18 +255,17 @@
      * Convert a single ZIP entry, which may or may not be a class file.
      */
     private fun convertSingleEntry(
-            inZip: ZipFile,
-            entry: ZipEntry,
-            stubOutStream: ZipOutputStream?,
-            implOutStream: ZipOutputStream?,
-            filter: OutputFilter,
-            packageRedirector: PackageRedirectRemapper,
-            remapper: Remapper?,
-            enableChecker: Boolean,
-            classes: ClassNodes,
-            errors: HostStubGenErrors,
-            stats: HostStubGenStats,
-            ) {
+        inZip: ZipFile,
+        entry: ZipEntry,
+        outStream: ZipOutputStream?,
+        filter: OutputFilter,
+        packageRedirector: PackageRedirectRemapper,
+        remapper: Remapper?,
+        enableChecker: Boolean,
+        classes: ClassNodes,
+        errors: HostStubGenErrors,
+        stats: HostStubGenStats
+    ) {
         log.d("Entry: %s", entry.name)
         log.withIndent {
             val name = entry.name
@@ -303,8 +277,10 @@
 
             // If it's a class, convert it.
             if (name.endsWith(".class")) {
-                processSingleClass(inZip, entry, stubOutStream, implOutStream, filter,
-                        packageRedirector, remapper, enableChecker, classes, errors, stats)
+                processSingleClass(
+                    inZip, entry, outStream, filter, packageRedirector,
+                    remapper, enableChecker, classes, errors, stats
+                )
                 return
             }
 
@@ -312,17 +288,14 @@
 
             // - *.uau seems to contain hidden API information.
             // -  *_compat_config.xml is also about compat-framework.
-            if (name.endsWith(".uau") ||
-                    name.endsWith("_compat_config.xml")) {
+            if (name.endsWith(".uau") || name.endsWith("_compat_config.xml")) {
                 log.d("Not needed: %s", entry.name)
                 return
             }
 
             // Unknown type, we just copy it to both output zip files.
-            // TODO: We probably shouldn't do it for stub jar?
             log.v("Copying: %s", entry.name)
-            stubOutStream?.let { copyZipEntry(inZip, entry, it) }
-            implOutStream?.let { copyZipEntry(inZip, entry, it) }
+            outStream?.let { copyZipEntry(inZip, entry, it) }
         }
     }
 
@@ -330,10 +303,10 @@
      * Copy a single ZIP entry to the output.
      */
     private fun copyZipEntry(
-            inZip: ZipFile,
-            entry: ZipEntry,
-            out: ZipOutputStream,
-            ) {
+        inZip: ZipFile,
+        entry: ZipEntry,
+        out: ZipOutputStream,
+    ) {
         // TODO: It seems like copying entries this way is _very_ slow,
         // even with out.setLevel(0). Look for other ways to do it.
 
@@ -350,18 +323,17 @@
      * Convert a single class to "stub" and "impl".
      */
     private fun processSingleClass(
-            inZip: ZipFile,
-            entry: ZipEntry,
-            stubOutStream: ZipOutputStream?,
-            implOutStream: ZipOutputStream?,
-            filter: OutputFilter,
-            packageRedirector: PackageRedirectRemapper,
-            remapper: Remapper?,
-            enableChecker: Boolean,
-            classes: ClassNodes,
-            errors: HostStubGenErrors,
-            stats: HostStubGenStats,
-            ) {
+        inZip: ZipFile,
+        entry: ZipEntry,
+        outStream: ZipOutputStream?,
+        filter: OutputFilter,
+        packageRedirector: PackageRedirectRemapper,
+        remapper: Remapper?,
+        enableChecker: Boolean,
+        classes: ClassNodes,
+        errors: HostStubGenErrors,
+        stats: HostStubGenStats
+    ) {
         val classInternalName = entry.name.replaceFirst("\\.class$".toRegex(), "")
         val classPolicy = filter.getPolicyForClass(classInternalName)
         if (classPolicy.policy == FilterPolicy.Remove) {
@@ -373,33 +345,22 @@
         remapper?.mapType(classInternalName)?.let { remappedName ->
             if (remappedName != classInternalName) {
                 log.d("Renaming class file: %s -> %s", classInternalName, remappedName)
-                newName = remappedName + ".class"
+                newName = "$remappedName.class"
             }
         }
-        // Generate stub first.
-        if (stubOutStream != null && classPolicy.policy.needsInStub) {
-            log.v("Creating stub class: %s Policy: %s", classInternalName, classPolicy)
+
+        if (outStream != null) {
+            log.v("Creating class: %s Policy: %s", classInternalName, classPolicy)
             log.withIndent {
                 BufferedInputStream(inZip.getInputStream(entry)).use { bis ->
                     val newEntry = ZipEntry(newName)
-                    stubOutStream.putNextEntry(newEntry)
-                    convertClass(classInternalName, /*forImpl=*/false, bis,
-                            stubOutStream, filter, packageRedirector, remapper,
-                            enableChecker, classes, errors, null)
-                    stubOutStream.closeEntry()
-                }
-            }
-        }
-        if (implOutStream != null && classPolicy.policy.needsInImpl) {
-            log.v("Creating impl class: %s Policy: %s", classInternalName, classPolicy)
-            log.withIndent {
-                BufferedInputStream(inZip.getInputStream(entry)).use { bis ->
-                    val newEntry = ZipEntry(newName)
-                    implOutStream.putNextEntry(newEntry)
-                    convertClass(classInternalName, /*forImpl=*/true, bis,
-                            implOutStream, filter, packageRedirector, remapper,
-                            enableChecker, classes, errors, stats)
-                    implOutStream.closeEntry()
+                    outStream.putNextEntry(newEntry)
+                    convertClass(
+                        classInternalName, bis,
+                        outStream, filter, packageRedirector, remapper,
+                        enableChecker, classes, errors, stats
+                    )
+                    outStream.closeEntry()
                 }
             }
         }
@@ -409,18 +370,17 @@
      * Convert a single class to either "stub" or "impl".
      */
     private fun convertClass(
-            classInternalName: String,
-            forImpl: Boolean,
-            input: InputStream,
-            out: OutputStream,
-            filter: OutputFilter,
-            packageRedirector: PackageRedirectRemapper,
-            remapper: Remapper?,
-            enableChecker: Boolean,
-            classes: ClassNodes,
-            errors: HostStubGenErrors,
-            stats: HostStubGenStats?,
-            ) {
+        classInternalName: String,
+        input: InputStream,
+        out: OutputStream,
+        filter: OutputFilter,
+        packageRedirector: PackageRedirectRemapper,
+        remapper: Remapper?,
+        enableChecker: Boolean,
+        classes: ClassNodes,
+        errors: HostStubGenErrors,
+        stats: HostStubGenStats?
+    ) {
         val cr = ClassReader(input)
 
         // COMPUTE_FRAMES wouldn't be happy if code uses
@@ -439,14 +399,15 @@
         }
 
         val visitorOptions = BaseAdapter.Options(
-                enablePreTrace = options.enablePreTrace.get,
-                enablePostTrace = options.enablePostTrace.get,
-                enableNonStubMethodCallDetection = options.enableNonStubMethodCallDetection.get,
-                errors = errors,
-                stats = stats,
+            errors = errors,
+            stats = stats,
+            enablePreTrace = options.enablePreTrace.get,
+            enablePostTrace = options.enablePostTrace.get,
         )
-        outVisitor = BaseAdapter.getVisitor(classInternalName, classes, outVisitor, filter,
-                packageRedirector, remapper, forImpl, visitorOptions)
+        outVisitor = BaseAdapter.getVisitor(
+            classInternalName, classes, outVisitor, filter,
+            packageRedirector, visitorOptions
+        )
 
         cr.accept(outVisitor, ClassReader.EXPAND_FRAMES)
         val data = cw.toByteArray()
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
index f88b107..1cedcc3 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
@@ -74,21 +74,16 @@
         /** Input jar file*/
         var inJar: SetOnce<String> = SetOnce(""),
 
-        /** Output stub jar file */
-        var outStubJar: SetOnce<String?> = SetOnce(null),
-
-        /** Output implementation jar file */
-        var outImplJar: SetOnce<String?> = SetOnce(null),
+        /** Output jar file */
+        var outJar: SetOnce<String?> = SetOnce(null),
 
         var inputJarDumpFile: SetOnce<String?> = SetOnce(null),
 
         var inputJarAsKeepAllFile: SetOnce<String?> = SetOnce(null),
 
-        var stubAnnotations: MutableSet<String> = mutableSetOf(),
         var keepAnnotations: MutableSet<String> = mutableSetOf(),
         var throwAnnotations: MutableSet<String> = mutableSetOf(),
         var removeAnnotations: MutableSet<String> = mutableSetOf(),
-        var stubClassAnnotations: MutableSet<String> = mutableSetOf(),
         var keepClassAnnotations: MutableSet<String> = mutableSetOf(),
 
         var substituteAnnotations: MutableSet<String> = mutableSetOf(),
@@ -103,8 +98,6 @@
         var defaultClassLoadHook: SetOnce<String?> = SetOnce(null),
         var defaultMethodCallHook: SetOnce<String?> = SetOnce(null),
 
-        var intersectStubJars: MutableSet<String> = mutableSetOf(),
-
         var policyOverrideFile: SetOnce<String?> = SetOnce(null),
 
         var defaultPolicy: SetOnce<FilterPolicy> = SetOnce(FilterPolicy.Remove),
@@ -115,8 +108,6 @@
         var enablePreTrace: SetOnce<Boolean> = SetOnce(false),
         var enablePostTrace: SetOnce<Boolean> = SetOnce(false),
 
-        var enableNonStubMethodCallDetection: SetOnce<Boolean> = SetOnce(false),
-
         var statsFile: SetOnce<String?> = SetOnce(null),
 
         var apiListFile: SetOnce<String?> = SetOnce(null),
@@ -150,10 +141,7 @@
             }
 
             while (true) {
-                val arg = ai.nextArgOptional()
-                if (arg == null) {
-                    break
-                }
+                val arg = ai.nextArgOptional() ?: break
 
                 // Define some shorthands...
                 fun nextArg(): String = ai.nextArgRequired(arg)
@@ -169,8 +157,9 @@
                         "-h", "--help" -> TODO("Help is not implemented yet")
 
                         "--in-jar" -> ret.inJar.set(nextArg()).ensureFileExists()
-                        "--out-stub-jar" -> ret.outStubJar.set(nextArg())
-                        "--out-impl-jar" -> ret.outImplJar.set(nextArg())
+                        // We support both arguments because some AOSP dependencies
+                        // still use the old argument
+                        "--out-jar", "--out-impl-jar" -> ret.outJar.set(nextArg())
 
                         "--policy-override-file" ->
                             ret.policyOverrideFile.set(nextArg())!!.ensureFileExists()
@@ -181,17 +170,10 @@
                         "--default-remove" -> ret.defaultPolicy.set(FilterPolicy.Remove)
                         "--default-throw" -> ret.defaultPolicy.set(FilterPolicy.Throw)
                         "--default-keep" -> ret.defaultPolicy.set(FilterPolicy.Keep)
-                        "--default-stub" -> ret.defaultPolicy.set(FilterPolicy.Stub)
-
-                        "--stub-annotation" ->
-                            ret.stubAnnotations.addUniqueAnnotationArg()
 
                         "--keep-annotation" ->
                             ret.keepAnnotations.addUniqueAnnotationArg()
 
-                        "--stub-class-annotation" ->
-                            ret.stubClassAnnotations.addUniqueAnnotationArg()
-
                         "--keep-class-annotation" ->
                             ret.keepClassAnnotations.addUniqueAnnotationArg()
 
@@ -225,9 +207,6 @@
                         "--default-method-call-hook" ->
                             ret.defaultMethodCallHook.set(nextArg())
 
-                        "--intersect-stub-jar" ->
-                            ret.intersectStubJars += nextArg().ensureFileExists()
-
                         "--gen-keep-all-file" ->
                             ret.inputJarAsKeepAllFile.set(nextArg())
 
@@ -241,12 +220,6 @@
                         "--enable-post-trace" -> ret.enablePostTrace.set(true)
                         "--no-post-trace" -> ret.enablePostTrace.set(false)
 
-                        "--enable-non-stub-method-check" ->
-                            ret.enableNonStubMethodCallDetection.set(true)
-
-                        "--no-non-stub-method-check" ->
-                            ret.enableNonStubMethodCallDetection.set(false)
-
                         "--gen-input-dump-file" -> ret.inputJarDumpFile.set(nextArg())
 
                         "--stats-file" -> ret.statsFile.set(nextArg())
@@ -273,9 +246,8 @@
             if (!ret.inJar.isSet) {
                 throw ArgumentsException("Required option missing: --in-jar")
             }
-            if (!ret.outStubJar.isSet && !ret.outImplJar.isSet) {
-                log.w("Neither --out-stub-jar nor --out-impl-jar is set." +
-                        " $executableName will not generate jar files.")
+            if (!ret.outJar.isSet) {
+                log.w("--out-jar is not set. $executableName will not generate jar files.")
             }
             if (ret.numShards.isSet != ret.shard.isSet) {
                 throw ArgumentsException("--num-shards and --shard-index must be used together")
@@ -287,11 +259,6 @@
                 }
             }
 
-            if (ret.enableNonStubMethodCallDetection.get) {
-                log.w("--enable-non-stub-method-check is not fully implemented yet." +
-                    " See the todo in doesMethodNeedNonStubCallCheck().")
-            }
-
             return ret
         }
     }
@@ -300,32 +267,27 @@
         return """
             HostStubGenOptions{
               inJar='$inJar',
-              outStubJar='$outStubJar',
-              outImplJar='$outImplJar',
+              outJar='$outJar',
               inputJarDumpFile=$inputJarDumpFile,
               inputJarAsKeepAllFile=$inputJarAsKeepAllFile,
-              stubAnnotations=$stubAnnotations,
               keepAnnotations=$keepAnnotations,
               throwAnnotations=$throwAnnotations,
               removeAnnotations=$removeAnnotations,
-              stubClassAnnotations=$stubClassAnnotations,
               keepClassAnnotations=$keepClassAnnotations,
               substituteAnnotations=$substituteAnnotations,
               nativeSubstituteAnnotations=$nativeSubstituteAnnotations,
               classLoadHookAnnotations=$classLoadHookAnnotations,
               keepStaticInitializerAnnotations=$keepStaticInitializerAnnotations,
               packageRedirects=$packageRedirects,
-              $annotationAllowedClassesFile=$annotationAllowedClassesFile,
+              annotationAllowedClassesFile=$annotationAllowedClassesFile,
               defaultClassLoadHook=$defaultClassLoadHook,
               defaultMethodCallHook=$defaultMethodCallHook,
-              intersectStubJars=$intersectStubJars,
               policyOverrideFile=$policyOverrideFile,
               defaultPolicy=$defaultPolicy,
               cleanUpOnError=$cleanUpOnError,
               enableClassChecker=$enableClassChecker,
               enablePreTrace=$enablePreTrace,
               enablePostTrace=$enablePostTrace,
-              enableNonStubMethodCallDetection=$enableNonStubMethodCallDetection,
               statsFile=$statsFile,
               apiListFile=$apiListFile,
               numShards=$numShards,
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
index 7dd4fdd..7197e0e 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
@@ -327,6 +327,10 @@
     return (this.access and Opcodes.ACC_PUBLIC) != 0
 }
 
+fun MethodNode.isNative(): Boolean {
+    return (this.access and Opcodes.ACC_NATIVE) != 0
+}
+
 fun MethodNode.isSpecial(): Boolean {
     return CTOR_NAME == this.name || CLASS_INITIALIZER_NAME == this.name
 }
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/dumper/ApiDumper.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/dumper/ApiDumper.kt
index aaefee4..5e4e70f 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/dumper/ApiDumper.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/dumper/ApiDumper.kt
@@ -44,7 +44,7 @@
         val descriptor: String,
     )
 
-    val javaStandardApiPolicy = FilterPolicy.Stub.withReason("Java standard API")
+    private val javaStandardApiPolicy = FilterPolicy.Keep.withReason("Java standard API")
 
     private val shownMethods = mutableSetOf<MethodKey>()
 
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt
index 248121c..38a41b2 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt
@@ -17,7 +17,6 @@
 
 import com.android.hoststubgen.ClassParseException
 import com.android.hoststubgen.HostStubGenErrors
-import com.android.hoststubgen.HostStubGenInternalException
 import com.android.hoststubgen.InvalidAnnotationException
 import com.android.hoststubgen.addNonNullElement
 import com.android.hoststubgen.asm.CLASS_INITIALIZER_DESC
@@ -35,258 +34,125 @@
 
 // TODO: Detect invalid cases, such as...
 // - Class's visibility is lower than the members'.
-// - HostSideTestSubstituteWith is set, but it doesn't have @Stub or @Keep
 
 /**
  * [OutputFilter] using Java annotations.
  */
 class AnnotationBasedFilter(
-        private val errors: HostStubGenErrors,
-        private val classes: ClassNodes,
-        stubAnnotations_: Set<String>,
-        keepAnnotations_: Set<String>,
-        stubClassAnnotations_: Set<String>,
-        keepClassAnnotations_: Set<String>,
-        throwAnnotations_: Set<String>,
-        removeAnnotations_: Set<String>,
-        substituteAnnotations_: Set<String>,
-        nativeSubstituteAnnotations_: Set<String>,
-        classLoadHookAnnotations_: Set<String>,
-        keepStaticInitializerAnnotations_: Set<String>,
-        private val annotationAllowedClassesFilter: ClassFilter,
-        fallback: OutputFilter,
+    private val errors: HostStubGenErrors,
+    private val classes: ClassNodes,
+    keepAnnotations_: Set<String>,
+    keepClassAnnotations_: Set<String>,
+    throwAnnotations_: Set<String>,
+    removeAnnotations_: Set<String>,
+    substituteAnnotations_: Set<String>,
+    nativeSubstituteAnnotations_: Set<String>,
+    classLoadHookAnnotations_: Set<String>,
+    keepStaticInitializerAnnotations_: Set<String>,
+    private val annotationAllowedClassesFilter: ClassFilter,
+    fallback: OutputFilter,
 ) : DelegatingFilter(fallback) {
-    private var stubAnnotations = convertToInternalNames(stubAnnotations_)
-    private var keepAnnotations = convertToInternalNames(keepAnnotations_)
-    private var stubClassAnnotations = convertToInternalNames(stubClassAnnotations_)
-    private var keepClassAnnotations = convertToInternalNames(keepClassAnnotations_)
-    private var throwAnnotations = convertToInternalNames(throwAnnotations_)
-    private var removeAnnotations = convertToInternalNames(removeAnnotations_)
-    private var substituteAnnotations = convertToInternalNames(substituteAnnotations_)
-    private var nativeSubstituteAnnotations = convertToInternalNames(nativeSubstituteAnnotations_)
-    private var classLoadHookAnnotations = convertToInternalNames(classLoadHookAnnotations_)
-    private var keepStaticInitializerAnnotations =
-            convertToInternalNames(keepStaticInitializerAnnotations_)
+    private val keepAnnotations = convertToInternalNames(keepAnnotations_)
+    private val keepClassAnnotations = convertToInternalNames(keepClassAnnotations_)
+    private val throwAnnotations = convertToInternalNames(throwAnnotations_)
+    private val removeAnnotations = convertToInternalNames(removeAnnotations_)
+    private val substituteAnnotations = convertToInternalNames(substituteAnnotations_)
+    private val nativeSubstituteAnnotations = convertToInternalNames(nativeSubstituteAnnotations_)
+    private val classLoadHookAnnotations = convertToInternalNames(classLoadHookAnnotations_)
+    private val keepStaticInitializerAnnotations =
+        convertToInternalNames(keepStaticInitializerAnnotations_)
 
     /** Annotations that control API visibility. */
-    private var visibilityAnnotations: Set<String> = convertToInternalNames(
-        stubAnnotations_ +
-        keepAnnotations_ +
-        stubClassAnnotations_ +
-        keepClassAnnotations_ +
-        throwAnnotations_ +
-        removeAnnotations_)
+    private val visibilityAnnotations = keepAnnotations +
+            keepClassAnnotations +
+            throwAnnotations +
+            removeAnnotations +
+            substituteAnnotations
+
+    /** All the annotations we use. */
+    private val allAnnotations = visibilityAnnotations +
+            nativeSubstituteAnnotations +
+            classLoadHookAnnotations +
+            keepStaticInitializerAnnotations
 
     /**
      * All the annotations we use. Note, this one is in a [convertToJvmNames] format unlike
      * other ones, because of how it's used.
      */
-    private var allAnnotations: Set<String> = convertToJvmNames(
-        stubAnnotations_ +
-                keepAnnotations_ +
-                stubClassAnnotations_ +
+    private val allAnnotationClasses: Set<String> = convertToJvmNames(
+        keepAnnotations_ +
                 keepClassAnnotations_ +
                 throwAnnotations_ +
                 removeAnnotations_ +
                 substituteAnnotations_ +
                 nativeSubstituteAnnotations_ +
-                classLoadHookAnnotations_)
+                classLoadHookAnnotations_ +
+                keepStaticInitializerAnnotations_
+    )
 
-    private val substitutionHelper = SubstitutionHelper()
+    private val policyCache = mutableMapOf<String, ClassAnnotations>()
 
-    private val reasonAnnotation = "annotation"
-    private val reasonClassAnnotation = "class-annotation"
-
-    /**
-     * Throw if an item has more than one visibility annotations.
-     *
-     * name1 - 4 are only used in exception messages. We take them as separate strings
-     * to avoid unnecessary string concatenations.
-     */
-    private fun detectInvalidAnnotations(
-        visibles: List<AnnotationNode>?,
-        invisibles: List<AnnotationNode>?,
-        type: String,
-        name1: String,
-        name2: String,
-        name3: String,
-    ) {
-        var count = 0
-        for (an in visibles ?: emptyList()) {
-            if (visibilityAnnotations.contains(an.desc)) {
-                count++
-            }
-        }
-        for (an in invisibles ?: emptyList()) {
-            if (visibilityAnnotations.contains(an.desc)) {
-                count++
-            }
-        }
-        if (count > 1) {
-            val description = if (name2 == "" && name3 == "") {
-                "$type $name1"
-            } else {
-                "$type $name1.$name2$name3"
-            }
-            throw InvalidAnnotationException(
-                "Found more than one visibility annotations on $description")
+    private val AnnotationNode.policy: FilterPolicyWithReason? get() {
+        return when (desc) {
+            in keepAnnotations -> FilterPolicy.Keep.withReason(REASON_ANNOTATION)
+            in keepClassAnnotations -> FilterPolicy.KeepClass.withReason(REASON_CLASS_ANNOTATION)
+            in substituteAnnotations -> FilterPolicy.Substitute.withReason(REASON_ANNOTATION)
+            in throwAnnotations -> FilterPolicy.Throw.withReason(REASON_ANNOTATION)
+            in removeAnnotations -> FilterPolicy.Remove.withReason(REASON_ANNOTATION)
+            else -> null
         }
     }
 
-    fun findAnyAnnotation(
-            className: String,
-            anyAnnotations: Set<String>,
-            visibleAnnotations: List<AnnotationNode>?,
-            invisibleAnnotations: List<AnnotationNode>?,
-    ): AnnotationNode? {
-        val ret = findAnyAnnotation(anyAnnotations, visibleAnnotations, invisibleAnnotations)
-
-        if (ret != null) {
-            if (!annotationAllowedClassesFilter.matches(className)) {
-                throw InvalidAnnotationException(
-                        "Class ${className.toHumanReadableClassName()} is not allowed to have " +
-                                "Ravenwood annotations. Contact g/ravenwood for more details.")
-            }
-        }
-
-        return ret
-    }
-
-    /**
-     * Find a visibility annotation.
-     *
-     * name1 - 4 are only used in exception messages.
-     */
-    private fun findAnnotation(
-            className: String,
-            visibles: List<AnnotationNode>?,
-            invisibles: List<AnnotationNode>?,
-            type: String,
-            name1: String,
-            name2: String = "",
-            name3: String = "",
-    ): FilterPolicyWithReason? {
-        detectInvalidAnnotations(visibles, invisibles, type, name1, name2, name3)
-
-        findAnyAnnotation(className, stubAnnotations, visibles, invisibles)?.let {
-            return FilterPolicy.Stub.withReason(reasonAnnotation)
-        }
-        findAnyAnnotation(className, stubClassAnnotations, visibles, invisibles)?.let {
-            return FilterPolicy.StubClass.withReason(reasonClassAnnotation)
-        }
-        findAnyAnnotation(className, keepAnnotations, visibles, invisibles)?.let {
-            return FilterPolicy.Keep.withReason(reasonAnnotation)
-        }
-        findAnyAnnotation(className, keepClassAnnotations, visibles, invisibles)?.let {
-            return FilterPolicy.KeepClass.withReason(reasonClassAnnotation)
-        }
-        findAnyAnnotation(className, throwAnnotations, visibles, invisibles)?.let {
-            return FilterPolicy.Throw.withReason(reasonAnnotation)
-        }
-        findAnyAnnotation(className, removeAnnotations, visibles, invisibles)?.let {
-            return FilterPolicy.Remove.withReason(reasonAnnotation)
-        }
-
-        return null
+    private fun getAnnotationPolicy(cn: ClassNode): ClassAnnotations {
+        return policyCache.getOrPut(cn.name) { ClassAnnotations(cn) }
     }
 
     override fun getPolicyForClass(className: String): FilterPolicyWithReason {
-        val cn = classes.getClass(className)
-
-        findAnnotation(
-            cn.name,
-            cn.visibleAnnotations,
-            cn.invisibleAnnotations,
-            "class",
-            className)?.let {
-            return it
-        }
-
         // If it's any of the annotations, then always keep it.
-        if (allAnnotations.contains(className)) {
+        if (allAnnotationClasses.contains(className)) {
             return FilterPolicy.KeepClass.withReason("HostStubGen Annotation")
         }
 
-        return super.getPolicyForClass(className)
+        val cn = classes.getClass(className)
+        return getAnnotationPolicy(cn).classPolicy ?: super.getPolicyForClass(className)
     }
 
-    override fun getPolicyForField(
-            className: String,
-            fieldName: String
-    ): FilterPolicyWithReason {
+    override fun getPolicyForField(className: String, fieldName: String): FilterPolicyWithReason {
         val cn = classes.getClass(className)
-
-        cn.fields?.firstOrNull { it.name == fieldName }?.let {fn ->
-            findAnnotation(
-                cn.name,
-                fn.visibleAnnotations,
-                fn.invisibleAnnotations,
-                "field",
-                className,
-                fieldName
-                )?.let { policy ->
-                // If the item has an annotation, then use it.
-                return policy
-            }
-        }
-        return super.getPolicyForField(className, fieldName)
+        return getAnnotationPolicy(cn).fieldPolicies[fieldName]
+            ?: super.getPolicyForField(className, fieldName)
     }
 
     override fun getPolicyForMethod(
-            className: String,
-            methodName: String,
-            descriptor: String
+        className: String,
+        methodName: String,
+        descriptor: String
     ): FilterPolicyWithReason {
         val cn = classes.getClass(className)
 
         if (methodName == CLASS_INITIALIZER_NAME && descriptor == CLASS_INITIALIZER_DESC) {
-            findAnyAnnotation(cn.name, keepStaticInitializerAnnotations,
-                    cn.visibleAnnotations, cn.invisibleAnnotations)?.let {
-                return FilterPolicy.Keep.withReason(reasonAnnotation)
+            if (cn.findAnyAnnotation(keepStaticInitializerAnnotations) != null) {
+                return FilterPolicy.Keep.withReason(REASON_ANNOTATION)
             }
         }
 
-        cn.methods?.firstOrNull { it.name == methodName && it.desc == descriptor }?.let { mn ->
-            // @SubstituteWith is going to complicate the policy here, so we ask helper
-            // what to do.
-            substitutionHelper.getPolicyFromSubstitution(cn, mn.name, mn.desc)?.let {
-                return it
-            }
-
-            // If there's no substitution, then we check the annotation.
-            findAnnotation(
-                cn.name,
-                mn.visibleAnnotations,
-                mn.invisibleAnnotations,
-                "method",
-                className,
-                methodName,
-                descriptor
-            )?.let { policy ->
-                return policy
-            }
-        }
-        return super.getPolicyForMethod(className, methodName, descriptor)
+        return getAnnotationPolicy(cn).methodPolicies[MethodKey(methodName, descriptor)]
+            ?: super.getPolicyForMethod(className, methodName, descriptor)
     }
 
     override fun getRenameTo(
-            className: String,
-            methodName: String,
-            descriptor: String
+        className: String,
+        methodName: String,
+        descriptor: String
     ): String? {
         val cn = classes.getClass(className)
-
-        // If the method has a "substitute with" annotation, then return its "value" parameter.
-        cn.methods?.firstOrNull { it.name == methodName && it.desc == descriptor }?.let { mn ->
-            return substitutionHelper.getRenameTo(cn, mn.name, mn.desc)
-        }
-        return null
+        return getAnnotationPolicy(cn).renamedMethods[MethodKey(methodName, descriptor)]
+            ?: super.getRenameTo(className, methodName, descriptor)
     }
 
     override fun getNativeSubstitutionClass(className: String): String? {
         classes.getClass(className).let { cn ->
-            findAnyAnnotation(nativeSubstituteAnnotations,
-                    cn.visibleAnnotations, cn.invisibleAnnotations)?.let { an ->
+            cn.findAnyAnnotation(nativeSubstituteAnnotations)?.let { an ->
                 return getAnnotationField(an, "value")?.toJvmClassName()
             }
         }
@@ -295,8 +161,7 @@
 
     override fun getClassLoadHooks(className: String): List<String> {
         val e = classes.getClass(className).let { cn ->
-            findAnyAnnotation(classLoadHookAnnotations,
-                cn.visibleAnnotations, cn.invisibleAnnotations)?.let { an ->
+            cn.findAnyAnnotation(classLoadHookAnnotations)?.let { an ->
                 getAnnotationField(an, "value")?.toHumanReadableMethodName()
             }
         }
@@ -306,102 +171,130 @@
     private data class MethodKey(val name: String, val desc: String)
 
     /**
-     * In order to handle substitution, we need to build a reverse mapping of substitution
-     * methods.
+     * Every time we see a class, we scan all its methods for substitution attributes,
+     * and compute (implicit) policies caused by them.
      *
-     * This class automatically builds such a map internally that the above methods can
-     * take advantage of.
+     * For example, for the following methods:
+     *
+     *   @Substitute(suffix = "_host")
+     *   private void foo() {
+     *      // This isn't supported on the host side.
+     *   }
+     *   private void foo_host() {
+     *      // Host side implementation
+     *   }
+     *
+     * We internally handle them as:
+     *
+     *   foo() -> Substitute
+     *   foo_host() -> Stub, and then rename it to foo().
      */
-    private inner class SubstitutionHelper {
-        private var currentClass: ClassNode? = null
+    private inner class ClassAnnotations(cn: ClassNode) {
 
-        private var policiesFromSubstitution = mutableMapOf<MethodKey, FilterPolicyWithReason>()
-        private var substituteToMethods = mutableMapOf<MethodKey, String>()
+        val classPolicy: FilterPolicyWithReason?
+        val fieldPolicies = mutableMapOf<String, FilterPolicyWithReason>()
+        val methodPolicies = mutableMapOf<MethodKey, FilterPolicyWithReason>()
+        val renamedMethods = mutableMapOf<MethodKey, String>()
 
-        fun getPolicyFromSubstitution(cn: ClassNode, methodName: String, descriptor: String):
-                FilterPolicyWithReason? {
-            setClass(cn)
-            return policiesFromSubstitution[MethodKey(methodName, descriptor)]
-        }
+        init {
+            val allowAnnotation = annotationAllowedClassesFilter.matches(cn.name)
+            detectInvalidAnnotations(
+                cn.name, allowAnnotation,
+                cn.visibleAnnotations, cn.invisibleAnnotations,
+                "class", cn.name
+            )
+            classPolicy = cn.findAnyAnnotation(visibilityAnnotations)?.policy
 
-        fun getRenameTo(cn: ClassNode, methodName: String, descriptor: String): String? {
-            setClass(cn)
-            return substituteToMethods[MethodKey(methodName, descriptor)]
+            for (fn in cn.fields ?: emptyList()) {
+                detectInvalidAnnotations(
+                    cn.name, allowAnnotation,
+                    fn.visibleAnnotations, fn.invisibleAnnotations,
+                    "field", cn.name, fn.name
+                )
+                fn.findAnyAnnotation(visibilityAnnotations)?.policy?.let {
+                    fieldPolicies[fn.name] = it
+                }
+            }
+
+            for (mn in cn.methods ?: emptyList()) {
+                detectInvalidAnnotations(
+                    cn.name, allowAnnotation,
+                    mn.visibleAnnotations, mn.invisibleAnnotations,
+                    "method", cn.name, mn.name, mn.desc
+                )
+
+                val an = mn.findAnyAnnotation(visibilityAnnotations) ?: continue
+                val policy = an.policy ?: continue
+                methodPolicies[MethodKey(mn.name, mn.desc)] = policy
+
+                if (policy.policy != FilterPolicy.Substitute) continue
+
+                // Handle substitution
+                val suffix = getAnnotationField(an, "suffix", false) ?: "\$ravenwood"
+                val replacement = mn.name + suffix
+
+                if (replacement == mn.name) {
+                    errors.onErrorFound("@SubstituteWith require a different name")
+                } else {
+                    // The replacement method has to be renamed
+                    methodPolicies[MethodKey(replacement, mn.desc)] =
+                        FilterPolicy.Keep.withReason(REASON_ANNOTATION)
+                    renamedMethods[MethodKey(replacement, mn.desc)] = mn.name
+
+                    log.v("Substitution found: %s%s -> %s", replacement, mn.desc, mn.name)
+                }
+            }
         }
 
         /**
-         * Every time we see a different class, we scan all its methods for substitution attributes,
-         * and compute (implicit) policies caused by them.
+         * Throw if an item has more than one visibility annotations, or the class is not allowed
          *
-         * For example, for the following methods:
-         *
-         *   @Stub
-         *   @Substitute(suffix = "_host")
-         *   private void foo() {
-         *      // This isn't supported on the host side.
-         *   }
-         *   private void foo_host() {
-         *      // Host side implementation
-         *   }
-         *
-         * We internally handle them as:
-         *
-         *   foo() -> Remove
-         *   foo_host() -> Stub, and then rename it to foo().
+         * name1 - 4 are only used in exception messages. We take them as separate strings
+         * to avoid unnecessary string concatenations.
          */
-        private fun setClass(cn: ClassNode) {
-            if (currentClass == cn) {
-                return
-            }
-            // If the class is changing, we'll rebuild the internal structure.
-            currentClass = cn
-
-            policiesFromSubstitution.clear()
-            substituteToMethods.clear()
-
-            for (mn in cn.methods ?: emptyList()) {
-                findAnyAnnotation(substituteAnnotations,
-                        mn.visibleAnnotations,
-                        mn.invisibleAnnotations)?.let { an ->
-
-                    // Find the policy for this method.
-                    val policy = outermostFilter.getPolicyForMethod(cn.name, mn.name, mn.desc)
-                            .policy.resolveClassWidePolicy()
-                    // Make sure it's either Stub or Keep.
-                    if (!(policy.needsInStub || policy.needsInImpl)) {
-                        // TODO: Use the real annotation names in the message
-                        errors.onErrorFound("@SubstituteWith must have either @Stub or @Keep")
-                        return@let
-                    }
-                    if (!policy.isUsableWithMethods) {
-                        throw HostStubGenInternalException("Policy $policy shouldn't show up here")
-                    }
-
-                    val suffix = getAnnotationField(an, "suffix", false) ?: "\$ravenwood"
-                    val renameFrom = mn.name + suffix
-                    val renameTo = mn.name
-
-                    if (renameFrom == renameTo) {
-                        errors.onErrorFound("@SubstituteWith have a different name")
-                        return@let
-                    }
-
-                    // This mn has "SubstituteWith". This means,
-                    // 1. Re move the "rename-to" method, so add it to substitutedMethods.
-                    policiesFromSubstitution[MethodKey(renameTo, mn.desc)] =
-                            FilterPolicy.Remove.withReason("substitute-to")
-
-                    // If the policy is "stub", use "stub".
-                    // Otherwise, it must be "keep" or "throw", but there's no point in using
-                    // "throw", so let's use "keep".
-                    val newPolicy = if (policy.needsInStub) policy else FilterPolicy.Keep
-                    // 2. We also keep the from-to in the map.
-                    policiesFromSubstitution[MethodKey(renameFrom, mn.desc)] =
-                            newPolicy.withReason("substitute-from")
-                    substituteToMethods[MethodKey(renameFrom, mn.desc)] = renameTo
-
-                    log.v("Substitution found: %s%s -> %s", renameFrom, mn.desc, renameTo)
+        private fun detectInvalidAnnotations(
+            className: String,
+            allowAnnotation: Boolean,
+            visibles: List<AnnotationNode>?,
+            invisibles: List<AnnotationNode>?,
+            type: String,
+            name1: String,
+            name2: String = "",
+            name3: String = "",
+        ) {
+            var count = 0
+            var visibleCount = 0
+            for (an in visibles ?: emptyList()) {
+                if (visibilityAnnotations.contains(an.desc)) {
+                    visibleCount++
                 }
+                if (allAnnotations.contains(an.desc)) {
+                    count++
+                }
+            }
+            for (an in invisibles ?: emptyList()) {
+                if (visibilityAnnotations.contains(an.desc)) {
+                    visibleCount++
+                }
+                if (allAnnotations.contains(an.desc)) {
+                    count++
+                }
+            }
+            if (count > 0 && !allowAnnotation) {
+                throw InvalidAnnotationException(
+                    "Class ${className.toHumanReadableClassName()} is not allowed to have " +
+                            "Ravenwood annotations. Contact g/ravenwood for more details."
+                )
+            }
+            if (visibleCount > 1) {
+                val description = if (name2 == "" && name3 == "") {
+                    "$type $name1"
+                } else {
+                    "$type $name1.$name2$name3"
+                }
+                throw InvalidAnnotationException(
+                    "Found more than one visibility annotations on $description"
+                )
             }
         }
     }
@@ -409,8 +302,11 @@
     /**
      * Return the (String) value of 'value' parameter from an annotation.
      */
-    private fun getAnnotationField(an: AnnotationNode, name: String,
-                                   required: Boolean = true): String? {
+    private fun getAnnotationField(
+        an: AnnotationNode,
+        name: String,
+        required: Boolean = true
+    ): String? {
         try {
             val suffix = findAnnotationValueAsString(an, name)
             if (suffix == null && required) {
@@ -424,6 +320,9 @@
     }
 
     companion object {
+        private const val REASON_ANNOTATION = "annotation"
+        private const val REASON_CLASS_ANNOTATION = "class-annotation"
+
         /**
          * Convert from human-readable type names (e.g. "com.android.TypeName") to the internal type
          * names (e.g. "Lcom/android/TypeName).
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt
index 37048d9..8ee3a94 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt
@@ -16,6 +16,7 @@
 package com.android.hoststubgen.filters
 
 import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.isNative
 
 /**
  * This is used as the second last fallback filter. This filter propagates the class-wide policy
@@ -52,7 +53,7 @@
 
     private fun getClassWidePolicy(className: String, resolve: Boolean): FilterPolicyWithReason? {
         outermostFilter.getPolicyForClass(className).let { policy ->
-            if (policy.policy.isClassWidePolicy) {
+            if (policy.policy == FilterPolicy.KeepClass) {
                 val p = if (resolve) {
                     policy.policy.resolveClassWidePolicy()
                 } else {
@@ -87,7 +88,16 @@
         methodName: String,
         descriptor: String
     ): FilterPolicyWithReason {
-        return getClassWidePolicy(className, resolve = true)
-                ?: super.getPolicyForMethod(className, methodName, descriptor)
+        return outermostFilter.getNativeSubstitutionClass(className)?.let {
+            // First check native substitution
+            classes.findMethod(className, methodName, descriptor)?.let { mn ->
+                if (mn.isNative()) {
+                    FilterPolicy.NativeSubstitute.withReason("class-wide in $className")
+                } else {
+                    null
+                }
+            }
+        } ?: getClassWidePolicy(className, resolve = true)
+        ?: super.getPolicyForMethod(className, methodName, descriptor)
     }
 }
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ConstantFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ConstantFilter.kt
index 678e6ea..be3c59c 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ConstantFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ConstantFilter.kt
@@ -26,23 +26,17 @@
  * @param policy the policy. Cannot be a "substitute" policy.
  */
 class ConstantFilter(
-        policy: FilterPolicy,
-        val reason: String
+    policy: FilterPolicy,
+    private val reason: String
 ) : OutputFilter() {
-    val classPolicy: FilterPolicy
-    val fieldPolicy: FilterPolicy
-    val methodPolicy: FilterPolicy
+
+    private val classPolicy: FilterPolicy
+    private val fieldPolicy: FilterPolicy
+    private val methodPolicy: FilterPolicy
 
     init {
-        if (policy.isSubstitute) {
-            throw HostStubGenInternalException(
-                    "ConstantFilter doesn't allow substitution policies.")
-        }
-        if (policy.isClassWidePolicy) {
-            // We prevent it, because there's no point in using class-wide policies because
-            // all members get othe same policy too anyway.
-            throw HostStubGenInternalException(
-                    "ConstantFilter doesn't allow class-wide policies.")
+        if (!policy.isUsableWithDefault) {
+            throw HostStubGenInternalException("ConstantFilter doesn't support $policy.")
         }
         methodPolicy = policy
 
@@ -63,10 +57,10 @@
     }
 
     override fun getPolicyForMethod(
-            className: String,
-            methodName: String,
-            descriptor: String,
-            ): FilterPolicyWithReason {
+        className: String,
+        methodName: String,
+        descriptor: String,
+    ): FilterPolicyWithReason {
         return methodPolicy.withReason(reason)
     }
 }
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt
index f839444..ab03874 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt
@@ -17,37 +17,25 @@
 
 enum class FilterPolicy {
     /**
-     * Keep the item in the stub jar file, so tests can use it.
-     */
-    Stub,
-
-    /**
-     * Keep the item in the impl jar file, but not in the stub file. Tests cannot use it directly,
-     * but indirectly.
+     * Keep the item in the jar file.
      */
     Keep,
 
     /**
-     * Only used for types. Keep the class in the stub, and also all its members.
-     * But each member can have another annotations to override it.
-     */
-    StubClass,
-
-    /**
-     * Only used for types. Keep the class in the impl, not in the stub, and also all its members.
-     * But each member can have another annotations to override it.
+     * Only usable with classes. Keep the class in the jar, and also all its members.
+     * Each member can have another policy to override it.
      */
     KeepClass,
 
     /**
-     * Same as [Stub], but replace it with a "substitution" method. Only usable with methods.
+     * Only usable with methods. Replace a method with a "substitution" method.
      */
-    SubstituteAndStub,
+    Substitute,
 
     /**
-     * Same as [Keep], but replace it with a "substitution" method. Only usable with methods.
+     * Only usable with methods. Replace a native method with a "substitution" method,
      */
-    SubstituteAndKeep,
+    NativeSubstitute,
 
     /**
      * Only usable with methods. The item will be kept in the impl jar file, but when called,
@@ -57,7 +45,7 @@
 
     /**
      * Only usable with methods. The item will be kept in the impl jar file, but when called,
-     * it'll no-op.  Currently only supported for methods returning `void`.
+     * it'll no-op.
      */
     Ignore,
 
@@ -66,20 +54,19 @@
      */
     Remove;
 
-    val isSubstitute: Boolean
-        get() = this == SubstituteAndStub || this == SubstituteAndKeep
-
-    val needsInStub: Boolean
-        get() = this == Stub || this == StubClass || this == SubstituteAndStub || this == Ignore
-
-    val needsInImpl: Boolean
-        get() = this != Remove
+    val needsInOutput: Boolean
+        get() {
+            return when (this) {
+                Remove -> false
+                else -> true
+            }
+        }
 
     /** Returns whether a policy can be used with classes */
     val isUsableWithClasses: Boolean
         get() {
             return when (this) {
-                Stub, StubClass, Keep, KeepClass, Remove -> true
+                Keep, KeepClass, Remove -> true
                 else -> false
             }
         }
@@ -88,7 +75,7 @@
     val isUsableWithFields: Boolean
         get() {
             return when (this) {
-                Stub, Keep, Remove -> true
+                Keep, Remove -> true
                 else -> false
             }
         }
@@ -97,16 +84,16 @@
     val isUsableWithMethods: Boolean
         get() {
             return when (this) {
-                StubClass, KeepClass -> false
+                KeepClass -> false
                 else -> true
             }
         }
 
-    /** Returns whether a policy is a class-wide one. */
-    val isClassWidePolicy: Boolean
+    /** Returns whether a policy can be used as default policy. */
+    val isUsableWithDefault: Boolean
         get() {
             return when (this) {
-                StubClass, KeepClass -> true
+                Keep, Throw, Remove -> true
                 else -> false
             }
         }
@@ -116,25 +103,24 @@
         get() {
             return when (this) {
                 // TODO: handle native method with no substitution as being unsupported
-                Stub, StubClass, Keep, KeepClass, SubstituteAndStub, SubstituteAndKeep -> true
+                Keep, KeepClass, Substitute, NativeSubstitute -> true
                 else -> false
             }
         }
 
-    fun getSubstitutionBasePolicy(): FilterPolicy {
-        return when (this) {
-            SubstituteAndKeep -> Keep
-            SubstituteAndStub -> Stub
-            else -> this
+    val isMethodRewriteBody: Boolean
+        get() {
+            return when (this) {
+                NativeSubstitute, Throw, Ignore -> true
+                else -> false
+            }
         }
-    }
 
     /**
-     * Convert {Stub,Keep}Class to the corresponding Stub or Keep.
+     * Convert KeepClass to Keep, or return itself.
      */
     fun resolveClassWidePolicy(): FilterPolicy {
         return when (this) {
-            StubClass -> Stub
             KeepClass -> Keep
             else -> this
         }
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicyWithReason.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicyWithReason.kt
index eb03f66..b10165b 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicyWithReason.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicyWithReason.kt
@@ -30,36 +30,6 @@
         return FilterPolicyWithReason(policy, "$reason [inner-reason: ${this.reason}]")
     }
 
-    /**
-     * If the visibility is lower than "Keep" (meaning if it's "remove"),
-     * then return a new [FilterPolicy] with "Keep".
-     * Otherwise, return itself
-     */
-    fun promoteToKeep(promotionReason: String): FilterPolicyWithReason {
-        if (policy.needsInImpl) {
-            return this
-        }
-        val newPolicy = if (policy.isClassWidePolicy) FilterPolicy.KeepClass else FilterPolicy.Keep
-
-        return FilterPolicyWithReason(newPolicy,
-                "$promotionReason [original remove reason: ${this.reason}]")
-    }
-
-    /**
-     * If the visibility is above "Keep" (meaning if it's "stub"),
-     * then return a new [FilterPolicy] with "Keep".
-     * Otherwise, return itself
-     */
-    fun demoteToKeep(promotionReason: String): FilterPolicyWithReason {
-        if (!policy.needsInStub) {
-            return this
-        }
-        val newPolicy = if (policy.isClassWidePolicy) FilterPolicy.KeepClass else FilterPolicy.Keep
-
-        return FilterPolicyWithReason(newPolicy,
-                "$promotionReason [original stub reason: ${this.reason}]")
-    }
-
     override fun toString(): String {
         return "[$policy - reason: $reason]"
     }
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt
index 5a26fc6..474da6d 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt
@@ -25,7 +25,6 @@
 import com.android.hoststubgen.asm.isAutoGeneratedEnumMember
 import com.android.hoststubgen.asm.isEnum
 import com.android.hoststubgen.asm.isSynthetic
-import com.android.hoststubgen.asm.isVisibilityPrivateOrPackagePrivate
 import com.android.hoststubgen.log
 import org.objectweb.asm.tree.ClassNode
 
@@ -53,7 +52,7 @@
             }
             // If the outer class needs to be in impl, it should be in impl too.
             val outerPolicy = outermostFilter.getPolicyForClass(cn.outerClass)
-            if (outerPolicy.policy.needsInImpl) {
+            if (outerPolicy.policy.needsInOutput) {
                 return FilterPolicy.KeepClass.withReason("anonymous-inner-class")
             }
         }
@@ -79,19 +78,6 @@
         val fallback = super.getPolicyForMethod(className, methodName, descriptor)
         val classPolicy = outermostFilter.getPolicyForClass(className)
 
-        // If the class is in the stub, then we need to put the private constructor in the stub too,
-        // to prevent the class from getting instantiated.
-        if (classPolicy.policy.needsInStub &&
-                !fallback.policy.needsInStub &&
-                (methodName == "<init>") && // Constructor?
-                (descriptor == "()V")) { // Has zero parameters?
-            classes.findMethod(className, methodName, descriptor)?.let { mn ->
-                if (isVisibilityPrivateOrPackagePrivate(mn.access)) {
-                    return FilterPolicy.Stub.withReason("private constructor in stub class")
-                }
-            }
-        }
-
         val cn = classes.getClass(className)
 
         // If we throw from the static initializer, the class would be useless, so we convert it
@@ -107,7 +93,7 @@
         }
 
         log.d("Class ${cn.name} Class policy: $classPolicy")
-        if (classPolicy.policy.needsInImpl) {
+        if (classPolicy.policy.needsInOutput) {
             // Do it only when the class needs to be kept...
 
             // Member policy should be "keep" or "stub".
@@ -152,7 +138,7 @@
         val classPolicy = outermostFilter.getPolicyForClass(className)
 
         log.d("Class ${cn.name} Class policy: $classPolicy")
-        if (classPolicy.policy.needsInImpl) {
+        if (classPolicy.policy.needsInOutput) {
             // Do it only when the class needs to be kept...
 
             // Member policy should be "keep" or "stub".
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/NativeFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/NativeFilter.kt
new file mode 100644
index 0000000..bd71931
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/NativeFilter.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 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.hoststubgen.filters
+
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.isNative
+
+class NativeFilter(
+    private val classes: ClassNodes,
+    fallback: OutputFilter
+) : DelegatingFilter(fallback) {
+    override fun getPolicyForMethod(
+        className: String,
+        methodName: String,
+        descriptor: String,
+    ): FilterPolicyWithReason {
+        return classes.findMethod(className, methodName, descriptor)?.let { mn ->
+            // For native methods that weren't handled by outer filters,
+            // we keep it so that native method registration will not crash.
+            if (mn.isNative()) {
+                FilterPolicy.Keep.withReason("native-preserve")
+            } else {
+                null
+            }
+        } ?: super.getPolicyForMethod(className, methodName, descriptor)
+    }
+}
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/StubIntersectingFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/StubIntersectingFilter.kt
deleted file mode 100644
index f92a027..0000000
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/StubIntersectingFilter.kt
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2023 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.hoststubgen.filters
-
-import com.android.hoststubgen.HostStubGenErrors
-import com.android.hoststubgen.asm.ClassNodes
-
-private const val REASON = "demoted, not in intersect jars"
-
-/**
- * An [OutputFilter] that will restrict what to put in stub to only what shows up in "intersecting
- * jar" files.
- *
- * For example, if the Android public API stub jar is provided, then the HostStubGen's output
- * stub will be restricted to public APIs.
- */
-class StubIntersectingFilter(
-        private val errors: HostStubGenErrors,
-        /**
-         * If a class / field / method is not in any of these jars, then we will not put it in
-         * stub.
-         */
-        private val intersectingJars: Map<String, ClassNodes>,
-        fallback: OutputFilter,
-) : DelegatingFilter(fallback) {
-    private inline fun exists(predicate: (ClassNodes) -> Boolean): Boolean {
-        intersectingJars.forEach { entry ->
-            if (predicate(entry.value)) {
-                return true
-            }
-        }
-        return false
-    }
-
-    /**
-     * If [origPolicy] is less than "Stub", then return it as-is.
-     *
-     * Otherwise, call [inStubChecker] to see if the API is in any of [intersectingJars].
-     * If yes, then return [origPolicy] as-is. Otherwise, demote to "Keep".
-     */
-    private fun intersectWithStub(
-            origPolicy: FilterPolicyWithReason,
-            inStubChecker: () -> Boolean,
-    ): FilterPolicyWithReason {
-        if (origPolicy.policy.needsInStub) {
-            // Only check the stub jars, when the class is supposed to be in stub otherwise.
-            if (!inStubChecker()) {
-                return origPolicy.demoteToKeep(REASON)
-            }
-        }
-        return origPolicy
-    }
-
-    override fun getPolicyForClass(className: String): FilterPolicyWithReason {
-        return intersectWithStub(super.getPolicyForClass(className)) {
-            exists { classes -> classes.findClass(className) != null }
-        }
-    }
-
-    override fun getPolicyForField(
-            className: String,
-            fieldName: String
-    ): FilterPolicyWithReason {
-        return intersectWithStub(super.getPolicyForField(className, fieldName)) {
-            exists { classes -> classes.findField(className, fieldName) != null }
-        }
-    }
-
-    override fun getPolicyForMethod(
-            className: String,
-            methodName: String,
-            descriptor: String
-    ): FilterPolicyWithReason {
-        return intersectWithStub(super.getPolicyForMethod(className, methodName, descriptor)) {
-            exists { classes -> classes.findMethod(className, methodName, descriptor) != null }
-        }
-    }
-}
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
index 53bcf10..14fd82b 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
@@ -240,7 +240,7 @@
 
                             imf.setPolicyForMethod(className, name, signature,
                                     policy.withReason(FILTER_REASON))
-                            if (policy.isSubstitute) {
+                            if (policy == FilterPolicy.Substitute) {
                                 val fromName = fields[3].substring(1)
 
                                 if (fromName == name) {
@@ -248,10 +248,9 @@
                                             "Substitution must have a different name")
                                 }
 
-                                // Set the policy  for the "from" method.
+                                // Set the policy for the "from" method.
                                 imf.setPolicyForMethod(className, fromName, signature,
-                                        policy.getSubstitutionBasePolicy()
-                                                .withReason(FILTER_REASON))
+                                    FilterPolicy.Keep.withReason(FILTER_REASON))
 
                                 val classAndMethod = splitWithLastPeriod(fromName)
                                 if (classAndMethod != null) {
@@ -346,18 +345,14 @@
 
 private fun parsePolicy(s: String): FilterPolicy {
     return when (s.lowercase()) {
-        "s", "stub" -> FilterPolicy.Stub
         "k", "keep" -> FilterPolicy.Keep
         "t", "throw" -> FilterPolicy.Throw
         "r", "remove" -> FilterPolicy.Remove
-        "sc", "stubclass" -> FilterPolicy.StubClass
         "kc", "keepclass" -> FilterPolicy.KeepClass
         "i", "ignore" -> FilterPolicy.Ignore
         else -> {
             if (s.startsWith("@")) {
-                FilterPolicy.SubstituteAndStub
-            } else if (s.startsWith("%")) {
-                FilterPolicy.SubstituteAndKeep
+                FilterPolicy.Substitute
             } else {
                 throw ParseException("Invalid policy \"$s\"")
             }
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/utils/ClassFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/utils/ClassFilter.kt
index 01a7ab3..7440b94 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/utils/ClassFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/utils/ClassFilter.kt
@@ -24,19 +24,19 @@
 /**
  * General purpose filter for class names.
  */
-class ClassFilter private constructor (
-        val defaultResult: Boolean,
+class ClassFilter private constructor(
+    private val defaultResult: Boolean,
 ) {
-    private data class FilterElement(
-            val allowed: Boolean,
-            val internalName: String,
-            val isPrefix: Boolean,
+    private class FilterElement(
+        val allowed: Boolean,
+        val internalName: String,
+        val isPrefix: Boolean,
     ) {
         fun matches(classInternalName: String): Boolean {
-            if (isPrefix) {
-                return classInternalName.startsWith(internalName)
+            return if (isPrefix) {
+                classInternalName.startsWith(internalName)
             } else {
-                return classInternalName == internalName
+                classInternalName == internalName
             }
         }
     }
@@ -54,15 +54,16 @@
             return it
         }
 
-        var result = defaultResult
-        run outer@{
-            elements.forEach { e ->
-                if (e.matches(classInternalName)) {
-                    result = e.allowed
-                    return@outer // break equivalent.
-                }
+        val testClasses = sequence {
+            // Yield itself and its outer class(es) one by one
+            var idx = classInternalName.length
+            while (idx > 0) {
+                yield(classInternalName.substring(0, idx))
+                idx = classInternalName.lastIndexOf('$', idx - 1)
             }
         }
+
+        val result = elements.find { testClasses.any(it::matches) }?.allowed ?: defaultResult
         cache[classInternalName] = result
 
         return result
@@ -87,9 +88,9 @@
 
         /** Build a filter from a string (for unit tests). */
         fun buildFromString(
-                filterString: String,
-                defaultResult: Boolean,
-                filenameForErrorMessage: String
+            filterString: String,
+            defaultResult: Boolean,
+            filenameForErrorMessage: String
         ): ClassFilter {
             val ret = ClassFilter(defaultResult)
 
@@ -119,17 +120,20 @@
 
                 // Handle wildcard -- e.g. "package.name.*"
                 if (line.endsWith(".*")) {
-                    ret.elements.add(FilterElement(
-                            allow, line.substring(0, line.length - 2).toJvmClassName(), true))
+                    ret.elements.add(
+                        FilterElement(
+                            allow, line.substring(0, line.length - 2).toJvmClassName(), true
+                        )
+                    )
                     return@forEach
                 }
 
                 // Any other uses of "*" would be an error.
                 if (line.contains('*')) {
                     throw ParseException(
-                            "Wildcard (*) can only show up as the last element",
-                            filenameForErrorMessage,
-                            lineNo
+                        "Wildcard (*) can only show up as the last element",
+                        filenameForErrorMessage,
+                        lineNo
                     )
                 }
                 ret.elements.add(FilterElement(allow, line.toJvmClassName(), false))
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt
index bad0449..41ba928 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt
@@ -26,67 +26,47 @@
 import com.android.hoststubgen.filters.FilterPolicy
 import com.android.hoststubgen.filters.FilterPolicyWithReason
 import com.android.hoststubgen.filters.OutputFilter
-import com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-import com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+import com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 import com.android.hoststubgen.log
+import java.io.PrintWriter
 import org.objectweb.asm.ClassVisitor
 import org.objectweb.asm.FieldVisitor
 import org.objectweb.asm.MethodVisitor
 import org.objectweb.asm.Opcodes
 import org.objectweb.asm.commons.ClassRemapper
-import org.objectweb.asm.commons.Remapper
 import org.objectweb.asm.util.TraceClassVisitor
-import java.io.PrintWriter
 
-val OPCODE_VERSION = Opcodes.ASM9
+const val OPCODE_VERSION = Opcodes.ASM9
 
-abstract class BaseAdapter (
-        protected val classes: ClassNodes,
-        nextVisitor: ClassVisitor,
-        protected val filter: OutputFilter,
-        protected val options: Options,
+abstract class BaseAdapter(
+    protected val classes: ClassNodes,
+    nextVisitor: ClassVisitor,
+    protected val filter: OutputFilter,
+    protected val options: Options,
 ) : ClassVisitor(OPCODE_VERSION, nextVisitor) {
 
     /**
      * Options to control the behavior.
      */
-    data class Options (
-            val errors: HostStubGenErrors,
-            val stats: HostStubGenStats?,
-            val enablePreTrace: Boolean,
-            val enablePostTrace: Boolean,
-            val enableNonStubMethodCallDetection: Boolean,
-            )
+    data class Options(
+        val errors: HostStubGenErrors,
+        val stats: HostStubGenStats?,
+        val enablePreTrace: Boolean,
+        val enablePostTrace: Boolean
+    )
 
     protected lateinit var currentPackageName: String
     protected lateinit var currentClassName: String
     protected var nativeSubstitutionClass: String? = null
     protected lateinit var classPolicy: FilterPolicyWithReason
 
-    /**
-     * Return whether an item with a given policy should be included in the output.
-     */
-    protected abstract fun shouldEmit(policy: FilterPolicy): Boolean
-
-    /**
-     * Inject [HostStubGenKeptInStub] and [HostStubGenKeptInImpl] as needed to an item.
-     */
-    protected fun injectInStubAndKeepAnnotations(policy: FilterPolicy, v: UnifiedVisitor) {
-        if (policy.needsInStub) {
-            v.visitAnnotation(HostStubGenKeptInStub.CLASS_DESCRIPTOR, true)
-        }
-        if (policy.needsInImpl) {
-            v.visitAnnotation(HostStubGenKeptInImpl.CLASS_DESCRIPTOR, true)
-        }
-    }
-
     override fun visit(
-            version: Int,
-            access: Int,
-            name: String,
-            signature: String?,
-            superName: String?,
-            interfaces: Array<String>,
+        version: Int,
+        access: Int,
+        name: String,
+        signature: String?,
+        superName: String?,
+        interfaces: Array<String>,
     ) {
         super.visit(version, access, name, signature, superName, interfaces)
         currentClassName = name
@@ -103,21 +83,25 @@
                 .toJvmClassName()
             log.d("  NativeSubstitutionClass: $fullClassName")
             if (classes.findClass(fullClassName) == null) {
-                log.w("Native substitution class $fullClassName not found. Class must be " +
-                        "available at runtime.")
+                log.w(
+                    "Native substitution class $fullClassName not found. Class must be " +
+                            "available at runtime."
+                )
             } else {
                 // If the class exists, it must have a KeepClass policy.
                 if (filter.getPolicyForClass(fullClassName).policy != FilterPolicy.KeepClass) {
                     // TODO: Use real annotation name.
                     options.errors.onErrorFound(
-                            "Native substitution class $fullClassName should have @Keep.")
+                        "Native substitution class $fullClassName should have @Keep."
+                    )
                 }
             }
 
             nativeSubstitutionClass = fullClassName
         }
+
         // Inject annotations to generated classes.
-        injectInStubAndKeepAnnotations(classPolicy.policy, UnifiedVisitor.on(this))
+        UnifiedVisitor.on(this).visitAnnotation(HostStubGenProcessedAsKeep.CLASS_DESCRIPTOR, true)
     }
 
     override fun visitEnd() {
@@ -141,11 +125,11 @@
     }
 
     override fun visitField(
-            access: Int,
-            name: String,
-            descriptor: String,
-            signature: String?,
-            value: Any?,
+        access: Int,
+        name: String,
+        descriptor: String,
+        signature: String?,
+        value: Any?,
     ): FieldVisitor? {
         if (skipMemberModificationNestCount > 0) {
             return super.visitField(access, name, descriptor, signature, value)
@@ -154,7 +138,7 @@
         log.d("visitField: %s %s [%x] Policy: %s", name, descriptor, access, policy)
 
         log.withIndent {
-            if (!shouldEmit(policy.policy)) {
+            if (policy.policy == FilterPolicy.Remove) {
                 log.d("Removing %s %s", name, policy)
                 return null
             }
@@ -162,18 +146,19 @@
             log.v("Emitting field: %s %s %s", name, descriptor, policy)
             val ret = super.visitField(access, name, descriptor, signature, value)
 
-            injectInStubAndKeepAnnotations(policy.policy, UnifiedVisitor.on(ret))
+            UnifiedVisitor.on(ret)
+                .visitAnnotation(HostStubGenProcessedAsKeep.CLASS_DESCRIPTOR, true)
 
             return ret
         }
     }
 
     override fun visitMethod(
-            access: Int,
-            name: String,
-            descriptor: String,
-            signature: String?,
-            exceptions: Array<String>?,
+        access: Int,
+        name: String,
+        descriptor: String,
+        signature: String?,
+        exceptions: Array<String>?,
     ): MethodVisitor? {
         if (skipMemberModificationNestCount > 0) {
             return super.visitMethod(access, name, descriptor, signature, exceptions)
@@ -187,11 +172,11 @@
             // Instead of this method, we rename the substitute-to method with the original
             // name, in the "Maybe rename the method" part below.
             val policy = filter.getPolicyForMethod(currentClassName, name, descriptor)
-            if (policy.policy.isSubstitute) {
+            if (policy.policy == FilterPolicy.Substitute) {
                 log.d("Skipping %s%s %s", name, descriptor, policy)
                 return null
             }
-            if (!shouldEmit(p.policy)) {
+            if (p.policy == FilterPolicy.Remove) {
                 log.d("Removing %s%s %s", name, descriptor, policy)
                 return null
             }
@@ -209,13 +194,16 @@
                 // `name` is the name of the method we're currently visiting, so it's usually a
                 // "...$ravewnwood" name.
                 newAccess = checkSubstitutionMethodCompatibility(
-                        classes, currentClassName, newName, name, descriptor, options.errors)
+                    classes, currentClassName, newName, name, descriptor, options.errors
+                )
                 if (newAccess == NOT_COMPATIBLE) {
                     return null
                 }
 
-                log.v("Emitting %s.%s%s as %s %s", currentClassName, name, descriptor,
-                        newName, policy)
+                log.v(
+                    "Emitting %s.%s%s as %s %s", currentClassName, name, descriptor,
+                    newName, policy
+                )
             } else {
                 log.v("Emitting method: %s%s %s", name, descriptor, policy)
                 newName = name
@@ -225,14 +213,17 @@
             // But note, we only use it when calling the super's method,
             // but not for visitMethodInner(), because when subclass wants to change access,
             // it can do so inside visitMethodInner().
-            newAccess = updateAccessFlags(newAccess, name, descriptor)
+            newAccess = updateAccessFlags(newAccess, name, descriptor, policy.policy)
 
-            val ret = visitMethodInner(access, newName, descriptor, signature, exceptions, policy,
+            val ret = visitMethodInner(
+                access, newName, descriptor, signature, exceptions, policy,
                 renameTo != null,
-                super.visitMethod(newAccess, newName, descriptor, signature, exceptions))
+                super.visitMethod(newAccess, newName, descriptor, signature, exceptions)
+            )
 
             ret?.let {
-                injectInStubAndKeepAnnotations(policy.policy, UnifiedVisitor.on(ret))
+                UnifiedVisitor.on(ret)
+                    .visitAnnotation(HostStubGenProcessedAsKeep.CLASS_DESCRIPTOR, true)
             }
 
             return ret
@@ -240,9 +231,10 @@
     }
 
     open fun updateAccessFlags(
-            access: Int,
-            name: String,
-            descriptor: String,
+        access: Int,
+        name: String,
+        descriptor: String,
+        policy: FilterPolicy,
     ): Int {
         return access
     }
@@ -256,7 +248,7 @@
         policy: FilterPolicyWithReason,
         substituted: Boolean,
         superVisitor: MethodVisitor?,
-        ): MethodVisitor?
+    ): MethodVisitor?
 
     companion object {
         fun getVisitor(
@@ -265,8 +257,6 @@
             nextVisitor: ClassVisitor,
             filter: OutputFilter,
             packageRedirector: PackageRedirectRemapper,
-            remapper: Remapper?,
-            forImpl: Boolean,
             options: Options,
         ): ClassVisitor {
             var next = nextVisitor
@@ -289,23 +279,20 @@
                 if (!packageRedirector.isTarget(classInternalName)) {
                     next = ClassRemapper(next, packageRedirector)
                 } else {
-                    log.v("Class $classInternalName is a redirect-from class, not applying" +
-                            " --package-redirect")
+                    log.v(
+                        "Class $classInternalName is a redirect-from class, not applying" +
+                                " --package-redirect"
+                    )
                 }
             }
 
-            var ret: ClassVisitor
-            if (forImpl) {
-                ret = ImplGeneratingAdapter(classes, next, filter, options)
-            } else {
-                ret = StubGeneratingAdapter(classes, next, filter, options)
-            }
+            next = ImplGeneratingAdapter(classes, next, filter, options)
 
             // Inject TraceClassVisitor for debugging.
             if (options.enablePreTrace) {
-                ret = TraceClassVisitor(ret, verbosePrinter)
+                next = TraceClassVisitor(next, verbosePrinter)
             }
-            return ret
+            return next
         }
     }
 }
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BodyReplacingMethodVisitor.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BodyReplacingMethodVisitor.kt
index 8250412..55d0c0e 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BodyReplacingMethodVisitor.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BodyReplacingMethodVisitor.kt
@@ -20,38 +20,23 @@
 import org.objectweb.asm.Handle
 import org.objectweb.asm.Label
 import org.objectweb.asm.MethodVisitor
-import org.objectweb.asm.Opcodes
 import org.objectweb.asm.TypePath
 
 /**
- * A method visitor that removes everything from method body.
+ * A method visitor that creates or replaces a method body.
  *
- * To inject a method body, override [visitCode] and create the opcodes there.
+ * Override [emitNewCode] to build the method body.
  */
 abstract class BodyReplacingMethodVisitor(
-    access: Int,
-    name: String,
-    descriptor: String,
-    signature: String?,
-    exceptions: Array<String>?,
-    next: MethodVisitor?,
+    private val createBody: Boolean,
+    next: MethodVisitor?
 ) : MethodVisitor(OPCODE_VERSION, next) {
-    val isVoid: Boolean
-    val isStatic: Boolean
-
-    init {
-        isVoid = descriptor.endsWith(")V")
-        isStatic = access and Opcodes.ACC_STATIC != 0
-    }
 
     // Following methods are for things that we need to keep.
     // Since they're all calling the super method, we can just remove them, but we keep them
     // just to clarify what we're keeping.
 
-    final override fun visitParameter(
-            name: String?,
-            access: Int
-    ) {
+    final override fun visitParameter(name: String?, access: Int) {
         super.visitParameter(name, access)
     }
 
@@ -59,10 +44,7 @@
         return super.visitAnnotationDefault()
     }
 
-    final override fun visitAnnotation(
-            descriptor: String?,
-            visible: Boolean
-    ): AnnotationVisitor? {
+    final override fun visitAnnotation(descriptor: String?, visible: Boolean): AnnotationVisitor? {
         return super.visitAnnotation(descriptor, visible)
     }
 
@@ -75,17 +57,14 @@
         return super.visitTypeAnnotation(typeRef, typePath, descriptor, visible)
     }
 
-    final override fun visitAnnotableParameterCount(
-            parameterCount: Int,
-            visible: Boolean
-    ) {
+    final override fun visitAnnotableParameterCount(parameterCount: Int, visible: Boolean) {
         super.visitAnnotableParameterCount(parameterCount, visible)
     }
 
     final override fun visitParameterAnnotation(
-            parameter: Int,
-            descriptor: String?,
-            visible: Boolean
+        parameter: Int,
+        descriptor: String?,
+        visible: Boolean
     ): AnnotationVisitor? {
         return super.visitParameterAnnotation(parameter, descriptor, visible)
     }
@@ -94,10 +73,6 @@
         super.visitAttribute(attribute)
     }
 
-    override fun visitEnd() {
-        super.visitEnd()
-    }
-
     /**
      * Control when to emit the code. We use this to ignore all visitXxx method calls caused by
      * the original method, so we'll remove all the original code.
@@ -108,9 +83,18 @@
      * (See also https://asm.ow2.io/asm4-guide.pdf section 3.2.1 about the MethovVisitor
      * call order.)
      */
-    var emitCode = false
+    private var emitCode = false
+
+    /**
+     * This value will be set as true when [visitCode] is called. In [visitEnd], if this value
+     * is still false, this means that the original method does not have a body.
+     *
+     * We want to forcefully inject a method body in [visitEnd] if [createBody] is true.
+     */
+    private var visitedCode = false
 
     final override fun visitCode() {
+        visitedCode = true
         super.visitCode()
 
         try {
@@ -122,15 +106,19 @@
         }
     }
 
+    final override fun visitEnd() {
+        if (!visitedCode && createBody) {
+            visitCode()
+        }
+        super.visitEnd()
+    }
+
     /**
      * Subclass must implement it and emit code, and call [visitMaxs] at the end.
      */
     abstract fun emitNewCode()
 
-    final override fun visitMaxs(
-            maxStack: Int,
-            maxLocals: Int
-    ) {
+    final override fun visitMaxs(maxStack: Int, maxLocals: Int) {
         if (emitCode) {
             super.visitMaxs(maxStack, maxLocals)
         }
@@ -140,11 +128,11 @@
     // emit any of them, so they are all no-op.
 
     final override fun visitFrame(
-            type: Int,
-            numLocal: Int,
-            local: Array<out Any>?,
-            numStack: Int,
-            stack: Array<out Any>?
+        type: Int,
+        numLocal: Int,
+        local: Array<out Any>?,
+        numStack: Int,
+        stack: Array<out Any>?
     ) {
         if (emitCode) {
             super.visitFrame(type, numLocal, local, numStack, stack)
@@ -157,38 +145,29 @@
         }
     }
 
-    final override fun visitIntInsn(
-            opcode: Int,
-            operand: Int
-    ) {
+    final override fun visitIntInsn(opcode: Int, operand: Int) {
         if (emitCode) {
             super.visitIntInsn(opcode, operand)
         }
     }
 
-    final override fun visitVarInsn(
-            opcode: Int,
-            varIndex: Int
-    ) {
+    final override fun visitVarInsn(opcode: Int, varIndex: Int) {
         if (emitCode) {
             super.visitVarInsn(opcode, varIndex)
         }
     }
 
-    final override fun visitTypeInsn(
-            opcode: Int,
-            type: String?
-    ) {
+    final override fun visitTypeInsn(opcode: Int, type: String?) {
         if (emitCode) {
             super.visitTypeInsn(opcode, type)
         }
     }
 
     final override fun visitFieldInsn(
-            opcode: Int,
-            owner: String?,
-            name: String?,
-            descriptor: String?
+        opcode: Int,
+        owner: String?,
+        name: String?,
+        descriptor: String?
     ) {
         if (emitCode) {
             super.visitFieldInsn(opcode, owner, name, descriptor)
@@ -196,11 +175,11 @@
     }
 
     final override fun visitMethodInsn(
-            opcode: Int,
-            owner: String?,
-            name: String?,
-            descriptor: String?,
-            isInterface: Boolean
+        opcode: Int,
+        owner: String?,
+        name: String?,
+        descriptor: String?,
+        isInterface: Boolean
     ) {
         if (emitCode) {
             super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
@@ -208,21 +187,20 @@
     }
 
     final override fun visitInvokeDynamicInsn(
-            name: String?,
-            descriptor: String?,
-            bootstrapMethodHandle: Handle?,
-            vararg bootstrapMethodArguments: Any?
+        name: String?,
+        descriptor: String?,
+        bootstrapMethodHandle: Handle?,
+        vararg bootstrapMethodArguments: Any?
     ) {
         if (emitCode) {
-            super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle,
-                    *bootstrapMethodArguments)
+            super.visitInvokeDynamicInsn(
+                name, descriptor, bootstrapMethodHandle,
+                *bootstrapMethodArguments
+            )
         }
     }
 
-    final override fun visitJumpInsn(
-            opcode: Int,
-            label: Label?
-    ) {
+    final override fun visitJumpInsn(opcode: Int, label: Label?) {
         if (emitCode) {
             super.visitJumpInsn(opcode, label)
         }
@@ -240,20 +218,17 @@
         }
     }
 
-    final override fun visitIincInsn(
-            varIndex: Int,
-            increment: Int
-    ) {
+    final override fun visitIincInsn(varIndex: Int, increment: Int) {
         if (emitCode) {
             super.visitIincInsn(varIndex, increment)
         }
     }
 
     final override fun visitTableSwitchInsn(
-            min: Int,
-            max: Int,
-            dflt: Label?,
-            vararg labels: Label?
+        min: Int,
+        max: Int,
+        dflt: Label?,
+        vararg labels: Label?
     ) {
         if (emitCode) {
             super.visitTableSwitchInsn(min, max, dflt, *labels)
@@ -261,29 +236,26 @@
     }
 
     final override fun visitLookupSwitchInsn(
-            dflt: Label?,
-            keys: IntArray?,
-            labels: Array<out Label>?
+        dflt: Label?,
+        keys: IntArray?,
+        labels: Array<out Label>?
     ) {
         if (emitCode) {
             super.visitLookupSwitchInsn(dflt, keys, labels)
         }
     }
 
-    final override fun visitMultiANewArrayInsn(
-            descriptor: String?,
-            numDimensions: Int
-    ) {
+    final override fun visitMultiANewArrayInsn(descriptor: String?, numDimensions: Int) {
         if (emitCode) {
             super.visitMultiANewArrayInsn(descriptor, numDimensions)
         }
     }
 
     final override fun visitInsnAnnotation(
-            typeRef: Int,
-            typePath: TypePath?,
-            descriptor: String?,
-            visible: Boolean
+        typeRef: Int,
+        typePath: TypePath?,
+        descriptor: String?,
+        visible: Boolean
     ): AnnotationVisitor? {
         if (emitCode) {
             return super.visitInsnAnnotation(typeRef, typePath, descriptor, visible)
@@ -292,10 +264,10 @@
     }
 
     final override fun visitTryCatchBlock(
-            start: Label?,
-            end: Label?,
-            handler: Label?,
-            type: String?
+        start: Label?,
+        end: Label?,
+        handler: Label?,
+        type: String?
     ) {
         if (emitCode) {
             super.visitTryCatchBlock(start, end, handler, type)
@@ -303,10 +275,10 @@
     }
 
     final override fun visitTryCatchAnnotation(
-            typeRef: Int,
-            typePath: TypePath?,
-            descriptor: String?,
-            visible: Boolean
+        typeRef: Int,
+        typePath: TypePath?,
+        descriptor: String?,
+        visible: Boolean
     ): AnnotationVisitor? {
         if (emitCode) {
             return super.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible)
@@ -315,12 +287,12 @@
     }
 
     final override fun visitLocalVariable(
-            name: String?,
-            descriptor: String?,
-            signature: String?,
-            start: Label?,
-            end: Label?,
-            index: Int
+        name: String?,
+        descriptor: String?,
+        signature: String?,
+        start: Label?,
+        end: Label?,
+        index: Int
     ) {
         if (emitCode) {
             super.visitLocalVariable(name, descriptor, signature, start, end, index)
@@ -328,25 +300,23 @@
     }
 
     final override fun visitLocalVariableAnnotation(
-            typeRef: Int,
-            typePath: TypePath?,
-            start: Array<out Label>?,
-            end: Array<out Label>?,
-            index: IntArray?,
-            descriptor: String?,
-            visible: Boolean
+        typeRef: Int,
+        typePath: TypePath?,
+        start: Array<out Label>?,
+        end: Array<out Label>?,
+        index: IntArray?,
+        descriptor: String?,
+        visible: Boolean
     ): AnnotationVisitor? {
         if (emitCode) {
             return super.visitLocalVariableAnnotation(
-                    typeRef, typePath, start, end, index, descriptor, visible)
+                typeRef, typePath, start, end, index, descriptor, visible
+            )
         }
         return null
     }
 
-    final override fun visitLineNumber(
-            line: Int,
-            start: Label?
-    ) {
+    final override fun visitLineNumber(line: Int, start: Label?) {
         if (emitCode) {
             super.visitLineNumber(line, start)
         }
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt
index 3d2e142..057d653 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt
@@ -18,7 +18,6 @@
 import com.android.hoststubgen.asm.CLASS_INITIALIZER_DESC
 import com.android.hoststubgen.asm.CLASS_INITIALIZER_NAME
 import com.android.hoststubgen.asm.ClassNodes
-import com.android.hoststubgen.asm.isVisibilityPrivateOrPackagePrivate
 import com.android.hoststubgen.asm.prependArgTypeToMethodDescriptor
 import com.android.hoststubgen.asm.writeByteCodeToPushArguments
 import com.android.hoststubgen.asm.writeByteCodeToReturn
@@ -42,16 +41,12 @@
  * An adapter that generates the "impl" class file from an input class file.
  */
 class ImplGeneratingAdapter(
-        classes: ClassNodes,
-        nextVisitor: ClassVisitor,
-        filter: OutputFilter,
-        options: Options,
+    classes: ClassNodes,
+    nextVisitor: ClassVisitor,
+    filter: OutputFilter,
+    options: Options,
 ) : BaseAdapter(classes, nextVisitor, filter, options) {
 
-    override fun shouldEmit(policy: FilterPolicy): Boolean {
-        return policy.needsInImpl
-    }
-
     private var classLoadHooks: List<String> = emptyList()
 
     override fun visit(
@@ -107,14 +102,14 @@
     private fun writeClassLoadHookCalls(mv: MethodVisitor) {
         classLoadHooks.forEach { classLoadHook ->
             // First argument: the class type.
-            mv.visitLdcInsn(Type.getType("L" + currentClassName + ";"))
+            mv.visitLdcInsn(Type.getType("L$currentClassName;"))
 
             // Second argument: method name
             mv.visitLdcInsn(classLoadHook)
 
             // Call HostTestUtils.onClassLoaded().
             mv.visitMethodInsn(
-                Opcodes.INVOKESTATIC,
+                INVOKESTATIC,
                 HostTestUtils.CLASS_INTERNAL_NAME,
                 "onClassLoaded",
                 "(Ljava/lang/Class;Ljava/lang/String;)V",
@@ -124,69 +119,49 @@
     }
 
     override fun updateAccessFlags(
-            access: Int,
-            name: String,
-            descriptor: String,
+        access: Int,
+        name: String,
+        descriptor: String,
+        policy: FilterPolicy,
     ): Int {
-        if ((access and Opcodes.ACC_NATIVE) != 0 && nativeSubstitutionClass != null) {
+        if (policy.isMethodRewriteBody) {
+            // If we are rewriting the entire method body, we need
+            // to convert native methods to non-native
             return access and Opcodes.ACC_NATIVE.inv()
         }
         return access
     }
 
     override fun visitMethodInner(
-            access: Int,
-            name: String,
-            descriptor: String,
-            signature: String?,
-            exceptions: Array<String>?,
-            policy: FilterPolicyWithReason,
-            substituted: Boolean,
-            superVisitor: MethodVisitor?,
+        access: Int,
+        name: String,
+        descriptor: String,
+        signature: String?,
+        exceptions: Array<String>?,
+        policy: FilterPolicyWithReason,
+        substituted: Boolean,
+        superVisitor: MethodVisitor?,
     ): MethodVisitor? {
-        // Inject method log, if needed.
         var innerVisitor = superVisitor
 
         //  If method logging is enabled, inject call to the logging method.
         val methodCallHooks = filter.getMethodCallHooks(currentClassName, name, descriptor)
         if (methodCallHooks.isNotEmpty()) {
             innerVisitor = MethodCallHookInjectingAdapter(
-                access,
                 name,
                 descriptor,
-                signature,
-                exceptions,
-                innerVisitor,
                 methodCallHooks,
-                )
+                innerVisitor,
+            )
         }
 
         // If this class already has a class initializer and a class load hook is needed, then
         // we inject code.
         if (classLoadHooks.isNotEmpty() &&
             name == CLASS_INITIALIZER_NAME &&
-            descriptor == CLASS_INITIALIZER_DESC) {
-            innerVisitor = ClassLoadHookInjectingMethodAdapter(
-                access,
-                name,
-                descriptor,
-                signature,
-                exceptions,
-                innerVisitor,
-            )
-        }
-
-        // If non-stub method call detection is enabled, then inject a call to the checker.
-        if (options.enableNonStubMethodCallDetection && doesMethodNeedNonStubCallCheck(
-                access, name, descriptor, policy) ) {
-            innerVisitor = NonStubMethodCallDetectingAdapter(
-                    access,
-                    name,
-                    descriptor,
-                    signature,
-                    exceptions,
-                    innerVisitor,
-            )
+            descriptor == CLASS_INITIALIZER_DESC
+        ) {
+            innerVisitor = ClassLoadHookInjectingMethodAdapter(innerVisitor)
         }
 
         fun MethodVisitor.withAnnotation(descriptor: String): MethodVisitor {
@@ -195,34 +170,31 @@
         }
 
         log.withIndent {
-            var willThrow = false
-            if (policy.policy == FilterPolicy.Throw) {
-                log.v("Making method throw...")
-                willThrow = true
-                innerVisitor = ThrowingMethodAdapter(
-                    access, name, descriptor, signature, exceptions, innerVisitor)
-                    .withAnnotation(HostStubGenProcessedAsThrow.CLASS_DESCRIPTOR)
+            // When we encounter native methods, we want to forcefully
+            // inject a method body. Also see [updateAccessFlags].
+            val forceCreateBody = (access and Opcodes.ACC_NATIVE) != 0
+            when (policy.policy) {
+                FilterPolicy.Throw -> {
+                    log.v("Making method throw...")
+                    return ThrowingMethodAdapter(forceCreateBody, innerVisitor)
+                        .withAnnotation(HostStubGenProcessedAsThrow.CLASS_DESCRIPTOR)
+                }
+                FilterPolicy.Ignore -> {
+                    log.v("Making method ignored...")
+                    return IgnoreMethodAdapter(descriptor, forceCreateBody, innerVisitor)
+                        .withAnnotation(HostStubGenProcessedAsIgnore.CLASS_DESCRIPTOR)
+                }
+                FilterPolicy.NativeSubstitute -> {
+                    log.v("Rewriting native method...")
+                    return NativeSubstitutingMethodAdapter(access, name, descriptor, innerVisitor)
+                        .withAnnotation(HostStubGenProcessedAsSubstitute.CLASS_DESCRIPTOR)
+                }
+                else -> {}
             }
-            if ((access and Opcodes.ACC_NATIVE) != 0 && nativeSubstitutionClass != null) {
-                log.v("Rewriting native method...")
-                return NativeSubstitutingMethodAdapter(
-                        access, name, descriptor, signature, exceptions, innerVisitor)
-                    .withAnnotation(HostStubGenProcessedAsSubstitute.CLASS_DESCRIPTOR)
-            }
-            if (willThrow) {
-                return innerVisitor
-            }
+        }
 
-            if (policy.policy == FilterPolicy.Ignore) {
-                log.v("Making method ignored...")
-                return IgnoreMethodAdapter(
-                    access, name, descriptor, signature, exceptions, innerVisitor)
-                    .withAnnotation(HostStubGenProcessedAsIgnore.CLASS_DESCRIPTOR)
-            }
-            if (filter.hasAnyMethodCallReplace()) {
-                innerVisitor = MethodCallReplacingAdapter(
-                    access, name, descriptor, signature, exceptions, innerVisitor)
-            }
+        if (filter.hasAnyMethodCallReplace()) {
+            innerVisitor = MethodCallReplacingAdapter(name, innerVisitor)
         }
         if (substituted) {
             innerVisitor?.withAnnotation(HostStubGenProcessedAsSubstitute.CLASS_DESCRIPTOR)
@@ -231,53 +203,32 @@
         return innerVisitor
     }
 
-    fun doesMethodNeedNonStubCallCheck(
-            access: Int,
-            name: String,
-            descriptor: String,
-            policy: FilterPolicyWithReason,
-    ): Boolean {
-        // If a method is in the stub, then no need to check.
-        if (policy.policy.needsInStub) {
-            return false
-        }
-        // If a method is private or package-private, no need to check.
-        // Technically test code can use framework package name, so it's a bit too lenient.
-        if (isVisibilityPrivateOrPackagePrivate(access)) {
-            return false
-        }
-        // TODO: If the method overrides a method that's accessible by tests, then we shouldn't
-        // do the check. (e.g. overrides a stub method or java standard method.)
-
-        return true
-    }
-
     /**
      * A method adapter that replaces the method body with a HostTestUtils.onThrowMethodCalled()
      * call.
      */
     private inner class ThrowingMethodAdapter(
-            access: Int,
-            val name: String,
-            descriptor: String,
-            signature: String?,
-            exceptions: Array<String>?,
-            next: MethodVisitor?
-    ) : BodyReplacingMethodVisitor(access, name, descriptor, signature, exceptions, next) {
+        createBody: Boolean,
+        next: MethodVisitor?
+    ) : BodyReplacingMethodVisitor(createBody, next) {
         override fun emitNewCode() {
-            visitMethodInsn(Opcodes.INVOKESTATIC,
-                    HostTestUtils.CLASS_INTERNAL_NAME,
-                    "onThrowMethodCalled",
-                    "()V",
-                    false)
+            visitMethodInsn(
+                INVOKESTATIC,
+                HostTestUtils.CLASS_INTERNAL_NAME,
+                "onThrowMethodCalled",
+                "()V",
+                false
+            )
 
             // We still need a RETURN opcode for the return type.
             // For now, let's just inject a `throw`.
             visitTypeInsn(Opcodes.NEW, "java/lang/RuntimeException")
             visitInsn(Opcodes.DUP)
             visitLdcInsn("Unreachable")
-            visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/RuntimeException",
-                    "<init>", "(Ljava/lang/String;)V", false)
+            visitMethodInsn(
+                Opcodes.INVOKESPECIAL, "java/lang/RuntimeException",
+                "<init>", "(Ljava/lang/String;)V", false
+            )
             visitInsn(Opcodes.ATHROW)
 
             // visitMaxs(3, if (isStatic) 0 else 1)
@@ -289,13 +240,10 @@
      * A method adapter that replaces the method body with a no-op return.
      */
     private inner class IgnoreMethodAdapter(
-            access: Int,
-            name: String,
-            val descriptor: String,
-            signature: String?,
-            exceptions: Array<String>?,
-            next: MethodVisitor?
-    ) : BodyReplacingMethodVisitor(access, name, descriptor, signature, exceptions, next) {
+        val descriptor: String,
+        createBody: Boolean,
+        next: MethodVisitor?
+    ) : BodyReplacingMethodVisitor(createBody, next) {
         override fun emitNewCode() {
             when (Type.getReturnType(descriptor)) {
                 Type.VOID_TYPE -> visitInsn(Opcodes.RETURN)
@@ -326,30 +274,24 @@
     }
 
     /**
-     * A method adapter that replaces a native method call with a call to the "native substitution"
-     * class.
+     * A method adapter that rewrite a native method body with a
+     * call to a method in the "native substitution" class.
      */
     private inner class NativeSubstitutingMethodAdapter(
-            val access: Int,
-            private val name: String,
-            private val descriptor: String,
-            signature: String?,
-            exceptions: Array<String>?,
-            next: MethodVisitor?
-    ) : MethodVisitor(OPCODE_VERSION, next) {
-        override fun visitCode() {
-            throw RuntimeException("NativeSubstitutingMethodVisitor should be called on " +
-                    " native method, where visitCode() shouldn't be called.")
-        }
+        access: Int,
+        private val name: String,
+        private val descriptor: String,
+        next: MethodVisitor?
+    ) : BodyReplacingMethodVisitor(true, next) {
 
-        override fun visitEnd() {
-            super.visitCode()
+        private val isStatic = (access and Opcodes.ACC_STATIC) != 0
 
+        override fun emitNewCode() {
             var targetDescriptor = descriptor
             var argOffset = 0
 
             // For non-static native method, we need to tweak it a bit.
-            if ((access and Opcodes.ACC_STATIC) == 0) {
+            if (!isStatic) {
                 // Push `this` as the first argument.
                 this.visitVarInsn(Opcodes.ALOAD, 0)
 
@@ -366,16 +308,17 @@
 
             writeByteCodeToPushArguments(descriptor, this, argOffset)
 
-            visitMethodInsn(Opcodes.INVOKESTATIC,
-                    nativeSubstitutionClass,
-                    name,
-                    targetDescriptor,
-                    false)
+            visitMethodInsn(
+                INVOKESTATIC,
+                nativeSubstitutionClass,
+                name,
+                targetDescriptor,
+                false
+            )
 
             writeByteCodeToReturn(descriptor, this)
 
             visitMaxs(99, 0) // We let ASM figure them out.
-            super.visitEnd()
         }
     }
 
@@ -386,25 +329,22 @@
      * `this(...)`. The logging code will be injected *before* such calls.
      */
     private inner class MethodCallHookInjectingAdapter(
-            access: Int,
-            val name: String,
-            val descriptor: String,
-            signature: String?,
-            exceptions: Array<String>?,
-            next: MethodVisitor?,
-            val hooks: List<String>,
+        val name: String,
+        val descriptor: String,
+        val hooks: List<String>,
+        next: MethodVisitor?,
     ) : MethodVisitor(OPCODE_VERSION, next) {
         override fun visitCode() {
             super.visitCode()
 
             hooks.forEach { hook ->
-                mv.visitLdcInsn(Type.getType("L" + currentClassName + ";"))
+                mv.visitLdcInsn(Type.getType("L$currentClassName;"))
                 visitLdcInsn(name)
                 visitLdcInsn(descriptor)
                 visitLdcInsn(hook)
 
                 visitMethodInsn(
-                    Opcodes.INVOKESTATIC,
+                    INVOKESTATIC,
                     HostTestUtils.CLASS_INTERNAL_NAME,
                     "callMethodCallHook",
                     "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
@@ -418,11 +358,6 @@
      * Inject a class load hook call.
      */
     private inner class ClassLoadHookInjectingMethodAdapter(
-        access: Int,
-        val name: String,
-        val descriptor: String,
-        signature: String?,
-        exceptions: Array<String>?,
         next: MethodVisitor?
     ) : MethodVisitor(OPCODE_VERSION, next) {
         override fun visitCode() {
@@ -432,53 +367,8 @@
         }
     }
 
-    /**
-     * A method adapter that detects calls to non-stub methods.
-     */
-    private inner class NonStubMethodCallDetectingAdapter(
-            access: Int,
-            val name: String,
-            val descriptor: String,
-            signature: String?,
-            exceptions: Array<String>?,
-            next: MethodVisitor?
-    ) : MethodVisitor(OPCODE_VERSION, next) {
-        override fun visitCode() {
-            super.visitCode()
-
-            // First three arguments to HostTestUtils.onNonStubMethodCalled().
-            visitLdcInsn(currentClassName)
-            visitLdcInsn(name)
-            visitLdcInsn(descriptor)
-
-            // Call: HostTestUtils.getStackWalker().getCallerClass().
-            // This push the caller Class in the stack.
-            visitMethodInsn(Opcodes.INVOKESTATIC,
-                    HostTestUtils.CLASS_INTERNAL_NAME,
-                    "getStackWalker",
-                    "()Ljava/lang/StackWalker;",
-                    false)
-            visitMethodInsn(Opcodes.INVOKEVIRTUAL,
-                    "java/lang/StackWalker",
-                    "getCallerClass",
-                    "()Ljava/lang/Class;",
-                    false)
-
-            // Then call onNonStubMethodCalled().
-            visitMethodInsn(Opcodes.INVOKESTATIC,
-                    HostTestUtils.CLASS_INTERNAL_NAME,
-                    "onNonStubMethodCalled",
-                    "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V",
-                    false)
-        }
-    }
-
     private inner class MethodCallReplacingAdapter(
-        access: Int,
         val callerMethodName: String,
-        val descriptor: String,
-        signature: String?,
-        exceptions: Array<String>?,
         next: MethodVisitor?,
     ) : MethodVisitor(OPCODE_VERSION, next) {
         override fun visitMethodInsn(
@@ -497,7 +387,8 @@
                 }
             }
             val to = filter.getMethodCallReplaceTo(
-                currentClassName, callerMethodName, owner!!, name!!, descriptor!!)
+                currentClassName, callerMethodName, owner!!, name!!, descriptor!!
+            )
 
             if (to == null
                 // Don't replace if the target is the callsite.
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt
deleted file mode 100644
index fc20f28..0000000
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2023 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.hoststubgen.visitors
-
-import com.android.hoststubgen.asm.ClassNodes
-import com.android.hoststubgen.filters.FilterPolicy
-import com.android.hoststubgen.filters.FilterPolicyWithReason
-import com.android.hoststubgen.filters.OutputFilter
-import com.android.hoststubgen.log
-import org.objectweb.asm.ClassVisitor
-import org.objectweb.asm.MethodVisitor
-import org.objectweb.asm.Opcodes
-
-/**
- * An adapter that generates the "impl" class file from an input class file.
- */
-class StubGeneratingAdapter(
-        classes: ClassNodes,
-        nextVisitor: ClassVisitor,
-        filter: OutputFilter,
-        options: Options,
-) : BaseAdapter(classes, nextVisitor, filter, options) {
-
-    override fun shouldEmit(policy: FilterPolicy): Boolean {
-        return policy.needsInStub
-    }
-
-    override fun visitMethodInner(
-            access: Int,
-            name: String,
-            descriptor: String,
-            signature: String?,
-            exceptions: Array<String>?,
-            policy: FilterPolicyWithReason,
-            substituted: Boolean,
-            superVisitor: MethodVisitor?,
-    ): MethodVisitor? {
-        return StubMethodVisitor(access, name, descriptor, signature, exceptions, superVisitor)
-    }
-
-    private inner class StubMethodVisitor(
-            access: Int,
-            val name: String,
-            descriptor: String,
-            signature: String?,
-            exceptions: Array<String>?,
-            next: MethodVisitor?
-    ) : BodyReplacingMethodVisitor(access, name, descriptor, signature, exceptions, next) {
-        override fun emitNewCode() {
-            log.d("  Generating stub method for $currentClassName.$name")
-
-            // Inject the following code:
-            //   throw new RuntimeException("Stub!");
-
-            /*
-                NEW java/lang/RuntimeException
-                DUP
-                LDC "not supported on host side"
-                INVOKESPECIAL java/lang/RuntimeException.<init> (Ljava/lang/String;)V
-                ATHROW
-                MAXSTACK = 3
-                MAXLOCALS = 2 <- 1 for this, 1 for return value.
-             */
-            visitTypeInsn(Opcodes.NEW, "java/lang/RuntimeException")
-            visitInsn(Opcodes.DUP)
-            visitLdcInsn("Stub!")
-            visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/RuntimeException",
-                    "<init>", "(Ljava/lang/String;)V", false)
-            visitInsn(Opcodes.ATHROW)
-            visitMaxs(0, 0) // We let ASM figure them out.
-        }
-    }
-}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp b/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp
index e7873d6..ba2c869 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp
@@ -21,7 +21,7 @@
 
 // Create stub/impl jars from "hoststubgen-test-tiny-framework", using the following 3 rules.
 java_genrule_host {
-    name: "hoststubgen-test-tiny-framework-host",
+    name: "hoststubgen-test-tiny-framework-host-base",
     defaults: ["hoststubgen-command-defaults"],
     cmd: hoststubgen_common_options +
         "--in-jar $(location :hoststubgen-test-tiny-framework) " +
@@ -35,25 +35,13 @@
 }
 
 java_genrule_host {
-    name: "hoststubgen-test-tiny-framework-host-stub",
+    name: "hoststubgen-test-tiny-framework-host",
     cmd: "cp $(in) $(out)",
     srcs: [
-        ":hoststubgen-test-tiny-framework-host{host_stub.jar}",
+        ":hoststubgen-test-tiny-framework-host-base{host.jar}",
     ],
     out: [
-        "host_stub.jar",
-    ],
-    visibility: ["//visibility:private"],
-}
-
-java_genrule_host {
-    name: "hoststubgen-test-tiny-framework-host-impl",
-    cmd: "cp $(in) $(out)",
-    srcs: [
-        ":hoststubgen-test-tiny-framework-host{host_impl.jar}",
-    ],
-    out: [
-        "host_impl.jar",
+        "host.jar",
     ],
     visibility: ["//visibility:private"],
 }
@@ -61,7 +49,7 @@
 // Same as "hoststubgen-test-tiny-framework-host", but with more options, to test more hoststubgen
 // features.
 java_genrule_host {
-    name: "hoststubgen-test-tiny-framework-host-ext",
+    name: "hoststubgen-test-tiny-framework-host-ext-base",
     defaults: ["hoststubgen-command-defaults"],
     cmd: hoststubgen_common_options +
         "--in-jar $(location :hoststubgen-test-tiny-framework) " +
@@ -79,37 +67,25 @@
 }
 
 java_genrule_host {
-    name: "hoststubgen-test-tiny-framework-host-ext-stub",
+    name: "hoststubgen-test-tiny-framework-host-ext",
     cmd: "cp $(in) $(out)",
     srcs: [
-        ":hoststubgen-test-tiny-framework-host-ext{host_stub.jar}",
+        ":hoststubgen-test-tiny-framework-host-ext-base{host.jar}",
     ],
     out: [
-        "host_stub.jar",
-    ],
-    visibility: ["//visibility:private"],
-}
-
-java_genrule_host {
-    name: "hoststubgen-test-tiny-framework-host-ext-impl",
-    cmd: "cp $(in) $(out)",
-    srcs: [
-        ":hoststubgen-test-tiny-framework-host-ext{host_impl.jar}",
-    ],
-    out: [
-        "host_impl.jar",
+        "host.jar",
     ],
     visibility: ["//visibility:private"],
 }
 
 // Compile the test jar, using 2 rules.
-// 1. Build the test against the stub.
+// 1. Build the test against the original framework.
 java_library_host {
     name: "hoststubgen-test-tiny-test-lib",
     srcs: ["tiny-test/src/**/*.java"],
 
     libs: [
-        "hoststubgen-test-tiny-framework-host-stub",
+        "hoststubgen-test-tiny-framework",
     ],
     static_libs: [
         "junit",
@@ -129,7 +105,7 @@
     static_libs: [
         "hoststubgen-test-tiny-test-lib",
         "hoststubgen-helper-runtime",
-        "hoststubgen-test-tiny-framework-host-impl",
+        "hoststubgen-test-tiny-framework-host",
     ],
     test_suites: ["general-tests"],
 }
@@ -149,49 +125,25 @@
 }
 
 java_genrule_host {
-    name: "hoststubgen-test-tiny-framework-host-stub-dump",
+    name: "hoststubgen-test-tiny-framework-host-dump",
     defaults: ["hoststubgen-jar-dump-defaults"],
     srcs: [
-        ":hoststubgen-test-tiny-framework-host-stub",
+        ":hoststubgen-test-tiny-framework-host",
     ],
     out: [
-        "02-hoststubgen-test-tiny-framework-host-stub-dump.txt",
+        "03-hoststubgen-test-tiny-framework-host-dump.txt",
     ],
     visibility: ["//visibility:private"],
 }
 
 java_genrule_host {
-    name: "hoststubgen-test-tiny-framework-host-impl-dump",
+    name: "hoststubgen-test-tiny-framework-host-ext-dump",
     defaults: ["hoststubgen-jar-dump-defaults"],
     srcs: [
-        ":hoststubgen-test-tiny-framework-host-impl",
+        ":hoststubgen-test-tiny-framework-host-ext",
     ],
     out: [
-        "03-hoststubgen-test-tiny-framework-host-impl-dump.txt",
-    ],
-    visibility: ["//visibility:private"],
-}
-
-java_genrule_host {
-    name: "hoststubgen-test-tiny-framework-host-ext-stub-dump",
-    defaults: ["hoststubgen-jar-dump-defaults"],
-    srcs: [
-        ":hoststubgen-test-tiny-framework-host-ext-stub",
-    ],
-    out: [
-        "12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt",
-    ],
-    visibility: ["//visibility:private"],
-}
-
-java_genrule_host {
-    name: "hoststubgen-test-tiny-framework-host-ext-impl-dump",
-    defaults: ["hoststubgen-jar-dump-defaults"],
-    srcs: [
-        ":hoststubgen-test-tiny-framework-host-ext-impl",
-    ],
-    out: [
-        "13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt",
+        "13-hoststubgen-test-tiny-framework-host-ext-dump.txt",
     ],
     visibility: ["//visibility:private"],
 }
@@ -206,11 +158,9 @@
         "golden-output/*.txt",
     ],
     java_data: [
-        "hoststubgen-test-tiny-framework-host-stub-dump",
-        "hoststubgen-test-tiny-framework-host-impl-dump",
         "hoststubgen-test-tiny-framework-orig-dump",
-        "hoststubgen-test-tiny-framework-host-ext-stub-dump",
-        "hoststubgen-test-tiny-framework-host-ext-impl-dump",
+        "hoststubgen-test-tiny-framework-host-dump",
+        "hoststubgen-test-tiny-framework-host-ext-dump",
     ],
     test_suites: ["general-tests"],
 }
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
index 845e1d0..5fde14f 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
@@ -104,26 +104,6 @@
     java.lang.annotation.Retention(
       value=Ljava/lang/annotation/RetentionPolicy;.CLASS
     )
-## Class: android/hosttest/annotation/HostSideTestStub.class
-  Compiled from "HostSideTestStub.java"
-public interface android.hosttest.annotation.HostSideTestStub extends java.lang.annotation.Annotation
-  minor version: 0
-  major version: 61
-  flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
-  this_class: #x                          // android/hosttest/annotation/HostSideTestStub
-  super_class: #x                         // java/lang/Object
-  interfaces: 1, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "HostSideTestStub.java"
-RuntimeVisibleAnnotations:
-  x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
-    java.lang.annotation.Target(
-      value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
-    )
-  x: #x(#x=e#x.#x)
-    java.lang.annotation.Retention(
-      value=Ljava/lang/annotation/RetentionPolicy;.CLASS
-    )
 ## Class: android/hosttest/annotation/HostSideTestSubstitute.class
   Compiled from "HostSideTestSubstitute.java"
 public interface android.hosttest.annotation.HostSideTestSubstitute extends java.lang.annotation.Annotation
@@ -187,26 +167,6 @@
     java.lang.annotation.Retention(
       value=Ljava/lang/annotation/RetentionPolicy;.CLASS
     )
-## Class: android/hosttest/annotation/HostSideTestWholeClassStub.class
-  Compiled from "HostSideTestWholeClassStub.java"
-public interface android.hosttest.annotation.HostSideTestWholeClassStub extends java.lang.annotation.Annotation
-  minor version: 0
-  major version: 61
-  flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
-  this_class: #x                          // android/hosttest/annotation/HostSideTestWholeClassStub
-  super_class: #x                         // java/lang/Object
-  interfaces: 1, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "HostSideTestWholeClassStub.java"
-RuntimeVisibleAnnotations:
-  x: #x(#x=[e#x.#x])
-    java.lang.annotation.Target(
-      value=[Ljava/lang/annotation/ElementType;.TYPE]
-    )
-  x: #x(#x=e#x.#x)
-    java.lang.annotation.Retention(
-      value=Ljava/lang/annotation/RetentionPolicy;.CLASS
-    )
 ## Class: android/hosttest/annotation/tests/HostSideTestSuppress.class
   Compiled from "HostSideTestSuppress.java"
 public interface android.hosttest.annotation.tests.HostSideTestSuppress extends java.lang.annotation.Annotation
@@ -402,14 +362,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 3, methods: 10, attributes: 2
-  public int stub;
-    descriptor: I
-    flags: (0x0001) ACC_PUBLIC
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
+  interfaces: 0, fields: 2, methods: 8, attributes: 2
   public int keep;
     descriptor: I
     flags: (0x0001) ACC_PUBLIC
@@ -430,42 +383,21 @@
          x: invokespecial #x                  // Method java/lang/Object."<init>":()V
          x: aload_0
          x: iconst_1
-         x: putfield      #x                  // Field stub:I
-         x: aload_0
-        x: iconst_2
-        x: putfield      #x                 // Field keep:I
-        x: return
+         x: putfield      #x                  // Field keep:I
+         x: return
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-            0      15     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
+            0      10     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public int addOne(int);
     descriptor: (I)I
     flags: (0x0001) ACC_PUBLIC
     Code:
       stack=2, locals=2, args_size=2
-         x: aload_0
-         x: iload_1
-         x: invokevirtual #x                 // Method addOneInner:(I)I
-         x: ireturn
-      LineNumberTable:
-      LocalVariableTable:
-        Start  Length  Slot  Name   Signature
-            0       6     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
-            0       6     1 value   I
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public int addOneInner(int);
-    descriptor: (I)I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=2, locals=2, args_size=2
          x: iload_1
          x: iconst_1
          x: iadd
@@ -513,8 +445,6 @@
             0      10     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
             0      10     1 value   I
     RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
       x: #x(#x=s#x)
         android.hosttest.annotation.HostSideTestSubstitute(
           suffix="_host"
@@ -539,8 +469,6 @@
     descriptor: (I)I
     flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
     RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
       x: #x(#x=s#x)
         android.hosttest.annotation.HostSideTestSubstitute(
           suffix="_host"
@@ -574,129 +502,15 @@
     RuntimeInvisibleAnnotations:
       x: #x()
         android.hosttest.annotation.HostSideTestThrow
-
-  public java.lang.String visibleButUsesUnsupportedMethod();
-    descriptor: ()Ljava/lang/String;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=1, locals=1, args_size=1
-         x: aload_0
-         x: invokevirtual #x                 // Method unsupportedMethod:()Ljava/lang/String;
-         x: areturn
-      LineNumberTable:
-      LocalVariableTable:
-        Start  Length  Slot  Name   Signature
-            0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
 }
 SourceFile: "TinyFrameworkAnnotations.java"
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestStub
+    android.hosttest.annotation.HostSideTestKeep
   x: #x(#x=s#x)
     android.hosttest.annotation.HostSideTestClassLoadHook(
       value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
     )
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class
-  Compiled from "TinyFrameworkCallerCheck.java"
-class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl
-  minor version: 0
-  major version: 61
-  flags: (0x0020) ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 3, attributes: 3
-  private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl();
-    descriptor: ()V
-    flags: (0x0002) ACC_PRIVATE
-    Code:
-      stack=1, locals=1, args_size=1
-         x: aload_0
-         x: invokespecial #x                  // Method java/lang/Object."<init>":()V
-         x: return
-      LineNumberTable:
-      LocalVariableTable:
-        Start  Length  Slot  Name   Signature
-            0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl;
-
-  public static int getOneKeep();
-    descriptor: ()I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=1, locals=0, args_size=0
-         x: iconst_1
-         x: ireturn
-      LineNumberTable:
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestKeep
-
-  public static int getOneStub();
-    descriptor: ()I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=1, locals=0, args_size=0
-         x: iconst_1
-         x: ireturn
-      LineNumberTable:
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-}
-SourceFile: "TinyFrameworkCallerCheck.java"
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-InnerClasses:
-  private static #x= #x of #x;          // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class
-  Compiled from "TinyFrameworkCallerCheck.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                         // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 3, attributes: 4
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=1, locals=1, args_size=1
-         x: aload_0
-         x: invokespecial #x                  // Method java/lang/Object."<init>":()V
-         x: return
-      LineNumberTable:
-      LocalVariableTable:
-        Start  Length  Slot  Name   Signature
-            0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck;
-
-  public static int getOne_withCheck();
-    descriptor: ()I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=1, locals=0, args_size=0
-         x: invokestatic  #x                  // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneKeep:()I
-         x: ireturn
-      LineNumberTable:
-
-  public static int getOne_noCheck();
-    descriptor: ()I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=1, locals=0, args_size=0
-         x: invokestatic  #x                 // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneStub:()I
-         x: ireturn
-      LineNumberTable:
-}
-SourceFile: "TinyFrameworkCallerCheck.java"
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
-NestMembers:
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
-InnerClasses:
-  private static #x= #x of #x;          // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class
   Compiled from "TinyFrameworkClassLoadHook.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook
@@ -758,7 +572,7 @@
 SourceFile: "TinyFrameworkClassLoadHook.java"
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations.class
   Compiled from "TinyFrameworkClassWideAnnotations.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations
@@ -767,11 +581,18 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 6, attributes: 2
-  public int stub;
+  interfaces: 0, fields: 2, methods: 6, attributes: 2
+  public int keep;
     descriptor: I
     flags: (0x0001) ACC_PUBLIC
 
+  public int remove;
+    descriptor: I
+    flags: (0x0001) ACC_PUBLIC
+    RuntimeInvisibleAnnotations:
+      x: #x()
+        android.hosttest.annotation.HostSideTestRemove
+
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations();
     descriptor: ()V
     flags: (0x0001) ACC_PUBLIC
@@ -781,7 +602,7 @@
          x: invokespecial #x                  // Method java/lang/Object."<init>":()V
          x: aload_0
          x: iconst_1
-         x: putfield      #x                  // Field stub:I
+         x: putfield      #x                  // Field keep:I
          x: return
       LineNumberTable:
       LocalVariableTable:
@@ -839,6 +660,24 @@
             0       4     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations;
             0       4     1 value   I
 
+  public void toBeRemoved(java.lang.String);
+    descriptor: (Ljava/lang/String;)V
+    flags: (0x0001) ACC_PUBLIC
+    Code:
+      stack=2, locals=2, args_size=2
+         x: new           #x                 // class java/lang/RuntimeException
+         x: dup
+         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":()V
+         x: athrow
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+            0       8     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations;
+            0       8     1   foo   Ljava/lang/String;
+    RuntimeInvisibleAnnotations:
+      x: #x()
+        android.hosttest.annotation.HostSideTestRemove
+
   public java.lang.String unsupportedMethod();
     descriptor: ()Ljava/lang/String;
     flags: (0x0001) ACC_PUBLIC
@@ -853,24 +692,11 @@
     RuntimeInvisibleAnnotations:
       x: #x()
         android.hosttest.annotation.HostSideTestThrow
-
-  public java.lang.String visibleButUsesUnsupportedMethod();
-    descriptor: ()Ljava/lang/String;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=1, locals=1, args_size=1
-         x: aload_0
-         x: invokevirtual #x                 // Method unsupportedMethod:()Ljava/lang/String;
-         x: areturn
-      LineNumberTable:
-      LocalVariableTable:
-        Start  Length  Slot  Name   Signature
-            0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations;
 }
 SourceFile: "TinyFrameworkClassWideAnnotations.java"
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.class
   Compiled from "TinyFrameworkClassWithInitializerDefault.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerDefault
@@ -885,14 +711,14 @@
     flags: (0x0009) ACC_PUBLIC, ACC_STATIC
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static java.lang.Object sObject;
     descriptor: Ljava/lang/Object;
     flags: (0x0009) ACC_PUBLIC, ACC_STATIC
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerDefault();
     descriptor: ()V
@@ -924,7 +750,7 @@
 SourceFile: "TinyFrameworkClassWithInitializerDefault.java"
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestStub
+    android.hosttest.annotation.HostSideTestKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.class
   Compiled from "TinyFrameworkClassWithInitializerStub.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerStub
@@ -939,14 +765,14 @@
     flags: (0x0009) ACC_PUBLIC, ACC_STATIC
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static java.lang.Object sObject;
     descriptor: Ljava/lang/Object;
     flags: (0x0009) ACC_PUBLIC, ACC_STATIC
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerStub();
     descriptor: ()V
@@ -982,7 +808,7 @@
       value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
     )
   x: #x()
-    android.hosttest.annotation.HostSideTestStub
+    android.hosttest.annotation.HostSideTestKeep
   x: #x()
     android.hosttest.annotation.HostSideTestStaticInitializerKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.class
@@ -999,21 +825,21 @@
     flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex GREEN;
     descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
     flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex BLUE;
     descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
     flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   private final java.lang.String mLongName;
     descriptor: Ljava/lang/String;
@@ -1093,7 +919,7 @@
     Signature: #x                          // (Ljava/lang/String;Ljava/lang/String;)V
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public java.lang.String getLongName();
     descriptor: ()Ljava/lang/String;
@@ -1109,7 +935,7 @@
             0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public java.lang.String getShortName();
     descriptor: ()Ljava/lang/String;
@@ -1125,7 +951,7 @@
             0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $values();
     descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
@@ -1187,7 +1013,7 @@
 SourceFile: "TinyFrameworkEnumComplex.java"
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestStub
+    android.hosttest.annotation.HostSideTestKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.class
   Compiled from "TinyFrameworkEnumSimple.java"
 public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple>
@@ -1202,14 +1028,14 @@
     flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple DOG;
     descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
     flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $VALUES;
     descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
@@ -1308,7 +1134,7 @@
 SourceFile: "TinyFrameworkEnumSimple.java"
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestStub
+    android.hosttest.annotation.HostSideTestKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class
   Compiled from "TinyFrameworkExceptionTester.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester
@@ -1362,7 +1188,7 @@
 SourceFile: "TinyFrameworkExceptionTester.java"
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class
   Compiled from "TinyFrameworkForTextPolicy.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy
@@ -1371,15 +1197,11 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 3, methods: 19, attributes: 1
+  interfaces: 0, fields: 2, methods: 17, attributes: 1
   public int stub;
     descriptor: I
     flags: (0x0001) ACC_PUBLIC
 
-  public int keep;
-    descriptor: I
-    flags: (0x0001) ACC_PUBLIC
-
   public int remove;
     descriptor: I
     flags: (0x0001) ACC_PUBLIC
@@ -1394,35 +1216,17 @@
          x: aload_0
          x: iconst_1
          x: putfield      #x                  // Field stub:I
-         x: aload_0
-        x: iconst_2
-        x: putfield      #x                 // Field keep:I
-        x: return
+         x: return
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-            0      15     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+            0      10     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
 
   public int addOne(int);
     descriptor: (I)I
     flags: (0x0001) ACC_PUBLIC
     Code:
       stack=2, locals=2, args_size=2
-         x: aload_0
-         x: iload_1
-         x: invokevirtual #x                 // Method addOneInner:(I)I
-         x: ireturn
-      LineNumberTable:
-      LocalVariableTable:
-        Start  Length  Slot  Name   Signature
-            0       6     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
-            0       6     1 value   I
-
-  public int addOneInner(int);
-    descriptor: (I)I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=2, locals=2, args_size=2
          x: iload_1
          x: iconst_1
          x: iadd
@@ -1634,19 +1438,6 @@
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
             0       3     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
-
-  public java.lang.String visibleButUsesUnsupportedMethod();
-    descriptor: ()Ljava/lang/String;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=1, locals=1, args_size=1
-         x: aload_0
-         x: invokevirtual #x                 // Method unsupportedMethod:()Ljava/lang/String;
-         x: areturn
-      LineNumberTable:
-      LocalVariableTable:
-        Start  Length  Slot  Name   Signature
-            0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
 }
 SourceFile: "TinyFrameworkForTextPolicy.java"
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.class
@@ -1664,7 +1455,7 @@
     Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
     descriptor: Ljava/util/function/Supplier;
@@ -1672,7 +1463,7 @@
     Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested();
     descriptor: ()V
@@ -1691,7 +1482,7 @@
             0      14     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested;
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public java.util.function.Supplier<java.lang.Integer> getSupplier();
     descriptor: ()Ljava/util/function/Supplier;
@@ -1707,7 +1498,7 @@
     Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
     descriptor: ()Ljava/util/function/Supplier;
@@ -1720,7 +1511,7 @@
     Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   private static java.lang.Integer lambda$getSupplier_static$3();
     descriptor: ()Ljava/lang/Integer;
@@ -1775,7 +1566,7 @@
 SourceFile: "TinyFrameworkLambdas.java"
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestStub
+    android.hosttest.annotation.HostSideTestKeep
   x: #x()
     android.hosttest.annotation.HostSideTestStaticInitializerKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
@@ -1818,7 +1609,7 @@
     Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
     descriptor: Ljava/util/function/Supplier;
@@ -1826,7 +1617,7 @@
     Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas();
     descriptor: ()V
@@ -1845,7 +1636,7 @@
             0      14     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas;
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public java.util.function.Supplier<java.lang.Integer> getSupplier();
     descriptor: ()Ljava/util/function/Supplier;
@@ -1861,7 +1652,7 @@
     Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
     descriptor: ()Ljava/util/function/Supplier;
@@ -1874,7 +1665,7 @@
     Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   private static java.lang.Integer lambda$getSupplier_static$3();
     descriptor: ()Ljava/lang/Integer;
@@ -1929,7 +1720,7 @@
 SourceFile: "TinyFrameworkLambdas.java"
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestStub
+    android.hosttest.annotation.HostSideTestKeep
   x: #x()
     android.hosttest.annotation.HostSideTestStaticInitializerKeep
 NestMembers:
@@ -2114,7 +1905,7 @@
 SourceFile: "TinyFrameworkMethodCallReplace.java"
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 NestMembers:
   com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
 BootstrapMethods:
@@ -2134,7 +1925,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                         // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 11, attributes: 2
+  interfaces: 0, fields: 1, methods: 12, attributes: 2
   int value;
     descriptor: I
     flags: (0x0000)
@@ -2229,6 +2020,13 @@
       x: #x()
         android.hosttest.annotation.HostSideTestThrow
 
+  public static native void nativeStillKeep();
+    descriptor: ()V
+    flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+    RuntimeInvisibleAnnotations:
+      x: #x()
+        android.hosttest.annotation.HostSideTestKeep
+
   public static void nativeStillNotSupported_should_be_like_this();
     descriptor: ()V
     flags: (0x0009) ACC_PUBLIC, ACC_STATIC
@@ -2247,7 +2045,7 @@
 SourceFile: "TinyFrameworkNative.java"
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
   x: #x(#x=s#x)
     android.hosttest.annotation.HostSideTestNativeSubstitutionClass(
       value="TinyFrameworkNative_host"
@@ -2901,7 +2699,7 @@
 SourceFile: "TinyFrameworkNestedClasses.java"
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 NestMembers:
   com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
   com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
@@ -2965,7 +2763,7 @@
 SourceFile: "TinyFrameworkPackageRedirect.java"
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.class
   Compiled from "TinyFrameworkRenamedClassCaller.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller
@@ -3007,7 +2805,7 @@
 SourceFile: "TinyFrameworkRenamedClassCaller.java"
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.class
   Compiled from "TinyFrameworkToBeRenamed.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed
@@ -3054,7 +2852,7 @@
 SourceFile: "TinyFrameworkToBeRenamed.java"
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 ## Class: com/android/hoststubgen/test/tinyframework/packagetest/A.class
   Compiled from "A.java"
 public class com.android.hoststubgen.test.tinyframework.packagetest.A
@@ -3800,4 +3598,4 @@
 SourceFile: "UnsupportedClass.java"
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt
deleted file mode 100644
index 86a9c65..0000000
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt
+++ /dev/null
@@ -1,2788 +0,0 @@
-## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy.class
-  Compiled from "IPretendingAidl.java"
-public class com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub$Proxy
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 2, attributes: 4
-  public com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub$Proxy();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int addTwo(int);
-    descriptor: (I)I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;           // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl
-  public static #x= #x of #x;           // Proxy=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy of class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
-SourceFile: "IPretendingAidl.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/IPretendingAidl
-## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub.class
-  Compiled from "IPretendingAidl.java"
-public class com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 2, attributes: 4
-  public com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int addOne(int);
-    descriptor: (I)I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;            // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl
-  public static #x= #x of #x;           // Proxy=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy of class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
-SourceFile: "IPretendingAidl.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/IPretendingAidl
-## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl.class
-  Compiled from "IPretendingAidl.java"
-public interface com.android.hoststubgen.test.tinyframework.IPretendingAidl
-  minor version: 0
-  major version: 61
-  flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/IPretendingAidl
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 0, attributes: 4
-}
-InnerClasses:
-  public static #x= #x of #x;            // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl
-  public static #x= #x of #x;           // Proxy=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy of class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
-SourceFile: "IPretendingAidl.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestMembers:
-  com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
-  com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy
-## Class: com/android/hoststubgen/test/tinyframework/R$Nested.class
-  Compiled from "R.java"
-public class com.android.hoststubgen.test.tinyframework.R$Nested
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/R$Nested
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 2, attributes: 4
-  public static int[] ARRAY;
-    descriptor: [I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public com.android.hoststubgen.test.tinyframework.R$Nested();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  static {};
-    descriptor: ()V
-    flags: (0x0008) ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;            // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R
-SourceFile: "R.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/R
-## Class: com/android/hoststubgen/test/tinyframework/R.class
-  Compiled from "R.java"
-public class com.android.hoststubgen.test.tinyframework.R
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/R
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 1, attributes: 4
-  public com.android.hoststubgen.test.tinyframework.R();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;            // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R
-SourceFile: "R.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestMembers:
-  com/android/hoststubgen/test/tinyframework/R$Nested
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.class
-  Compiled from "TinyFrameworkAnnotations.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 5, attributes: 3
-  public int stub;
-    descriptor: I
-    flags: (0x0001) ACC_PUBLIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public int addOne(int);
-    descriptor: (I)I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public int addTwo(int);
-    descriptor: (I)I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int nativeAddThree(int);
-    descriptor: (I)I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public java.lang.String visibleButUsesUnsupportedMethod();
-    descriptor: ()Ljava/lang/String;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-}
-SourceFile: "TinyFrameworkAnnotations.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestStub
-  x: #x(#x=s#x)
-    android.hosttest.annotation.HostSideTestClassLoadHook(
-      value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
-    )
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class
-  Compiled from "TinyFrameworkCallerCheck.java"
-class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl
-  minor version: 0
-  major version: 61
-  flags: (0x0020) ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 2, attributes: 4
-  private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl();
-    descriptor: ()V
-    flags: (0x0002) ACC_PRIVATE
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int getOneStub();
-    descriptor: ()I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-}
-InnerClasses:
-  private static #x= #x of #x;           // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-SourceFile: "TinyFrameworkCallerCheck.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class
-  Compiled from "TinyFrameworkCallerCheck.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 3, attributes: 5
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int getOne_withCheck();
-    descriptor: ()I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int getOne_noCheck();
-    descriptor: ()I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  private static #x= #x of #x;          // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-SourceFile: "TinyFrameworkCallerCheck.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
-NestMembers:
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class
-  Compiled from "TinyFrameworkClassLoadHook.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 3, attributes: 3
-  public static final java.util.Set<java.lang.Class<?>> sLoadedClasses;
-    descriptor: Ljava/util/Set;
-    flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
-    Signature: #x                          // Ljava/util/Set<Ljava/lang/Class<*>;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook();
-    descriptor: ()V
-    flags: (0x0002) ACC_PRIVATE
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static void onClassLoaded(java.lang.Class<?>);
-    descriptor: (Ljava/lang/Class;)V
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    Signature: #x                          // (Ljava/lang/Class<*>;)V
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  static {};
-    descriptor: ()V
-    flags: (0x0008) ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkClassLoadHook.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations.class
-  Compiled from "TinyFrameworkClassWideAnnotations.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 4, attributes: 3
-  public int stub;
-    descriptor: I
-    flags: (0x0001) ACC_PUBLIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public int addOne(int);
-    descriptor: (I)I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public int addTwo(int);
-    descriptor: (I)I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public java.lang.String visibleButUsesUnsupportedMethod();
-    descriptor: ()Ljava/lang/String;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkClassWideAnnotations.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.class
-  Compiled from "TinyFrameworkClassWithInitializerDefault.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerDefault
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 2, methods: 0, attributes: 3
-  public static boolean sInitialized;
-    descriptor: Z
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public static java.lang.Object sObject;
-    descriptor: Ljava/lang/Object;
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-}
-SourceFile: "TinyFrameworkClassWithInitializerDefault.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.class
-  Compiled from "TinyFrameworkClassWithInitializerStub.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerStub
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 2, methods: 0, attributes: 3
-  public static boolean sInitialized;
-    descriptor: Z
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public static java.lang.Object sObject;
-    descriptor: Ljava/lang/Object;
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-}
-SourceFile: "TinyFrameworkClassWithInitializerStub.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x(#x=s#x)
-    android.hosttest.annotation.HostSideTestClassLoadHook(
-      value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
-    )
-  x: #x()
-    android.hosttest.annotation.HostSideTestStub
-  x: #x()
-    android.hosttest.annotation.HostSideTestStaticInitializerKeep
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.class
-  Compiled from "TinyFrameworkEnumComplex.java"
-public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex>
-  minor version: 0
-  major version: 61
-  flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex
-  super_class: #x                         // java/lang/Enum
-  interfaces: 0, fields: 4, methods: 7, attributes: 4
-  public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex RED;
-    descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
-    flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex GREEN;
-    descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
-    flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex BLUE;
-    descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
-    flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $VALUES;
-    descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
-    flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] values();
-    descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex valueOf(java.lang.String);
-    descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    MethodParameters:
-      Name                           Flags
-      <no name>                      mandated
-
-  private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex(java.lang.String, java.lang.String);
-    descriptor: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V
-    flags: (0x0002) ACC_PRIVATE
-    Code:
-      stack=3, locals=5, args_size=5
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    Signature: #x                          // (Ljava/lang/String;Ljava/lang/String;)V
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-    MethodParameters:
-      Name                           Flags
-      <no name>                      synthetic
-      <no name>                      synthetic
-      <no name>
-      <no name>
-
-  public java.lang.String getLongName();
-    descriptor: ()Ljava/lang/String;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public java.lang.String getShortName();
-    descriptor: ()Ljava/lang/String;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $values();
-    descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
-    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  static {};
-    descriptor: ()V
-    flags: (0x0008) ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-Signature: #x                           // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;>;
-SourceFile: "TinyFrameworkEnumComplex.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.class
-  Compiled from "TinyFrameworkEnumSimple.java"
-public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple>
-  minor version: 0
-  major version: 61
-  flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple
-  super_class: #x                         // java/lang/Enum
-  interfaces: 0, fields: 3, methods: 5, attributes: 4
-  public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple CAT;
-    descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
-    flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple DOG;
-    descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
-    flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $VALUES;
-    descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
-    flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] values();
-    descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple valueOf(java.lang.String);
-    descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    MethodParameters:
-      Name                           Flags
-      <no name>                      mandated
-
-  private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple();
-    descriptor: (Ljava/lang/String;I)V
-    flags: (0x0002) ACC_PRIVATE
-    Code:
-      stack=3, locals=3, args_size=3
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    Signature: #x                          // ()V
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    MethodParameters:
-      Name                           Flags
-      <no name>                      synthetic
-      <no name>                      synthetic
-
-  private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $values();
-    descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
-    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  static {};
-    descriptor: ()V
-    flags: (0x0008) ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-Signature: #x                           // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;>;
-SourceFile: "TinyFrameworkEnumSimple.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class
-  Compiled from "TinyFrameworkExceptionTester.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 2, attributes: 3
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int testException();
-    descriptor: ()I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkExceptionTester.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class
-  Compiled from "TinyFrameworkForTextPolicy.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 14, attributes: 2
-  public int stub;
-    descriptor: I
-    flags: (0x0001) ACC_PUBLIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public int addOne(int);
-    descriptor: (I)I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public java.lang.String toBeIgnoredObj();
-    descriptor: ()Ljava/lang/String;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public void toBeIgnoredV();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public boolean toBeIgnoredZ();
-    descriptor: ()Z
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public byte toBeIgnoredB();
-    descriptor: ()B
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public char toBeIgnoredC();
-    descriptor: ()C
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public short toBeIgnoredS();
-    descriptor: ()S
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public int toBeIgnoredI();
-    descriptor: ()I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public float toBeIgnoredF();
-    descriptor: ()F
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public double toBeIgnoredD();
-    descriptor: ()D
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public int addTwo(int);
-    descriptor: (I)I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int nativeAddThree(int);
-    descriptor: (I)I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public java.lang.String visibleButUsesUnsupportedMethod();
-    descriptor: ()Ljava/lang/String;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkForTextPolicy.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.class
-  Compiled from "TinyFrameworkLambdas.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 2, methods: 7, attributes: 5
-  public final java.util.function.Supplier<java.lang.Integer> mSupplier;
-    descriptor: Ljava/util/function/Supplier;
-    flags: (0x0011) ACC_PUBLIC, ACC_FINAL
-    Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
-    descriptor: Ljava/util/function/Supplier;
-    flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
-    Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public java.util.function.Supplier<java.lang.Integer> getSupplier();
-    descriptor: ()Ljava/util/function/Supplier;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
-    descriptor: ()Ljava/util/function/Supplier;
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  private static java.lang.Integer lambda$getSupplier_static$3();
-    descriptor: ()Ljava/lang/Integer;
-    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  private static java.lang.Integer lambda$getSupplier$2();
-    descriptor: ()Ljava/lang/Integer;
-    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  private static java.lang.Integer lambda$static$1();
-    descriptor: ()Ljava/lang/Integer;
-    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  private static java.lang.Integer lambda$new$0();
-    descriptor: ()Ljava/lang/Integer;
-    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;            // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
-  public static final #x= #x of #x;    // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
-SourceFile: "TinyFrameworkLambdas.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestStub
-  x: #x()
-    android.hosttest.annotation.HostSideTestStaticInitializerKeep
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.class
-  Compiled from "TinyFrameworkLambdas.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 2, methods: 7, attributes: 5
-  public final java.util.function.Supplier<java.lang.Integer> mSupplier;
-    descriptor: Ljava/util/function/Supplier;
-    flags: (0x0011) ACC_PUBLIC, ACC_FINAL
-    Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
-    descriptor: Ljava/util/function/Supplier;
-    flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
-    Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public java.util.function.Supplier<java.lang.Integer> getSupplier();
-    descriptor: ()Ljava/util/function/Supplier;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
-    descriptor: ()Ljava/util/function/Supplier;
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  private static java.lang.Integer lambda$getSupplier_static$3();
-    descriptor: ()Ljava/lang/Integer;
-    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  private static java.lang.Integer lambda$getSupplier$2();
-    descriptor: ()Ljava/lang/Integer;
-    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  private static java.lang.Integer lambda$static$1();
-    descriptor: ()Ljava/lang/Integer;
-    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  private static java.lang.Integer lambda$new$0();
-    descriptor: ()Ljava/lang/Integer;
-    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;           // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
-  public static final #x= #x of #x;    // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
-SourceFile: "TinyFrameworkLambdas.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestStub
-  x: #x()
-    android.hosttest.annotation.HostSideTestStaticInitializerKeep
-NestMembers:
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class
-  Compiled from "TinyFrameworkMethodCallReplace.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 3, attributes: 4
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static void startThread(java.lang.Thread);
-    descriptor: (Ljava/lang/Thread;)V
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int add(int, int);
-    descriptor: (II)I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;            // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
-SourceFile: "TinyFrameworkMethodCallReplace.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.class
-  Compiled from "TinyFrameworkMethodCallReplace.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 4, attributes: 5
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static boolean nonStaticMethodCallReplaceTester() throws java.lang.Exception;
-    descriptor: ()Z
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    Exceptions:
-      throws java.lang.Exception
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int staticMethodCallReplaceTester();
-    descriptor: ()I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean);
-    descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V
-    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;           // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
-  public static final #x= #x of #x;    // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
-SourceFile: "TinyFrameworkMethodCallReplace.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
-NestMembers:
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
-  Compiled from "TinyFrameworkNative.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 10, attributes: 3
-  int value;
-    descriptor: I
-    flags: (0x0000)
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static native int nativeAddTwo(int);
-    descriptor: (I)I
-    flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int nativeAddTwo_should_be_like_this(int);
-    descriptor: (I)I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static native long nativeLongPlus(long, long);
-    descriptor: (JJ)J
-    flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static long nativeLongPlus_should_be_like_this(long, long);
-    descriptor: (JJ)J
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=4, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public void setValue(int);
-    descriptor: (I)V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public native int nativeNonStaticAddToValue(int);
-    descriptor: (I)I
-    flags: (0x0101) ACC_PUBLIC, ACC_NATIVE
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public int nativeNonStaticAddToValue_should_be_like_this(int);
-    descriptor: (I)I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static void nativeStillNotSupported_should_be_like_this();
-    descriptor: ()V
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static native byte nativeBytePlus(byte, byte);
-    descriptor: (BB)B
-    flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkNative.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
-  x: #x(#x=s#x)
-    android.hosttest.annotation.HostSideTestNativeSubstitutionClass(
-      value="TinyFrameworkNative_host"
-    )
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class
-  Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 1, attributes: 4
-  public int value;
-    descriptor: I
-    flags: (0x0001) ACC_PUBLIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass(int);
-    descriptor: (I)V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;            // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass.class
-  Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 2, methods: 1, attributes: 4
-  public int value;
-    descriptor: I
-    flags: (0x0001) ACC_PUBLIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
-    descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
-    flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
-    descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    MethodParameters:
-      Name                           Flags
-      <no name>                      final mandated
-}
-InnerClasses:
-  public #x= #x of #x;                   // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass.class
-  Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 1, attributes: 4
-  public int value;
-    descriptor: I
-    flags: (0x0001) ACC_PUBLIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;           // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-  public static #x= #x of #x;           // Double$NestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass.class
-  Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 2, attributes: 4
-  public int value;
-    descriptor: I
-    flags: (0x0001) ACC_PUBLIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
-    descriptor: ()Ljava/util/function/Supplier;
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;            // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-  #x;                                    // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
-  public static #x= #x of #x;           // Double$NestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass.class
-  Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass extends com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
-  super_class: #x                         // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
-  interfaces: 0, fields: 0, methods: 1, attributes: 4
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass(int);
-    descriptor: (I)V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;            // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-  public static #x= #x of #x;            // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.class
-  Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 2, methods: 4, attributes: 5
-  public final java.util.function.Supplier<java.lang.Integer> mSupplier;
-    descriptor: Ljava/util/function/Supplier;
-    flags: (0x0011) ACC_PUBLIC, ACC_FINAL
-    Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
-    descriptor: Ljava/util/function/Supplier;
-    flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
-    Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public java.util.function.Supplier<java.lang.Integer> getSupplier();
-    descriptor: ()Ljava/util/function/Supplier;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
-    descriptor: ()Ljava/util/function/Supplier;
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  static {};
-    descriptor: ()V
-    flags: (0x0008) ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  #x;                                    // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
-  #x;                                    // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
-  #x;                                    // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
-  #x;                                    // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
-  public static #x= #x of #x;           // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-  public static #x= #x of #x;           // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-  public static #x= #x of #x;           // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-  public #x= #x of #x;                  // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-  public static #x= #x of #x;          // Double$NestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
-  #x;                                    // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
-NestMembers:
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect.class
-  Compiled from "TinyFrameworkPackageRedirect.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 2, attributes: 3
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int foo(int);
-    descriptor: (I)I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkPackageRedirect.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.class
-  Compiled from "TinyFrameworkRenamedClassCaller.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 2, attributes: 3
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int foo(int);
-    descriptor: (I)I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkRenamedClassCaller.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: com/android/hoststubgen/test/tinyframework/packagetest/A.class
-  Compiled from "A.java"
-public class com.android.hoststubgen.test.tinyframework.packagetest.A
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/packagetest/A
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "A.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/packagetest/sub/A.class
-  Compiled from "A.java"
-public class com.android.hoststubgen.test.tinyframework.packagetest.sub.A
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/packagetest/sub/A
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "A.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C1.class
-  Compiled from "C1.java"
-public class com.android.hoststubgen.test.tinyframework.subclasstest.C1
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/subclasstest/C1
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "C1.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C2.class
-  Compiled from "C2.java"
-public class com.android.hoststubgen.test.tinyframework.subclasstest.C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/subclasstest/C2
-  super_class: #x                         // com/android/hoststubgen/test/tinyframework/subclasstest/C1
-  interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "C2.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C3.class
-  Compiled from "C3.java"
-public class com.android.hoststubgen.test.tinyframework.subclasstest.C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/subclasstest/C3
-  super_class: #x                         // com/android/hoststubgen/test/tinyframework/subclasstest/C2
-  interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "C3.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CA.class
-  Compiled from "CA.java"
-public class com.android.hoststubgen.test.tinyframework.subclasstest.CA
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/subclasstest/CA
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "CA.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CB.class
-  Compiled from "CB.java"
-public class com.android.hoststubgen.test.tinyframework.subclasstest.CB
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/subclasstest/CB
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "CB.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I1.class
-  Compiled from "I1.java"
-public interface com.android.hoststubgen.test.tinyframework.subclasstest.I1
-  minor version: 0
-  major version: 61
-  flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/subclasstest/I1
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "I1.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I2.class
-  Compiled from "I2.java"
-public interface com.android.hoststubgen.test.tinyframework.subclasstest.I2 extends com.android.hoststubgen.test.tinyframework.subclasstest.I1
-  minor version: 0
-  major version: 61
-  flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/subclasstest/I2
-  super_class: #x                         // java/lang/Object
-  interfaces: 1, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "I2.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I3.class
-  Compiled from "I3.java"
-public interface com.android.hoststubgen.test.tinyframework.subclasstest.I3 extends com.android.hoststubgen.test.tinyframework.subclasstest.I2
-  minor version: 0
-  major version: 61
-  flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/subclasstest/I3
-  super_class: #x                         // java/lang/Object
-  interfaces: 1, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "I3.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IA.class
-  Compiled from "IA.java"
-public interface com.android.hoststubgen.test.tinyframework.subclasstest.IA
-  minor version: 0
-  major version: 61
-  flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/subclasstest/IA
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "IA.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IB.class
-  Compiled from "IB.java"
-public interface com.android.hoststubgen.test.tinyframework.subclasstest.IB
-  minor version: 0
-  major version: 61
-  flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/subclasstest/IB
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "IB.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/unsupported/UnsupportedClass.class
-  Compiled from "UnsupportedClass.java"
-public class com.unsupported.UnsupportedClass
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/unsupported/UnsupportedClass
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 2, attributes: 3
-  public com.unsupported.UnsupportedClass(int);
-    descriptor: (I)V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public int getValue();
-    descriptor: ()I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "UnsupportedClass.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.class
-  Compiled from "TinyFrameworkToBeRenamed.java"
-public class rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 2, attributes: 3
-  private final int mValue;
-    descriptor: I
-    flags: (0x0012) ACC_PRIVATE, ACC_FINAL
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed(int);
-    descriptor: (I)V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public int getValue();
-    descriptor: ()I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkToBeRenamed.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-dump.txt
similarity index 68%
rename from tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt
rename to tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-dump.txt
index c6b9c7a..e41d46d 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-dump.txt
@@ -12,12 +12,12 @@
     flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "HostSideTestClassLoadHook.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
   x: #x(#x=[e#x.#x])
     java.lang.annotation.Target(
       value=[Ljava/lang/annotation/ElementType;.TYPE]
@@ -39,7 +39,7 @@
 SourceFile: "HostSideTestKeep.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
   x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
     java.lang.annotation.Target(
       value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
@@ -62,12 +62,12 @@
     flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "HostSideTestNativeSubstitutionClass.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
   x: #x(#x=[e#x.#x])
     java.lang.annotation.Target(
       value=[Ljava/lang/annotation/ElementType;.TYPE]
@@ -89,7 +89,7 @@
 SourceFile: "HostSideTestRemove.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
   x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
     java.lang.annotation.Target(
       value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
@@ -98,20 +98,20 @@
     java.lang.annotation.Retention(
       value=Ljava/lang/annotation/RetentionPolicy;.CLASS
     )
-## Class: android/hosttest/annotation/HostSideTestStub.class
-  Compiled from "HostSideTestStub.java"
-public interface android.hosttest.annotation.HostSideTestStub extends java.lang.annotation.Annotation
+## Class: android/hosttest/annotation/HostSideTestStaticInitializerKeep.class
+  Compiled from "HostSideTestStaticInitializerKeep.java"
+public interface android.hosttest.annotation.HostSideTestStaticInitializerKeep extends java.lang.annotation.Annotation
   minor version: 0
   major version: 61
   flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
-  this_class: #x                          // android/hosttest/annotation/HostSideTestStub
+  this_class: #x                          // android/hosttest/annotation/HostSideTestStaticInitializerKeep
   super_class: #x                         // java/lang/Object
   interfaces: 1, fields: 0, methods: 0, attributes: 2
 }
-SourceFile: "HostSideTestStub.java"
+SourceFile: "HostSideTestStaticInitializerKeep.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
   x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
     java.lang.annotation.Target(
       value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
@@ -134,12 +134,12 @@
     flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "HostSideTestSubstitute.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
   x: #x(#x=[e#x.#x])
     java.lang.annotation.Target(
       value=[Ljava/lang/annotation/ElementType;.METHOD]
@@ -161,7 +161,7 @@
 SourceFile: "HostSideTestThrow.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
   x: #x(#x=[e#x.#x,e#x.#x])
     java.lang.annotation.Target(
       value=[Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
@@ -183,29 +183,7 @@
 SourceFile: "HostSideTestWholeClassKeep.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-  x: #x(#x=[e#x.#x])
-    java.lang.annotation.Target(
-      value=[Ljava/lang/annotation/ElementType;.TYPE]
-    )
-  x: #x(#x=e#x.#x)
-    java.lang.annotation.Retention(
-      value=Ljava/lang/annotation/RetentionPolicy;.CLASS
-    )
-## Class: android/hosttest/annotation/HostSideTestWholeClassStub.class
-  Compiled from "HostSideTestWholeClassStub.java"
-public interface android.hosttest.annotation.HostSideTestWholeClassStub extends java.lang.annotation.Annotation
-  minor version: 0
-  major version: 61
-  flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
-  this_class: #x                          // android/hosttest/annotation/HostSideTestWholeClassStub
-  super_class: #x                         // java/lang/Object
-  interfaces: 1, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "HostSideTestWholeClassStub.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
   x: #x(#x=[e#x.#x])
     java.lang.annotation.Target(
       value=[Ljava/lang/annotation/ElementType;.TYPE]
@@ -237,9 +215,7 @@
             0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int addTwo(int);
     descriptor: (I)I
@@ -256,9 +232,7 @@
             0       4     0     a   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   public static #x= #x of #x;           // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl
@@ -266,9 +240,7 @@
 SourceFile: "IPretendingAidl.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/IPretendingAidl
 ## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub.class
   Compiled from "IPretendingAidl.java"
@@ -293,9 +265,7 @@
             0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int addOne(int);
     descriptor: (I)I
@@ -312,19 +282,15 @@
             0       4     0     a   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
-  public static #x= #x of #x;            // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl
+  public static #x= #x of #x;             // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl
   public static #x= #x of #x;           // Proxy=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy of class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
 SourceFile: "IPretendingAidl.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/IPretendingAidl
 ## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl.class
   Compiled from "IPretendingAidl.java"
@@ -342,9 +308,7 @@
 SourceFile: "IPretendingAidl.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestMembers:
   com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
   com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy
@@ -362,9 +326,7 @@
     flags: (0x0009) ACC_PUBLIC, ACC_STATIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public com.android.hoststubgen.test.tinyframework.R$Nested();
     descriptor: ()V
@@ -380,9 +342,7 @@
             0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/R$Nested;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   static {};
     descriptor: ()V
@@ -400,18 +360,14 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
-  public static #x= #x of #x;            // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R
+  public static #x= #x of #x;             // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R
 SourceFile: "R.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/R
 ## Class: com/android/hoststubgen/test/tinyframework/R.class
   Compiled from "R.java"
@@ -436,18 +392,14 @@
             0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/R;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
-  public static #x= #x of #x;            // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R
+  public static #x= #x of #x;             // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R
 SourceFile: "R.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestMembers:
   com/android/hoststubgen/test/tinyframework/R$Nested
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.class
@@ -458,25 +410,13 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 2, methods: 8, attributes: 3
-  public int stub;
-    descriptor: I
-    flags: (0x0001) ACC_PUBLIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
+  interfaces: 0, fields: 1, methods: 6, attributes: 3
   public int keep;
     descriptor: I
     flags: (0x0001) ACC_PUBLIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
         android.hosttest.annotation.HostSideTestKeep
@@ -487,7 +427,7 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
-         x: ldc           #x                 // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 
@@ -500,70 +440,36 @@
          x: invokespecial #x                 // Method java/lang/Object."<init>":()V
          x: aload_0
          x: iconst_1
-         x: putfield      #x                 // Field stub:I
-         x: aload_0
-        x: iconst_2
-        x: putfield      #x                 // Field keep:I
-        x: return
+         x: putfield      #x                 // Field keep:I
+         x: return
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-            0      15     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
+            0      10     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public int addOne(int);
     descriptor: (I)I
     flags: (0x0001) ACC_PUBLIC
     Code:
       stack=2, locals=2, args_size=2
-         x: aload_0
          x: iload_1
-         x: invokevirtual #x                 // Method addOneInner:(I)I
+         x: iconst_1
+         x: iadd
          x: ireturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-            0       6     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
-            0       6     1 value   I
+            0       4     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
+            0       4     1 value   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public int addOneInner(int);
-    descriptor: (I)I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=4, locals=2, args_size=2
-         x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
-         x: ldc           #x                 // String addOneInner
-         x: ldc           #x                 // String (I)I
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: iload_1
-        x: iconst_1
-        x: iadd
-        x: ireturn
-      LineNumberTable:
-      LocalVariableTable:
-        Start  Length  Slot  Name   Signature
-           15       4     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
-           15       4     1 value   I
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
         android.hosttest.annotation.HostSideTestKeep
@@ -586,9 +492,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int nativeAddThree(int);
     descriptor: (I)I
@@ -607,212 +511,39 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.String unsupportedMethod();
     descriptor: ()Ljava/lang/String;
     flags: (0x0001) ACC_PUBLIC
     Code:
-      stack=4, locals=1, args_size=1
-         x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
-         x: ldc           #x                 // String unsupportedMethod
-         x: ldc           #x                 // String ()Ljava/lang/String;
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
-        x: new           #x                 // class java/lang/RuntimeException
-        x: dup
-        x: ldc           #x                 // String Unreachable
-        x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+      stack=3, locals=1, args_size=1
+         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
+         x: new           #x                 // class java/lang/RuntimeException
+         x: dup
+         x: ldc           #x                 // String Unreachable
+         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
         x: athrow
     RuntimeVisibleAnnotations:
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
         android.hosttest.annotation.HostSideTestThrow
-
-  public java.lang.String visibleButUsesUnsupportedMethod();
-    descriptor: ()Ljava/lang/String;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=1, locals=1, args_size=1
-         x: aload_0
-         x: invokevirtual #x                 // Method unsupportedMethod:()Ljava/lang/String;
-         x: areturn
-      LineNumberTable:
-      LocalVariableTable:
-        Start  Length  Slot  Name   Signature
-            0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
 }
 SourceFile: "TinyFrameworkAnnotations.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestStub
+    android.hosttest.annotation.HostSideTestKeep
   x: #x(#x=s#x)
     android.hosttest.annotation.HostSideTestClassLoadHook(
       value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
     )
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class
-  Compiled from "TinyFrameworkCallerCheck.java"
-class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl
-  minor version: 0
-  major version: 61
-  flags: (0x0020) ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 3, attributes: 4
-  private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl();
-    descriptor: ()V
-    flags: (0x0002) ACC_PRIVATE
-    Code:
-      stack=1, locals=1, args_size=1
-         x: aload_0
-         x: invokespecial #x                 // Method java/lang/Object."<init>":()V
-         x: return
-      LineNumberTable:
-      LocalVariableTable:
-        Start  Length  Slot  Name   Signature
-            0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int getOneKeep();
-    descriptor: ()I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=4, locals=0, args_size=0
-         x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
-         x: ldc           #x                 // String getOneKeep
-         x: ldc           #x                 // String ()I
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: iconst_1
-        x: ireturn
-      LineNumberTable:
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestKeep
-
-  public static int getOneStub();
-    descriptor: ()I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=1, locals=0, args_size=0
-         x: iconst_1
-         x: ireturn
-      LineNumberTable:
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-}
-InnerClasses:
-  private static #x= #x of #x;           // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-SourceFile: "TinyFrameworkCallerCheck.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class
-  Compiled from "TinyFrameworkCallerCheck.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 3, attributes: 5
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=1, locals=1, args_size=1
-         x: aload_0
-         x: invokespecial #x                 // Method java/lang/Object."<init>":()V
-         x: return
-      LineNumberTable:
-      LocalVariableTable:
-        Start  Length  Slot  Name   Signature
-            0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int getOne_withCheck();
-    descriptor: ()I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=1, locals=0, args_size=0
-         x: invokestatic  #x                 // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneKeep:()I
-         x: ireturn
-      LineNumberTable:
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int getOne_noCheck();
-    descriptor: ()I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=1, locals=0, args_size=0
-         x: invokestatic  #x                 // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneStub:()I
-         x: ireturn
-      LineNumberTable:
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  private static #x= #x of #x;          // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-SourceFile: "TinyFrameworkCallerCheck.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
-NestMembers:
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class
   Compiled from "TinyFrameworkClassLoadHook.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook
@@ -828,9 +559,7 @@
     Signature: #x                          // Ljava/util/Set<Ljava/lang/Class<*>;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook();
     descriptor: ()V
@@ -846,9 +575,7 @@
             0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static void onClassLoaded(java.lang.Class<?>);
     descriptor: (Ljava/lang/Class;)V
@@ -870,9 +597,7 @@
     Signature: #x                          // (Ljava/lang/Class<*>;)V
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   static {};
     descriptor: ()V
@@ -887,19 +612,15 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "TinyFrameworkClassLoadHook.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations.class
   Compiled from "TinyFrameworkClassWideAnnotations.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations
@@ -908,15 +629,13 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 5, attributes: 3
-  public int stub;
+  interfaces: 0, fields: 1, methods: 4, attributes: 3
+  public int keep;
     descriptor: I
     flags: (0x0001) ACC_PUBLIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations();
     descriptor: ()V
@@ -927,7 +646,7 @@
          x: invokespecial #x                 // Method java/lang/Object."<init>":()V
          x: aload_0
          x: iconst_1
-         x: putfield      #x                 // Field stub:I
+         x: putfield      #x                 // Field keep:I
          x: return
       LineNumberTable:
       LocalVariableTable:
@@ -935,9 +654,7 @@
             0      10     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public int addOne(int);
     descriptor: (I)I
@@ -955,9 +672,7 @@
             0       4     1 value   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public int addTwo(int);
     descriptor: (I)I
@@ -977,63 +692,35 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.String unsupportedMethod();
     descriptor: ()Ljava/lang/String;
     flags: (0x0001) ACC_PUBLIC
     Code:
-      stack=4, locals=1, args_size=1
-         x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations
-         x: ldc           #x                 // String unsupportedMethod
-         x: ldc           #x                 // String ()Ljava/lang/String;
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
-        x: new           #x                 // class java/lang/RuntimeException
-        x: dup
-        x: ldc           #x                 // String Unreachable
-        x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+      stack=3, locals=1, args_size=1
+         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
+         x: new           #x                 // class java/lang/RuntimeException
+         x: dup
+         x: ldc           #x                 // String Unreachable
+         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
         x: athrow
     RuntimeVisibleAnnotations:
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
         android.hosttest.annotation.HostSideTestThrow
-
-  public java.lang.String visibleButUsesUnsupportedMethod();
-    descriptor: ()Ljava/lang/String;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=1, locals=1, args_size=1
-         x: aload_0
-         x: invokevirtual #x                 // Method unsupportedMethod:()Ljava/lang/String;
-         x: areturn
-      LineNumberTable:
-      LocalVariableTable:
-        Start  Length  Slot  Name   Signature
-            0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
 }
 SourceFile: "TinyFrameworkClassWideAnnotations.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.class
   Compiled from "TinyFrameworkClassWithInitializerDefault.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerDefault
@@ -1048,35 +735,29 @@
     flags: (0x0009) ACC_PUBLIC, ACC_STATIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static java.lang.Object sObject;
     descriptor: Ljava/lang/Object;
     flags: (0x0009) ACC_PUBLIC, ACC_STATIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
 }
 SourceFile: "TinyFrameworkClassWithInitializerDefault.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestStub
+    android.hosttest.annotation.HostSideTestKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.class
   Compiled from "TinyFrameworkClassWithInitializerStub.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerStub
@@ -1091,24 +772,20 @@
     flags: (0x0009) ACC_PUBLIC, ACC_STATIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static java.lang.Object sObject;
     descriptor: Ljava/lang/Object;
     flags: (0x0009) ACC_PUBLIC, ACC_STATIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   static {};
     descriptor: ()V
@@ -1128,21 +805,19 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "TinyFrameworkClassWithInitializerStub.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x(#x=s#x)
     android.hosttest.annotation.HostSideTestClassLoadHook(
       value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
     )
   x: #x()
-    android.hosttest.annotation.HostSideTestStub
+    android.hosttest.annotation.HostSideTestKeep
   x: #x()
     android.hosttest.annotation.HostSideTestStaticInitializerKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.class
@@ -1159,43 +834,37 @@
     flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex GREEN;
     descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
     flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex BLUE;
     descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
     flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   private final java.lang.String mLongName;
     descriptor: Ljava/lang/String;
     flags: (0x0012) ACC_PRIVATE, ACC_FINAL
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
         android.hosttest.annotation.HostSideTestKeep
@@ -1205,7 +874,7 @@
     flags: (0x0012) ACC_PRIVATE, ACC_FINAL
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
         android.hosttest.annotation.HostSideTestKeep
@@ -1215,9 +884,7 @@
     flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] values();
     descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
@@ -1231,9 +898,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex valueOf(java.lang.String);
     descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
@@ -1251,9 +916,7 @@
             0      10     0  name   Ljava/lang/String;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     MethodParameters:
       Name                           Flags
       <no name>                      mandated
@@ -1283,12 +946,10 @@
     Signature: #x                          // (Ljava/lang/String;Ljava/lang/String;)V
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
     MethodParameters:
       Name                           Flags
       <no name>                      synthetic
@@ -1310,12 +971,10 @@
             0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public java.lang.String getShortName();
     descriptor: ()Ljava/lang/String;
@@ -1331,12 +990,10 @@
             0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $values();
     descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
@@ -1361,9 +1018,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   static {};
     descriptor: ()V
@@ -1400,20 +1055,16 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 Signature: #x                           // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;>;
 SourceFile: "TinyFrameworkEnumComplex.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestStub
+    android.hosttest.annotation.HostSideTestKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.class
   Compiled from "TinyFrameworkEnumSimple.java"
 public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple>
@@ -1428,33 +1079,27 @@
     flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple DOG;
     descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
     flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $VALUES;
     descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
     flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] values();
     descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
@@ -1468,9 +1113,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple valueOf(java.lang.String);
     descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
@@ -1488,9 +1131,7 @@
             0      10     0  name   Ljava/lang/String;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     MethodParameters:
       Name                           Flags
       <no name>                      mandated
@@ -1512,9 +1153,7 @@
     Signature: #x                          // ()V
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     MethodParameters:
       Name                           Flags
       <no name>                      synthetic
@@ -1539,9 +1178,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   static {};
     descriptor: ()V
@@ -1566,20 +1203,16 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 Signature: #x                           // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;>;
 SourceFile: "TinyFrameworkEnumSimple.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestStub
+    android.hosttest.annotation.HostSideTestKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class
   Compiled from "TinyFrameworkExceptionTester.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester
@@ -1603,9 +1236,7 @@
             0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int testException();
     descriptor: ()I
@@ -1636,19 +1267,15 @@
            11      11     0     e   Ljava/lang/Exception;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "TinyFrameworkExceptionTester.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class
   Compiled from "TinyFrameworkForTextPolicy.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy
@@ -1657,22 +1284,13 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 2, methods: 17, attributes: 2
+  interfaces: 0, fields: 1, methods: 15, attributes: 2
   public int stub;
     descriptor: I
     flags: (0x0001) ACC_PUBLIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public int keep;
-    descriptor: I
-    flags: (0x0001) ACC_PUBLIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static {};
     descriptor: ()V
@@ -1680,7 +1298,7 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
-         x: ldc           #x                 // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 
@@ -1694,63 +1312,32 @@
          x: aload_0
          x: iconst_1
          x: putfield      #x                 // Field stub:I
-         x: aload_0
-        x: iconst_2
-        x: putfield      #x                 // Field keep:I
-        x: return
+         x: return
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-            0      15     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+            0      10     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public int addOne(int);
     descriptor: (I)I
     flags: (0x0001) ACC_PUBLIC
     Code:
       stack=2, locals=2, args_size=2
-         x: aload_0
          x: iload_1
-         x: invokevirtual #x                 // Method addOneInner:(I)I
+         x: iconst_1
+         x: iadd
          x: ireturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-            0       6     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
-            0       6     1 value   I
+            0       4     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+            0       4     1 value   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public int addOneInner(int);
-    descriptor: (I)I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=4, locals=2, args_size=2
-         x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
-         x: ldc           #x                 // String addOneInner
-         x: ldc           #x                 // String (I)I
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: iload_1
-        x: iconst_1
-        x: iadd
-        x: ireturn
-      LineNumberTable:
-      LocalVariableTable:
-        Start  Length  Slot  Name   Signature
-           15       4     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
-           15       4     1 value   I
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.String toBeIgnoredObj();
     descriptor: ()Ljava/lang/String;
@@ -1763,9 +1350,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public void toBeIgnoredV();
     descriptor: ()V
@@ -1777,9 +1362,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public boolean toBeIgnoredZ();
     descriptor: ()Z
@@ -1792,9 +1375,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public byte toBeIgnoredB();
     descriptor: ()B
@@ -1807,9 +1388,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public char toBeIgnoredC();
     descriptor: ()C
@@ -1822,9 +1401,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public short toBeIgnoredS();
     descriptor: ()S
@@ -1837,9 +1414,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public int toBeIgnoredI();
     descriptor: ()I
@@ -1852,9 +1427,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public float toBeIgnoredF();
     descriptor: ()F
@@ -1867,9 +1440,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public double toBeIgnoredD();
     descriptor: ()D
@@ -1882,9 +1453,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public int addTwo(int);
     descriptor: (I)I
@@ -1904,9 +1473,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int nativeAddThree(int);
     descriptor: (I)I
@@ -1925,57 +1492,29 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.String unsupportedMethod();
     descriptor: ()Ljava/lang/String;
     flags: (0x0001) ACC_PUBLIC
     Code:
-      stack=4, locals=1, args_size=1
-         x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
-         x: ldc           #x                 // String unsupportedMethod
-         x: ldc           #x                 // String ()Ljava/lang/String;
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
-        x: new           #x                 // class java/lang/RuntimeException
-        x: dup
-        x: ldc           #x                 // String Unreachable
-        x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+      stack=3, locals=1, args_size=1
+         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
+         x: new           #x                 // class java/lang/RuntimeException
+         x: dup
+         x: ldc           #x                 // String Unreachable
+         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
         x: athrow
     RuntimeVisibleAnnotations:
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public java.lang.String visibleButUsesUnsupportedMethod();
-    descriptor: ()Ljava/lang/String;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=1, locals=1, args_size=1
-         x: aload_0
-         x: invokevirtual #x                 // Method unsupportedMethod:()Ljava/lang/String;
-         x: areturn
-      LineNumberTable:
-      LocalVariableTable:
-        Start  Length  Slot  Name   Signature
-            0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "TinyFrameworkForTextPolicy.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.class
   Compiled from "TinyFrameworkLambdas.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested
@@ -1991,12 +1530,10 @@
     Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
     descriptor: Ljava/util/function/Supplier;
@@ -2004,12 +1541,10 @@
     Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested();
     descriptor: ()V
@@ -2028,12 +1563,10 @@
             0      14     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public java.util.function.Supplier<java.lang.Integer> getSupplier();
     descriptor: ()Ljava/util/function/Supplier;
@@ -2049,12 +1582,10 @@
     Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
     descriptor: ()Ljava/util/function/Supplier;
@@ -2067,12 +1598,10 @@
     Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   private static java.lang.Integer lambda$getSupplier_static$3();
     descriptor: ()Ljava/lang/Integer;
@@ -2085,9 +1614,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static java.lang.Integer lambda$getSupplier$2();
     descriptor: ()Ljava/lang/Integer;
@@ -2100,9 +1627,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static java.lang.Integer lambda$static$1();
     descriptor: ()Ljava/lang/Integer;
@@ -2115,9 +1640,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static java.lang.Integer lambda$new$0();
     descriptor: ()Ljava/lang/Integer;
@@ -2130,9 +1653,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   static {};
     descriptor: ()V
@@ -2145,7 +1666,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   public static #x= #x of #x;            // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
@@ -2153,12 +1674,10 @@
 SourceFile: "TinyFrameworkLambdas.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestStub
+    android.hosttest.annotation.HostSideTestKeep
   x: #x()
     android.hosttest.annotation.HostSideTestStaticInitializerKeep
 BootstrapMethods:
@@ -2198,12 +1717,10 @@
     Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
     descriptor: Ljava/util/function/Supplier;
@@ -2211,12 +1728,10 @@
     Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas();
     descriptor: ()V
@@ -2235,12 +1750,10 @@
             0      14     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public java.util.function.Supplier<java.lang.Integer> getSupplier();
     descriptor: ()Ljava/util/function/Supplier;
@@ -2256,12 +1769,10 @@
     Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
     descriptor: ()Ljava/util/function/Supplier;
@@ -2274,12 +1785,10 @@
     Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   private static java.lang.Integer lambda$getSupplier_static$3();
     descriptor: ()Ljava/lang/Integer;
@@ -2292,9 +1801,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static java.lang.Integer lambda$getSupplier$2();
     descriptor: ()Ljava/lang/Integer;
@@ -2307,9 +1814,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static java.lang.Integer lambda$static$1();
     descriptor: ()Ljava/lang/Integer;
@@ -2322,9 +1827,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static java.lang.Integer lambda$new$0();
     descriptor: ()Ljava/lang/Integer;
@@ -2337,9 +1840,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   static {};
     descriptor: ()V
@@ -2352,7 +1853,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   public static #x= #x of #x;           // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
@@ -2360,12 +1861,10 @@
 SourceFile: "TinyFrameworkLambdas.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestStub
+    android.hosttest.annotation.HostSideTestKeep
   x: #x()
     android.hosttest.annotation.HostSideTestStaticInitializerKeep
 BootstrapMethods:
@@ -2414,9 +1913,7 @@
             0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static void startThread(java.lang.Thread);
     descriptor: (Ljava/lang/Thread;)V
@@ -2435,9 +1932,7 @@
             0      10     0 thread   Ljava/lang/Thread;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int add(int, int);
     descriptor: (II)I
@@ -2455,18 +1950,14 @@
             0       4     1     b   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
-  public static #x= #x of #x;            // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+  public static #x= #x of #x;             // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
 SourceFile: "TinyFrameworkMethodCallReplace.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.class
   Compiled from "TinyFrameworkMethodCallReplace.java"
@@ -2491,9 +1982,7 @@
             0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static boolean nonStaticMethodCallReplaceTester() throws java.lang.Exception;
     descriptor: ()Z
@@ -2527,9 +2016,7 @@
       throws java.lang.Exception
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int staticMethodCallReplaceTester();
     descriptor: ()I
@@ -2543,9 +2030,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean);
     descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V
@@ -2563,22 +2048,18 @@
             0      11     0    ab   Ljava/util/concurrent/atomic/AtomicBoolean;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
-  public static #x= #x of #x;           // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+  public static #x= #x of #x;            // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
   public static final #x= #x of #x;    // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
 SourceFile: "TinyFrameworkMethodCallReplace.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 BootstrapMethods:
   x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
     Method arguments:
@@ -2595,15 +2076,13 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 11, attributes: 3
+  interfaces: 0, fields: 1, methods: 12, attributes: 3
   int value;
     descriptor: I
     flags: (0x0000)
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative();
     descriptor: ()V
@@ -2619,9 +2098,7 @@
             0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int nativeAddTwo(int);
     descriptor: (I)I
@@ -2635,9 +2112,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int nativeAddTwo_should_be_like_this(int);
     descriptor: (I)I
@@ -2653,9 +2128,7 @@
             0       5     0   arg   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static long nativeLongPlus(long, long);
     descriptor: (JJ)J
@@ -2670,9 +2143,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static long nativeLongPlus_should_be_like_this(long, long);
     descriptor: (JJ)J
@@ -2690,9 +2161,7 @@
             0       6     2  arg2   J
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public void setValue(int);
     descriptor: (I)V
@@ -2710,9 +2179,7 @@
             0       6     1     v   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public int nativeNonStaticAddToValue(int);
     descriptor: (I)I
@@ -2727,9 +2194,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public int nativeNonStaticAddToValue_should_be_like_this(int);
     descriptor: (I)I
@@ -2747,38 +2212,38 @@
             0       6     1   arg   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static void nativeStillNotSupported();
     descriptor: ()V
     flags: (0x0009) ACC_PUBLIC, ACC_STATIC
     Code:
-      stack=4, locals=0, args_size=0
-         x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
-         x: ldc           #x                 // String nativeStillNotSupported
-         x: ldc           #x                 // String ()V
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
-        x: new           #x                 // class java/lang/RuntimeException
-        x: dup
-        x: ldc           #x                 // String Unreachable
-        x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+      stack=3, locals=0, args_size=0
+         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
+         x: new           #x                 // class java/lang/RuntimeException
+         x: dup
+         x: ldc           #x                 // String Unreachable
+         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
         x: athrow
     RuntimeVisibleAnnotations:
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
         android.hosttest.annotation.HostSideTestThrow
 
+  public static native void nativeStillKeep();
+    descriptor: ()V
+    flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+    RuntimeInvisibleAnnotations:
+      x: #x()
+        android.hosttest.annotation.HostSideTestKeep
+
   public static void nativeStillNotSupported_should_be_like_this();
     descriptor: ()V
     flags: (0x0009) ACC_PUBLIC, ACC_STATIC
@@ -2791,9 +2256,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static byte nativeBytePlus(byte, byte);
     descriptor: (BB)B
@@ -2808,19 +2271,15 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "TinyFrameworkNative.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
   x: #x(#x=s#x)
     android.hosttest.annotation.HostSideTestNativeSubstitutionClass(
       value="TinyFrameworkNative_host"
@@ -2838,125 +2297,95 @@
     descriptor: ()V
     flags: (0x0001) ACC_PUBLIC
     Code:
-      stack=4, locals=1, args_size=1
-         x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
-         x: ldc           #x                 // String <init>
-         x: ldc           #x                 // String ()V
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: aload_0
-        x: invokespecial #x                 // Method java/lang/Object."<init>":()V
-        x: return
+      stack=1, locals=1, args_size=1
+         x: aload_0
+         x: invokespecial #x                 // Method java/lang/Object."<init>":()V
+         x: return
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           15       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host;
+            0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int nativeAddTwo(int);
     descriptor: (I)I
     flags: (0x0009) ACC_PUBLIC, ACC_STATIC
     Code:
-      stack=4, locals=1, args_size=1
-         x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
-         x: ldc           #x                 // String nativeAddTwo
-         x: ldc           #x                 // String (I)I
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: iload_0
-        x: iconst_2
-        x: iadd
-        x: ireturn
+      stack=2, locals=1, args_size=1
+         x: iload_0
+         x: iconst_2
+         x: iadd
+         x: ireturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           15       4     0   arg   I
+            0       4     0   arg   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static long nativeLongPlus(long, long);
     descriptor: (JJ)J
     flags: (0x0009) ACC_PUBLIC, ACC_STATIC
     Code:
       stack=4, locals=4, args_size=2
-         x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
-         x: ldc           #x                 // String nativeLongPlus
-         x: ldc           #x                 // String (JJ)J
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: lload_0
-        x: lload_2
-        x: ladd
-        x: lreturn
+         x: lload_0
+         x: lload_2
+         x: ladd
+         x: lreturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           15       4     0  arg1   J
-           15       4     2  arg2   J
+            0       4     0  arg1   J
+            0       4     2  arg2   J
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int nativeNonStaticAddToValue(com.android.hoststubgen.test.tinyframework.TinyFrameworkNative, int);
     descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I
     flags: (0x0009) ACC_PUBLIC, ACC_STATIC
     Code:
-      stack=4, locals=2, args_size=2
-         x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
-         x: ldc           #x                 // String nativeNonStaticAddToValue
-         x: ldc           #x                 // String (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: aload_0
-        x: getfield      #x                 // Field com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.value:I
-        x: iload_1
-        x: iadd
-        x: ireturn
+      stack=2, locals=2, args_size=2
+         x: aload_0
+         x: getfield      #x                 // Field com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.value:I
+         x: iload_1
+         x: iadd
+         x: ireturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           15       7     0 source   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
-           15       7     1   arg   I
+            0       7     0 source   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
+            0       7     1   arg   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static byte nativeBytePlus(byte, byte);
     descriptor: (BB)B
     flags: (0x0009) ACC_PUBLIC, ACC_STATIC
     Code:
-      stack=4, locals=2, args_size=2
-         x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
-         x: ldc           #x                 // String nativeBytePlus
-         x: ldc           #x                 // String (BB)B
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: iload_0
-        x: iload_1
-        x: iadd
-        x: i2b
-        x: ireturn
+      stack=2, locals=2, args_size=2
+         x: iload_0
+         x: iload_1
+         x: iadd
+         x: i2b
+         x: ireturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           15       5     0  arg1   B
-           15       5     1  arg2   B
+            0       5     0  arg1   B
+            0       5     1  arg2   B
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "TinyFrameworkNative_host.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
     android.hosttest.annotation.HostSideTestWholeClassKeep
@@ -2974,7 +2403,7 @@
     flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
     descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
@@ -2994,7 +2423,7 @@
             0      10     1 this$0   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     MethodParameters:
       Name                           Flags
       <no name>                      final mandated
@@ -3003,45 +2432,33 @@
     descriptor: ()Ljava/lang/Integer;
     flags: (0x0001) ACC_PUBLIC
     Code:
-      stack=4, locals=1, args_size=1
-         x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
-         x: ldc           #x                 // String get
-         x: ldc           #x                 // String ()Ljava/lang/Integer;
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: iconst_1
-        x: invokestatic  #x                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
-        x: areturn
+      stack=1, locals=1, args_size=1
+         x: iconst_1
+         x: invokestatic  #x                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+         x: areturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           15       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+            0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.Object get();
     descriptor: ()Ljava/lang/Object;
     flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
     Code:
-      stack=4, locals=1, args_size=1
-         x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
-         x: ldc           #x                 // String get
-         x: ldc           #x                 // String ()Ljava/lang/Object;
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: aload_0
-        x: invokevirtual #x                 // Method get:()Ljava/lang/Integer;
-        x: areturn
+      stack=1, locals=1, args_size=1
+         x: aload_0
+         x: invokevirtual #x                 // Method get:()Ljava/lang/Integer;
+         x: areturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           15       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+            0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   #x;                                     // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
@@ -3050,7 +2467,7 @@
 SourceFile: "TinyFrameworkNestedClasses.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2.class
   Compiled from "TinyFrameworkNestedClasses.java"
@@ -3075,51 +2492,39 @@
             0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.Integer get();
     descriptor: ()Ljava/lang/Integer;
     flags: (0x0001) ACC_PUBLIC
     Code:
-      stack=4, locals=1, args_size=1
-         x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
-         x: ldc           #x                 // String get
-         x: ldc           #x                 // String ()Ljava/lang/Integer;
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: iconst_2
-        x: invokestatic  #x                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
-        x: areturn
+      stack=1, locals=1, args_size=1
+         x: iconst_2
+         x: invokestatic  #x                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+         x: areturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           15       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+            0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.Object get();
     descriptor: ()Ljava/lang/Object;
     flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
     Code:
-      stack=4, locals=1, args_size=1
-         x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
-         x: ldc           #x                 // String get
-         x: ldc           #x                 // String ()Ljava/lang/Object;
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: aload_0
-        x: invokevirtual #x                 // Method get:()Ljava/lang/Integer;
-        x: areturn
+      stack=1, locals=1, args_size=1
+         x: aload_0
+         x: invokevirtual #x                 // Method get:()Ljava/lang/Integer;
+         x: areturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           15       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+            0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   #x;                                     // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
@@ -3128,7 +2533,7 @@
 SourceFile: "TinyFrameworkNestedClasses.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3.class
   Compiled from "TinyFrameworkNestedClasses.java"
@@ -3144,7 +2549,7 @@
     flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
     descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
@@ -3164,7 +2569,7 @@
             0      10     1 this$0   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     MethodParameters:
       Name                           Flags
       <no name>                      final mandated
@@ -3173,45 +2578,33 @@
     descriptor: ()Ljava/lang/Integer;
     flags: (0x0001) ACC_PUBLIC
     Code:
-      stack=4, locals=1, args_size=1
-         x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
-         x: ldc           #x                 // String get
-         x: ldc           #x                 // String ()Ljava/lang/Integer;
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: iconst_3
-        x: invokestatic  #x                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
-        x: areturn
+      stack=1, locals=1, args_size=1
+         x: iconst_3
+         x: invokestatic  #x                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+         x: areturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           15       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+            0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.Object get();
     descriptor: ()Ljava/lang/Object;
     flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
     Code:
-      stack=4, locals=1, args_size=1
-         x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
-         x: ldc           #x                 // String get
-         x: ldc           #x                 // String ()Ljava/lang/Object;
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: aload_0
-        x: invokevirtual #x                 // Method get:()Ljava/lang/Integer;
-        x: areturn
+      stack=1, locals=1, args_size=1
+         x: aload_0
+         x: invokevirtual #x                 // Method get:()Ljava/lang/Integer;
+         x: areturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           15       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+            0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   #x;                                     // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
@@ -3220,7 +2613,7 @@
 SourceFile: "TinyFrameworkNestedClasses.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4.class
   Compiled from "TinyFrameworkNestedClasses.java"
@@ -3245,51 +2638,39 @@
             0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.Integer get();
     descriptor: ()Ljava/lang/Integer;
     flags: (0x0001) ACC_PUBLIC
     Code:
-      stack=4, locals=1, args_size=1
-         x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
-         x: ldc           #x                 // String get
-         x: ldc           #x                 // String ()Ljava/lang/Integer;
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: iconst_4
-        x: invokestatic  #x                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
-        x: areturn
+      stack=1, locals=1, args_size=1
+         x: iconst_4
+         x: invokestatic  #x                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+         x: areturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           15       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+            0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.Object get();
     descriptor: ()Ljava/lang/Object;
     flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
     Code:
-      stack=4, locals=1, args_size=1
-         x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
-         x: ldc           #x                 // String get
-         x: ldc           #x                 // String ()Ljava/lang/Object;
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: aload_0
-        x: invokevirtual #x                 // Method get:()Ljava/lang/Integer;
-        x: areturn
+      stack=1, locals=1, args_size=1
+         x: aload_0
+         x: invokevirtual #x                 // Method get:()Ljava/lang/Integer;
+         x: areturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           15       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+            0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   #x;                                     // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
@@ -3298,7 +2679,7 @@
 SourceFile: "TinyFrameworkNestedClasses.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class
   Compiled from "TinyFrameworkNestedClasses.java"
@@ -3314,9 +2695,7 @@
     flags: (0x0001) ACC_PUBLIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass(int);
     descriptor: (I)V
@@ -3336,18 +2715,14 @@
             0      10     1     x   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
-  public static #x= #x of #x;            // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+  public static #x= #x of #x;             // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 SourceFile: "TinyFrameworkNestedClasses.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass.class
   Compiled from "TinyFrameworkNestedClasses.java"
@@ -3363,18 +2738,14 @@
     flags: (0x0001) ACC_PUBLIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
     descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
     flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
     descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
@@ -3397,21 +2768,17 @@
             0      15     1 this$0   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     MethodParameters:
       Name                           Flags
       <no name>                      final mandated
 }
 InnerClasses:
-  public #x= #x of #x;                   // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+  public #x= #x of #x;                    // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 SourceFile: "TinyFrameworkNestedClasses.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1.class
   Compiled from "TinyFrameworkNestedClasses.java"
@@ -3436,51 +2803,39 @@
             0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.Integer get();
     descriptor: ()Ljava/lang/Integer;
     flags: (0x0001) ACC_PUBLIC
     Code:
-      stack=4, locals=1, args_size=1
-         x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
-         x: ldc           #x                 // String get
-         x: ldc           #x                 // String ()Ljava/lang/Integer;
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: bipush        7
-        x: invokestatic  #x                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
-        x: areturn
+      stack=1, locals=1, args_size=1
+         x: bipush        7
+         x: invokestatic  #x                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+         x: areturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           15       6     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+            0       6     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.Object get();
     descriptor: ()Ljava/lang/Object;
     flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
     Code:
-      stack=4, locals=1, args_size=1
-         x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
-         x: ldc           #x                 // String get
-         x: ldc           #x                 // String ()Ljava/lang/Object;
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: aload_0
-        x: invokevirtual #x                 // Method get:()Ljava/lang/Integer;
-        x: areturn
+      stack=1, locals=1, args_size=1
+         x: aload_0
+         x: invokevirtual #x                 // Method get:()Ljava/lang/Integer;
+         x: areturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           15       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+            0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   public static #x= #x of #x;          // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
@@ -3490,7 +2845,7 @@
 SourceFile: "TinyFrameworkNestedClasses.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass.class
   Compiled from "TinyFrameworkNestedClasses.java"
@@ -3506,9 +2861,7 @@
     flags: (0x0001) ACC_PUBLIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass();
     descriptor: ()V
@@ -3527,9 +2880,7 @@
             0      11     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   public static #x= #x of #x;           // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
@@ -3537,9 +2888,7 @@
 SourceFile: "TinyFrameworkNestedClasses.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass.class
   Compiled from "TinyFrameworkNestedClasses.java"
@@ -3555,9 +2904,7 @@
     flags: (0x0001) ACC_PUBLIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass();
     descriptor: ()V
@@ -3576,9 +2923,7 @@
             0      11     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
     descriptor: ()Ljava/util/function/Supplier;
@@ -3593,20 +2938,16 @@
     Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
-  public static #x= #x of #x;            // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+  public static #x= #x of #x;             // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
   #x;                                    // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
   public static #x= #x of #x;           // Double$NestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
 SourceFile: "TinyFrameworkNestedClasses.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass.class
   Compiled from "TinyFrameworkNestedClasses.java"
@@ -3633,19 +2974,15 @@
             0       6     1     x   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
-  public static #x= #x of #x;            // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+  public static #x= #x of #x;             // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
   public static #x= #x of #x;            // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 SourceFile: "TinyFrameworkNestedClasses.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.class
   Compiled from "TinyFrameworkNestedClasses.java"
@@ -3662,9 +2999,7 @@
     Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
     descriptor: Ljava/util/function/Supplier;
@@ -3672,9 +3007,7 @@
     Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses();
     descriptor: ()V
@@ -3696,9 +3029,7 @@
             0      17     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.util.function.Supplier<java.lang.Integer> getSupplier();
     descriptor: ()Ljava/util/function/Supplier;
@@ -3717,9 +3048,7 @@
     Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
     descriptor: ()Ljava/util/function/Supplier;
@@ -3734,9 +3063,7 @@
     Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   static {};
     descriptor: ()V
@@ -3751,16 +3078,14 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   #x;                                    // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
   #x;                                    // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
   #x;                                    // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
   #x;                                    // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
-  public static #x= #x of #x;           // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+  public static #x= #x of #x;            // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
   public static #x= #x of #x;           // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
   public static #x= #x of #x;           // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
   public #x= #x of #x;                  // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
@@ -3769,12 +3094,10 @@
 SourceFile: "TinyFrameworkNestedClasses.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 NestMembers:
   com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
   com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
@@ -3809,9 +3132,7 @@
             0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int foo(int);
     descriptor: (I)I
@@ -3830,19 +3151,15 @@
             0      12     0 value   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "TinyFrameworkPackageRedirect.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.class
   Compiled from "TinyFrameworkRenamedClassCaller.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller
@@ -3866,9 +3183,7 @@
             0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int foo(int);
     descriptor: (I)I
@@ -3887,19 +3202,15 @@
             0      12     0 value   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "TinyFrameworkRenamedClassCaller.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 ## Class: com/android/hoststubgen/test/tinyframework/packagetest/A.class
   Compiled from "A.java"
 public class com.android.hoststubgen.test.tinyframework.packagetest.A
@@ -3913,9 +3224,7 @@
 SourceFile: "A.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/packagetest/sub/A.class
   Compiled from "A.java"
 public class com.android.hoststubgen.test.tinyframework.packagetest.sub.A
@@ -3929,9 +3238,7 @@
 SourceFile: "A.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C1.class
   Compiled from "C1.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.C1
@@ -3945,9 +3252,7 @@
 SourceFile: "C1.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C2.class
   Compiled from "C2.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1
@@ -3961,9 +3266,7 @@
 SourceFile: "C2.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C3.class
   Compiled from "C3.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2
@@ -3977,9 +3280,7 @@
 SourceFile: "C3.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CA.class
   Compiled from "CA.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.CA
@@ -3993,9 +3294,7 @@
 SourceFile: "CA.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CB.class
   Compiled from "CB.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.CB
@@ -4009,9 +3308,7 @@
 SourceFile: "CB.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C1.class
   Compiled from "Class_C1.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C1 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1
@@ -4025,7 +3322,7 @@
 SourceFile: "Class_C1.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C2.class
   Compiled from "Class_C2.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2
@@ -4039,7 +3336,7 @@
 SourceFile: "Class_C2.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C3.class
   Compiled from "Class_C3.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C3
@@ -4053,7 +3350,7 @@
 SourceFile: "Class_C3.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1.class
   Compiled from "Class_I1.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1 implements com.android.hoststubgen.test.tinyframework.subclasstest.I1
@@ -4067,7 +3364,7 @@
 SourceFile: "Class_I1.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA.class
   Compiled from "Class_I1_IA.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1_IA implements com.android.hoststubgen.test.tinyframework.subclasstest.I1,com.android.hoststubgen.test.tinyframework.subclasstest.IA
@@ -4081,7 +3378,7 @@
 SourceFile: "Class_I1_IA.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I2.class
   Compiled from "Class_I2.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I2 implements com.android.hoststubgen.test.tinyframework.subclasstest.I2
@@ -4095,7 +3392,7 @@
 SourceFile: "Class_I2.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3.class
   Compiled from "Class_I3.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3 implements com.android.hoststubgen.test.tinyframework.subclasstest.I3
@@ -4109,7 +3406,7 @@
 SourceFile: "Class_I3.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I1.class
   Compiled from "I1.java"
 public interface com.android.hoststubgen.test.tinyframework.subclasstest.I1
@@ -4123,9 +3420,7 @@
 SourceFile: "I1.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I2.class
   Compiled from "I2.java"
 public interface com.android.hoststubgen.test.tinyframework.subclasstest.I2 extends com.android.hoststubgen.test.tinyframework.subclasstest.I1
@@ -4139,9 +3434,7 @@
 SourceFile: "I2.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I3.class
   Compiled from "I3.java"
 public interface com.android.hoststubgen.test.tinyframework.subclasstest.I3 extends com.android.hoststubgen.test.tinyframework.subclasstest.I2
@@ -4155,9 +3448,7 @@
 SourceFile: "I3.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IA.class
   Compiled from "IA.java"
 public interface com.android.hoststubgen.test.tinyframework.subclasstest.IA
@@ -4171,9 +3462,7 @@
 SourceFile: "IA.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IB.class
   Compiled from "IB.java"
 public interface com.android.hoststubgen.test.tinyframework.subclasstest.IB
@@ -4187,9 +3476,7 @@
 SourceFile: "IB.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/supported/UnsupportedClass.class
   Compiled from "UnsupportedClass.java"
 public class com.supported.UnsupportedClass
@@ -4204,60 +3491,48 @@
     flags: (0x0012) ACC_PRIVATE, ACC_FINAL
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public com.supported.UnsupportedClass(int);
     descriptor: (I)V
     flags: (0x0001) ACC_PUBLIC
     Code:
-      stack=4, locals=2, args_size=2
-         x: ldc           #x                 // String com/supported/UnsupportedClass
-         x: ldc           #x                 // String <init>
-         x: ldc           #x                 // String (I)V
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: aload_0
-        x: invokespecial #x                 // Method java/lang/Object."<init>":()V
-        x: aload_0
-        x: iload_1
-        x: putfield      #x                 // Field mValue:I
-        x: return
+      stack=2, locals=2, args_size=2
+         x: aload_0
+         x: invokespecial #x                 // Method java/lang/Object."<init>":()V
+         x: aload_0
+         x: iload_1
+         x: putfield      #x                 // Field mValue:I
+         x: return
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           15      10     0  this   Lcom/supported/UnsupportedClass;
-           15      10     1 value   I
+            0      10     0  this   Lcom/supported/UnsupportedClass;
+            0      10     1 value   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public int getValue();
     descriptor: ()I
     flags: (0x0001) ACC_PUBLIC
     Code:
-      stack=4, locals=1, args_size=1
-         x: ldc           #x                 // String com/supported/UnsupportedClass
-         x: ldc           #x                 // String getValue
-         x: ldc           #x                 // String ()I
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: aload_0
-        x: getfield      #x                 // Field mValue:I
-        x: ireturn
+      stack=1, locals=1, args_size=1
+         x: aload_0
+         x: getfield      #x                 // Field mValue:I
+         x: ireturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           15       5     0  this   Lcom/supported/UnsupportedClass;
+            0       5     0  this   Lcom/supported/UnsupportedClass;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "UnsupportedClass.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
     android.hosttest.annotation.HostSideTestWholeClassKeep
@@ -4289,9 +3564,7 @@
             0      14     1 value   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public int getValue();
     descriptor: ()I
@@ -4309,19 +3582,15 @@
             0      10     0  this   Lcom/unsupported/UnsupportedClass;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "UnsupportedClass.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 ## Class: rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.class
   Compiled from "TinyFrameworkToBeRenamed.java"
 public class rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed
@@ -4336,9 +3605,7 @@
     flags: (0x0012) ACC_PRIVATE, ACC_FINAL
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed(int);
     descriptor: (I)V
@@ -4358,9 +3625,7 @@
             0      10     1 value   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public int getValue();
     descriptor: ()I
@@ -4376,16 +3641,12 @@
             0       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "TinyFrameworkToBeRenamed.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt
deleted file mode 100644
index 86a9c65..0000000
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt
+++ /dev/null
@@ -1,2788 +0,0 @@
-## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy.class
-  Compiled from "IPretendingAidl.java"
-public class com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub$Proxy
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 2, attributes: 4
-  public com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub$Proxy();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int addTwo(int);
-    descriptor: (I)I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;           // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl
-  public static #x= #x of #x;           // Proxy=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy of class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
-SourceFile: "IPretendingAidl.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/IPretendingAidl
-## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub.class
-  Compiled from "IPretendingAidl.java"
-public class com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 2, attributes: 4
-  public com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int addOne(int);
-    descriptor: (I)I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;            // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl
-  public static #x= #x of #x;           // Proxy=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy of class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
-SourceFile: "IPretendingAidl.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/IPretendingAidl
-## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl.class
-  Compiled from "IPretendingAidl.java"
-public interface com.android.hoststubgen.test.tinyframework.IPretendingAidl
-  minor version: 0
-  major version: 61
-  flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/IPretendingAidl
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 0, attributes: 4
-}
-InnerClasses:
-  public static #x= #x of #x;            // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl
-  public static #x= #x of #x;           // Proxy=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy of class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
-SourceFile: "IPretendingAidl.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestMembers:
-  com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
-  com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy
-## Class: com/android/hoststubgen/test/tinyframework/R$Nested.class
-  Compiled from "R.java"
-public class com.android.hoststubgen.test.tinyframework.R$Nested
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/R$Nested
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 2, attributes: 4
-  public static int[] ARRAY;
-    descriptor: [I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public com.android.hoststubgen.test.tinyframework.R$Nested();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  static {};
-    descriptor: ()V
-    flags: (0x0008) ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;            // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R
-SourceFile: "R.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/R
-## Class: com/android/hoststubgen/test/tinyframework/R.class
-  Compiled from "R.java"
-public class com.android.hoststubgen.test.tinyframework.R
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/R
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 1, attributes: 4
-  public com.android.hoststubgen.test.tinyframework.R();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;            // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R
-SourceFile: "R.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestMembers:
-  com/android/hoststubgen/test/tinyframework/R$Nested
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.class
-  Compiled from "TinyFrameworkAnnotations.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 5, attributes: 3
-  public int stub;
-    descriptor: I
-    flags: (0x0001) ACC_PUBLIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public int addOne(int);
-    descriptor: (I)I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public int addTwo(int);
-    descriptor: (I)I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int nativeAddThree(int);
-    descriptor: (I)I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public java.lang.String visibleButUsesUnsupportedMethod();
-    descriptor: ()Ljava/lang/String;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-}
-SourceFile: "TinyFrameworkAnnotations.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestStub
-  x: #x(#x=s#x)
-    android.hosttest.annotation.HostSideTestClassLoadHook(
-      value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
-    )
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class
-  Compiled from "TinyFrameworkCallerCheck.java"
-class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl
-  minor version: 0
-  major version: 61
-  flags: (0x0020) ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 2, attributes: 4
-  private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl();
-    descriptor: ()V
-    flags: (0x0002) ACC_PRIVATE
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int getOneStub();
-    descriptor: ()I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-}
-InnerClasses:
-  private static #x= #x of #x;           // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-SourceFile: "TinyFrameworkCallerCheck.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class
-  Compiled from "TinyFrameworkCallerCheck.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 3, attributes: 5
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int getOne_withCheck();
-    descriptor: ()I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int getOne_noCheck();
-    descriptor: ()I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  private static #x= #x of #x;          // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-SourceFile: "TinyFrameworkCallerCheck.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
-NestMembers:
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class
-  Compiled from "TinyFrameworkClassLoadHook.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 3, attributes: 3
-  public static final java.util.Set<java.lang.Class<?>> sLoadedClasses;
-    descriptor: Ljava/util/Set;
-    flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
-    Signature: #x                          // Ljava/util/Set<Ljava/lang/Class<*>;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook();
-    descriptor: ()V
-    flags: (0x0002) ACC_PRIVATE
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static void onClassLoaded(java.lang.Class<?>);
-    descriptor: (Ljava/lang/Class;)V
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    Signature: #x                          // (Ljava/lang/Class<*>;)V
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  static {};
-    descriptor: ()V
-    flags: (0x0008) ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkClassLoadHook.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations.class
-  Compiled from "TinyFrameworkClassWideAnnotations.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 4, attributes: 3
-  public int stub;
-    descriptor: I
-    flags: (0x0001) ACC_PUBLIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public int addOne(int);
-    descriptor: (I)I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public int addTwo(int);
-    descriptor: (I)I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public java.lang.String visibleButUsesUnsupportedMethod();
-    descriptor: ()Ljava/lang/String;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkClassWideAnnotations.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.class
-  Compiled from "TinyFrameworkClassWithInitializerDefault.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerDefault
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 2, methods: 0, attributes: 3
-  public static boolean sInitialized;
-    descriptor: Z
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public static java.lang.Object sObject;
-    descriptor: Ljava/lang/Object;
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-}
-SourceFile: "TinyFrameworkClassWithInitializerDefault.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.class
-  Compiled from "TinyFrameworkClassWithInitializerStub.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerStub
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 2, methods: 0, attributes: 3
-  public static boolean sInitialized;
-    descriptor: Z
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public static java.lang.Object sObject;
-    descriptor: Ljava/lang/Object;
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-}
-SourceFile: "TinyFrameworkClassWithInitializerStub.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x(#x=s#x)
-    android.hosttest.annotation.HostSideTestClassLoadHook(
-      value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
-    )
-  x: #x()
-    android.hosttest.annotation.HostSideTestStub
-  x: #x()
-    android.hosttest.annotation.HostSideTestStaticInitializerKeep
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.class
-  Compiled from "TinyFrameworkEnumComplex.java"
-public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex>
-  minor version: 0
-  major version: 61
-  flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex
-  super_class: #x                         // java/lang/Enum
-  interfaces: 0, fields: 4, methods: 7, attributes: 4
-  public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex RED;
-    descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
-    flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex GREEN;
-    descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
-    flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex BLUE;
-    descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
-    flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $VALUES;
-    descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
-    flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] values();
-    descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex valueOf(java.lang.String);
-    descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    MethodParameters:
-      Name                           Flags
-      <no name>                      mandated
-
-  private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex(java.lang.String, java.lang.String);
-    descriptor: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V
-    flags: (0x0002) ACC_PRIVATE
-    Code:
-      stack=3, locals=5, args_size=5
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    Signature: #x                          // (Ljava/lang/String;Ljava/lang/String;)V
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-    MethodParameters:
-      Name                           Flags
-      <no name>                      synthetic
-      <no name>                      synthetic
-      <no name>
-      <no name>
-
-  public java.lang.String getLongName();
-    descriptor: ()Ljava/lang/String;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public java.lang.String getShortName();
-    descriptor: ()Ljava/lang/String;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $values();
-    descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
-    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  static {};
-    descriptor: ()V
-    flags: (0x0008) ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-Signature: #x                           // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;>;
-SourceFile: "TinyFrameworkEnumComplex.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.class
-  Compiled from "TinyFrameworkEnumSimple.java"
-public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple>
-  minor version: 0
-  major version: 61
-  flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple
-  super_class: #x                         // java/lang/Enum
-  interfaces: 0, fields: 3, methods: 5, attributes: 4
-  public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple CAT;
-    descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
-    flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple DOG;
-    descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
-    flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $VALUES;
-    descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
-    flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] values();
-    descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple valueOf(java.lang.String);
-    descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    MethodParameters:
-      Name                           Flags
-      <no name>                      mandated
-
-  private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple();
-    descriptor: (Ljava/lang/String;I)V
-    flags: (0x0002) ACC_PRIVATE
-    Code:
-      stack=3, locals=3, args_size=3
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    Signature: #x                          // ()V
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    MethodParameters:
-      Name                           Flags
-      <no name>                      synthetic
-      <no name>                      synthetic
-
-  private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $values();
-    descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
-    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  static {};
-    descriptor: ()V
-    flags: (0x0008) ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-Signature: #x                           // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;>;
-SourceFile: "TinyFrameworkEnumSimple.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class
-  Compiled from "TinyFrameworkExceptionTester.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 2, attributes: 3
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int testException();
-    descriptor: ()I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkExceptionTester.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class
-  Compiled from "TinyFrameworkForTextPolicy.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 14, attributes: 2
-  public int stub;
-    descriptor: I
-    flags: (0x0001) ACC_PUBLIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public int addOne(int);
-    descriptor: (I)I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public java.lang.String toBeIgnoredObj();
-    descriptor: ()Ljava/lang/String;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public void toBeIgnoredV();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public boolean toBeIgnoredZ();
-    descriptor: ()Z
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public byte toBeIgnoredB();
-    descriptor: ()B
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public char toBeIgnoredC();
-    descriptor: ()C
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public short toBeIgnoredS();
-    descriptor: ()S
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public int toBeIgnoredI();
-    descriptor: ()I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public float toBeIgnoredF();
-    descriptor: ()F
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public double toBeIgnoredD();
-    descriptor: ()D
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public int addTwo(int);
-    descriptor: (I)I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int nativeAddThree(int);
-    descriptor: (I)I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public java.lang.String visibleButUsesUnsupportedMethod();
-    descriptor: ()Ljava/lang/String;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkForTextPolicy.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.class
-  Compiled from "TinyFrameworkLambdas.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 2, methods: 7, attributes: 5
-  public final java.util.function.Supplier<java.lang.Integer> mSupplier;
-    descriptor: Ljava/util/function/Supplier;
-    flags: (0x0011) ACC_PUBLIC, ACC_FINAL
-    Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
-    descriptor: Ljava/util/function/Supplier;
-    flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
-    Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public java.util.function.Supplier<java.lang.Integer> getSupplier();
-    descriptor: ()Ljava/util/function/Supplier;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
-    descriptor: ()Ljava/util/function/Supplier;
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  private static java.lang.Integer lambda$getSupplier_static$3();
-    descriptor: ()Ljava/lang/Integer;
-    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  private static java.lang.Integer lambda$getSupplier$2();
-    descriptor: ()Ljava/lang/Integer;
-    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  private static java.lang.Integer lambda$static$1();
-    descriptor: ()Ljava/lang/Integer;
-    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  private static java.lang.Integer lambda$new$0();
-    descriptor: ()Ljava/lang/Integer;
-    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;            // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
-  public static final #x= #x of #x;    // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
-SourceFile: "TinyFrameworkLambdas.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestStub
-  x: #x()
-    android.hosttest.annotation.HostSideTestStaticInitializerKeep
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.class
-  Compiled from "TinyFrameworkLambdas.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 2, methods: 7, attributes: 5
-  public final java.util.function.Supplier<java.lang.Integer> mSupplier;
-    descriptor: Ljava/util/function/Supplier;
-    flags: (0x0011) ACC_PUBLIC, ACC_FINAL
-    Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
-    descriptor: Ljava/util/function/Supplier;
-    flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
-    Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public java.util.function.Supplier<java.lang.Integer> getSupplier();
-    descriptor: ()Ljava/util/function/Supplier;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
-    descriptor: ()Ljava/util/function/Supplier;
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  private static java.lang.Integer lambda$getSupplier_static$3();
-    descriptor: ()Ljava/lang/Integer;
-    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  private static java.lang.Integer lambda$getSupplier$2();
-    descriptor: ()Ljava/lang/Integer;
-    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  private static java.lang.Integer lambda$static$1();
-    descriptor: ()Ljava/lang/Integer;
-    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  private static java.lang.Integer lambda$new$0();
-    descriptor: ()Ljava/lang/Integer;
-    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;           // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
-  public static final #x= #x of #x;    // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
-SourceFile: "TinyFrameworkLambdas.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestStub
-  x: #x()
-    android.hosttest.annotation.HostSideTestStaticInitializerKeep
-NestMembers:
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class
-  Compiled from "TinyFrameworkMethodCallReplace.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 3, attributes: 4
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static void startThread(java.lang.Thread);
-    descriptor: (Ljava/lang/Thread;)V
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int add(int, int);
-    descriptor: (II)I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;            // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
-SourceFile: "TinyFrameworkMethodCallReplace.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.class
-  Compiled from "TinyFrameworkMethodCallReplace.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 4, attributes: 5
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static boolean nonStaticMethodCallReplaceTester() throws java.lang.Exception;
-    descriptor: ()Z
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    Exceptions:
-      throws java.lang.Exception
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int staticMethodCallReplaceTester();
-    descriptor: ()I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean);
-    descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V
-    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;           // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
-  public static final #x= #x of #x;    // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
-SourceFile: "TinyFrameworkMethodCallReplace.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
-NestMembers:
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
-  Compiled from "TinyFrameworkNative.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 10, attributes: 3
-  int value;
-    descriptor: I
-    flags: (0x0000)
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static native int nativeAddTwo(int);
-    descriptor: (I)I
-    flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int nativeAddTwo_should_be_like_this(int);
-    descriptor: (I)I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static native long nativeLongPlus(long, long);
-    descriptor: (JJ)J
-    flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static long nativeLongPlus_should_be_like_this(long, long);
-    descriptor: (JJ)J
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=4, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public void setValue(int);
-    descriptor: (I)V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public native int nativeNonStaticAddToValue(int);
-    descriptor: (I)I
-    flags: (0x0101) ACC_PUBLIC, ACC_NATIVE
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public int nativeNonStaticAddToValue_should_be_like_this(int);
-    descriptor: (I)I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static void nativeStillNotSupported_should_be_like_this();
-    descriptor: ()V
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static native byte nativeBytePlus(byte, byte);
-    descriptor: (BB)B
-    flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkNative.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
-  x: #x(#x=s#x)
-    android.hosttest.annotation.HostSideTestNativeSubstitutionClass(
-      value="TinyFrameworkNative_host"
-    )
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class
-  Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 1, attributes: 4
-  public int value;
-    descriptor: I
-    flags: (0x0001) ACC_PUBLIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass(int);
-    descriptor: (I)V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;            // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass.class
-  Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 2, methods: 1, attributes: 4
-  public int value;
-    descriptor: I
-    flags: (0x0001) ACC_PUBLIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
-    descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
-    flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
-    descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    MethodParameters:
-      Name                           Flags
-      <no name>                      final mandated
-}
-InnerClasses:
-  public #x= #x of #x;                   // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass.class
-  Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 1, attributes: 4
-  public int value;
-    descriptor: I
-    flags: (0x0001) ACC_PUBLIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;           // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-  public static #x= #x of #x;           // Double$NestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass.class
-  Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 2, attributes: 4
-  public int value;
-    descriptor: I
-    flags: (0x0001) ACC_PUBLIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
-    descriptor: ()Ljava/util/function/Supplier;
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;            // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-  #x;                                    // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
-  public static #x= #x of #x;           // Double$NestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass.class
-  Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass extends com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
-  super_class: #x                         // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
-  interfaces: 0, fields: 0, methods: 1, attributes: 4
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass(int);
-    descriptor: (I)V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  public static #x= #x of #x;            // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-  public static #x= #x of #x;            // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.class
-  Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 2, methods: 4, attributes: 5
-  public final java.util.function.Supplier<java.lang.Integer> mSupplier;
-    descriptor: Ljava/util/function/Supplier;
-    flags: (0x0011) ACC_PUBLIC, ACC_FINAL
-    Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
-    descriptor: Ljava/util/function/Supplier;
-    flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
-    Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public java.util.function.Supplier<java.lang.Integer> getSupplier();
-    descriptor: ()Ljava/util/function/Supplier;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
-    descriptor: ()Ljava/util/function/Supplier;
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  static {};
-    descriptor: ()V
-    flags: (0x0008) ACC_STATIC
-    Code:
-      stack=3, locals=0, args_size=0
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  #x;                                    // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
-  #x;                                    // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
-  #x;                                    // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
-  #x;                                    // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
-  public static #x= #x of #x;           // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-  public static #x= #x of #x;           // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-  public static #x= #x of #x;           // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-  public #x= #x of #x;                  // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-  public static #x= #x of #x;          // Double$NestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
-  #x;                                    // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
-NestMembers:
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect.class
-  Compiled from "TinyFrameworkPackageRedirect.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 2, attributes: 3
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int foo(int);
-    descriptor: (I)I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkPackageRedirect.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.class
-  Compiled from "TinyFrameworkRenamedClassCaller.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 2, attributes: 3
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int foo(int);
-    descriptor: (I)I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkRenamedClassCaller.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: com/android/hoststubgen/test/tinyframework/packagetest/A.class
-  Compiled from "A.java"
-public class com.android.hoststubgen.test.tinyframework.packagetest.A
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/packagetest/A
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "A.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/packagetest/sub/A.class
-  Compiled from "A.java"
-public class com.android.hoststubgen.test.tinyframework.packagetest.sub.A
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/packagetest/sub/A
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "A.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C1.class
-  Compiled from "C1.java"
-public class com.android.hoststubgen.test.tinyframework.subclasstest.C1
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/subclasstest/C1
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "C1.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C2.class
-  Compiled from "C2.java"
-public class com.android.hoststubgen.test.tinyframework.subclasstest.C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/subclasstest/C2
-  super_class: #x                         // com/android/hoststubgen/test/tinyframework/subclasstest/C1
-  interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "C2.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C3.class
-  Compiled from "C3.java"
-public class com.android.hoststubgen.test.tinyframework.subclasstest.C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/subclasstest/C3
-  super_class: #x                         // com/android/hoststubgen/test/tinyframework/subclasstest/C2
-  interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "C3.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CA.class
-  Compiled from "CA.java"
-public class com.android.hoststubgen.test.tinyframework.subclasstest.CA
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/subclasstest/CA
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "CA.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CB.class
-  Compiled from "CB.java"
-public class com.android.hoststubgen.test.tinyframework.subclasstest.CB
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/subclasstest/CB
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "CB.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I1.class
-  Compiled from "I1.java"
-public interface com.android.hoststubgen.test.tinyframework.subclasstest.I1
-  minor version: 0
-  major version: 61
-  flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/subclasstest/I1
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "I1.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I2.class
-  Compiled from "I2.java"
-public interface com.android.hoststubgen.test.tinyframework.subclasstest.I2 extends com.android.hoststubgen.test.tinyframework.subclasstest.I1
-  minor version: 0
-  major version: 61
-  flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/subclasstest/I2
-  super_class: #x                         // java/lang/Object
-  interfaces: 1, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "I2.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I3.class
-  Compiled from "I3.java"
-public interface com.android.hoststubgen.test.tinyframework.subclasstest.I3 extends com.android.hoststubgen.test.tinyframework.subclasstest.I2
-  minor version: 0
-  major version: 61
-  flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/subclasstest/I3
-  super_class: #x                         // java/lang/Object
-  interfaces: 1, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "I3.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IA.class
-  Compiled from "IA.java"
-public interface com.android.hoststubgen.test.tinyframework.subclasstest.IA
-  minor version: 0
-  major version: 61
-  flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/subclasstest/IA
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "IA.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IB.class
-  Compiled from "IB.java"
-public interface com.android.hoststubgen.test.tinyframework.subclasstest.IB
-  minor version: 0
-  major version: 61
-  flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/subclasstest/IB
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "IB.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/unsupported/UnsupportedClass.class
-  Compiled from "UnsupportedClass.java"
-public class com.unsupported.UnsupportedClass
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/unsupported/UnsupportedClass
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 2, attributes: 3
-  public com.unsupported.UnsupportedClass(int);
-    descriptor: (I)V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public int getValue();
-    descriptor: ()I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "UnsupportedClass.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.class
-  Compiled from "TinyFrameworkToBeRenamed.java"
-public class rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 2, attributes: 3
-  private final int mValue;
-    descriptor: I
-    flags: (0x0012) ACC_PRIVATE, ACC_FINAL
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed(int);
-    descriptor: (I)V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=2, args_size=2
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public int getValue();
-    descriptor: ()I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=3, locals=1, args_size=1
-         x: new           #x                 // class java/lang/RuntimeException
-         x: dup
-         x: ldc           #x                 // String Stub!
-         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
-         x: athrow
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkToBeRenamed.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-dump.txt
similarity index 77%
rename from tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt
rename to tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-dump.txt
index da434a6..2ca723b 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-dump.txt
@@ -22,12 +22,12 @@
     flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "HostSideTestClassLoadHook.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
   x: #x(#x=[e#x.#x])
     java.lang.annotation.Target(
       value=[Ljava/lang/annotation/ElementType;.TYPE]
@@ -58,7 +58,7 @@
 SourceFile: "HostSideTestKeep.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
   x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
     java.lang.annotation.Target(
       value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
@@ -91,12 +91,12 @@
     flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "HostSideTestNativeSubstitutionClass.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
   x: #x(#x=[e#x.#x])
     java.lang.annotation.Target(
       value=[Ljava/lang/annotation/ElementType;.TYPE]
@@ -127,7 +127,7 @@
 SourceFile: "HostSideTestRemove.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
   x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
     java.lang.annotation.Target(
       value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
@@ -136,13 +136,13 @@
     java.lang.annotation.Retention(
       value=Ljava/lang/annotation/RetentionPolicy;.CLASS
     )
-## Class: android/hosttest/annotation/HostSideTestStub.class
-  Compiled from "HostSideTestStub.java"
-public interface android.hosttest.annotation.HostSideTestStub extends java.lang.annotation.Annotation
+## Class: android/hosttest/annotation/HostSideTestStaticInitializerKeep.class
+  Compiled from "HostSideTestStaticInitializerKeep.java"
+public interface android.hosttest.annotation.HostSideTestStaticInitializerKeep extends java.lang.annotation.Annotation
   minor version: 0
   major version: 61
   flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
-  this_class: #x                          // android/hosttest/annotation/HostSideTestStub
+  this_class: #x                          // android/hosttest/annotation/HostSideTestStaticInitializerKeep
   super_class: #x                         // java/lang/Object
   interfaces: 1, fields: 0, methods: 1, attributes: 2
   private static {};
@@ -150,15 +150,15 @@
     flags: (0x000a) ACC_PRIVATE, ACC_STATIC
     Code:
       stack=2, locals=0, args_size=0
-         x: ldc           #x                  // class android/hosttest/annotation/HostSideTestStub
+         x: ldc           #x                  // class android/hosttest/annotation/HostSideTestStaticInitializerKeep
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 }
-SourceFile: "HostSideTestStub.java"
+SourceFile: "HostSideTestStaticInitializerKeep.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
   x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
     java.lang.annotation.Target(
       value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
@@ -191,12 +191,12 @@
     flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "HostSideTestSubstitute.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
   x: #x(#x=[e#x.#x])
     java.lang.annotation.Target(
       value=[Ljava/lang/annotation/ElementType;.METHOD]
@@ -227,7 +227,7 @@
 SourceFile: "HostSideTestThrow.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
   x: #x(#x=[e#x.#x,e#x.#x])
     java.lang.annotation.Target(
       value=[Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
@@ -258,38 +258,7 @@
 SourceFile: "HostSideTestWholeClassKeep.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-  x: #x(#x=[e#x.#x])
-    java.lang.annotation.Target(
-      value=[Ljava/lang/annotation/ElementType;.TYPE]
-    )
-  x: #x(#x=e#x.#x)
-    java.lang.annotation.Retention(
-      value=Ljava/lang/annotation/RetentionPolicy;.CLASS
-    )
-## Class: android/hosttest/annotation/HostSideTestWholeClassStub.class
-  Compiled from "HostSideTestWholeClassStub.java"
-public interface android.hosttest.annotation.HostSideTestWholeClassStub extends java.lang.annotation.Annotation
-  minor version: 0
-  major version: 61
-  flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
-  this_class: #x                          // android/hosttest/annotation/HostSideTestWholeClassStub
-  super_class: #x                         // java/lang/Object
-  interfaces: 1, fields: 0, methods: 1, attributes: 2
-  private static {};
-    descriptor: ()V
-    flags: (0x000a) ACC_PRIVATE, ACC_STATIC
-    Code:
-      stack=2, locals=0, args_size=0
-         x: ldc           #x                  // class android/hosttest/annotation/HostSideTestWholeClassStub
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
-         x: return
-}
-SourceFile: "HostSideTestWholeClassStub.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
   x: #x(#x=[e#x.#x])
     java.lang.annotation.Target(
       value=[Ljava/lang/annotation/ElementType;.TYPE]
@@ -313,7 +282,7 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 
@@ -336,9 +305,7 @@
            11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int addTwo(int);
     descriptor: (I)I
@@ -360,9 +327,7 @@
            11       4     0     a   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   public static #x= #x of #x;          // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl
@@ -370,9 +335,7 @@
 SourceFile: "IPretendingAidl.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/IPretendingAidl
 ## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub.class
   Compiled from "IPretendingAidl.java"
@@ -389,7 +352,7 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 
@@ -412,9 +375,7 @@
            11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int addOne(int);
     descriptor: (I)I
@@ -436,9 +397,7 @@
            11       4     0     a   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   public static #x= #x of #x;           // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl
@@ -446,9 +405,7 @@
 SourceFile: "IPretendingAidl.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/IPretendingAidl
 ## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl.class
   Compiled from "IPretendingAidl.java"
@@ -465,7 +422,7 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/IPretendingAidl
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 }
@@ -475,9 +432,7 @@
 SourceFile: "IPretendingAidl.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestMembers:
   com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
   com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy
@@ -495,9 +450,7 @@
     flags: (0x0009) ACC_PUBLIC, ACC_STATIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public com.android.hoststubgen.test.tinyframework.R$Nested();
     descriptor: ()V
@@ -518,9 +471,7 @@
            11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/R$Nested;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   static {};
     descriptor: ()V
@@ -546,18 +497,14 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
-  public static #x= #x of #x;            // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R
+  public static #x= #x of #x;             // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R
 SourceFile: "R.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/R
 ## Class: com/android/hoststubgen/test/tinyframework/R.class
   Compiled from "R.java"
@@ -574,7 +521,7 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/R
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 
@@ -597,18 +544,14 @@
            11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/R;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   public static #x= #x of #x;           // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R
 SourceFile: "R.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestMembers:
   com/android/hoststubgen/test/tinyframework/R$Nested
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.class
@@ -619,25 +562,13 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 2, methods: 8, attributes: 3
-  public int stub;
-    descriptor: I
-    flags: (0x0001) ACC_PUBLIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
+  interfaces: 0, fields: 1, methods: 6, attributes: 3
   public int keep;
     descriptor: I
     flags: (0x0001) ACC_PUBLIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
         android.hosttest.annotation.HostSideTestKeep
@@ -648,7 +579,7 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
          x: ldc           #x                 // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
@@ -669,23 +600,18 @@
         x: invokespecial #x                 // Method java/lang/Object."<init>":()V
         x: aload_0
         x: iconst_1
-        x: putfield      #x                 // Field stub:I
-        x: aload_0
-        x: iconst_2
         x: putfield      #x                 // Field keep:I
         x: return
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           11      15     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
+           11      10     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public int addOne(int);
     descriptor: (I)I
@@ -697,40 +623,6 @@
          x: ldc           #x                 // String (I)I
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: aload_0
-        x: iload_1
-        x: invokevirtual #x                 // Method addOneInner:(I)I
-        x: ireturn
-      LineNumberTable:
-      LocalVariableTable:
-        Start  Length  Slot  Name   Signature
-           11       6     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
-           11       6     1 value   I
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-
-  public int addOneInner(int);
-    descriptor: (I)I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=4, locals=2, args_size=2
-         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
-         x: ldc           #x                 // String addOneInner
-         x: ldc           #x                 // String (I)I
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
-        x: ldc           #x                 // String addOneInner
-        x: ldc           #x                 // String (I)I
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
         x: iload_1
         x: iconst_1
         x: iadd
@@ -738,11 +630,11 @@
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           26       4     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
-           26       4     1 value   I
+           11       4     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
+           11       4     1 value   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
         android.hosttest.annotation.HostSideTestKeep
@@ -770,9 +662,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int nativeAddThree(int);
     descriptor: (I)I
@@ -796,9 +686,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.String unsupportedMethod();
     descriptor: ()Ljava/lang/String;
@@ -810,12 +698,6 @@
          x: ldc           #x                 // String ()Ljava/lang/String;
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
-        x: ldc           #x                 // String unsupportedMethod
-        x: ldc           #x                 // String ()Ljava/lang/String;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
         x: new           #x                 // class java/lang/RuntimeException
         x: dup
@@ -826,242 +708,22 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
         android.hosttest.annotation.HostSideTestThrow
-
-  public java.lang.String visibleButUsesUnsupportedMethod();
-    descriptor: ()Ljava/lang/String;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=4, locals=1, args_size=1
-         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
-         x: ldc           #x                 // String visibleButUsesUnsupportedMethod
-         x: ldc           #x                 // String ()Ljava/lang/String;
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: aload_0
-        x: invokevirtual #x                 // Method unsupportedMethod:()Ljava/lang/String;
-        x: areturn
-      LineNumberTable:
-      LocalVariableTable:
-        Start  Length  Slot  Name   Signature
-           11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
 }
 SourceFile: "TinyFrameworkAnnotations.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestStub
+    android.hosttest.annotation.HostSideTestKeep
   x: #x(#x=s#x)
     android.hosttest.annotation.HostSideTestClassLoadHook(
       value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
     )
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class
-  Compiled from "TinyFrameworkCallerCheck.java"
-class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl
-  minor version: 0
-  major version: 61
-  flags: (0x0020) ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 4, attributes: 4
-  private static {};
-    descriptor: ()V
-    flags: (0x000a) ACC_PRIVATE, ACC_STATIC
-    Code:
-      stack=2, locals=0, args_size=0
-         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
-         x: return
-
-  private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl();
-    descriptor: ()V
-    flags: (0x0002) ACC_PRIVATE
-    Code:
-      stack=4, locals=1, args_size=1
-         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
-         x: ldc           #x                 // String <init>
-         x: ldc           #x                 // String ()V
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: aload_0
-        x: invokespecial #x                 // Method java/lang/Object."<init>":()V
-        x: return
-      LineNumberTable:
-      LocalVariableTable:
-        Start  Length  Slot  Name   Signature
-           11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int getOneKeep();
-    descriptor: ()I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=4, locals=0, args_size=0
-         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
-         x: ldc           #x                 // String getOneKeep
-         x: ldc           #x                 // String ()I
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
-        x: ldc           #x                 // String getOneKeep
-        x: ldc           #x                 // String ()I
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: iconst_1
-        x: ireturn
-      LineNumberTable:
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestKeep
-
-  public static int getOneStub();
-    descriptor: ()I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=4, locals=0, args_size=0
-         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
-         x: ldc           #x                 // String getOneStub
-         x: ldc           #x                 // String ()I
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: iconst_1
-        x: ireturn
-      LineNumberTable:
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestStub
-}
-InnerClasses:
-  private static #x= #x of #x;          // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-SourceFile: "TinyFrameworkCallerCheck.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class
-  Compiled from "TinyFrameworkCallerCheck.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck
-  minor version: 0
-  major version: 61
-  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
-  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-  super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 4, attributes: 5
-  private static {};
-    descriptor: ()V
-    flags: (0x000a) ACC_PRIVATE, ACC_STATIC
-    Code:
-      stack=2, locals=0, args_size=0
-         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
-         x: return
-
-  public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck();
-    descriptor: ()V
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=4, locals=1, args_size=1
-         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-         x: ldc           #x                 // String <init>
-         x: ldc           #x                 // String ()V
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: aload_0
-        x: invokespecial #x                 // Method java/lang/Object."<init>":()V
-        x: return
-      LineNumberTable:
-      LocalVariableTable:
-        Start  Length  Slot  Name   Signature
-           11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int getOne_withCheck();
-    descriptor: ()I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=4, locals=0, args_size=0
-         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-         x: ldc           #x                 // String getOne_withCheck
-         x: ldc           #x                 // String ()I
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: invokestatic  #x                 // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneKeep:()I
-        x: ireturn
-      LineNumberTable:
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public static int getOne_noCheck();
-    descriptor: ()I
-    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
-    Code:
-      stack=4, locals=0, args_size=0
-         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-         x: ldc           #x                 // String getOne_noCheck
-         x: ldc           #x                 // String ()I
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: invokestatic  #x                 // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneStub:()I
-        x: ireturn
-      LineNumberTable:
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
-  private static #x= #x of #x;          // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-SourceFile: "TinyFrameworkCallerCheck.java"
-RuntimeVisibleAnnotations:
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
-  x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
-NestMembers:
-  com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class
   Compiled from "TinyFrameworkClassLoadHook.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook
@@ -1077,9 +739,7 @@
     Signature: #x                          // Ljava/util/Set<Ljava/lang/Class<*>;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook();
     descriptor: ()V
@@ -1100,9 +760,7 @@
            11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static void onClassLoaded(java.lang.Class<?>);
     descriptor: (Ljava/lang/Class;)V
@@ -1129,9 +787,7 @@
     Signature: #x                          // (Ljava/lang/Class<*>;)V
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   static {};
     descriptor: ()V
@@ -1154,19 +810,15 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "TinyFrameworkClassLoadHook.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations.class
   Compiled from "TinyFrameworkClassWideAnnotations.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations
@@ -1175,15 +827,13 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 6, attributes: 3
-  public int stub;
+  interfaces: 0, fields: 1, methods: 5, attributes: 3
+  public int keep;
     descriptor: I
     flags: (0x0001) ACC_PUBLIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static {};
     descriptor: ()V
@@ -1191,7 +841,7 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 
@@ -1209,7 +859,7 @@
         x: invokespecial #x                 // Method java/lang/Object."<init>":()V
         x: aload_0
         x: iconst_1
-        x: putfield      #x                 // Field stub:I
+        x: putfield      #x                 // Field keep:I
         x: return
       LineNumberTable:
       LocalVariableTable:
@@ -1217,9 +867,7 @@
            11      10     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public int addOne(int);
     descriptor: (I)I
@@ -1242,9 +890,7 @@
            11       4     1 value   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public int addTwo(int);
     descriptor: (I)I
@@ -1269,9 +915,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.String unsupportedMethod();
     descriptor: ()Ljava/lang/String;
@@ -1283,12 +927,6 @@
          x: ldc           #x                 // String ()Ljava/lang/String;
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations
-        x: ldc           #x                 // String unsupportedMethod
-        x: ldc           #x                 // String ()Ljava/lang/String;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
         x: new           #x                 // class java/lang/RuntimeException
         x: dup
@@ -1299,43 +937,18 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
         android.hosttest.annotation.HostSideTestThrow
-
-  public java.lang.String visibleButUsesUnsupportedMethod();
-    descriptor: ()Ljava/lang/String;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=4, locals=1, args_size=1
-         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations
-         x: ldc           #x                 // String visibleButUsesUnsupportedMethod
-         x: ldc           #x                 // String ()Ljava/lang/String;
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: aload_0
-        x: invokevirtual #x                 // Method unsupportedMethod:()Ljava/lang/String;
-        x: areturn
-      LineNumberTable:
-      LocalVariableTable:
-        Start  Length  Slot  Name   Signature
-           11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
 }
 SourceFile: "TinyFrameworkClassWideAnnotations.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.class
   Compiled from "TinyFrameworkClassWithInitializerDefault.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerDefault
@@ -1350,35 +963,29 @@
     flags: (0x0009) ACC_PUBLIC, ACC_STATIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static java.lang.Object sObject;
     descriptor: Ljava/lang/Object;
     flags: (0x0009) ACC_PUBLIC, ACC_STATIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
 }
 SourceFile: "TinyFrameworkClassWithInitializerDefault.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestStub
+    android.hosttest.annotation.HostSideTestKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.class
   Compiled from "TinyFrameworkClassWithInitializerStub.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerStub
@@ -1393,24 +1000,20 @@
     flags: (0x0009) ACC_PUBLIC, ACC_STATIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static java.lang.Object sObject;
     descriptor: Ljava/lang/Object;
     flags: (0x0009) ACC_PUBLIC, ACC_STATIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   static {};
     descriptor: ()V
@@ -1438,21 +1041,19 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "TinyFrameworkClassWithInitializerStub.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x(#x=s#x)
     android.hosttest.annotation.HostSideTestClassLoadHook(
       value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
     )
   x: #x()
-    android.hosttest.annotation.HostSideTestStub
+    android.hosttest.annotation.HostSideTestKeep
   x: #x()
     android.hosttest.annotation.HostSideTestStaticInitializerKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.class
@@ -1469,43 +1070,37 @@
     flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex GREEN;
     descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
     flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex BLUE;
     descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
     flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   private final java.lang.String mLongName;
     descriptor: Ljava/lang/String;
     flags: (0x0012) ACC_PRIVATE, ACC_FINAL
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
         android.hosttest.annotation.HostSideTestKeep
@@ -1515,7 +1110,7 @@
     flags: (0x0012) ACC_PRIVATE, ACC_FINAL
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
         android.hosttest.annotation.HostSideTestKeep
@@ -1525,9 +1120,7 @@
     flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] values();
     descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
@@ -1546,9 +1139,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex valueOf(java.lang.String);
     descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
@@ -1571,9 +1162,7 @@
            11      10     0  name   Ljava/lang/String;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     MethodParameters:
       Name                           Flags
       <no name>                      mandated
@@ -1608,12 +1197,10 @@
     Signature: #x                          // (Ljava/lang/String;Ljava/lang/String;)V
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
     MethodParameters:
       Name                           Flags
       <no name>                      synthetic
@@ -1640,12 +1227,10 @@
            11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public java.lang.String getShortName();
     descriptor: ()Ljava/lang/String;
@@ -1666,12 +1251,10 @@
            11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $values();
     descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
@@ -1701,9 +1284,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   static {};
     descriptor: ()V
@@ -1738,7 +1319,7 @@
         x: dup
         x: ldc           #x                 // String BLUE
         x: iconst_2
-        x: ldc           #x                // String Blue
+        x: ldc           #x                 // String Blue
         x: ldc           #x                // String B
         x: invokespecial #x                 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V
         x: putstatic     #x                 // Field BLUE:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
@@ -1748,20 +1329,16 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 Signature: #x                           // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;>;
 SourceFile: "TinyFrameworkEnumComplex.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestStub
+    android.hosttest.annotation.HostSideTestKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.class
   Compiled from "TinyFrameworkEnumSimple.java"
 public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple>
@@ -1776,33 +1353,27 @@
     flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple DOG;
     descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
     flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $VALUES;
     descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
     flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] values();
     descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
@@ -1821,9 +1392,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple valueOf(java.lang.String);
     descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
@@ -1846,9 +1415,7 @@
            11      10     0  name   Ljava/lang/String;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     MethodParameters:
       Name                           Flags
       <no name>                      mandated
@@ -1875,9 +1442,7 @@
     Signature: #x                          // ()V
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     MethodParameters:
       Name                           Flags
       <no name>                      synthetic
@@ -1907,9 +1472,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   static {};
     descriptor: ()V
@@ -1942,20 +1505,16 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 Signature: #x                           // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;>;
 SourceFile: "TinyFrameworkEnumSimple.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestStub
+    android.hosttest.annotation.HostSideTestKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class
   Compiled from "TinyFrameworkExceptionTester.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester
@@ -1971,7 +1530,7 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 
@@ -1994,9 +1553,7 @@
            11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int testException();
     descriptor: ()I
@@ -2032,19 +1589,15 @@
            22      11     0     e   Ljava/lang/Exception;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "TinyFrameworkExceptionTester.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class
   Compiled from "TinyFrameworkForTextPolicy.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy
@@ -2053,22 +1606,13 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 2, methods: 17, attributes: 2
+  interfaces: 0, fields: 1, methods: 15, attributes: 2
   public int stub;
     descriptor: I
     flags: (0x0001) ACC_PUBLIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public int keep;
-    descriptor: I
-    flags: (0x0001) ACC_PUBLIC
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static {};
     descriptor: ()V
@@ -2076,7 +1620,7 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
          x: ldc           #x                 // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
@@ -2098,19 +1642,14 @@
         x: aload_0
         x: iconst_1
         x: putfield      #x                 // Field stub:I
-        x: aload_0
-        x: iconst_2
-        x: putfield      #x                 // Field keep:I
         x: return
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           11      15     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+           11      10     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public int addOne(int);
     descriptor: (I)I
@@ -2122,37 +1661,6 @@
          x: ldc           #x                 // String (I)I
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: aload_0
-        x: iload_1
-        x: invokevirtual #x                 // Method addOneInner:(I)I
-        x: ireturn
-      LineNumberTable:
-      LocalVariableTable:
-        Start  Length  Slot  Name   Signature
-           11       6     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
-           11       6     1 value   I
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public int addOneInner(int);
-    descriptor: (I)I
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=4, locals=2, args_size=2
-         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
-         x: ldc           #x                 // String addOneInner
-         x: ldc           #x                 // String (I)I
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
-        x: ldc           #x                 // String addOneInner
-        x: ldc           #x                 // String (I)I
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
         x: iload_1
         x: iconst_1
         x: iadd
@@ -2160,11 +1668,11 @@
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           26       4     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
-           26       4     1 value   I
+           11       4     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+           11       4     1 value   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.String toBeIgnoredObj();
     descriptor: ()Ljava/lang/String;
@@ -2182,9 +1690,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public void toBeIgnoredV();
     descriptor: ()V
@@ -2201,9 +1707,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public boolean toBeIgnoredZ();
     descriptor: ()Z
@@ -2221,9 +1725,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public byte toBeIgnoredB();
     descriptor: ()B
@@ -2241,9 +1743,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public char toBeIgnoredC();
     descriptor: ()C
@@ -2261,9 +1761,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public short toBeIgnoredS();
     descriptor: ()S
@@ -2281,9 +1779,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public int toBeIgnoredI();
     descriptor: ()I
@@ -2301,9 +1797,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public float toBeIgnoredF();
     descriptor: ()F
@@ -2321,9 +1815,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public double toBeIgnoredD();
     descriptor: ()D
@@ -2341,9 +1833,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public int addTwo(int);
     descriptor: (I)I
@@ -2351,7 +1841,7 @@
     Code:
       stack=4, locals=2, args_size=2
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
-         x: ldc           #x                // String addTwo
+         x: ldc           #x                 // String addTwo
          x: ldc           #x                 // String (I)I
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
@@ -2368,9 +1858,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int nativeAddThree(int);
     descriptor: (I)I
@@ -2378,7 +1866,7 @@
     Code:
       stack=4, locals=1, args_size=1
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
-         x: ldc           #x                // String nativeAddThree
+         x: ldc           #x                 // String nativeAddThree
          x: ldc           #x                 // String (I)I
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
@@ -2394,9 +1882,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.String unsupportedMethod();
     descriptor: ()Ljava/lang/String;
@@ -2404,57 +1890,26 @@
     Code:
       stack=4, locals=1, args_size=1
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
-         x: ldc           #x                // String unsupportedMethod
+         x: ldc           #x                 // String unsupportedMethod
          x: ldc           #x                 // String ()Ljava/lang/String;
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
-        x: ldc           #x                // String unsupportedMethod
-        x: ldc           #x                 // String ()Ljava/lang/String;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
-        x: invokestatic  #x                // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
-        x: new           #x                // class java/lang/RuntimeException
+        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
+        x: new           #x                 // class java/lang/RuntimeException
         x: dup
-        x: ldc           #x                // String Unreachable
-        x: invokespecial #x                // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+        x: ldc           #x                 // String Unreachable
+        x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
         x: athrow
     RuntimeVisibleAnnotations:
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
-  public java.lang.String visibleButUsesUnsupportedMethod();
-    descriptor: ()Ljava/lang/String;
-    flags: (0x0001) ACC_PUBLIC
-    Code:
-      stack=4, locals=1, args_size=1
-         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
-         x: ldc           #x                // String visibleButUsesUnsupportedMethod
-         x: ldc           #x                 // String ()Ljava/lang/String;
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
-         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: aload_0
-        x: invokevirtual #x                // Method unsupportedMethod:()Ljava/lang/String;
-        x: areturn
-      LineNumberTable:
-      LocalVariableTable:
-        Start  Length  Slot  Name   Signature
-           11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
-    RuntimeVisibleAnnotations:
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "TinyFrameworkForTextPolicy.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.class
   Compiled from "TinyFrameworkLambdas.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested
@@ -2470,12 +1925,10 @@
     Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
     descriptor: Ljava/util/function/Supplier;
@@ -2483,12 +1936,10 @@
     Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested();
     descriptor: ()V
@@ -2512,12 +1963,10 @@
            11      14     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public java.util.function.Supplier<java.lang.Integer> getSupplier();
     descriptor: ()Ljava/util/function/Supplier;
@@ -2538,12 +1987,10 @@
     Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
     descriptor: ()Ljava/util/function/Supplier;
@@ -2561,12 +2008,10 @@
     Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   private static java.lang.Integer lambda$getSupplier_static$3();
     descriptor: ()Ljava/lang/Integer;
@@ -2584,9 +2029,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static java.lang.Integer lambda$getSupplier$2();
     descriptor: ()Ljava/lang/Integer;
@@ -2604,9 +2047,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static java.lang.Integer lambda$static$1();
     descriptor: ()Ljava/lang/Integer;
@@ -2624,9 +2065,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static java.lang.Integer lambda$new$0();
     descriptor: ()Ljava/lang/Integer;
@@ -2644,9 +2083,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   static {};
     descriptor: ()V
@@ -2662,12 +2099,12 @@
         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
         x: invokedynamic #x,  0             // InvokeDynamic #x:get:()Ljava/util/function/Supplier;
-        x: putstatic     #x                // Field sSupplier:Ljava/util/function/Supplier;
+        x: putstatic     #x                 // Field sSupplier:Ljava/util/function/Supplier;
         x: return
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   public static #x= #x of #x;            // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
@@ -2675,12 +2112,10 @@
 SourceFile: "TinyFrameworkLambdas.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestStub
+    android.hosttest.annotation.HostSideTestKeep
   x: #x()
     android.hosttest.annotation.HostSideTestStaticInitializerKeep
 BootstrapMethods:
@@ -2720,12 +2155,10 @@
     Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
     descriptor: Ljava/util/function/Supplier;
@@ -2733,12 +2166,10 @@
     Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas();
     descriptor: ()V
@@ -2762,12 +2193,10 @@
            11      14     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public java.util.function.Supplier<java.lang.Integer> getSupplier();
     descriptor: ()Ljava/util/function/Supplier;
@@ -2788,12 +2217,10 @@
     Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
     descriptor: ()Ljava/util/function/Supplier;
@@ -2811,12 +2238,10 @@
     Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
-        android.hosttest.annotation.HostSideTestStub
+        android.hosttest.annotation.HostSideTestKeep
 
   private static java.lang.Integer lambda$getSupplier_static$3();
     descriptor: ()Ljava/lang/Integer;
@@ -2834,9 +2259,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static java.lang.Integer lambda$getSupplier$2();
     descriptor: ()Ljava/lang/Integer;
@@ -2854,9 +2277,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static java.lang.Integer lambda$static$1();
     descriptor: ()Ljava/lang/Integer;
@@ -2874,9 +2295,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static java.lang.Integer lambda$new$0();
     descriptor: ()Ljava/lang/Integer;
@@ -2894,9 +2313,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   static {};
     descriptor: ()V
@@ -2912,12 +2329,12 @@
         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
         x: invokedynamic #x,  0             // InvokeDynamic #x:get:()Ljava/util/function/Supplier;
-        x: putstatic     #x                // Field sSupplier:Ljava/util/function/Supplier;
+        x: putstatic     #x                 // Field sSupplier:Ljava/util/function/Supplier;
         x: return
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   public static #x= #x of #x;           // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
@@ -2925,12 +2342,10 @@
 SourceFile: "TinyFrameworkLambdas.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestStub
+    android.hosttest.annotation.HostSideTestKeep
   x: #x()
     android.hosttest.annotation.HostSideTestStaticInitializerKeep
 BootstrapMethods:
@@ -2971,7 +2386,7 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 
@@ -2994,9 +2409,7 @@
            11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static void startThread(java.lang.Thread);
     descriptor: (Ljava/lang/Thread;)V
@@ -3020,9 +2433,7 @@
            11      10     0 thread   Ljava/lang/Thread;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int add(int, int);
     descriptor: (II)I
@@ -3045,18 +2456,14 @@
            11       4     1     b   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   public static #x= #x of #x;           // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
 SourceFile: "TinyFrameworkMethodCallReplace.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.class
   Compiled from "TinyFrameworkMethodCallReplace.java"
@@ -3073,7 +2480,7 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 
@@ -3096,9 +2503,7 @@
            11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static boolean nonStaticMethodCallReplaceTester() throws java.lang.Exception;
     descriptor: ()Z
@@ -3137,9 +2542,7 @@
       throws java.lang.Exception
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int staticMethodCallReplaceTester();
     descriptor: ()I
@@ -3158,9 +2561,7 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean);
     descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V
@@ -3173,7 +2574,7 @@
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
         x: aload_0
-        x: invokestatic  #x                // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
+        x: invokestatic  #x                 // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
         x: invokevirtual #x                // Method java/lang/Thread.isDaemon:()Z
         x: invokevirtual #x                // Method java/util/concurrent/atomic/AtomicBoolean.set:(Z)V
         x: return
@@ -3183,9 +2584,7 @@
            11      11     0    ab   Ljava/util/concurrent/atomic/AtomicBoolean;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   public static #x= #x of #x;           // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
@@ -3193,12 +2592,10 @@
 SourceFile: "TinyFrameworkMethodCallReplace.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 BootstrapMethods:
   x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
     Method arguments:
@@ -3215,15 +2612,13 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 12, attributes: 3
+  interfaces: 0, fields: 1, methods: 13, attributes: 3
   int value;
     descriptor: I
     flags: (0x0000)
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static {};
     descriptor: ()V
@@ -3231,7 +2626,7 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 
@@ -3254,9 +2649,7 @@
            11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int nativeAddTwo(int);
     descriptor: (I)I
@@ -3275,9 +2668,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int nativeAddTwo_should_be_like_this(int);
     descriptor: (I)I
@@ -3298,9 +2689,7 @@
            11       5     0   arg   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static long nativeLongPlus(long, long);
     descriptor: (JJ)J
@@ -3320,9 +2709,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static long nativeLongPlus_should_be_like_this(long, long);
     descriptor: (JJ)J
@@ -3345,9 +2732,7 @@
            11       6     2  arg2   J
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public void setValue(int);
     descriptor: (I)V
@@ -3370,9 +2755,7 @@
            11       6     1     v   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public int nativeNonStaticAddToValue(int);
     descriptor: (I)I
@@ -3392,9 +2775,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public int nativeNonStaticAddToValue_should_be_like_this(int);
     descriptor: (I)I
@@ -3417,9 +2798,7 @@
            11       6     1   arg   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static void nativeStillNotSupported();
     descriptor: ()V
@@ -3431,49 +2810,49 @@
          x: ldc           #x                 // String ()V
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
-        x: ldc           #x                 // String nativeStillNotSupported
-        x: ldc           #x                 // String ()V
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
         x: new           #x                 // class java/lang/RuntimeException
         x: dup
         x: ldc           #x                 // String Unreachable
-        x: invokespecial #x                // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+        x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
         x: athrow
     RuntimeVisibleAnnotations:
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     RuntimeInvisibleAnnotations:
       x: #x()
         android.hosttest.annotation.HostSideTestThrow
 
+  public static native void nativeStillKeep();
+    descriptor: ()V
+    flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+    RuntimeInvisibleAnnotations:
+      x: #x()
+        android.hosttest.annotation.HostSideTestKeep
+
   public static void nativeStillNotSupported_should_be_like_this();
     descriptor: ()V
     flags: (0x0009) ACC_PUBLIC, ACC_STATIC
     Code:
       stack=4, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
-         x: ldc           #x                // String nativeStillNotSupported_should_be_like_this
+         x: ldc           #x                 // String nativeStillNotSupported_should_be_like_this
          x: ldc           #x                 // String ()V
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
         x: new           #x                 // class java/lang/RuntimeException
         x: dup
-        x: invokespecial #x                // Method java/lang/RuntimeException."<init>":()V
+        x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":()V
         x: athrow
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static byte nativeBytePlus(byte, byte);
     descriptor: (BB)B
@@ -3481,31 +2860,27 @@
     Code:
       stack=4, locals=2, args_size=2
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
-         x: ldc           #x                // String nativeBytePlus
-         x: ldc           #x                // String (BB)B
+         x: ldc           #x                 // String nativeBytePlus
+         x: ldc           #x                 // String (BB)B
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
         x: iload_0
         x: iload_1
-        x: invokestatic  #x                // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeBytePlus:(BB)B
+        x: invokestatic  #x                 // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeBytePlus:(BB)B
         x: ireturn
     RuntimeVisibleAnnotations:
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "TinyFrameworkNative.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
   x: #x(#x=s#x)
     android.hosttest.annotation.HostSideTestNativeSubstitutionClass(
       value="TinyFrameworkNative_host"
@@ -3539,22 +2914,16 @@
          x: ldc           #x                 // String ()V
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
-        x: ldc           #x                 // String <init>
-        x: ldc           #x                 // String ()V
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
         x: aload_0
         x: invokespecial #x                 // Method java/lang/Object."<init>":()V
         x: return
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           26       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host;
+           11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int nativeAddTwo(int);
     descriptor: (I)I
@@ -3566,12 +2935,6 @@
          x: ldc           #x                 // String (I)I
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
-        x: ldc           #x                 // String nativeAddTwo
-        x: ldc           #x                 // String (I)I
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
         x: iload_0
         x: iconst_2
         x: iadd
@@ -3579,10 +2942,10 @@
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           26       4     0   arg   I
+           11       4     0   arg   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static long nativeLongPlus(long, long);
     descriptor: (JJ)J
@@ -3594,12 +2957,6 @@
          x: ldc           #x                 // String (JJ)J
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
-        x: ldc           #x                 // String nativeLongPlus
-        x: ldc           #x                 // String (JJ)J
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
         x: lload_0
         x: lload_2
         x: ladd
@@ -3607,11 +2964,11 @@
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           26       4     0  arg1   J
-           26       4     2  arg2   J
+           11       4     0  arg1   J
+           11       4     2  arg2   J
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int nativeNonStaticAddToValue(com.android.hoststubgen.test.tinyframework.TinyFrameworkNative, int);
     descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I
@@ -3623,12 +2980,6 @@
          x: ldc           #x                 // String (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
-        x: ldc           #x                 // String nativeNonStaticAddToValue
-        x: ldc           #x                 // String (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
         x: aload_0
         x: getfield      #x                 // Field com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.value:I
         x: iload_1
@@ -3637,11 +2988,11 @@
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           26       7     0 source   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
-           26       7     1   arg   I
+           11       7     0 source   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
+           11       7     1   arg   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static byte nativeBytePlus(byte, byte);
     descriptor: (BB)B
@@ -3653,12 +3004,6 @@
          x: ldc           #x                 // String (BB)B
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
-        x: ldc           #x                 // String nativeBytePlus
-        x: ldc           #x                 // String (BB)B
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
         x: iload_0
         x: iload_1
         x: iadd
@@ -3667,16 +3012,16 @@
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           26       5     0  arg1   B
-           26       5     1  arg2   B
+           11       5     0  arg1   B
+           11       5     1  arg2   B
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "TinyFrameworkNative_host.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
     android.hosttest.annotation.HostSideTestWholeClassKeep
@@ -3694,7 +3039,7 @@
     flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static {};
     descriptor: ()V
@@ -3729,7 +3074,7 @@
            11      10     1 this$0   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     MethodParameters:
       Name                           Flags
       <no name>                      final mandated
@@ -3744,22 +3089,16 @@
          x: ldc           #x                 // String ()Ljava/lang/Integer;
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
-        x: ldc           #x                 // String get
-        x: ldc           #x                 // String ()Ljava/lang/Integer;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
         x: iconst_1
         x: invokestatic  #x                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
         x: areturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           26       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+           11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.Object get();
     descriptor: ()Ljava/lang/Object;
@@ -3771,22 +3110,16 @@
          x: ldc           #x                 // String ()Ljava/lang/Object;
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
-        x: ldc           #x                 // String get
-        x: ldc           #x                 // String ()Ljava/lang/Object;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
         x: aload_0
         x: invokevirtual #x                 // Method get:()Ljava/lang/Integer;
         x: areturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           26       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+           11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   #x;                                     // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
@@ -3795,7 +3128,7 @@
 SourceFile: "TinyFrameworkNestedClasses.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2.class
   Compiled from "TinyFrameworkNestedClasses.java"
@@ -3835,7 +3168,7 @@
            11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.Integer get();
     descriptor: ()Ljava/lang/Integer;
@@ -3847,22 +3180,16 @@
          x: ldc           #x                 // String ()Ljava/lang/Integer;
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
-        x: ldc           #x                 // String get
-        x: ldc           #x                 // String ()Ljava/lang/Integer;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
         x: iconst_2
         x: invokestatic  #x                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
         x: areturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           26       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+           11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.Object get();
     descriptor: ()Ljava/lang/Object;
@@ -3874,22 +3201,16 @@
          x: ldc           #x                 // String ()Ljava/lang/Object;
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
-        x: ldc           #x                 // String get
-        x: ldc           #x                 // String ()Ljava/lang/Object;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
         x: aload_0
         x: invokevirtual #x                 // Method get:()Ljava/lang/Integer;
         x: areturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           26       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+           11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   #x;                                     // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
@@ -3898,7 +3219,7 @@
 SourceFile: "TinyFrameworkNestedClasses.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3.class
   Compiled from "TinyFrameworkNestedClasses.java"
@@ -3914,7 +3235,7 @@
     flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static {};
     descriptor: ()V
@@ -3949,7 +3270,7 @@
            11      10     1 this$0   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     MethodParameters:
       Name                           Flags
       <no name>                      final mandated
@@ -3964,22 +3285,16 @@
          x: ldc           #x                 // String ()Ljava/lang/Integer;
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
-        x: ldc           #x                 // String get
-        x: ldc           #x                 // String ()Ljava/lang/Integer;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
         x: iconst_3
         x: invokestatic  #x                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
         x: areturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           26       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+           11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.Object get();
     descriptor: ()Ljava/lang/Object;
@@ -3991,22 +3306,16 @@
          x: ldc           #x                 // String ()Ljava/lang/Object;
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
-        x: ldc           #x                 // String get
-        x: ldc           #x                 // String ()Ljava/lang/Object;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
         x: aload_0
         x: invokevirtual #x                 // Method get:()Ljava/lang/Integer;
         x: areturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           26       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+           11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   #x;                                     // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
@@ -4015,7 +3324,7 @@
 SourceFile: "TinyFrameworkNestedClasses.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4.class
   Compiled from "TinyFrameworkNestedClasses.java"
@@ -4055,7 +3364,7 @@
            11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.Integer get();
     descriptor: ()Ljava/lang/Integer;
@@ -4067,22 +3376,16 @@
          x: ldc           #x                 // String ()Ljava/lang/Integer;
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
-        x: ldc           #x                 // String get
-        x: ldc           #x                 // String ()Ljava/lang/Integer;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
         x: iconst_4
         x: invokestatic  #x                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
         x: areturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           26       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+           11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.Object get();
     descriptor: ()Ljava/lang/Object;
@@ -4094,22 +3397,16 @@
          x: ldc           #x                 // String ()Ljava/lang/Object;
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
-        x: ldc           #x                 // String get
-        x: ldc           #x                 // String ()Ljava/lang/Object;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
         x: aload_0
         x: invokevirtual #x                 // Method get:()Ljava/lang/Integer;
         x: areturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           26       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+           11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   #x;                                     // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
@@ -4118,7 +3415,7 @@
 SourceFile: "TinyFrameworkNestedClasses.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class
   Compiled from "TinyFrameworkNestedClasses.java"
@@ -4134,9 +3431,7 @@
     flags: (0x0001) ACC_PUBLIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static {};
     descriptor: ()V
@@ -4144,7 +3439,7 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 
@@ -4171,18 +3466,14 @@
            11      10     1     x   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   public static #x= #x of #x;           // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 SourceFile: "TinyFrameworkNestedClasses.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass.class
   Compiled from "TinyFrameworkNestedClasses.java"
@@ -4198,18 +3489,14 @@
     flags: (0x0001) ACC_PUBLIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
     descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
     flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static {};
     descriptor: ()V
@@ -4217,7 +3504,7 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 
@@ -4247,9 +3534,7 @@
            11      15     1 this$0   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
     MethodParameters:
       Name                           Flags
       <no name>                      final mandated
@@ -4259,9 +3544,7 @@
 SourceFile: "TinyFrameworkNestedClasses.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1.class
   Compiled from "TinyFrameworkNestedClasses.java"
@@ -4301,7 +3584,7 @@
            11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.Integer get();
     descriptor: ()Ljava/lang/Integer;
@@ -4313,22 +3596,16 @@
          x: ldc           #x                 // String ()Ljava/lang/Integer;
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
-        x: ldc           #x                 // String get
-        x: ldc           #x                 // String ()Ljava/lang/Integer;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
         x: bipush        7
         x: invokestatic  #x                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
         x: areturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           26       6     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+           11       6     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.lang.Object get();
     descriptor: ()Ljava/lang/Object;
@@ -4340,22 +3617,16 @@
          x: ldc           #x                 // String ()Ljava/lang/Object;
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
-        x: ldc           #x                 // String get
-        x: ldc           #x                 // String ()Ljava/lang/Object;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
         x: aload_0
         x: invokevirtual #x                 // Method get:()Ljava/lang/Integer;
         x: areturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           26       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+           11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   public static #x= #x of #x;          // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
@@ -4365,7 +3636,7 @@
 SourceFile: "TinyFrameworkNestedClasses.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass.class
   Compiled from "TinyFrameworkNestedClasses.java"
@@ -4381,9 +3652,7 @@
     flags: (0x0001) ACC_PUBLIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static {};
     descriptor: ()V
@@ -4391,7 +3660,7 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 
@@ -4417,9 +3686,7 @@
            11      11     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   public static #x= #x of #x;          // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
@@ -4427,9 +3694,7 @@
 SourceFile: "TinyFrameworkNestedClasses.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass.class
   Compiled from "TinyFrameworkNestedClasses.java"
@@ -4445,9 +3710,7 @@
     flags: (0x0001) ACC_PUBLIC
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static {};
     descriptor: ()V
@@ -4455,7 +3718,7 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 
@@ -4481,9 +3744,7 @@
            11      11     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
     descriptor: ()Ljava/util/function/Supplier;
@@ -4503,9 +3764,7 @@
     Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   public static #x= #x of #x;           // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
@@ -4514,9 +3773,7 @@
 SourceFile: "TinyFrameworkNestedClasses.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass.class
   Compiled from "TinyFrameworkNestedClasses.java"
@@ -4533,7 +3790,7 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 
@@ -4558,9 +3815,7 @@
            11       6     1     x   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   public static #x= #x of #x;           // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
@@ -4568,9 +3823,7 @@
 SourceFile: "TinyFrameworkNestedClasses.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.class
   Compiled from "TinyFrameworkNestedClasses.java"
@@ -4587,9 +3840,7 @@
     Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
     descriptor: Ljava/util/function/Supplier;
@@ -4597,9 +3848,7 @@
     Signature: #x                          // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses();
     descriptor: ()V
@@ -4626,9 +3875,7 @@
            11      17     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public java.util.function.Supplier<java.lang.Integer> getSupplier();
     descriptor: ()Ljava/util/function/Supplier;
@@ -4652,9 +3899,7 @@
     Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
     descriptor: ()Ljava/util/function/Supplier;
@@ -4674,9 +3919,7 @@
     Signature: #x                          // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   static {};
     descriptor: ()V
@@ -4699,16 +3942,14 @@
       LineNumberTable:
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
   #x;                                    // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
   #x;                                    // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
   #x;                                    // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
   #x;                                    // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
-  public static #x= #x of #x;           // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+  public static #x= #x of #x;            // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
   public static #x= #x of #x;           // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
   public static #x= #x of #x;           // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
   public #x= #x of #x;                  // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
@@ -4717,12 +3958,10 @@
 SourceFile: "TinyFrameworkNestedClasses.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 NestMembers:
   com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
   com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
@@ -4749,7 +3988,7 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 
@@ -4772,9 +4011,7 @@
            11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int foo(int);
     descriptor: (I)I
@@ -4798,19 +4035,15 @@
            11      12     0 value   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "TinyFrameworkPackageRedirect.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.class
   Compiled from "TinyFrameworkRenamedClassCaller.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller
@@ -4826,7 +4059,7 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 
@@ -4849,9 +4082,7 @@
            11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public static int foo(int);
     descriptor: (I)I
@@ -4875,19 +4106,15 @@
            11      12     0 value   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "TinyFrameworkRenamedClassCaller.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 ## Class: com/android/hoststubgen/test/tinyframework/packagetest/A.class
   Compiled from "A.java"
 public class com.android.hoststubgen.test.tinyframework.packagetest.A
@@ -4903,16 +4130,14 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/packagetest/A
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 }
 SourceFile: "A.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/packagetest/sub/A.class
   Compiled from "A.java"
 public class com.android.hoststubgen.test.tinyframework.packagetest.sub.A
@@ -4928,16 +4153,14 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/packagetest/sub/A
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 }
 SourceFile: "A.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C1.class
   Compiled from "C1.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.C1
@@ -4953,16 +4176,14 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/subclasstest/C1
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 }
 SourceFile: "C1.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C2.class
   Compiled from "C2.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1
@@ -4978,16 +4199,14 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/subclasstest/C2
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 }
 SourceFile: "C2.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C3.class
   Compiled from "C3.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2
@@ -5003,16 +4222,14 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/subclasstest/C3
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 }
 SourceFile: "C3.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CA.class
   Compiled from "CA.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.CA
@@ -5028,16 +4245,14 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/subclasstest/CA
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 }
 SourceFile: "CA.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CB.class
   Compiled from "CB.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.CB
@@ -5053,16 +4268,14 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/subclasstest/CB
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 }
 SourceFile: "CB.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C1.class
   Compiled from "Class_C1.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C1 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1
@@ -5085,7 +4298,7 @@
 SourceFile: "Class_C1.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C2.class
   Compiled from "Class_C2.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2
@@ -5108,7 +4321,7 @@
 SourceFile: "Class_C2.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C3.class
   Compiled from "Class_C3.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C3
@@ -5131,7 +4344,7 @@
 SourceFile: "Class_C3.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1.class
   Compiled from "Class_I1.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1 implements com.android.hoststubgen.test.tinyframework.subclasstest.I1
@@ -5154,7 +4367,7 @@
 SourceFile: "Class_I1.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA.class
   Compiled from "Class_I1_IA.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1_IA implements com.android.hoststubgen.test.tinyframework.subclasstest.I1,com.android.hoststubgen.test.tinyframework.subclasstest.IA
@@ -5177,7 +4390,7 @@
 SourceFile: "Class_I1_IA.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I2.class
   Compiled from "Class_I2.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I2 implements com.android.hoststubgen.test.tinyframework.subclasstest.I2
@@ -5200,7 +4413,7 @@
 SourceFile: "Class_I2.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3.class
   Compiled from "Class_I3.java"
 public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3 implements com.android.hoststubgen.test.tinyframework.subclasstest.I3
@@ -5223,7 +4436,7 @@
 SourceFile: "Class_I3.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I1.class
   Compiled from "I1.java"
 public interface com.android.hoststubgen.test.tinyframework.subclasstest.I1
@@ -5239,16 +4452,14 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/subclasstest/I1
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 }
 SourceFile: "I1.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I2.class
   Compiled from "I2.java"
 public interface com.android.hoststubgen.test.tinyframework.subclasstest.I2 extends com.android.hoststubgen.test.tinyframework.subclasstest.I1
@@ -5271,9 +4482,7 @@
 SourceFile: "I2.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I3.class
   Compiled from "I3.java"
 public interface com.android.hoststubgen.test.tinyframework.subclasstest.I3 extends com.android.hoststubgen.test.tinyframework.subclasstest.I2
@@ -5296,9 +4505,7 @@
 SourceFile: "I3.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IA.class
   Compiled from "IA.java"
 public interface com.android.hoststubgen.test.tinyframework.subclasstest.IA
@@ -5314,16 +4521,14 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/subclasstest/IA
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 }
 SourceFile: "IA.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IB.class
   Compiled from "IB.java"
 public interface com.android.hoststubgen.test.tinyframework.subclasstest.IB
@@ -5339,16 +4544,14 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/subclasstest/IB
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 }
 SourceFile: "IB.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 ## Class: com/supported/UnsupportedClass.class
   Compiled from "UnsupportedClass.java"
 public class com.supported.UnsupportedClass
@@ -5363,7 +4566,7 @@
     flags: (0x0012) ACC_PRIVATE, ACC_FINAL
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static {};
     descriptor: ()V
@@ -5385,12 +4588,6 @@
          x: ldc           #x                 // String (I)V
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/supported/UnsupportedClass
-        x: ldc           #x                 // String <init>
-        x: ldc           #x                 // String (I)V
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
         x: aload_0
         x: invokespecial #x                 // Method java/lang/Object."<init>":()V
         x: aload_0
@@ -5400,11 +4597,11 @@
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           26      10     0  this   Lcom/supported/UnsupportedClass;
-           26      10     1 value   I
+           11      10     0  this   Lcom/supported/UnsupportedClass;
+           11      10     1 value   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public int getValue();
     descriptor: ()I
@@ -5416,27 +4613,21 @@
          x: ldc           #x                 // String ()I
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-        x: ldc           #x                 // String com/supported/UnsupportedClass
-        x: ldc           #x                 // String getValue
-        x: ldc           #x                 // String ()I
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
-        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
-        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
         x: aload_0
         x: getfield      #x                 // Field mValue:I
         x: ireturn
       LineNumberTable:
       LocalVariableTable:
         Start  Length  Slot  Name   Signature
-           26       5     0  this   Lcom/supported/UnsupportedClass;
+           11       5     0  this   Lcom/supported/UnsupportedClass;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "UnsupportedClass.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
     android.hosttest.annotation.HostSideTestWholeClassKeep
@@ -5455,7 +4646,7 @@
     Code:
       stack=2, locals=0, args_size=0
          x: ldc           #x                  // class com/unsupported/UnsupportedClass
-         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
 
@@ -5483,9 +4674,7 @@
            11      14     1 value   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public int getValue();
     descriptor: ()I
@@ -5508,19 +4697,15 @@
            11      10     0  this   Lcom/unsupported/UnsupportedClass;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "UnsupportedClass.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
 ## Class: rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.class
   Compiled from "TinyFrameworkToBeRenamed.java"
 public class rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed
@@ -5535,16 +4720,14 @@
     flags: (0x0012) ACC_PRIVATE, ACC_FINAL
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   private static {};
     descriptor: ()V
     flags: (0x000a) ACC_PRIVATE, ACC_STATIC
     Code:
       stack=2, locals=0, args_size=0
-         x: ldc           #x                 // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
@@ -5554,7 +4737,7 @@
     flags: (0x0001) ACC_PUBLIC
     Code:
       stack=4, locals=2, args_size=2
-         x: ldc           #x                 // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
          x: ldc           #x                 // String <init>
          x: ldc           #x                 // String (I)V
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
@@ -5572,16 +4755,14 @@
            11      10     1 value   I
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
   public int getValue();
     descriptor: ()I
     flags: (0x0001) ACC_PUBLIC
     Code:
       stack=4, locals=1, args_size=1
-         x: ldc           #x                 // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
          x: ldc           #x                 // String getValue
          x: ldc           #x                 // String ()I
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
@@ -5595,16 +4776,12 @@
            11       5     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
     RuntimeVisibleAnnotations:
       x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-      x: #x()
-        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "TinyFrameworkToBeRenamed.java"
 RuntimeVisibleAnnotations:
   x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
-  x: #x()
-    com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 RuntimeInvisibleAnnotations:
   x: #x()
-    android.hosttest.annotation.HostSideTestWholeClassStub
+    android.hosttest.annotation.HostSideTestWholeClassKeep
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt
index f064433..3c138d2 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt
@@ -1,9 +1,8 @@
-class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy	stub
-  field stub	stub
-  field keep	keep
+class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy	keep
+  field stub	keep
   # field remove	remove # Implicitly remove
-  method <init>	()V	            stub
-  method addOne	(I)I	        stub
+  method <init>	()V	            keep
+  method addOne	(I)I	        keep
   method addOneInner	(I)I	keep
   method toBeRemoved	(Ljava/lang/String;)V	remove
   method addTwo	(I)I	        @addTwo_host
@@ -11,7 +10,7 @@
   method nativeAddThree	(I)I	@addThree_host
   # method addThree_host	(I)I	# used as a substitute
   method unsupportedMethod	()Ljava/lang/String;	throw
-  method visibleButUsesUnsupportedMethod	()Ljava/lang/String;	stub
+  method visibleButUsesUnsupportedMethod	()Ljava/lang/String;	keep
   method toBeIgnoredObj	()Ljava/lang/String;	ignore
   method toBeIgnoredV	()V	ignore
   method toBeIgnoredZ	()Z	ignore
@@ -27,22 +26,22 @@
 class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy	~com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
 
 # Heuristics rule: Stub all the AIDL classes.
-class :aidl stubclass
+class :aidl keepclass
 
 # Heuristics rule: Stub all the R classes.
-class :r stubclass
+class :r keepclass
 
 # Default is "remove", so let's put all the base classes / interfaces in the stub first.
-class com.android.hoststubgen.test.tinyframework.subclasstest.C1 stub
-class com.android.hoststubgen.test.tinyframework.subclasstest.C2 stub
-class com.android.hoststubgen.test.tinyframework.subclasstest.C3 stub
-class com.android.hoststubgen.test.tinyframework.subclasstest.CA stub
-class com.android.hoststubgen.test.tinyframework.subclasstest.CB stub
-class com.android.hoststubgen.test.tinyframework.subclasstest.I1 stub
-class com.android.hoststubgen.test.tinyframework.subclasstest.I2 stub
-class com.android.hoststubgen.test.tinyframework.subclasstest.I3 stub
-class com.android.hoststubgen.test.tinyframework.subclasstest.IA stub
-class com.android.hoststubgen.test.tinyframework.subclasstest.IB stub
+class com.android.hoststubgen.test.tinyframework.subclasstest.C1 keep
+class com.android.hoststubgen.test.tinyframework.subclasstest.C2 keep
+class com.android.hoststubgen.test.tinyframework.subclasstest.C3 keep
+class com.android.hoststubgen.test.tinyframework.subclasstest.CA keep
+class com.android.hoststubgen.test.tinyframework.subclasstest.CB keep
+class com.android.hoststubgen.test.tinyframework.subclasstest.I1 keep
+class com.android.hoststubgen.test.tinyframework.subclasstest.I2 keep
+class com.android.hoststubgen.test.tinyframework.subclasstest.I3 keep
+class com.android.hoststubgen.test.tinyframework.subclasstest.IA keep
+class com.android.hoststubgen.test.tinyframework.subclasstest.IB keep
 
 # Then define inheritance based policies.
 class *com.android.hoststubgen.test.tinyframework.subclasstest.C1 keep
@@ -52,15 +51,15 @@
 class *com.android.hoststubgen.test.tinyframework.subclasstest.IA remove
 
 # Test package directive
-package com.android.hoststubgen.test.tinyframework.packagetest stub
+package com.android.hoststubgen.test.tinyframework.packagetest keep
 class com.android.hoststubgen.test.tinyframework.packagetest.B remove
 class com.android.hoststubgen.test.tinyframework.packagetest.sub.B remove
 # The following rules are the same as above
-# class com.android.hoststubgen.test.tinyframework.packagetest.A stub
-# class com.android.hoststubgen.test.tinyframework.packagetest.sub.A stub
+# class com.android.hoststubgen.test.tinyframework.packagetest.A keep
+# class com.android.hoststubgen.test.tinyframework.packagetest.sub.A keep
 
 # Used to test method call replacement.
-class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace stubclass
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace keepclass
   method originalAdd (II)I @com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo.add
 
 # Used to test method call replacement.
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/run-test-manually.sh b/tools/hoststubgen/hoststubgen/test-tiny-framework/run-test-manually.sh
index 872bbf8..80ebf3a 100755
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/run-test-manually.sh
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/run-test-manually.sh
@@ -43,8 +43,7 @@
 
 tiny_framework_classes=$out/tiny-framework/classes/
 tiny_framework_jar=$out/tiny-framework.jar
-tiny_framework_host_stub_jar=$out/tiny-framework_host_stub.jar
-tiny_framework_host_impl_jar=$out/tiny-framework_host_impl.jar
+tiny_framework_host_jar=$out/tiny-framework_host.jar
 
 tiny_test_classes=$out/tiny-test/classes/
 tiny_test_jar=$out/tiny-test.jar
@@ -87,8 +86,7 @@
 run $HOSTSTUBGEN \
     @../hoststubgen-standard-options.txt \
     --in-jar $tiny_framework_jar \
-    --out-stub-jar $tiny_framework_host_stub_jar \
-    --out-impl-jar $tiny_framework_host_impl_jar \
+    --out-jar $tiny_framework_host_jar \
     --policy-override-file policy-override-tiny-framework.txt \
     --gen-keep-all-file out/tiny-framework_keep_all.txt \
     --gen-input-dump-file out/tiny-framework_dump.txt \
@@ -97,14 +95,14 @@
     $HOSTSTUBGEN_OPTS
 
 # Extract the jar files, so we can look into them.
-extract $tiny_framework_host_stub_jar $tiny_framework_host_impl_jar
+extract $tiny_framework_host_jar
 
 # Build the test
 echo "# Building tiny-test..."
 run $JAVAC \
     -cp $( \
         join : \
-        $tiny_framework_host_stub_jar \
+        $tiny_framework_jar \
         "${test_compile_classpaths[@]}" \
         ) \
     -d $tiny_test_classes \
@@ -124,7 +122,7 @@
     -cp $( \
         join : \
         $tiny_test_jar \
-        $tiny_framework_host_impl_jar \
+        $tiny_framework_host_jar \
         "${test_compile_classpaths[@]}" \
         "${test_runtime_classpaths[@]}" \
         ) \
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.java
index 30dfc80..ed0fa26 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.java
@@ -18,39 +18,30 @@
 import android.hosttest.annotation.HostSideTestClassLoadHook;
 import android.hosttest.annotation.HostSideTestKeep;
 import android.hosttest.annotation.HostSideTestRemove;
-import android.hosttest.annotation.HostSideTestStub;
 import android.hosttest.annotation.HostSideTestSubstitute;
 import android.hosttest.annotation.HostSideTestThrow;
 
 /**
  * Test without class-wide annotations.
  */
-@HostSideTestStub
+@HostSideTestKeep
 @HostSideTestClassLoadHook(
         "com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded")
 public class TinyFrameworkAnnotations {
-    @HostSideTestStub
+    @HostSideTestKeep
     public TinyFrameworkAnnotations() {
     }
 
-    @HostSideTestStub
-    public int stub = 1;
-
     @HostSideTestKeep
-    public int keep = 2;
+    public int keep = 1;
 
     // Members will be deleted by default.
     // Deleted fields cannot have an initial value, because otherwise .ctor will fail to set it at
     // runtime.
     public int remove;
 
-    @HostSideTestStub
-    public int addOne(int value) {
-        return addOneInner(value);
-    }
-
     @HostSideTestKeep
-    public int addOneInner(int value) {
+    public int addOne(int value) {
         return value + 1;
     }
 
@@ -59,7 +50,6 @@
         throw new RuntimeException();
     }
 
-    @HostSideTestStub
     @HostSideTestSubstitute(suffix = "_host")
     public int addTwo(int value) {
         throw new RuntimeException("not supported on host side");
@@ -69,7 +59,6 @@
         return value + 2;
     }
 
-    @HostSideTestStub
     @HostSideTestSubstitute(suffix = "_host")
     public static native int nativeAddThree(int value);
 
@@ -82,9 +71,4 @@
     public String unsupportedMethod() {
         return "This value shouldn't be seen on the host side.";
     }
-
-    @HostSideTestStub
-    public String visibleButUsesUnsupportedMethod() {
-        return unsupportedMethod();
-    }
 }
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.java
deleted file mode 100644
index f530207..0000000
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2023 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.hoststubgen.test.tinyframework;
-
-import android.hosttest.annotation.HostSideTestKeep;
-import android.hosttest.annotation.HostSideTestStub;
-import android.hosttest.annotation.HostSideTestWholeClassStub;
-
-/**
- * Used by the benchmark.
- */
-@HostSideTestWholeClassStub
-public class TinyFrameworkCallerCheck {
-
-    /**
-     * This method uses an inner method (which has the caller check).
-     *
-     * Benchmark result: 768ns
-     */
-    public static int getOne_withCheck() {
-        return Impl.getOneKeep();
-    }
-
-    /**
-     * This method doesn't have any caller check.
-     *
-     * Benchmark result: 2ns
-     */
-    public static int getOne_noCheck() {
-        return Impl.getOneStub();
-    }
-
-    private static class Impl {
-        @HostSideTestKeep
-        public static int getOneKeep() {
-            return 1;
-        }
-
-        @HostSideTestStub
-        public static int getOneStub() {
-            return 1;
-        }
-    }
-}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.java
index 98fc634..f734790 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.java
@@ -15,12 +15,12 @@
  */
 package com.android.hoststubgen.test.tinyframework;
 
-import android.hosttest.annotation.HostSideTestWholeClassStub;
+import android.hosttest.annotation.HostSideTestWholeClassKeep;
 
 import java.util.HashSet;
 import java.util.Set;
 
-@HostSideTestWholeClassStub
+@HostSideTestWholeClassKeep
 public class TinyFrameworkClassLoadHook {
     private TinyFrameworkClassLoadHook() {
     }
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations.java
index a626bc9..e83163e 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations.java
@@ -15,16 +15,20 @@
  */
 package com.android.hoststubgen.test.tinyframework;
 
+import android.hosttest.annotation.HostSideTestRemove;
 import android.hosttest.annotation.HostSideTestSubstitute;
 import android.hosttest.annotation.HostSideTestThrow;
-import android.hosttest.annotation.HostSideTestWholeClassStub;
+import android.hosttest.annotation.HostSideTestWholeClassKeep;
 
-@HostSideTestWholeClassStub
+@HostSideTestWholeClassKeep
 public class TinyFrameworkClassWideAnnotations {
     public TinyFrameworkClassWideAnnotations() {
     }
 
-    public int stub = 1;
+    public int keep = 1;
+
+    @HostSideTestRemove
+    public int remove;
 
     public int addOne(int value) {
         return value + 1;
@@ -39,12 +43,13 @@
         return value + 2;
     }
 
+    @HostSideTestRemove
+    public void toBeRemoved(String foo) {
+        throw new RuntimeException();
+    }
+
     @HostSideTestThrow
     public String unsupportedMethod() {
         return "This value shouldn't be seen on the host side.";
     }
-
-    public String visibleButUsesUnsupportedMethod() {
-        return unsupportedMethod();
-    }
 }
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.java
index 8324ed9..3df21d9 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.java
@@ -15,18 +15,16 @@
  */
 package com.android.hoststubgen.test.tinyframework;
 
-import android.hosttest.annotation.HostSideTestClassLoadHook;
-import android.hosttest.annotation.HostSideTestStub;
-import android.hosttest.annotation.HostSideTestWholeClassStub;
+import android.hosttest.annotation.HostSideTestKeep;
 
-@HostSideTestStub
+@HostSideTestKeep
 public class TinyFrameworkClassWithInitializerDefault {
     static {
         sInitialized = true;
     }
 
-    @HostSideTestStub
+    @HostSideTestKeep
     public static boolean sInitialized;
-    @HostSideTestStub
+    @HostSideTestKeep
     public static Object sObject = new Object();
 }
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.java
index ea1ad93..cc665de 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.java
@@ -16,20 +16,20 @@
 package com.android.hoststubgen.test.tinyframework;
 
 import android.hosttest.annotation.HostSideTestClassLoadHook;
+import android.hosttest.annotation.HostSideTestKeep;
 import android.hosttest.annotation.HostSideTestStaticInitializerKeep;
-import android.hosttest.annotation.HostSideTestStub;
 
 @HostSideTestClassLoadHook(
         "com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded")
-@HostSideTestStub
+@HostSideTestKeep
 @HostSideTestStaticInitializerKeep
 public class TinyFrameworkClassWithInitializerStub {
     static {
         sInitialized = true;
     }
 
-    @HostSideTestStub
+    @HostSideTestKeep
     public static boolean sInitialized;
-    @HostSideTestStub
+    @HostSideTestKeep
     public static Object sObject = new Object();
 }
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.java
index 51f4818..f833ad8 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.java
@@ -16,15 +16,14 @@
 package com.android.hoststubgen.test.tinyframework;
 
 import android.hosttest.annotation.HostSideTestKeep;
-import android.hosttest.annotation.HostSideTestStub;
 
-@HostSideTestStub
+@HostSideTestKeep
 public enum TinyFrameworkEnumComplex {
-    @HostSideTestStub
+    @HostSideTestKeep
     RED("Red", "R"),
-    @HostSideTestStub
+    @HostSideTestKeep
     GREEN("Green", "G"),
-    @HostSideTestStub
+    @HostSideTestKeep
     BLUE("Blue", "B");
 
     @HostSideTestKeep
@@ -33,18 +32,18 @@
     @HostSideTestKeep
     private final String mShortName;
 
-    @HostSideTestStub
+    @HostSideTestKeep
     TinyFrameworkEnumComplex(String longName, String shortName) {
         mLongName = longName;
         mShortName = shortName;
     }
 
-    @HostSideTestStub
+    @HostSideTestKeep
     public String getLongName() {
         return mLongName;
     }
 
-    @HostSideTestStub
+    @HostSideTestKeep
     public String getShortName() {
         return mShortName;
     }
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.java
index f440d86..c023169 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.java
@@ -15,12 +15,12 @@
  */
 package com.android.hoststubgen.test.tinyframework;
 
-import android.hosttest.annotation.HostSideTestStub;
+import android.hosttest.annotation.HostSideTestKeep;
 
-@HostSideTestStub
+@HostSideTestKeep
 public enum TinyFrameworkEnumSimple {
-    @HostSideTestStub
+    @HostSideTestKeep
     CAT,
-    @HostSideTestStub
+    @HostSideTestKeep
     DOG,
 }
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.java
index 909d3b4..f7cae7d 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.java
@@ -15,9 +15,9 @@
  */
 package com.android.hoststubgen.test.tinyframework;
 
-import android.hosttest.annotation.HostSideTestWholeClassStub;
+import android.hosttest.annotation.HostSideTestWholeClassKeep;
 
-@HostSideTestWholeClassStub
+@HostSideTestWholeClassKeep
 public class TinyFrameworkExceptionTester {
     public static int testException() {
         try {
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java
index 1977c90..ec1efba 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java
@@ -24,17 +24,11 @@
 
     public int stub = 1;
 
-    public int keep = 2;
-
     // Removed fields cannot have an initial value, because otherwise .ctor will fail to set it at
     // runtime.
     public int remove;
 
     public int addOne(int value) {
-        return addOneInner(value);
-    }
-
-    public int addOneInner(int value) {
         return value + 1;
     }
 
@@ -95,8 +89,4 @@
     public String unsupportedMethod() {
         return "This value shouldn't be seen on the host side.";
     }
-
-    public String visibleButUsesUnsupportedMethod() {
-        return unsupportedMethod();
-    }
 }
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.java
index 0d1203b..1ca653e 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.java
@@ -15,8 +15,8 @@
  */
 package com.android.hoststubgen.test.tinyframework;
 
+import android.hosttest.annotation.HostSideTestKeep;
 import android.hosttest.annotation.HostSideTestStaticInitializerKeep;
-import android.hosttest.annotation.HostSideTestStub;
 
 import java.util.function.Supplier;
 
@@ -28,48 +28,48 @@
  *
  * Implicit filter should take care of them.
  */
-@HostSideTestStub
+@HostSideTestKeep
 @HostSideTestStaticInitializerKeep
 public class TinyFrameworkLambdas {
-    @HostSideTestStub
+    @HostSideTestKeep
     public TinyFrameworkLambdas() {
     }
 
-    @HostSideTestStub
+    @HostSideTestKeep
     public final Supplier<Integer> mSupplier = () -> 1;
 
-    @HostSideTestStub
+    @HostSideTestKeep
     public static final Supplier<Integer> sSupplier = () -> 2;
 
-    @HostSideTestStub
+    @HostSideTestKeep
     public Supplier<Integer> getSupplier() {
         return () -> 3;
     }
 
-    @HostSideTestStub
+    @HostSideTestKeep
     public static Supplier<Integer> getSupplier_static() {
         return () -> 4;
     }
 
-    @HostSideTestStub
+    @HostSideTestKeep
     @HostSideTestStaticInitializerKeep
     public static class Nested {
-        @HostSideTestStub
+        @HostSideTestKeep
         public Nested() {
         }
 
-        @HostSideTestStub
+        @HostSideTestKeep
         public final Supplier<Integer> mSupplier = () -> 5;
 
-        @HostSideTestStub
+        @HostSideTestKeep
         public static final Supplier<Integer> sSupplier = () -> 6;
 
-        @HostSideTestStub
+        @HostSideTestKeep
         public Supplier<Integer> getSupplier() {
             return () -> 7;
         }
 
-        @HostSideTestStub
+        @HostSideTestKeep
         public static Supplier<Integer> getSupplier_static() {
             return () -> 8;
         }
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.java
index 1ff3744..57c69a3 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.java
@@ -15,11 +15,11 @@
  */
 package com.android.hoststubgen.test.tinyframework;
 
-import android.hosttest.annotation.HostSideTestWholeClassStub;
+import android.hosttest.annotation.HostSideTestWholeClassKeep;
 
 import java.util.concurrent.atomic.AtomicBoolean;
 
-@HostSideTestWholeClassStub
+@HostSideTestWholeClassKeep
 public class TinyFrameworkMethodCallReplace {
     //  This method should return true.
     public static boolean nonStaticMethodCallReplaceTester() throws Exception {
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java
index 09ee183..73b5e2f 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java
@@ -15,11 +15,12 @@
  */
 package com.android.hoststubgen.test.tinyframework;
 
+import android.hosttest.annotation.HostSideTestKeep;
 import android.hosttest.annotation.HostSideTestNativeSubstitutionClass;
 import android.hosttest.annotation.HostSideTestThrow;
-import android.hosttest.annotation.HostSideTestWholeClassStub;
+import android.hosttest.annotation.HostSideTestWholeClassKeep;
 
-@HostSideTestWholeClassStub
+@HostSideTestWholeClassKeep
 @HostSideTestNativeSubstitutionClass("TinyFrameworkNative_host")
 public class TinyFrameworkNative {
     public static native int nativeAddTwo(int arg);
@@ -49,6 +50,9 @@
     @HostSideTestThrow
     public static native void nativeStillNotSupported();
 
+    @HostSideTestKeep
+    public static native void nativeStillKeep();
+
     public static void nativeStillNotSupported_should_be_like_this() {
         throw new RuntimeException();
     }
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.java
index fec307a..c1ea2ee 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.java
@@ -15,11 +15,11 @@
  */
 package com.android.hoststubgen.test.tinyframework;
 
-import android.hosttest.annotation.HostSideTestWholeClassStub;
+import android.hosttest.annotation.HostSideTestWholeClassKeep;
 
 import java.util.function.Supplier;
 
-@HostSideTestWholeClassStub
+@HostSideTestWholeClassKeep
 public class TinyFrameworkNestedClasses {
     public final Supplier<Integer> mSupplier = new Supplier<Integer>() {
         @Override
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect.java
index a82be54..941fcff 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect.java
@@ -15,9 +15,9 @@
  */
 package com.android.hoststubgen.test.tinyframework;
 
-import android.hosttest.annotation.HostSideTestWholeClassStub;
+import android.hosttest.annotation.HostSideTestWholeClassKeep;
 
-@HostSideTestWholeClassStub
+@HostSideTestWholeClassKeep
 public class TinyFrameworkPackageRedirect {
     /**
      * A method that uses "unsupported" class. HostStubGen will redirect them to the "supported"
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.java
index 31a164a..707bc0e 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.java
@@ -15,9 +15,9 @@
  */
 package com.android.hoststubgen.test.tinyframework;
 
-import android.hosttest.annotation.HostSideTestWholeClassStub;
+import android.hosttest.annotation.HostSideTestWholeClassKeep;
 
-@HostSideTestWholeClassStub
+@HostSideTestWholeClassKeep
 public class TinyFrameworkRenamedClassCaller {
     /** Calls the class that'll be renamed. */
     public static int foo(int value) {
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.java
index 1430bcb..8319ced 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.java
@@ -15,12 +15,12 @@
  */
 package com.android.hoststubgen.test.tinyframework;
 
-import android.hosttest.annotation.HostSideTestWholeClassStub;
+import android.hosttest.annotation.HostSideTestWholeClassKeep;
 
 /**
  * This class will be renamed by the "rename" directive in the policy file.
  */
-@HostSideTestWholeClassStub
+@HostSideTestWholeClassKeep
 public class TinyFrameworkToBeRenamed {
     private final int mValue;
 
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/unsupported/UnsupportedClass.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/unsupported/UnsupportedClass.java
index 0409b02..92f41ac 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/unsupported/UnsupportedClass.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/unsupported/UnsupportedClass.java
@@ -15,10 +15,10 @@
  */
 package com.unsupported;
 
-import android.hosttest.annotation.HostSideTestWholeClassStub;
+import android.hosttest.annotation.HostSideTestWholeClassKeep;
 
 // Used for testing --package-redirect.
-@HostSideTestWholeClassStub
+@HostSideTestWholeClassKeep
 public class UnsupportedClass {
     public UnsupportedClass(int value) {
         throw new RuntimeException("This class is not supported");
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/LargeTest.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/LargeTest.java
deleted file mode 100644
index 76bbcad..0000000
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/LargeTest.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2023 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.hoststubgen.test.tinyframework;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * We don't want to use any android classes in this module, so we create our own copy of it here.
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD, ElementType.TYPE})
-public @interface LargeTest {}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotationsTest.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotationsTest.java
index 181902a..1ae0493 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotationsTest.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotationsTest.java
@@ -17,6 +17,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.junit.Assert.assertThrows;
+
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -29,19 +31,15 @@
     public void testSimple() {
         TinyFrameworkAnnotations tfc = new TinyFrameworkAnnotations();
         assertThat(tfc.addOne(1)).isEqualTo(2);
-        assertThat(tfc.stub).isEqualTo(1);
+        assertThat(tfc.keep).isEqualTo(1);
     }
 
-//    @Test
-//    public void testDoesntCompile() {
-//        TinyFrameworkAnnotations tfc = new TinyFrameworkAnnotations();
-//
-//        tfc.addOneInner(1); // Shouldn't compile.
-//        tfc.toBeRemoved("abc"); // Shouldn't compile.
-//        tfc.unsupportedMethod(); // Shouldn't compile.
-//        int a = tfc.keep; // Shouldn't compile
-//        int b = tfc.remove; // Shouldn't compile
-//    }
+    @Test
+    public void testRemove() {
+        TinyFrameworkAnnotations tfc = new TinyFrameworkAnnotations();
+        assertThrows(NoSuchMethodError.class, () -> tfc.toBeRemoved("abc"));
+        assertThrows(NoSuchFieldError.class, () -> tfc.remove = 1);
+    }
 
     @Test
     public void testSubstitute() {
@@ -56,11 +54,11 @@
     }
 
     @Test
-    public void testVisibleButUsesUnsupportedMethod() {
+    public void testUnsupportedMethod() {
         TinyFrameworkAnnotations tfc = new TinyFrameworkAnnotations();
 
         thrown.expect(RuntimeException.class);
         thrown.expectMessage("not yet supported");
-        tfc.visibleButUsesUnsupportedMethod();
+        tfc.unsupportedMethod();
     }
 }
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkBenchmark.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkBenchmark.java
deleted file mode 100644
index d57735b..0000000
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkBenchmark.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2023 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.hoststubgen.test.tinyframework;
-
-import org.junit.Test;
-
-import java.text.DecimalFormat;
-
-/**
- * Contains simple micro-benchmarks.
- */
-@LargeTest
-public class TinyFrameworkBenchmark {
-    private static final int MINIMAL_ITERATION = 1000;
-    private static final int MEASURE_SECONDS = 1;
-
-    private static final DecimalFormat sFormatter = new DecimalFormat("#,###");
-
-    private void doBenchmark(String name, Runnable r) {
-        // Worm up
-        for (int i = 0; i < MINIMAL_ITERATION; i++) {
-            r.run();
-        }
-
-        // Start measuring.
-        final long start = System.nanoTime();
-        final long end = start + MEASURE_SECONDS * 1_000_000_000L;
-
-        double iteration = 0;
-        while (System.nanoTime() <= end) {
-            for (int i = 0; i < MINIMAL_ITERATION; i++) {
-                r.run();
-            }
-            iteration += MINIMAL_ITERATION;
-        }
-
-        final long realEnd = System.nanoTime();
-
-        System.out.println(String.format("%s\t%s", name,
-                sFormatter.format((((double) realEnd - start)) / iteration)));
-    }
-
-    /**
-     * Micro-benchmark for a method without a non-stub caller check.
-     */
-    @Test
-    public void benchNoCallerCheck() {
-        doBenchmark("No caller check", TinyFrameworkCallerCheck::getOne_noCheck);
-    }
-
-    /**
-     * Micro-benchmark for a method with a non-stub caller check.
-     */
-    @Test
-    public void benchWithCallerCheck() {
-        doBenchmark("With caller check", TinyFrameworkCallerCheck::getOne_withCheck);
-    }
-}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
index dda5a05..14229a0 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
@@ -17,7 +17,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThrows;
 
 import com.android.hoststubgen.test.tinyframework.R.Nested;
 
@@ -40,16 +40,12 @@
         assertThat(tfc.stub).isEqualTo(1);
     }
 
-//    @Test
-//    public void testDoesntCompile() {
-//        TinyFrameworkClass tfc = new TinyFrameworkClass();
-//
-//        tfc.addOneInner(1); // Shouldn't compile.
-//        tfc.toBeRemoved("abc"); // Shouldn't compile.
-//        tfc.unsupportedMethod(); // Shouldn't compile.
-//        int a = tfc.keep; // Shouldn't compile
-//        int b = tfc.remove; // Shouldn't compile
-//    }
+    @Test
+    public void testRemove() {
+        TinyFrameworkForTextPolicy tfc = new TinyFrameworkForTextPolicy();
+        assertThrows(NoSuchMethodError.class, () -> tfc.toBeRemoved("abc"));
+        assertThrows(NoSuchFieldError.class, () -> tfc.remove = 1);
+    }
 
     @Test
     public void testIgnore() {
@@ -78,12 +74,12 @@
     }
 
     @Test
-    public void testVisibleButUsesUnsupportedMethod() {
+    public void testUnsupportedMethod() {
         TinyFrameworkForTextPolicy tfc = new TinyFrameworkForTextPolicy();
 
         thrown.expect(RuntimeException.class);
         thrown.expectMessage("not yet supported");
-        tfc.visibleButUsesUnsupportedMethod();
+        tfc.unsupportedMethod();
     }
 
     @Test
@@ -149,28 +145,22 @@
     }
 
     @Test
-    public void testSubstituteNativeWithThrow() throws Exception {
-        // We can't use TinyFrameworkNative.nativeStillNotSupported() directly in this class,
-        // because @Throw implies @Keep (not @Stub), and we currently compile this test
-        // against the stub jar (so it won't contain @Throw methods).
-        //
-        // But the method exists at runtime, so we can use reflections to call it.
-        //
-        // In the real Ravenwood environment, we don't use HostStubGen's stub jar at all,
-        // so it's not a problem.
+    public void testSubstituteNativeWithThrow() {
+        thrown.expect(RuntimeException.class);
+        thrown.expectMessage("not yet supported");
 
-        final var clazz = TinyFrameworkNative.class;
-        final var method = clazz.getMethod("nativeStillNotSupported");
+        TinyFrameworkNative.nativeStillNotSupported();
+    }
 
-        try {
-            method.invoke(null);
+    @Test
+    public void testSubstituteNativeWithKeep() {
+        // We don't want to complicate the test by setting up JNI,
+        // so to test out whether the native method is preserved, we
+        // check whether calling it will throw UnsatisfiedLinkError,
+        // which would only happen on native methods.
+        thrown.expect(UnsatisfiedLinkError.class);
 
-            fail("java.lang.reflect.InvocationTargetException expected");
-
-        } catch (java.lang.reflect.InvocationTargetException e) {
-            var inner = e.getCause();
-            assertThat(inner.getMessage()).contains("not yet supported");
-        }
+        TinyFrameworkNative.nativeStillKeep();
     }
 
     @Test
@@ -179,7 +169,6 @@
         thrown.expectMessage("Outer exception");
 
         TinyFrameworkExceptionTester.testException();
-
     }
 
     @Test
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotationsTest.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotationsTest.java
index 83753b5..34c98e9 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotationsTest.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotationsTest.java
@@ -17,6 +17,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.junit.Assert.assertThrows;
+
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -29,7 +31,14 @@
     public void testSimple() {
         var tfc = new TinyFrameworkClassWideAnnotations();
         assertThat(tfc.addOne(1)).isEqualTo(2);
-        assertThat(tfc.stub).isEqualTo(1);
+        assertThat(tfc.keep).isEqualTo(1);
+    }
+
+    @Test
+    public void testRemove() {
+        var tfc = new TinyFrameworkClassWideAnnotations();
+        assertThrows(NoSuchMethodError.class, () -> tfc.toBeRemoved("abc"));
+        assertThrows(NoSuchFieldError.class, () -> tfc.remove = 1);
     }
 
     @Test
@@ -39,12 +48,12 @@
     }
 
     @Test
-    public void testVisibleButUsesUnsupportedMethod() {
+    public void testUnsupportedMethod() {
         var tfc = new TinyFrameworkClassWideAnnotations();
 
         thrown.expect(RuntimeException.class);
         thrown.expectMessage("not yet supported");
-        tfc.visibleButUsesUnsupportedMethod();
+        tfc.unsupportedMethod();
     }
 
     @Test
diff --git a/tools/hoststubgen/hoststubgen/test/com/android/hoststubgen/utils/ClassFilterTest.kt b/tools/hoststubgen/hoststubgen/test/com/android/hoststubgen/utils/ClassFilterTest.kt
index f651514..85b6e80 100644
--- a/tools/hoststubgen/hoststubgen/test/com/android/hoststubgen/utils/ClassFilterTest.kt
+++ b/tools/hoststubgen/hoststubgen/test/com/android/hoststubgen/utils/ClassFilterTest.kt
@@ -72,6 +72,18 @@
     }
 
     @Test
+    fun testNestedClass() {
+        val f = ClassFilter.buildFromString("a.b.c\nm.n.o\$p\n", false, "X")
+        assertThat(f.matches("a/b/c")).isEqualTo(true)
+        assertThat(f.matches("a/b/c\$d")).isEqualTo(true)
+        assertThat(f.matches("a/b/c\$d\$e")).isEqualTo(true)
+        assertThat(f.matches("m/n/o")).isEqualTo(false)
+        assertThat(f.matches("m/n/o\$p")).isEqualTo(true)
+        assertThat(f.matches("m/n/o\$p\$r")).isEqualTo(true)
+        assertThat(f.matches("m/n/o\$p\$r\$")).isEqualTo(true)
+    }
+
+    @Test
     fun testBadFilter1() {
         try {
             ClassFilter.buildFromString("""