Merge "Ringtone picker to handle RESULT_CANCELED from Add ringtone" into main
diff --git a/core/api/current.txt b/core/api/current.txt
index de2b41c..2900bc8 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -39247,6 +39247,7 @@
     method @Deprecated public boolean isInsideSecureHardware();
     method public boolean isInvalidatedByBiometricEnrollment();
     method public boolean isTrustedUserPresenceRequired();
+    method @FlaggedApi("android.security.keyinfo_unlocked_device_required") public boolean isUnlockedDeviceRequired();
     method public boolean isUserAuthenticationRequired();
     method public boolean isUserAuthenticationRequirementEnforcedBySecureHardware();
     method public boolean isUserAuthenticationValidWhileOnBody();
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 194001ad..12802e4 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -298,7 +298,7 @@
     field public static final String RECOVER_KEYSTORE = "android.permission.RECOVER_KEYSTORE";
     field public static final String REGISTER_CALL_PROVIDER = "android.permission.REGISTER_CALL_PROVIDER";
     field public static final String REGISTER_CONNECTION_MANAGER = "android.permission.REGISTER_CONNECTION_MANAGER";
-    field @FlaggedApi("com.android.net.flags.register_nsd_offload_engine") public static final String REGISTER_NSD_OFFLOAD_ENGINE = "android.permission.REGISTER_NSD_OFFLOAD_ENGINE";
+    field @FlaggedApi("android.net.platform.flags.register_nsd_offload_engine") public static final String REGISTER_NSD_OFFLOAD_ENGINE = "android.permission.REGISTER_NSD_OFFLOAD_ENGINE";
     field public static final String REGISTER_SIM_SUBSCRIPTION = "android.permission.REGISTER_SIM_SUBSCRIPTION";
     field public static final String REGISTER_STATS_PULL_ATOM = "android.permission.REGISTER_STATS_PULL_ATOM";
     field public static final String REMOTE_DISPLAY_PROVIDER = "android.permission.REMOTE_DISPLAY_PROVIDER";
diff --git a/core/java/android/net/flags.aconfig b/core/java/android/net/flags.aconfig
index 6efb872..9f9aef8 100644
--- a/core/java/android/net/flags.aconfig
+++ b/core/java/android/net/flags.aconfig
@@ -17,3 +17,9 @@
     bug: "307898240"
 }
 
+flag {
+  name: "register_nsd_offload_engine"
+  namespace: "android_core_networking"
+  description: "Flag for registerOffloadEngine API in NsdManager"
+  bug: "294777050"
+}
diff --git a/core/java/android/os/storage/OWNERS b/core/java/android/os/storage/OWNERS
index 5e0a563..a26fb62 100644
--- a/core/java/android/os/storage/OWNERS
+++ b/core/java/android/os/storage/OWNERS
@@ -3,11 +3,15 @@
 # Please assign new bugs to android-storage-triage@, not to individual people
 
 # Android Storage Team
+aibra@google.com
+akgaurav@google.com
 alukin@google.com
 ankitavyas@google.com
 dipankarb@google.com
 gargshivam@google.com
+ishneet@google.com
 krishang@google.com
+oeissa@google.com
 riyaghai@google.com
 sahanas@google.com
 shikhamalhotra@google.com
diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig
index 7631454..5e7edda 100644
--- a/core/java/android/security/flags.aconfig
+++ b/core/java/android/security/flags.aconfig
@@ -31,6 +31,13 @@
 }
 
 flag {
+    name: "keyinfo_unlocked_device_required"
+    namespace: "hardware_backed_security"
+    description: "Add the API android.security.keystore.KeyInfo#isUnlockedDeviceRequired()"
+    bug: "296475382"
+}
+
+flag {
     name: "deprecate_fsv_sig"
     namespace: "hardware_backed_security"
     description: "Feature flag for deprecating .fsv_sig"
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index a436e08a..2eece6d 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -69,6 +69,7 @@
     private final String mName;
     private final int mVendorId;
     private final int mProductId;
+    private final int mDeviceBus;
     private final String mDescriptor;
     private final InputDeviceIdentifier mIdentifier;
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
@@ -468,8 +469,8 @@
      * Called by native code
      */
     private InputDevice(int id, int generation, int controllerNumber, String name, int vendorId,
-            int productId, String descriptor, boolean isExternal, int sources, int keyboardType,
-            KeyCharacterMap keyCharacterMap, @Nullable String keyboardLanguageTag,
+            int productId, int deviceBus, String descriptor, boolean isExternal, int sources,
+            int keyboardType, KeyCharacterMap keyCharacterMap, @Nullable String keyboardLanguageTag,
             @Nullable String keyboardLayoutType, boolean hasVibrator, boolean hasMicrophone,
             boolean hasButtonUnderPad, boolean hasSensor, boolean hasBattery, int usiVersionMajor,
             int usiVersionMinor, int associatedDisplayId) {
@@ -479,6 +480,7 @@
         mName = name;
         mVendorId = vendorId;
         mProductId = productId;
+        mDeviceBus = deviceBus;
         mDescriptor = descriptor;
         mIsExternal = isExternal;
         mSources = sources;
@@ -512,6 +514,7 @@
         mName = in.readString();
         mVendorId = in.readInt();
         mProductId = in.readInt();
+        mDeviceBus = in.readInt();
         mDescriptor = in.readString();
         mIsExternal = in.readInt() != 0;
         mSources = in.readInt();
@@ -551,6 +554,7 @@
         private String mName = "";
         private int mVendorId = 0;
         private int mProductId = 0;
+        private int mDeviceBus = 0;
         private String mDescriptor = "";
         private boolean mIsExternal = false;
         private int mSources = 0;
@@ -604,6 +608,12 @@
             return this;
         }
 
+        /** @see InputDevice#getDeviceBus() */
+        public Builder setDeviceBus(int deviceBus) {
+            mDeviceBus = deviceBus;
+            return this;
+        }
+
         /** @see InputDevice#getDescriptor() */
         public Builder setDescriptor(String descriptor) {
             mDescriptor = descriptor;
@@ -705,6 +715,7 @@
                     mName,
                     mVendorId,
                     mProductId,
+                    mDeviceBus,
                     mDescriptor,
                     mIsExternal,
                     mSources,
@@ -846,6 +857,21 @@
     }
 
     /**
+     * Gets the device bus used by given device, if available.
+     * <p>
+     * The device bus is the communication system used for transferring data
+     * (e.g. USB, Bluetooth etc.). This value comes from the kernel (from input.h).
+     * A value of 0 will be assigned where the device bus is not available.
+     * </p>
+     *
+     * @return The device bus of a given device
+     * @hide
+     */
+    public int getDeviceBus() {
+        return mDeviceBus;
+    }
+
+    /**
      * Gets the input device descriptor, which is a stable identifier for an input device.
      * <p>
      * An input device descriptor uniquely identifies an input device.  Its value
@@ -1444,6 +1470,7 @@
         out.writeString(mName);
         out.writeInt(mVendorId);
         out.writeInt(mProductId);
+        out.writeInt(mDeviceBus);
         out.writeString(mDescriptor);
         out.writeInt(mIsExternal ? 1 : 0);
         out.writeInt(mSources);
diff --git a/core/jni/android_view_InputDevice.cpp b/core/jni/android_view_InputDevice.cpp
index f97d41b..baea3bc 100644
--- a/core/jni/android_view_InputDevice.cpp
+++ b/core/jni/android_view_InputDevice.cpp
@@ -83,7 +83,8 @@
                                           deviceInfo.getId(), deviceInfo.getGeneration(),
                                           deviceInfo.getControllerNumber(), nameObj.get(),
                                           static_cast<int32_t>(ident.vendor),
-                                          static_cast<int32_t>(ident.product), descriptorObj.get(),
+                                          static_cast<int32_t>(ident.product),
+                                          static_cast<int32_t>(ident.bus), descriptorObj.get(),
                                           deviceInfo.isExternal(), deviceInfo.getSources(),
                                           deviceInfo.getKeyboardType(), kcmObj.get(),
                                           keyboardLanguageTagObj.get(), keyboardLayoutTypeObj.get(),
@@ -113,7 +114,7 @@
     gInputDeviceClassInfo.clazz = MakeGlobalRefOrDie(env, gInputDeviceClassInfo.clazz);
 
     gInputDeviceClassInfo.ctor = GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz, "<init>",
-                                                  "(IIILjava/lang/String;IILjava/lang/"
+                                                  "(IIILjava/lang/String;IIILjava/lang/"
                                                   "String;ZIILandroid/view/KeyCharacterMap;Ljava/"
                                                   "lang/String;Ljava/lang/String;ZZZZZIII)V");
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c7324a2..5713e9e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2287,7 +2287,7 @@
     <!-- Allows system apps to call methods to register itself as a mDNS offload engine.
         <p>Not for use by third-party or privileged applications.
         @SystemApi
-        @FlaggedApi("com.android.net.flags.register_nsd_offload_engine")
+        @FlaggedApi("android.net.platform.flags.register_nsd_offload_engine")
         @hide This should only be used by system apps.
     -->
     <permission android:name="android.permission.REGISTER_NSD_OFFLOAD_ENGINE"
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 11b8271..bd9abec 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -21,12 +21,14 @@
 import android.os.StrictMode;
 
 /**
- * @hide This should not be made public in its present form because it
- * assumes that private and secret key bytes are available and would
- * preclude the use of hardware crypto.
+ * This class provides some constants and helper methods related to Android's Keystore service.
+ * This class was originally much larger, but its functionality was superseded by other classes.
+ * It now just contains a few remaining pieces for which the users haven't been updated yet.
+ * You may be looking for {@link java.security.KeyStore} instead.
+ *
+ * @hide
  */
 public class KeyStore {
-    private static final String TAG = "KeyStore";
 
     // ResponseCodes - see system/security/keystore/include/keystore/keystore.h
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@@ -42,50 +44,6 @@
         return KEY_STORE;
     }
 
-    /** @hide */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public byte[] get(String key) {
-        return null;
-    }
-
-    /** @hide */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public boolean delete(String key) {
-        return false;
-    }
-
-    /**
-     * List uids of all keys that are auth bound to the current user.
-     * Only system is allowed to call this method.
-     * @hide
-     * @deprecated This function always returns null.
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public int[] listUidsOfAuthBoundKeys() {
-        return null;
-    }
-
-
-    /**
-     * @hide
-     * @deprecated This function has no effect.
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public boolean unlock(String password) {
-        return false;
-    }
-
-    /**
-     *
-     * @return
-     * @deprecated This function always returns true.
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
-    public boolean isEmpty() {
-        return true;
-    }
-
     /**
      * Add an authentication record to the keystore authorization table.
      *
@@ -105,13 +63,4 @@
     public void onDeviceOffBody() {
         AndroidKeyStoreMaintenance.onDeviceOffBody();
     }
-
-    /**
-     * Returns a {@link KeyStoreException} corresponding to the provided keystore/keymaster error
-     * code.
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public static KeyStoreException getKeyStoreException(int errorCode) {
-        return new KeyStoreException(-10000, "Should not be called.");
-    }
 }
diff --git a/keystore/java/android/security/keystore/KeyInfo.java b/keystore/java/android/security/keystore/KeyInfo.java
index f50efd2..5cffe46 100644
--- a/keystore/java/android/security/keystore/KeyInfo.java
+++ b/keystore/java/android/security/keystore/KeyInfo.java
@@ -16,6 +16,7 @@
 
 package android.security.keystore;
 
+import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 
@@ -81,6 +82,7 @@
     private final @KeyProperties.AuthEnum int mUserAuthenticationType;
     private final boolean mUserAuthenticationRequirementEnforcedBySecureHardware;
     private final boolean mUserAuthenticationValidWhileOnBody;
+    private final boolean mUnlockedDeviceRequired;
     private final boolean mTrustedUserPresenceRequired;
     private final boolean mInvalidatedByBiometricEnrollment;
     private final boolean mUserConfirmationRequired;
@@ -107,6 +109,7 @@
             @KeyProperties.AuthEnum int userAuthenticationType,
             boolean userAuthenticationRequirementEnforcedBySecureHardware,
             boolean userAuthenticationValidWhileOnBody,
+            boolean unlockedDeviceRequired,
             boolean trustedUserPresenceRequired,
             boolean invalidatedByBiometricEnrollment,
             boolean userConfirmationRequired,
@@ -132,6 +135,7 @@
         mUserAuthenticationRequirementEnforcedBySecureHardware =
                 userAuthenticationRequirementEnforcedBySecureHardware;
         mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
+        mUnlockedDeviceRequired = unlockedDeviceRequired;
         mTrustedUserPresenceRequired = trustedUserPresenceRequired;
         mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
         mUserConfirmationRequired = userConfirmationRequired;
@@ -275,6 +279,20 @@
     }
 
     /**
+     * Returns {@code true} if the key is authorized to be used only when the device is unlocked.
+     *
+     * <p>This authorization applies only to secret key and private key operations. Public key
+     * operations are not restricted.
+     *
+     * @see KeyGenParameterSpec.Builder#setUnlockedDeviceRequired(boolean)
+     * @see KeyProtection.Builder#setUnlockedDeviceRequired(boolean)
+     */
+    @FlaggedApi(android.security.Flags.FLAG_KEYINFO_UNLOCKED_DEVICE_REQUIRED)
+    public boolean isUnlockedDeviceRequired() {
+        return mUnlockedDeviceRequired;
+    }
+
+    /**
      * Returns {@code true} if the key is authorized to be used only for messages confirmed by the
      * user.
      *
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java
index 97592b4..2682eb6 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java
@@ -93,6 +93,7 @@
         long userAuthenticationValidityDurationSeconds = 0;
         boolean userAuthenticationRequired = true;
         boolean userAuthenticationValidWhileOnBody = false;
+        boolean unlockedDeviceRequired = false;
         boolean trustedUserPresenceRequired = false;
         boolean trustedUserConfirmationRequired = false;
         int remainingUsageCount = KeyProperties.UNRESTRICTED_USAGE_COUNT;
@@ -184,6 +185,9 @@
                                     + userAuthenticationValidityDurationSeconds + " seconds");
                         }
                         break;
+                    case KeymasterDefs.KM_TAG_UNLOCKED_DEVICE_REQUIRED:
+                        unlockedDeviceRequired = true;
+                        break;
                     case KeymasterDefs.KM_TAG_ALLOW_WHILE_ON_BODY:
                         userAuthenticationValidWhileOnBody =
                                 KeyStore2ParameterUtils.isSecureHardware(a.securityLevel);
@@ -257,6 +261,7 @@
                         : keymasterSwEnforcedUserAuthenticators,
                 userAuthenticationRequirementEnforcedBySecureHardware,
                 userAuthenticationValidWhileOnBody,
+                unlockedDeviceRequired,
                 trustedUserPresenceRequired,
                 invalidatedByBiometricEnrollment,
                 trustedUserConfirmationRequired,
diff --git a/packages/CrashRecovery/framework/Android.bp b/packages/CrashRecovery/framework/Android.bp
index c0d93531..9480327 100644
--- a/packages/CrashRecovery/framework/Android.bp
+++ b/packages/CrashRecovery/framework/Android.bp
@@ -3,7 +3,7 @@
     module_type: "filegroup",
     config_namespace: "ANDROID",
     bool_variables: [
-        "move_crashrecovery_files",
+        "crashrecovery_files_in_platform",
     ],
     properties: [
         "srcs",
@@ -12,14 +12,13 @@
 
 platform_filegroup {
     name: "framework-crashrecovery-sources",
-    srcs: [
-        "java/**/*.java",
-        "java/**/*.aidl",
-    ],
     soong_config_variables: {
-        // if the flag is enabled, then files would be moved to module
-        move_crashrecovery_files: {
-            srcs: [],
+        // if this flag is enabled, then files are part of platform
+        crashrecovery_files_in_platform: {
+            srcs: [
+                "java/**/*.java",
+                "java/**/*.aidl",
+            ],
         },
     },
     path: "java",
@@ -31,7 +30,7 @@
     module_type: "filegroup",
     config_namespace: "ANDROID",
     bool_variables: [
-        "move_crashrecovery_files",
+        "crashrecovery_files_in_module",
     ],
     properties: [
         "srcs",
@@ -40,10 +39,9 @@
 
 module_filegroup {
     name: "framework-crashrecovery-module-sources",
-    srcs: [],
     soong_config_variables: {
-        // if the flag is enabled, then files would be moved to module
-        move_crashrecovery_files: {
+        // if this flag is enabled, then files are part of module
+        crashrecovery_files_in_module: {
             srcs: [
                 "java/**/*.java",
                 "java/**/*.aidl",
diff --git a/packages/CrashRecovery/services/Android.bp b/packages/CrashRecovery/services/Android.bp
index ab10b5a..961b41f 100644
--- a/packages/CrashRecovery/services/Android.bp
+++ b/packages/CrashRecovery/services/Android.bp
@@ -3,7 +3,7 @@
     module_type: "filegroup",
     config_namespace: "ANDROID",
     bool_variables: [
-        "move_crashrecovery_files",
+        "crashrecovery_files_in_platform",
     ],
     properties: [
         "srcs",
@@ -12,15 +12,14 @@
 
 platform_filegroup {
     name: "services-crashrecovery-sources",
-    srcs: [
-        "java/**/*.java",
-        "java/**/*.aidl",
-        ":statslog-crashrecovery-java-gen",
-    ],
     soong_config_variables: {
-        // if the flag is enabled, then files would be moved to module
-        move_crashrecovery_files: {
-            srcs: [],
+        // if this flag is enabled, then files are part of platform
+        crashrecovery_files_in_platform: {
+            srcs: [
+                "java/**/*.java",
+                "java/**/*.aidl",
+                ":statslog-crashrecovery-java-gen",
+            ],
         },
     },
     visibility: ["//frameworks/base:__subpackages__"],
@@ -31,7 +30,7 @@
     module_type: "filegroup",
     config_namespace: "ANDROID",
     bool_variables: [
-        "move_crashrecovery_files",
+        "crashrecovery_files_in_module",
     ],
     properties: [
         "srcs",
@@ -40,10 +39,9 @@
 
 module_filegroup {
     name: "services-crashrecovery-module-sources",
-    srcs: [],
     soong_config_variables: {
-        // if the flag is enabled, then files would be moved to module
-        move_crashrecovery_files: {
+        // if this flag is enabled, then files are part of module
+        crashrecovery_files_in_module: {
             srcs: [
                 "java/**/*.java",
                 "java/**/*.aidl",
diff --git a/packages/CrashRecovery/services/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/packages/CrashRecovery/services/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index 5fb47dd..0fb9327 100644
--- a/packages/CrashRecovery/services/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/packages/CrashRecovery/services/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -75,6 +75,9 @@
     private static final int PERSISTENT_MASK = ApplicationInfo.FLAG_PERSISTENT
             | ApplicationInfo.FLAG_SYSTEM;
 
+    private static final String PROP_DISABLE_HIGH_IMPACT_ROLLBACK_FLAG =
+            "persist.device_config.configuration.disable_high_impact_rollback";
+
     private final Context mContext;
     private final Handler mHandler;
     private final ApexManager mApexManager;
@@ -605,6 +608,10 @@
             // Apply all available low impact rollbacks.
             mHandler.post(() -> rollbackAllLowImpact(availableRollbacks, rollbackReason));
         } else if (minRollbackImpactLevel == PackageManager.ROLLBACK_USER_IMPACT_HIGH) {
+            // Check disable_high_impact_rollback device config before performing rollback
+            if (SystemProperties.getBoolean(PROP_DISABLE_HIGH_IMPACT_ROLLBACK_FLAG, false)) {
+                return;
+            }
             // Rollback one package at a time. If that doesn't resolve the issue, rollback
             // next with same impact level.
             mHandler.post(() -> rollbackHighImpact(availableRollbacks, rollbackReason));
@@ -718,7 +725,9 @@
                 impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_70;
                 break;
             case PackageManager.ROLLBACK_USER_IMPACT_HIGH:
-                impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_90;
+                if (!SystemProperties.getBoolean(PROP_DISABLE_HIGH_IMPACT_ROLLBACK_FLAG, false)) {
+                    impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_90;
+                }
                 break;
             default:
                 impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 6dbf707..4a5d84a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -22,6 +22,7 @@
 import android.app.ActivityTaskManager;
 import android.app.AlarmManager;
 import android.app.AlarmManager.AlarmClockInfo;
+import android.app.NotificationManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -376,7 +377,7 @@
     }
 
     @Override
-    public void onConfigChanged(ZenModeConfig config) {
+    public void onConsolidatedPolicyChanged(NotificationManager.Policy policy) {
         updateVolumeZen();
     }
 
diff --git a/services/core/java/com/android/server/input/KeyboardMetricsCollector.java b/services/core/java/com/android/server/input/KeyboardMetricsCollector.java
index 08e5977..8e2484e 100644
--- a/services/core/java/com/android/server/input/KeyboardMetricsCollector.java
+++ b/services/core/java/com/android/server/input/KeyboardMetricsCollector.java
@@ -369,15 +369,15 @@
         if (inputDevice == null || inputDevice.isVirtual() || !inputDevice.isFullKeyboard()) {
             return;
         }
-        int vendorId = inputDevice.getVendorId();
-        int productId = inputDevice.getProductId();
         if (keyboardSystemEvent == null) {
             Slog.w(TAG, "Invalid keyboard event logging, keycode = " + Arrays.toString(keyCodes)
                     + ", modifier state = " + modifierState);
             return;
         }
         FrameworkStatsLog.write(FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED,
-                vendorId, productId, keyboardSystemEvent.getIntValue(), keyCodes, modifierState);
+                inputDevice.getVendorId(), inputDevice.getProductId(),
+                keyboardSystemEvent.getIntValue(), keyCodes, modifierState,
+                inputDevice.getDeviceBus());
 
         if (DEBUG) {
             Slog.d(TAG, "Logging Keyboard system event: " + keyboardSystemEvent.mName);
@@ -402,7 +402,7 @@
         // Push the atom to Statsd
         FrameworkStatsLog.write(FrameworkStatsLog.KEYBOARD_CONFIGURED,
                 event.isFirstConfiguration(), event.getVendorId(), event.getProductId(),
-                proto.getBytes());
+                proto.getBytes(), event.getDeviceBus());
 
         if (DEBUG) {
             Slog.d(TAG, "Logging Keyboard configuration event: " + event);
@@ -467,6 +467,10 @@
             return mInputDevice.getProductId();
         }
 
+        public int getDeviceBus() {
+            return mInputDevice.getDeviceBus();
+        }
+
         public boolean isFirstConfiguration() {
             return mIsFirstConfiguration;
         }
@@ -479,6 +483,7 @@
         public String toString() {
             return "InputDevice = {VendorId = " + Integer.toHexString(getVendorId())
                     + ", ProductId = " + Integer.toHexString(getProductId())
+                    + ", Device Bus = " + Integer.toHexString(getDeviceBus())
                     + "}, isFirstConfiguration = " + mIsFirstConfiguration
                     + ", LayoutConfigurations = " + mLayoutConfigurations;
         }
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index c11356b..44c4b57 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -339,8 +339,6 @@
     static final String TAG = NetworkPolicyLogger.TAG;
     private static final boolean LOGD = NetworkPolicyLogger.LOGD;
     private static final boolean LOGV = NetworkPolicyLogger.LOGV;
-    // TODO: b/304347838 - Remove once the feature is in staging.
-    private static final boolean ALWAYS_RESTRICT_BACKGROUND_NETWORK = false;
 
     /**
      * No opportunistic quota could be calculated from user data plan or data settings.
@@ -728,7 +726,7 @@
      * Map of uid -> UidStateCallbackInfo objects holding the data received from
      * {@link IUidObserver#onUidStateChanged(int, int, long, int)} callbacks. In order to avoid
      * creating a new object for every callback received, we hold onto the object created for each
-     * uid and reuse it.
+     * uid and reuse it until the uid stays alive.
      *
      * Note that the lock used for accessing this object should not be used for anything else and we
      * should not be acquiring new locks or doing any heavy work while this lock is held since this
@@ -801,6 +799,13 @@
                 Clock.systemUTC());
     }
 
+    @VisibleForTesting
+    UidState getUidStateForTest(int uid) {
+        synchronized (mUidRulesFirstLock) {
+            return mUidState.get(uid);
+        }
+    }
+
     static class Dependencies {
         final Context mContext;
         final NetworkStatsManager mNetworkStatsManager;
@@ -1062,8 +1067,7 @@
                     }
 
                     // The flag is boot-stable.
-                    mBackgroundNetworkRestricted = ALWAYS_RESTRICT_BACKGROUND_NETWORK
-                            && Flags.networkBlockedForTopSleepingAndAbove();
+                    mBackgroundNetworkRestricted = Flags.networkBlockedForTopSleepingAndAbove();
                     if (mBackgroundNetworkRestricted) {
                         // Firewall rules and UidBlockedState will get updated in
                         // updateRulesForGlobalChangeAL below.
@@ -1256,6 +1260,10 @@
         }
 
         @Override public void onUidGone(int uid, boolean disabled) {
+            synchronized (mUidStateCallbackInfos) {
+                mUidStateCallbackInfos.remove(uid);
+            }
+            // TODO: b/327058756 - Remove any pending UID_MSG_STATE_CHANGED on the handler.
             mUidEventHandler.obtainMessage(UID_MSG_GONE, uid, 0).sendToTarget();
         }
     };
@@ -5899,7 +5907,7 @@
     void handleUidGone(int uid) {
         Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "onUidGone");
         try {
-            boolean updated;
+            final boolean updated;
             synchronized (mUidRulesFirstLock) {
                 updated = removeUidStateUL(uid);
             }
diff --git a/services/tests/mockingservicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java b/services/tests/mockingservicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java
index d6e246f..6e41685 100644
--- a/services/tests/mockingservicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java
@@ -25,6 +25,8 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
@@ -42,6 +44,7 @@
 import android.crashrecovery.flags.Flags;
 import android.os.Handler;
 import android.os.MessageQueue;
+import android.os.SystemProperties;
 import android.platform.test.flag.junit.SetFlagsRule;
 
 import androidx.test.runner.AndroidJUnit4;
@@ -65,6 +68,7 @@
 import org.mockito.stubbing.Answer;
 
 import java.time.Duration;
+import java.util.HashMap;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -90,7 +94,7 @@
 
     @Rule
     public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
-
+    private HashMap<String, String> mSystemSettingsMap;
     private MockitoSession mSession;
     private static final String APP_A = "com.package.a";
     private static final String APP_B = "com.package.b";
@@ -99,6 +103,9 @@
     private static final long VERSION_CODE_2 = 2L;
     private static final String LOG_TAG = "RollbackPackageHealthObserverTest";
 
+    private static final String PROP_DISABLE_HIGH_IMPACT_ROLLBACK_FLAG =
+            "persist.device_config.configuration.disable_high_impact_rollback";
+
     private SystemConfig mSysConfig;
 
     @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
@@ -111,11 +118,34 @@
                 .initMocks(this)
                 .strictness(Strictness.LENIENT)
                 .spyStatic(PackageWatchdog.class)
+                .spyStatic(SystemProperties.class)
                 .startMocking();
+        mSystemSettingsMap = new HashMap<>();
 
         // Mock PackageWatchdog
         doAnswer((Answer<PackageWatchdog>) invocationOnMock -> mMockPackageWatchdog)
                 .when(() -> PackageWatchdog.getInstance(mMockContext));
+
+        // Mock SystemProperties setter and various getters
+        doAnswer((Answer<Void>) invocationOnMock -> {
+                    String key = invocationOnMock.getArgument(0);
+                    String value = invocationOnMock.getArgument(1);
+
+                    mSystemSettingsMap.put(key, value);
+                    return null;
+                }
+        ).when(() -> SystemProperties.set(anyString(), anyString()));
+
+        doAnswer((Answer<Boolean>) invocationOnMock -> {
+                    String key = invocationOnMock.getArgument(0);
+                    boolean defaultValue = invocationOnMock.getArgument(1);
+
+                    String storedValue = mSystemSettingsMap.get(key);
+                    return storedValue == null ? defaultValue : Boolean.parseBoolean(storedValue);
+                }
+        ).when(() -> SystemProperties.getBoolean(anyString(), anyBoolean()));
+
+        SystemProperties.set(PROP_DISABLE_HIGH_IMPACT_ROLLBACK_FLAG, Boolean.toString(false));
     }
 
     @After
@@ -609,6 +639,32 @@
                 observer.onBootLoop(1));
     }
 
+    @Test
+    public void onBootLoop_impactLevelHighDisableHighImpactRollback_onePackage()
+            throws PackageManager.NameNotFoundException {
+        mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+        SystemProperties.set(PROP_DISABLE_HIGH_IMPACT_ROLLBACK_FLAG, Boolean.toString(true));
+        VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
+        VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
+        PackageRollbackInfo packageRollbackInfo = new PackageRollbackInfo(appAFrom, appATo,
+                null, null, false, false,
+                null);
+        RollbackInfo rollbackInfo1 = new RollbackInfo(1, List.of(packageRollbackInfo),
+                false, null, 111,
+                PackageManager.ROLLBACK_USER_IMPACT_HIGH);
+        RollbackPackageHealthObserver observer =
+                spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
+
+        when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+        // Make the rollbacks available
+        when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(rollbackInfo1));
+        when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+        when(mMockPackageManager.getModuleInfo(any(), eq(0))).thenReturn(null);
+
+        assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_0,
+                observer.onBootLoop(1));
+    }
+
     /**
      * When the rollback impact level is manual only return user impact level 0. (User impact level
      * 0 is ignored by package watchdog)
@@ -924,6 +980,50 @@
         assertThat(argument.getAllValues()).isEqualTo(List.of(rollbackId2));
     }
 
+    /**
+     * Don't roll back if kill switch is enabled.
+     */
+    @Test
+    public void executeBootLoopMitigation_impactLevelHighKillSwitchTrue_rollbackHigh()
+            throws PackageManager.NameNotFoundException {
+        mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+        SystemProperties.set(PROP_DISABLE_HIGH_IMPACT_ROLLBACK_FLAG, Boolean.toString(true));
+        int rollbackId1 = 1;
+        VersionedPackage appBFrom = new VersionedPackage(APP_B, VERSION_CODE_2);
+        VersionedPackage appBTo = new VersionedPackage(APP_B, VERSION_CODE);
+        PackageRollbackInfo packageRollbackInfoB = new PackageRollbackInfo(appBFrom, appBTo,
+                null, null , false, false,
+                null);
+        RollbackInfo rollbackInfo1 = new RollbackInfo(rollbackId1, List.of(packageRollbackInfoB),
+                false, null, 111,
+                PackageManager.ROLLBACK_USER_IMPACT_HIGH);
+        int rollbackId2 = 2;
+        VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
+        VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
+        PackageRollbackInfo packageRollbackInfoA = new PackageRollbackInfo(appAFrom, appATo,
+                null, null , false, false,
+                null);
+        RollbackInfo rollbackInfo2 = new RollbackInfo(rollbackId2, List.of(packageRollbackInfoA),
+                false, null, 111,
+                PackageManager.ROLLBACK_USER_IMPACT_HIGH);
+        RollbackPackageHealthObserver observer =
+                spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
+        ArgumentCaptor<Integer> argument = ArgumentCaptor.forClass(Integer.class);
+
+        when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+        // Make the rollbacks available
+        when(mRollbackManager.getAvailableRollbacks()).thenReturn(
+                List.of(rollbackInfo1, rollbackInfo2));
+        when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+        when(mMockPackageManager.getModuleInfo(any(), eq(0))).thenReturn(null);
+
+        observer.executeBootLoopMitigation(1);
+        waitForIdleHandler(observer.getHandler(), Duration.ofSeconds(10));
+
+        verify(mRollbackManager, never()).commitRollback(
+                argument.capture(), any(), any());
+    }
+
     private void waitForIdleHandler(Handler handler, Duration timeout) {
         final MessageQueue queue = handler.getLooper().getQueue();
         final CountDownLatch latch = new CountDownLatch(1);
diff --git a/services/tests/servicestests/src/com/android/server/input/KeyboardMetricsCollectorTests.kt b/services/tests/servicestests/src/com/android/server/input/KeyboardMetricsCollectorTests.kt
index 84af9dd..218b7c0 100644
--- a/services/tests/servicestests/src/com/android/server/input/KeyboardMetricsCollectorTests.kt
+++ b/services/tests/servicestests/src/com/android/server/input/KeyboardMetricsCollectorTests.kt
@@ -30,6 +30,7 @@
     deviceId: Int,
     vendorId: Int,
     productId: Int,
+    deviceBus: Int,
     languageTag: String?,
     layoutType: String?
 ): InputDevice =
@@ -42,6 +43,7 @@
         .setExternal(true)
         .setVendorId(vendorId)
         .setProductId(productId)
+        .setDeviceBus(deviceBus)
         .setKeyboardLanguageTag(languageTag)
         .setKeyboardLayoutType(layoutType)
         .build()
@@ -67,6 +69,7 @@
         const val DEVICE_ID = 1
         const val DEFAULT_VENDOR_ID = 123
         const val DEFAULT_PRODUCT_ID = 456
+        const val DEFAULT_DEVICE_BUS = 789
     }
 
     @Test
@@ -77,6 +80,7 @@
                     DEVICE_ID,
                     DEFAULT_VENDOR_ID,
                     DEFAULT_PRODUCT_ID,
+                    DEFAULT_DEVICE_BUS,
                     null,
                     null
                 )
@@ -92,6 +96,7 @@
                     DEVICE_ID,
                     DEFAULT_VENDOR_ID,
                     DEFAULT_PRODUCT_ID,
+                    DEFAULT_DEVICE_BUS,
                     null,
                     null
                 )
@@ -107,6 +112,7 @@
                 DEVICE_ID,
                 DEFAULT_VENDOR_ID,
                 DEFAULT_PRODUCT_ID,
+                DEFAULT_DEVICE_BUS,
                 "de-CH",
                 "qwertz"
             )
@@ -135,6 +141,11 @@
             DEFAULT_PRODUCT_ID,
             event.productId
         )
+        assertEquals(
+             "KeyboardConfigurationEvent should pick device bus from provided InputDevice",
+             DEFAULT_DEVICE_BUS,
+             event.deviceBus
+        )
         assertTrue(event.isFirstConfiguration)
 
         assertEquals(
@@ -178,6 +189,7 @@
                 DEVICE_ID,
                 DEFAULT_VENDOR_ID,
                 DEFAULT_PRODUCT_ID,
+                DEFAULT_DEVICE_BUS,
                 "und", // Undefined language tag
                 "azerty"
             )
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index a529382..15cd511 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -149,6 +149,7 @@
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkPolicy;
+import android.net.NetworkPolicyManager;
 import android.net.NetworkStateSnapshot;
 import android.net.NetworkTemplate;
 import android.net.TelephonyNetworkSpecifier;
@@ -205,7 +206,6 @@
 import org.junit.After;
 import org.junit.Assume;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.MethodRule;
@@ -1620,6 +1620,12 @@
         verify(mActivityManagerInternal).notifyNetworkPolicyRulesUpdated(UID_A, procStateSeq);
     }
 
+    private void callAndWaitOnUidGone(int uid) throws Exception {
+        // The disabled argument is used only for ephemeral apps and does not matter here.
+        mUidObserver.onUidGone(uid, false /* disabled */);
+        waitForUidEventHandlerIdle();
+    }
+
     private void callAndWaitOnUidStateChanged(int uid, int procState, long procStateSeq)
             throws Exception {
         callAndWaitOnUidStateChanged(uid, procState, procStateSeq,
@@ -2144,14 +2150,12 @@
         assertFalse(mService.isUidNetworkingBlocked(UID_E, false));
     }
 
-    @Ignore("Temporarily disabled until the feature is enabled")
     @Test
     @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
     public void testBackgroundChainEnabled() throws Exception {
         verify(mNetworkManager).setFirewallChainEnabled(FIREWALL_CHAIN_BACKGROUND, true);
     }
 
-    @Ignore("Temporarily disabled until the feature is enabled")
     @Test
     @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
     public void testBackgroundChainOnProcStateChange() throws Exception {
@@ -2181,7 +2185,6 @@
         assertTrue(mService.isUidNetworkingBlocked(UID_A, false));
     }
 
-    @Ignore("Temporarily disabled until the feature is enabled")
     @Test
     @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
     public void testBackgroundChainOnAllowlistChange() throws Exception {
@@ -2220,7 +2223,6 @@
         assertFalse(mService.isUidNetworkingBlocked(UID_B, false));
     }
 
-    @Ignore("Temporarily disabled until the feature is enabled")
     @Test
     @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
     public void testBackgroundChainOnTempAllowlistChange() throws Exception {
@@ -2250,7 +2252,15 @@
         assertTrue(mService.isUidNetworkingBlocked(UID_A, false));
     }
 
-    @Ignore("Temporarily disabled until the feature is enabled")
+    private boolean isUidState(int uid, int procState, int procStateSeq, int capability) {
+        final NetworkPolicyManager.UidState uidState = mService.getUidStateForTest(uid);
+        if (uidState == null) {
+            return false;
+        }
+        return uidState.uid == uid && uidState.procStateSeq == procStateSeq
+                && uidState.procState == procState && uidState.capability == capability;
+    }
+
     @Test
     @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
     public void testUidObserverFiltersProcStateChanges() throws Exception {
@@ -2313,7 +2323,6 @@
         waitForUidEventHandlerIdle();
     }
 
-    @Ignore("Temporarily disabled until the feature is enabled")
     @Test
     @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
     public void testUidObserverFiltersStaleChanges() throws Exception {
@@ -2334,7 +2343,6 @@
         waitForUidEventHandlerIdle();
     }
 
-    @Ignore("Temporarily disabled until the feature is enabled")
     @Test
     @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
     public void testUidObserverFiltersCapabilityChanges() throws Exception {
@@ -2371,6 +2379,31 @@
     }
 
     @Test
+    public void testUidStateChangeAfterUidGone() throws Exception {
+        final int testProcStateSeq = 51;
+        final int testProcState = PROCESS_STATE_IMPORTANT_FOREGROUND;
+
+        try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
+            // First callback for uid.
+            callOnUidStatechanged(UID_B, testProcState, testProcStateSeq, PROCESS_CAPABILITY_NONE);
+            assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
+        }
+        waitForUidEventHandlerIdle();
+        assertTrue(isUidState(UID_B, testProcState, testProcStateSeq, PROCESS_CAPABILITY_NONE));
+
+        callAndWaitOnUidGone(UID_B);
+        try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
+            // Even though the procState is the same, the uid had exited - so this should be
+            // processed as a fresh callback.
+            callOnUidStatechanged(UID_B, testProcState, testProcStateSeq + 1,
+                    PROCESS_CAPABILITY_NONE);
+            assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
+        }
+        waitForUidEventHandlerIdle();
+        assertTrue(isUidState(UID_B, testProcState, testProcStateSeq + 1, PROCESS_CAPABILITY_NONE));
+    }
+
+    @Test
     public void testLowPowerStandbyAllowlist() throws Exception {
         // Chain background is also enabled but these procstates are important enough to be exempt.
         callAndWaitOnUidStateChanged(UID_A, PROCESS_STATE_TOP, 0);
diff --git a/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java b/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java
index feca326..84925f9 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java
@@ -38,6 +38,7 @@
 
     private static final int VENDOR_ID = 0x123;
     private static final int PRODUCT_ID = 0x456;
+    private static final int DEVICE_BUS = 0x789;
     private static final int META_KEY = KeyEvent.KEYCODE_META_LEFT;
     private static final int META_ON = MODIFIER.get(KeyEvent.KEYCODE_META_LEFT);
     private static final int ALT_KEY = KeyEvent.KEYCODE_ALT_LEFT;
@@ -224,7 +225,7 @@
     @Override
     public void setUp() {
         super.setUp();
-        mPhoneWindowManager.overrideKeyEventSource(VENDOR_ID, PRODUCT_ID);
+        mPhoneWindowManager.overrideKeyEventSource(VENDOR_ID, PRODUCT_ID, DEVICE_BUS);
         mPhoneWindowManager.overrideLaunchHome();
         mPhoneWindowManager.overrideSearchKeyBehavior(
                 PhoneWindowManager.SEARCH_BEHAVIOR_TARGET_ACTIVITY);
@@ -240,6 +241,7 @@
             int expectedKey, int expectedModifierState) {
         sendKeyCombination(testKeys, 0);
         mPhoneWindowManager.assertShortcutLogged(VENDOR_ID, PRODUCT_ID, expectedLogEvent,
-                expectedKey, expectedModifierState, "Failed while executing " + testName);
+                expectedKey, expectedModifierState, DEVICE_BUS,
+                "Failed while executing " + testName);
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
index 1866767..9aaf291 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -423,10 +423,15 @@
         doReturn(isShowing).when(mKeyguardServiceDelegate).isShowing();
     }
 
-    void overrideKeyEventSource(int vendorId, int productId) {
-        InputDevice device = new InputDevice.Builder().setId(1).setVendorId(vendorId).setProductId(
-                productId).setSources(InputDevice.SOURCE_KEYBOARD).setKeyboardType(
-                InputDevice.KEYBOARD_TYPE_ALPHABETIC).build();
+    void overrideKeyEventSource(int vendorId, int productId, int deviceBus) {
+        InputDevice device = new InputDevice.Builder()
+                .setId(1)
+                .setVendorId(vendorId)
+                .setProductId(productId)
+                .setDeviceBus(deviceBus)
+                .setSources(InputDevice.SOURCE_KEYBOARD)
+                .setKeyboardType(InputDevice.KEYBOARD_TYPE_ALPHABETIC)
+                .build();
         doReturn(mInputManager).when(mContext).getSystemService(eq(InputManager.class));
         doReturn(device).when(mInputManager).getInputDevice(anyInt());
     }
@@ -604,10 +609,10 @@
     }
 
     void assertShortcutLogged(int vendorId, int productId, KeyboardLogEvent logEvent,
-            int expectedKey, int expectedModifierState, String errorMsg) {
+            int expectedKey, int expectedModifierState, int deviceBus, String errorMsg) {
         waitForIdle();
         verify(() -> FrameworkStatsLog.write(FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED,
                         vendorId, productId, logEvent.getIntValue(), new int[]{expectedKey},
-                        expectedModifierState), description(errorMsg));
+                        expectedModifierState, deviceBus), description(errorMsg));
     }
 }
diff --git a/tests/Input/src/com/android/test/input/InputDeviceTest.java b/tests/Input/src/com/android/test/input/InputDeviceTest.java
index d075b5f..5434c82 100644
--- a/tests/Input/src/com/android/test/input/InputDeviceTest.java
+++ b/tests/Input/src/com/android/test/input/InputDeviceTest.java
@@ -51,6 +51,7 @@
         assertEquals(device.getName(), outDevice.getName());
         assertEquals(device.getVendorId(), outDevice.getVendorId());
         assertEquals(device.getProductId(), outDevice.getProductId());
+        assertEquals(device.getDeviceBus(), outDevice.getDeviceBus());
         assertEquals(device.getDescriptor(), outDevice.getDescriptor());
         assertEquals(device.isExternal(), outDevice.isExternal());
         assertEquals(device.getSources(), outDevice.getSources());
@@ -79,6 +80,7 @@
                 .setName("Test Device " + DEVICE_ID)
                 .setVendorId(44)
                 .setProductId(45)
+                .setDeviceBus(3)
                 .setDescriptor("descriptor")
                 .setExternal(true)
                 .setSources(InputDevice.SOURCE_HDMI)