Merge "Return early when the caller doesn't have any permission." into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index bd17d6d..8a2616e 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -25,6 +25,7 @@
         "android.app.appfunctions.flags-aconfig-java",
         "android.app.contextualsearch.flags-aconfig-java",
         "android.app.flags-aconfig-java",
+        "android.app.jank.flags-aconfig-java",
         "android.app.ondeviceintelligence-aconfig-java",
         "android.app.smartspace.flags-aconfig-java",
         "android.app.supervision.flags-aconfig-java",
@@ -1606,3 +1607,17 @@
     aconfig_declarations: "interaction_jank_monitor_flags",
     defaults: ["framework-minus-apex-aconfig-java-defaults"],
 }
+
+// App Jank
+aconfig_declarations {
+    name: "android.app.jank.flags-aconfig",
+    package: "android.app.jank",
+    container: "system",
+    srcs: ["core/java/android/app/jank/flags.aconfig"],
+}
+
+java_aconfig_library {
+    name: "android.app.jank.flags-aconfig-java",
+    aconfig_declarations: "android.app.jank.flags-aconfig",
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index df707d1..1e94c2f 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -673,8 +673,8 @@
     method @Nullable public android.content.pm.PackageInfo getCurrentWebViewPackage();
     method @Nullable public String getCurrentWebViewPackageName();
     method @FlaggedApi("android.webkit.update_service_v2") @NonNull public android.webkit.WebViewProviderInfo getDefaultWebViewPackage();
-    method @Nullable public static android.webkit.WebViewUpdateManager getInstance();
-    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.INTERACT_ACROSS_USERS, android.Manifest.permission.QUERY_ALL_PACKAGES}) public android.webkit.WebViewProviderInfo[] getValidWebViewPackages();
+    method @NonNull public static android.webkit.WebViewUpdateManager getInstance();
+    method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.webkit.WebViewProviderInfo[] getValidWebViewPackages();
     method @NonNull public android.webkit.WebViewProviderResponse waitForAndGetProvider();
   }
 
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index fb425a9..475b1e2 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -18769,7 +18769,7 @@
   public final class WebViewUpdateService {
     method public static android.webkit.WebViewProviderInfo[] getAllWebViewPackages();
     method public static String getCurrentWebViewPackageName();
-    method public static android.webkit.WebViewProviderInfo[] getValidWebViewPackages();
+    method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public static android.webkit.WebViewProviderInfo[] getValidWebViewPackages();
   }
 
 }
diff --git a/core/java/android/app/jank/flags.aconfig b/core/java/android/app/jank/flags.aconfig
new file mode 100644
index 0000000..5657f7e
--- /dev/null
+++ b/core/java/android/app/jank/flags.aconfig
@@ -0,0 +1,16 @@
+package: "android.app.jank"
+container: "system"
+
+flag {
+  name: "detailed_app_jank_metrics_api"
+  namespace: "system_performance"
+  description: "Control the API portion of Detailed Application Jank Metrics"
+  bug: "366264614"
+}
+
+flag {
+  name: "detailed_app_jank_metrics_logging_enabled"
+  namespace: "system_performance"
+  description: "Controls whether the system will log frame metrics related to app jank"
+  bug: "366265225"
+}
\ No newline at end of file
diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig
index 991611a..b0791e3 100644
--- a/core/java/android/permission/flags.aconfig
+++ b/core/java/android/permission/flags.aconfig
@@ -257,3 +257,11 @@
     description: "This flag is used to enable replacing permission BODY_SENSORS(and BODY_SENSORS_BACKGROUND) with granular health permission READ_HEART_RATE(and READ_HEALTH_DATA_IN_BACKGROUND)"
     bug: "364638912"
 }
+
+flag {
+    name: "appop_access_tracking_logging_enabled"
+    is_fixed_read_only: true
+    namespace: "permissions"
+    description: "Enables logging of the AppOp access tracking"
+    bug: "365584286"
+}
diff --git a/core/java/android/webkit/WebViewUpdateManager.java b/core/java/android/webkit/WebViewUpdateManager.java
index 0eb71001..b9a5e4ae 100644
--- a/core/java/android/webkit/WebViewUpdateManager.java
+++ b/core/java/android/webkit/WebViewUpdateManager.java
@@ -43,22 +43,29 @@
     /**
      * Get the singleton instance of the manager.
      *
-     * This exists for the benefit of callsites without a {@link Context}; prefer
+     * <p>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}.
+     * <p>This must only be called on devices with {@link PackageManager#FEATURE_WEBVIEW},
+     * and will WTF or throw {@link UnsupportedOperationException} otherwise.
      */
     @SuppressLint("ManagerLookup") // service opts in to getSystemServiceWithNoContext()
     @RequiresFeature(PackageManager.FEATURE_WEBVIEW)
-    public static @Nullable WebViewUpdateManager getInstance() {
-        return (WebViewUpdateManager) SystemServiceRegistry.getSystemServiceWithNoContext(
-                Context.WEBVIEW_UPDATE_SERVICE);
+    public static @NonNull WebViewUpdateManager getInstance() {
+        WebViewUpdateManager manager =
+                (WebViewUpdateManager) SystemServiceRegistry.getSystemServiceWithNoContext(
+                        Context.WEBVIEW_UPDATE_SERVICE);
+        if (manager == null) {
+            throw new UnsupportedOperationException("WebView not supported by device");
+        } else {
+            return manager;
+        }
     }
 
     /**
      * Block until system-level WebView preparations are complete.
      *
-     * This also makes the current WebView provider package visible to the caller.
+     * <p>This also makes the current WebView provider package visible to the caller.
      *
      * @return the status of WebView preparation and the current provider package.
      */
@@ -86,7 +93,7 @@
     /**
      * Get the complete list of supported WebView providers for this device.
      *
-     * This includes all configured providers, regardless of whether they are currently available
+     * <p>This includes all configured providers, regardless of whether they are currently available
      * or valid.
      */
     @SuppressLint({"ParcelableList", "ArrayReturn"})
@@ -101,13 +108,15 @@
     /**
      * Get the list of currently-valid WebView providers for this device.
      *
-     * This only includes providers that are currently present on the device and meet the validity
-     * criteria (signature, version, etc), but does not check if the provider is installed and
-     * enabled for all users.
+     * <p>This only includes providers that are currently present on the device and meet the
+     * validity criteria (signature, version, etc), but does not check if the provider is installed
+     * and enabled for all users.
+     *
+     * <p>Note that this will be filtered by the caller's package visibility; callers should
+     * have QUERY_ALL_PACKAGES permission to ensure that the list is complete.
      */
     @SuppressLint({"ParcelableList", "ArrayReturn"})
-    @RequiresPermission(allOf = {android.Manifest.permission.INTERACT_ACROSS_USERS,
-            android.Manifest.permission.QUERY_ALL_PACKAGES})
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public @NonNull WebViewProviderInfo[] getValidWebViewPackages() {
         try {
             return mService.getValidWebViewPackages();
@@ -132,7 +141,7 @@
     /**
      * Ask the system to switch to a specific WebView implementation if possible.
      *
-     * This choice will be stored persistently.
+     * <p>This choice will be stored persistently.
      *
      * @param newProvider the package name to use.
      * @return the package name which is now in use, which may not be the
@@ -162,7 +171,7 @@
     /**
      * Get the WebView provider which will be used if no explicit choice has been made.
      *
-     * The default provider is not guaranteed to be a valid/usable WebView implementation.
+     * <p>The default provider is not guaranteed to be a valid/usable WebView implementation.
      *
      * @return the default WebView provider.
      */
diff --git a/core/java/android/webkit/WebViewUpdateService.java b/core/java/android/webkit/WebViewUpdateService.java
index 01af182..644d917 100644
--- a/core/java/android/webkit/WebViewUpdateService.java
+++ b/core/java/android/webkit/WebViewUpdateService.java
@@ -16,6 +16,7 @@
 
 package android.webkit;
 
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.RemoteException;
@@ -54,7 +55,11 @@
 
     /**
      * Fetch all packages that could potentially implement WebView and are currently valid.
+     *
+     * <p>Note that this will be filtered by the caller's package visibility; callers should
+     * have QUERY_ALL_PACKAGES permission to ensure that the list is complete.
      */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public static WebViewProviderInfo[] getValidWebViewPackages() {
         if (Flags.updateServiceIpcWrapper()) {
             if (WebViewFactory.isWebViewSupported()) {
diff --git a/packages/SettingsLib/Ipc/Android.bp b/packages/SettingsLib/Ipc/Android.bp
new file mode 100644
index 0000000..61adb46
--- /dev/null
+++ b/packages/SettingsLib/Ipc/Android.bp
@@ -0,0 +1,22 @@
+package {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+filegroup {
+    name: "SettingsLibIpc-srcs",
+    srcs: ["src/**/*.kt"],
+}
+
+android_library {
+    name: "SettingsLibIpc",
+    defaults: [
+        "SettingsLintDefaults",
+    ],
+    srcs: [":SettingsLibIpc-srcs"],
+    static_libs: [
+        "androidx.collection_collection",
+        "guava",
+        "kotlinx-coroutines-android",
+    ],
+    kotlincflags: ["-Xjvm-default=all"],
+}
diff --git a/packages/SettingsLib/Ipc/AndroidManifest.xml b/packages/SettingsLib/Ipc/AndroidManifest.xml
new file mode 100644
index 0000000..fc48a7d
--- /dev/null
+++ b/packages/SettingsLib/Ipc/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.settingslib.ipc">
+
+    <uses-sdk android:minSdkVersion="21" />
+</manifest>
diff --git a/packages/SettingsLib/Ipc/README.md b/packages/SettingsLib/Ipc/README.md
new file mode 100644
index 0000000..ea2c3a1b5
--- /dev/null
+++ b/packages/SettingsLib/Ipc/README.md
@@ -0,0 +1,116 @@
+# Service IPC library
+
+This library provides a kind of IPC (inter-process communication) framework
+based on Android
+[bound service](https://developer.android.com/develop/background-work/services/bound-services)
+with [Messenger](https://developer.android.com/reference/android/os/Messenger).
+
+Following benefits are offered by the library to improve and simplify IPC
+development:
+
+-   Enforce permission check for every API implementation to avoid security
+    vulnerability.
+-   Allow modular API development for better code maintenance (no more huge
+    Service class).
+-   Prevent common mistakes, e.g. Service context leaking, ServiceConnection
+    management.
+
+## Overview
+
+In this manner of IPC,
+[Service](https://developer.android.com/reference/android/app/Service) works
+with [Handler](https://developer.android.com/reference/android/os/Handler) to
+deal with different types of
+[Message](https://developer.android.com/reference/android/os/Message) objects.
+
+Under the hood, each API is represented as a `Message` object:
+
+-   [what](https://developer.android.com/reference/android/os/Message#what):
+    used to identify API.
+-   [data](https://developer.android.com/reference/android/os/Message#getData\(\)):
+    payload of the API parameters and result.
+
+This could be mapped to the `ApiHandler` interface abstraction exactly.
+Specifically, the API implementation needs to provide:
+
+-   An unique id for the API.
+-   How to marshall/unmarshall the request and response.
+-   Whether the given request is permitted.
+
+## Threading model
+
+`MessengerService` starts a dedicated
+[HandlerThread](https://developer.android.com/reference/android/os/HandlerThread)
+to handle requests. `ApiHandler` implementation uses Kotlin `suspend`, which
+allows flexible threading model on top of the
+[Kotlin coroutines](https://kotlinlang.org/docs/coroutines-overview.html).
+
+## Usage
+
+The service provider should extend `MessengerService` and provide API
+implementations. In `AndroidManifest.xml`, declare `<service>` with permission,
+intent filter, etc. if needed.
+
+Meanwhile, the service client implements `MessengerServiceClient` with API
+descriptors to make requests.
+
+Here is an example:
+
+```kotlin
+import android.app.Application
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import kotlinx.coroutines.runBlocking
+
+class EchoService :
+  MessengerService(
+    listOf(EchoApiImpl),
+    PermissionChecker { _, _, _ -> true },
+  )
+
+class EchoServiceClient(context: Context) : MessengerServiceClient(context) {
+  override val serviceIntentFactory: () -> Intent
+    get() = { Intent("example.intent.action.ECHO") }
+
+  fun echo(data: String?): String? =
+    runBlocking { invoke(context.packageName, EchoApi, data).await() }
+}
+
+object EchoApi : ApiDescriptor<String?, String?> {
+  private val codec =
+    object : MessageCodec<String?> {
+      override fun encode(data: String?) =
+        Bundle(1).apply { putString("data", data) }
+
+      override fun decode(data: Bundle): String? = data.getString("data", null)
+    }
+
+  override val id: Int
+    get() = 1
+
+  override val requestCodec: MessageCodec<String?>
+    get() = codec
+
+  override val responseCodec: MessageCodec<String?>
+    get() = codec
+}
+
+// This is not needed by EchoServiceClient.
+object EchoApiImpl : ApiHandler<String?, String?>,
+                     ApiDescriptor<String?, String?> by EchoApi {
+  override suspend fun invoke(
+    application: Application,
+    myUid: Int,
+    callingUid: Int,
+    request: String?,
+  ): String? = request
+
+  override fun hasPermission(
+    application: Application,
+    myUid: Int,
+    callingUid: Int,
+    request: String?,
+  ): Boolean = (request?.length ?: 0) <= 5
+}
+```
diff --git a/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/ApiException.kt b/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/ApiException.kt
new file mode 100644
index 0000000..42772a4
--- /dev/null
+++ b/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/ApiException.kt
@@ -0,0 +1,91 @@
+/*
+ * 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.settingslib.ipc
+
+/** Exception raised when handle request. */
+sealed class ApiException : Exception {
+    constructor() : super()
+
+    constructor(cause: Throwable?) : super(cause)
+
+    constructor(message: String, cause: Throwable?) : super(message, cause)
+}
+
+/** Exception occurred on client side. */
+open class ApiClientException : ApiException {
+    constructor() : super()
+
+    constructor(cause: Throwable?) : super(cause)
+
+    constructor(message: String, cause: Throwable?) : super(message, cause)
+}
+
+/** Client has already been closed. */
+class ClientClosedException : ApiClientException()
+
+/** Api to request is invalid, e.g. negative identity number. */
+class ClientInvalidApiException(message: String) : ApiClientException(message, null)
+
+/**
+ * Exception when bind service failed.
+ *
+ * This exception may be raised for following reasons:
+ * - Context used to bind service has finished its lifecycle (e.g. activity stopped).
+ * - Service not found.
+ * - Permission denied.
+ */
+class ClientBindServiceException(cause: Throwable?) : ApiClientException(cause)
+
+/** Exception when encode request. */
+class ClientEncodeException(cause: Throwable) : ApiClientException(cause)
+
+/** Exception when decode response. */
+class ClientDecodeException(cause: Throwable) : ApiClientException(cause)
+
+/** Exception when send message. */
+class ClientSendException(message: String, cause: Throwable) : ApiClientException(message, cause)
+
+/** Service returns unknown error code. */
+class ClientUnknownResponseCodeException(code: Int) :
+    ApiClientException("Unknown code: $code", null)
+
+/** Exception returned from service. */
+open class ApiServiceException : ApiException() {
+    companion object {
+        internal const val CODE_OK = 0
+        internal const val CODE_PERMISSION_DENIED = 1
+        internal const val CODE_UNKNOWN_API = 2
+        internal const val CODE_INTERNAL_ERROR = 3
+
+        internal fun of(code: Int): ApiServiceException? =
+            when (code) {
+                CODE_PERMISSION_DENIED -> ServicePermissionDeniedException()
+                CODE_UNKNOWN_API -> ServiceUnknownApiException()
+                CODE_INTERNAL_ERROR -> ServiceInternalException()
+                else -> null
+            }
+    }
+}
+
+/** Exception indicates the request is rejected due to permission deny. */
+class ServicePermissionDeniedException : ApiServiceException()
+
+/** Exception indicates API request is unknown. */
+class ServiceUnknownApiException : ApiServiceException()
+
+/** Exception indicates internal issue occurred when service handles the request. */
+class ServiceInternalException : ApiServiceException()
diff --git a/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/ApiHandler.kt b/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/ApiHandler.kt
new file mode 100644
index 0000000..802141d
--- /dev/null
+++ b/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/ApiHandler.kt
@@ -0,0 +1,92 @@
+/*
+ * 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.settingslib.ipc
+
+import android.app.Application
+import android.os.Bundle
+
+/**
+ * Codec to marshall/unmarshall data between given type and [Bundle].
+ *
+ * The implementation must be threadsafe and stateless.
+ */
+interface MessageCodec<T> {
+    /** Converts given data to [Bundle]. */
+    fun encode(data: T): Bundle
+
+    /** Converts [Bundle] to an object of given data type. */
+    fun decode(data: Bundle): T
+}
+
+/**
+ * Descriptor of API.
+ *
+ * Used by both [MessengerService] and [MessengerServiceClient] to identify API and encode/decode
+ * messages.
+ */
+interface ApiDescriptor<Request, Response> {
+    /**
+     * Identity of the API.
+     *
+     * The id must be:
+     * - Positive: the negative numbers are reserved for internal messages.
+     * - Unique within the [MessengerService].
+     * - Permanent to achieve backward compatibility.
+     */
+    val id: Int
+
+    /** Codec for request. */
+    val requestCodec: MessageCodec<Request>
+
+    /** Codec for response. */
+    val responseCodec: MessageCodec<Response>
+}
+
+/**
+ * Handler of API.
+ *
+ * This is the API implementation portion, which is used by [MessengerService] only.
+ * [MessengerServiceClient] does NOT need this interface at all to make request.
+ *
+ * The implementation must be threadsafe.
+ */
+interface ApiHandler<Request, Response> : ApiDescriptor<Request, Response> {
+    /**
+     * Returns if the request is permitted.
+     *
+     * @return `false` if permission is denied, otherwise `true`
+     */
+    fun hasPermission(
+        application: Application,
+        myUid: Int,
+        callingUid: Int,
+        request: Request,
+    ): Boolean
+
+    /**
+     * Invokes the API.
+     *
+     * The API is invoked from Service handler thread, do not perform time-consuming task. Start
+     * coroutine in another thread if it takes time to complete.
+     */
+    suspend fun invoke(
+        application: Application,
+        myUid: Int,
+        callingUid: Int,
+        request: Request,
+    ): Response
+}
diff --git a/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/MessageCodecs.kt b/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/MessageCodecs.kt
new file mode 100644
index 0000000..4b7572b
--- /dev/null
+++ b/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/MessageCodecs.kt
@@ -0,0 +1,42 @@
+/*
+ * 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.settingslib.ipc
+
+import android.os.Bundle
+
+/** [MessageCodec] for [Int]. */
+object IntMessageCodec : MessageCodec<Int> {
+    override fun encode(data: Int): Bundle = Bundle(1).apply { putInt(null, data) }
+
+    override fun decode(data: Bundle): Int = data.getInt(null)
+}
+
+/** [MessageCodec] for [Set<Int>]. */
+class IntSetMessageCodec : MessageCodec<Set<Int>> {
+    override fun encode(data: Set<Int>): Bundle =
+        Bundle(1).apply { putIntArray(null, data.toIntArray()) }
+
+    override fun decode(data: Bundle): Set<Int> = data.getIntArray(null)?.toSet() ?: setOf()
+}
+
+/** [MessageCodec] for [Set<String>]. */
+class StringSetMessageCodec : MessageCodec<Set<String>> {
+    override fun encode(data: Set<String>): Bundle =
+        Bundle(1).apply { putStringArray(null, data.toTypedArray()) }
+
+    override fun decode(data: Bundle): Set<String> = data.getStringArray(null)?.toSet() ?: setOf()
+}
diff --git a/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/MessengerService.kt b/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/MessengerService.kt
new file mode 100644
index 0000000..0bdae38
--- /dev/null
+++ b/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/MessengerService.kt
@@ -0,0 +1,180 @@
+/*
+ * 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.settingslib.ipc
+
+import android.app.Application
+import android.app.Service
+import android.content.Intent
+import android.os.Handler
+import android.os.HandlerThread
+import android.os.IBinder
+import android.os.Looper
+import android.os.Message
+import android.os.Messenger
+import android.os.Process
+import android.util.Log
+import androidx.annotation.VisibleForTesting
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.android.asCoroutineDispatcher
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.launch
+
+/**
+ * [Messenger] based bound service for IPC.
+ *
+ * A dedicated [HandlerThread] is created to handle all requests.
+ *
+ * @param apiHandlers API handlers associated with the service
+ * @param permissionChecker Checker for permission
+ * @param name name of the handler thread
+ */
+open class MessengerService(
+    private val apiHandlers: List<ApiHandler<*, *>>,
+    private val permissionChecker: PermissionChecker,
+    name: String = TAG,
+) : Service() {
+    @VisibleForTesting internal val handlerThread = HandlerThread(name)
+    @VisibleForTesting internal lateinit var handler: IncomingHandler
+    private lateinit var messenger: Messenger
+
+    override fun onCreate() {
+        super.onCreate()
+        handlerThread.start()
+        handler =
+            IncomingHandler(
+                handlerThread.looper,
+                applicationContext as Application,
+                apiHandlers.toSortedArray(),
+                permissionChecker,
+            )
+        messenger = Messenger(handler)
+        Log.i(TAG, "onCreate HandlerThread ${handlerThread.threadId}")
+    }
+
+    override fun onBind(intent: Intent): IBinder? {
+        // this method is executed only once even there is more than 1 client
+        Log.i(TAG, "onBind $intent")
+        return messenger.binder
+    }
+
+    override fun onUnbind(intent: Intent): Boolean {
+        // invoked when ALL clients are unbound
+        Log.i(TAG, "onUnbind $intent")
+        handler.coroutineScope.cancel()
+        return super.onUnbind(intent)
+    }
+
+    override fun onDestroy() {
+        Log.i(TAG, "onDestroy HandlerThread ${handlerThread.threadId}")
+        handlerThread.quitSafely()
+        super.onDestroy()
+    }
+
+    @VisibleForTesting
+    internal class IncomingHandler(
+        looper: Looper,
+        private val application: Application,
+        private val apiHandlers: Array<ApiHandler<*, *>>,
+        private val permissionChecker: PermissionChecker,
+    ) : Handler(looper) {
+        @VisibleForTesting internal val myUid = Process.myUid()
+        val coroutineScope = CoroutineScope(asCoroutineDispatcher().immediate + SupervisorJob())
+
+        override fun handleMessage(msg: Message) {
+            coroutineScope.launch { handle(msg) }
+        }
+
+        @VisibleForTesting
+        internal suspend fun handle(msg: Message) {
+            Log.d(TAG, "receive request $msg")
+            val replyTo = msg.replyTo
+            if (replyTo == null) {
+                Log.e(TAG, "Ignore msg without replyTo: $msg")
+                return
+            }
+            val apiId = msg.what
+            val txnId = msg.arg1
+            val callingUid = msg.sendingUid
+            val data = msg.data
+            // WARNING: never access "msg" beyond this point as it may be recycled by Looper
+            val response = Message.obtain(null, apiId, txnId, ApiServiceException.CODE_OK)
+            try {
+                if (permissionChecker.check(application, myUid, callingUid)) {
+                    @Suppress("UNCHECKED_CAST")
+                    val apiHandler = findApiHandler(apiId) as? ApiHandler<Any, Any>
+                    if (apiHandler != null) {
+                        val request = apiHandler.requestCodec.decode(data)
+                        if (apiHandler.hasPermission(application, myUid, callingUid, request)) {
+                            val result = apiHandler.invoke(application, myUid, callingUid, request)
+                            response.data = apiHandler.responseCodec.encode(result)
+                        } else {
+                            response.arg2 = ApiServiceException.CODE_PERMISSION_DENIED
+                        }
+                    } else {
+                        response.arg2 = ApiServiceException.CODE_UNKNOWN_API
+                        Log.e(TAG, "Unknown request [txnId=$txnId,apiId=$apiId]")
+                    }
+                } else {
+                    response.arg2 = ApiServiceException.CODE_PERMISSION_DENIED
+                }
+            } catch (e: Exception) {
+                response.arg2 = ApiServiceException.CODE_INTERNAL_ERROR
+                Log.e(TAG, "Internal error when handle [txnId=$txnId,apiId=$apiId]", e)
+            }
+            try {
+                replyTo.send(response)
+            } catch (e: Exception) {
+                Log.w(TAG, "Fail to send response for [txnId=$txnId,apiId=$apiId]", e)
+                // nothing to do
+            }
+        }
+
+        @VisibleForTesting
+        internal fun findApiHandler(id: Int): ApiHandler<*, *>? {
+            var low = 0
+            var high = apiHandlers.size
+            while (low < high) {
+                val mid = (low + high).ushr(1) // safe from overflows
+                val api = apiHandlers[mid]
+                when {
+                    api.id < id -> low = mid + 1
+                    api.id > id -> high = mid
+                    else -> return api
+                }
+            }
+            return null
+        }
+    }
+
+    companion object {
+        @VisibleForTesting internal const val TAG = "MessengerService"
+    }
+}
+
+@VisibleForTesting
+internal fun List<ApiHandler<*, *>>.toSortedArray() =
+    toTypedArray().also { array ->
+        if (array.isEmpty()) return@also
+        array.sortBy { it.id }
+        if (array[0].id < 0) throw IllegalArgumentException("negative id: ${array[0]}")
+        for (index in 1 until array.size) {
+            if (array[index - 1].id == array[index].id) {
+                throw IllegalArgumentException("conflict id: ${array[index - 1]} ${array[index]}")
+            }
+        }
+    }
diff --git a/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/MessengerServiceClient.kt b/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/MessengerServiceClient.kt
new file mode 100644
index 0000000..7ffefed
--- /dev/null
+++ b/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/MessengerServiceClient.kt
@@ -0,0 +1,471 @@
+/*
+ * 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.settingslib.ipc
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.ServiceConnection
+import android.os.Bundle
+import android.os.DeadObjectException
+import android.os.Handler
+import android.os.HandlerThread
+import android.os.IBinder
+import android.os.Looper
+import android.os.Message
+import android.os.Messenger
+import android.util.Log
+import androidx.annotation.OpenForTesting
+import androidx.annotation.VisibleForTesting
+import androidx.collection.ArrayMap
+import com.google.common.base.Ticker
+import java.util.concurrent.atomic.AtomicInteger
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.CompletionHandler
+import kotlinx.coroutines.Deferred
+import kotlinx.coroutines.DisposableHandle
+
+/**
+ * Client to communicate with [MessengerService].
+ *
+ * A dedicated [HandlerThread] is created to handle requests **sequentially**, there is only one
+ * ongoing request per package.
+ *
+ * Must call [close] before [context] is destroyed to avoid context leaking. Note that
+ * [MessengerService] is automatically unbound when context lifecycle is stopped. Further request
+ * will result in service binding exception.
+ *
+ * @param context context used for service binding, note that context lifecycle affects the IPC
+ *   service lifecycle
+ * @param serviceConnectionIdleMs idle time in milliseconds before closing the service connection
+ * @param name name of the handler thread
+ */
+abstract class MessengerServiceClient
+@JvmOverloads
+constructor(
+    protected val context: Context,
+    private val serviceConnectionIdleMs: Long = 30000L,
+    name: String = TAG,
+    private val metricsLogger: MetricsLogger? = null,
+) : AutoCloseable {
+    /** Per package [ServiceConnection]. */
+    @VisibleForTesting internal val messengers = ArrayMap<String, Connection>()
+    private val handlerThread = HandlerThread(name)
+    @VisibleForTesting internal val handler: Handler
+
+    init {
+        handlerThread.start()
+        val looper = handlerThread.looper
+        handler = Handler(looper)
+    }
+
+    /**
+     * Factory for service [Intent] creation.
+     *
+     * A typical implementation is create [Intent] with specific action.
+     */
+    protected abstract val serviceIntentFactory: () -> Intent
+
+    override fun close() = close(true)
+
+    fun close(join: Boolean) {
+        handler.post {
+            val exception = ClientClosedException()
+            val connections = messengers.values.toTypedArray()
+            for (connection in connections) connection.close(exception)
+        }
+        handlerThread.quitSafely()
+        if (join) handlerThread.join()
+    }
+
+    /**
+     * Invokes given API.
+     *
+     * @param packageName package name of the target service
+     * @param apiDescriptor descriptor of API
+     * @param request request parameter
+     * @return Deferred object of the response, which could be used for [Deferred.await],
+     *   [Deferred.cancel], etc.
+     * @exception ApiException
+     */
+    // TODO: support timeout
+    fun <Request, Response> invoke(
+        packageName: String,
+        apiDescriptor: ApiDescriptor<Request, Response>,
+        request: Request,
+    ): Deferred<Response> {
+        if (apiDescriptor.id < 0) throw ClientInvalidApiException("Invalid id: ${apiDescriptor.id}")
+        if (
+            packageName == context.packageName &&
+                Looper.getMainLooper().thread === Thread.currentThread()
+        ) {
+            // Deadlock as it might involve service creation, which requires main thread
+            throw IllegalStateException("Invoke on main thread causes deadlock")
+        }
+        val wrapper = RequestWrapper(packageName, apiDescriptor, request, txnId.getAndIncrement())
+        metricsLogger?.run {
+            wrapper.logIpcEvent(this, IpcEvent.ENQUEUED)
+            wrapper.deferred.invokeOnCompletion {
+                wrapper.logIpcEvent(this, IpcEvent.COMPLETED, it)
+            }
+        }
+        if (!handler.post { getConnection(packageName).enqueueRequest(wrapper) }) {
+            wrapper.completeExceptionally(ClientClosedException())
+        }
+        return wrapper.deferred
+    }
+
+    private fun getConnection(packageName: String) =
+        messengers.getOrPut(packageName) {
+            Connection(
+                handler.looper,
+                context,
+                packageName,
+                serviceConnectionIdleMs,
+                serviceIntentFactory,
+                messengers,
+                metricsLogger,
+            )
+        }
+
+    @VisibleForTesting
+    internal data class RequestWrapper<Request, Response>(
+        val packageName: String,
+        val apiDescriptor: ApiDescriptor<Request, Response>,
+        val request: Request,
+        val txnId: Int,
+        val deferred: CompletableDeferred<Response> = CompletableDeferred(),
+    ) {
+        val data: Bundle
+            get() = request.let { apiDescriptor.requestCodec.encode(it) }
+
+        fun completeExceptionally(e: Exception) {
+            deferred.completeExceptionally(e)
+        }
+
+        fun logIpcEvent(
+            metricsLogger: MetricsLogger,
+            event: @IpcEvent Int,
+            cause: Throwable? = null,
+        ) {
+            try {
+                metricsLogger.logIpcEvent(
+                    packageName,
+                    txnId,
+                    apiDescriptor.id,
+                    event,
+                    cause,
+                    ticker.read(),
+                )
+            } catch (e: Exception) {
+                Log.e(TAG, "fail to log ipc event: $event", e)
+            }
+        }
+    }
+
+    // NOTE: All ServiceConnection callbacks are invoked from main thread.
+    @OpenForTesting
+    @VisibleForTesting
+    internal open class Connection(
+        looper: Looper,
+        private val context: Context,
+        private val packageName: String,
+        private val serviceConnectionIdleMs: Long,
+        private val serviceIntentFactory: () -> Intent,
+        private val messengers: ArrayMap<String, Connection>,
+        private val metricsLogger: MetricsLogger?,
+    ) : Handler(looper), ServiceConnection {
+        private val clientMessenger = Messenger(this)
+        internal val pendingRequests = ArrayDeque<RequestWrapper<*, *>>()
+        internal var serviceMessenger: Messenger? = null
+        internal open var connectionState: Int = STATE_INIT
+
+        internal var disposableHandle: DisposableHandle? = null
+        private val requestCompletionHandler =
+            object : CompletionHandler {
+                override fun invoke(cause: Throwable?) {
+                    sendEmptyMessage(MSG_CHECK_REQUEST_STATE)
+                }
+            }
+
+        override fun handleMessage(msg: Message) {
+            if (msg.what < 0) {
+                handleClientMessage(msg)
+                return
+            }
+            Log.d(TAG, "receive response $msg")
+            val request = pendingRequests.removeFirstOrNull()
+            if (request == null) {
+                Log.w(TAG, "Pending request is empty when got response")
+                return
+            }
+            if (msg.arg1 != request.txnId || request.apiDescriptor.id != msg.what) {
+                Log.w(TAG, "Mismatch ${request.apiDescriptor.id}, response=$msg")
+                // add request back for retry
+                pendingRequests.addFirst(request)
+                return
+            }
+            handleServiceMessage(request, msg)
+        }
+
+        internal open fun handleClientMessage(msg: Message) {
+            when (msg.what) {
+                MSG_ON_SERVICE_CONNECTED -> {
+                    if (connectionState == STATE_BINDING) {
+                        connectionState = STATE_CONNECTED
+                        serviceMessenger = Messenger(msg.obj as IBinder)
+                        drainPendingRequests()
+                    } else {
+                        Log.w(TAG, "Got onServiceConnected when state is $connectionState")
+                    }
+                }
+                MSG_REBIND_SERVICE -> {
+                    if (pendingRequests.isEmpty()) {
+                        removeMessages(MSG_CLOSE_ON_IDLE)
+                        close(null)
+                    } else {
+                        // died when binding, reset state for rebinding
+                        if (msg.obj != null && connectionState == STATE_BINDING) {
+                            connectionState = STATE_CONNECTED
+                        }
+                        rebindService()
+                    }
+                }
+                MSG_CLOSE_ON_IDLE -> {
+                    if (pendingRequests.isEmpty()) close(null)
+                }
+                MSG_CHECK_REQUEST_STATE -> {
+                    val request = pendingRequests.firstOrNull()
+                    if (request != null && request.deferred.isCompleted) {
+                        drainPendingRequests()
+                    }
+                }
+                else -> Log.e(TAG, "Unknown msg: $msg")
+            }
+        }
+
+        internal open fun handleServiceMessage(request: RequestWrapper<*, *>, response: Message) {
+            @Suppress("UNCHECKED_CAST") val deferred = request.deferred as CompletableDeferred<Any?>
+            if (deferred.isCompleted) {
+                drainPendingRequests()
+                return
+            }
+            metricsLogger?.let { request.logIpcEvent(it, IpcEvent.RESPONSE_RECEIVED) }
+            disposableHandle?.dispose()
+            if (response.arg2 == ApiServiceException.CODE_OK) {
+                try {
+                    deferred.complete(request.apiDescriptor.responseCodec.decode(response.data))
+                } catch (e: Exception) {
+                    request.completeExceptionally(ClientDecodeException(e))
+                }
+            } else {
+                val errorCode = response.arg2
+                val exception = ApiServiceException.of(errorCode)
+                if (exception != null) {
+                    request.completeExceptionally(exception)
+                } else {
+                    request.completeExceptionally(ClientUnknownResponseCodeException(errorCode))
+                }
+            }
+            drainPendingRequests()
+        }
+
+        fun enqueueRequest(request: RequestWrapper<*, *>) {
+            if (connectionState == STATE_CLOSED) {
+                request.completeExceptionally(ClientClosedException())
+                return
+            }
+            pendingRequests.add(request)
+            if (pendingRequests.size == 1) {
+                removeMessages(MSG_CLOSE_ON_IDLE)
+                drainPendingRequests()
+            }
+        }
+
+        override fun onServiceConnected(name: ComponentName, service: IBinder) {
+            Log.i(TAG, "onServiceConnected $name")
+            metricsLogger?.logServiceEvent(ServiceEvent.ON_SERVICE_CONNECTED)
+            sendMessage(obtainMessage(MSG_ON_SERVICE_CONNECTED, service))
+        }
+
+        override fun onServiceDisconnected(name: ComponentName) {
+            // Service process crashed or killed, the connection remains alive, will receive
+            // onServiceConnected when the Service is next running
+            Log.i(TAG, "onServiceDisconnected $name")
+            metricsLogger?.logServiceEvent(ServiceEvent.ON_SERVICE_DISCONNECTED)
+            sendMessage(obtainMessage(MSG_REBIND_SERVICE))
+        }
+
+        override fun onBindingDied(name: ComponentName) {
+            Log.i(TAG, "onBindingDied $name")
+            metricsLogger?.logServiceEvent(ServiceEvent.ON_BINDING_DIED)
+            // When service is connected and peer happens to be updated, both onServiceDisconnected
+            // and onBindingDied callbacks are invoked.
+            if (!hasMessages(MSG_REBIND_SERVICE)) {
+                sendMessage(obtainMessage(MSG_REBIND_SERVICE, true))
+            }
+        }
+
+        internal open fun drainPendingRequests() {
+            disposableHandle = null
+            if (pendingRequests.isEmpty()) {
+                closeOnIdle(serviceConnectionIdleMs)
+                return
+            }
+            val serviceMessenger = this.serviceMessenger
+            if (serviceMessenger == null) {
+                bindService()
+                return
+            }
+            do {
+                val request = pendingRequests.first()
+                if (request.deferred.isCompleted) {
+                    pendingRequests.removeFirst()
+                } else {
+                    sendServiceMessage(serviceMessenger, request)
+                    return
+                }
+            } while (pendingRequests.isNotEmpty())
+            closeOnIdle(serviceConnectionIdleMs)
+        }
+
+        internal open fun closeOnIdle(idleMs: Long) {
+            if (idleMs <= 0 || !sendEmptyMessageDelayed(MSG_CLOSE_ON_IDLE, idleMs)) {
+                close(null)
+            }
+        }
+
+        internal open fun sendServiceMessage(
+            serviceMessenger: Messenger,
+            request: RequestWrapper<*, *>,
+        ) {
+            fun completeExceptionally(exception: Exception) {
+                pendingRequests.removeFirst()
+                request.completeExceptionally(exception)
+                drainPendingRequests()
+            }
+            val message =
+                obtainMessage(request.apiDescriptor.id, request.txnId, 0).apply {
+                    replyTo = clientMessenger
+                }
+            try {
+                message.data = request.data
+            } catch (e: Exception) {
+                completeExceptionally(ClientEncodeException(e))
+                return
+            }
+            Log.d(TAG, "send $message")
+            try {
+                sendServiceMessage(serviceMessenger, message)
+                metricsLogger?.let { request.logIpcEvent(it, IpcEvent.REQUEST_SENT) }
+                disposableHandle = request.deferred.invokeOnCompletion(requestCompletionHandler)
+            } catch (e: DeadObjectException) {
+                Log.w(TAG, "Got DeadObjectException")
+                rebindService()
+            } catch (e: Exception) {
+                completeExceptionally(ClientSendException("Fail to send $message", e))
+            }
+        }
+
+        @Throws(Exception::class)
+        internal open fun sendServiceMessage(serviceMessenger: Messenger, message: Message) =
+            serviceMessenger.send(message)
+
+        internal fun bindService() {
+            if (connectionState == STATE_BINDING || connectionState == STATE_CLOSED) {
+                Log.w(TAG, "Ignore bindService $packageName, state: $connectionState")
+                return
+            }
+            connectionState = STATE_BINDING
+            Log.i(TAG, "bindService $packageName")
+            val intent = serviceIntentFactory.invoke()
+            intent.setPackage(packageName)
+            metricsLogger?.logServiceEvent(ServiceEvent.BIND_SERVICE)
+            bindService(intent)?.let { close(it) }
+        }
+
+        private fun bindService(intent: Intent): Exception? =
+            try {
+                if (context.bindService(intent, this, Context.BIND_AUTO_CREATE)) {
+                    null
+                } else {
+                    ClientBindServiceException(null)
+                }
+            } catch (e: Exception) {
+                ClientBindServiceException(e)
+            }
+
+        internal open fun rebindService() {
+            Log.i(TAG, "rebindService $packageName")
+            metricsLogger?.logServiceEvent(ServiceEvent.REBIND_SERVICE)
+            unbindService()
+            bindService()
+        }
+
+        internal fun close(exception: Exception?) {
+            Log.i(TAG, "close connection $packageName", exception)
+            connectionState = STATE_CLOSED
+            messengers.remove(packageName, this)
+            unbindService()
+            if (pendingRequests.isNotEmpty()) {
+                val reason = exception ?: ClientClosedException()
+                do {
+                    pendingRequests.removeFirst().deferred.completeExceptionally(reason)
+                } while (pendingRequests.isNotEmpty())
+            }
+        }
+
+        private fun unbindService() {
+            disposableHandle?.dispose()
+            disposableHandle = null
+            serviceMessenger = null
+            metricsLogger?.logServiceEvent(ServiceEvent.UNBIND_SERVICE)
+            try {
+                // "IllegalArgumentException: Service not registered" may be raised when peer app is
+                // just updated (e.g. upgraded)
+                context.unbindService(this)
+            } catch (e: Exception) {
+                Log.w(TAG, "exception raised when unbindService", e)
+            }
+        }
+
+        private fun MetricsLogger.logServiceEvent(event: @ServiceEvent Int) {
+            try {
+                logServiceEvent(packageName, event, ticker.read())
+            } catch (e: Exception) {
+                Log.e(TAG, "fail to log service event: $event", e)
+            }
+        }
+    }
+
+    companion object {
+        private const val TAG = "MessengerServiceClient"
+        private val ticker: Ticker by lazy { Ticker.systemTicker() }
+
+        @VisibleForTesting internal const val STATE_INIT = 0
+        @VisibleForTesting internal const val STATE_BINDING = 1
+        @VisibleForTesting internal const val STATE_CONNECTED = 2
+        @VisibleForTesting internal const val STATE_CLOSED = 3
+
+        @VisibleForTesting internal const val MSG_ON_SERVICE_CONNECTED = -1
+        @VisibleForTesting internal const val MSG_REBIND_SERVICE = -2
+        @VisibleForTesting internal const val MSG_CLOSE_ON_IDLE = -3
+        @VisibleForTesting internal const val MSG_CHECK_REQUEST_STATE = -4
+
+        @VisibleForTesting internal val txnId = AtomicInteger()
+    }
+}
diff --git a/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/MetricsLogger.kt b/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/MetricsLogger.kt
new file mode 100644
index 0000000..795a920
--- /dev/null
+++ b/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/MetricsLogger.kt
@@ -0,0 +1,107 @@
+/*
+ * 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.settingslib.ipc
+
+import androidx.annotation.IntDef
+
+/** Interface for metrics logging. */
+interface MetricsLogger {
+
+    /**
+     * Logs service connection event.
+     *
+     * @param packageName package name of the service connection
+     * @param event service event type
+     * @param elapsedRealtimeNanos nanoseconds since boot, including time spent in sleep
+     * @see [android.os.SystemClock.elapsedRealtimeNanos]
+     */
+    fun logServiceEvent(packageName: String, event: @ServiceEvent Int, elapsedRealtimeNanos: Long)
+
+    /**
+     * Logs ipc call event.
+     *
+     * @param packageName package name of the service connection
+     * @param txnId unique transaction id of the ipc call
+     * @param ipc ipc API id
+     * @param event ipc event type
+     * @param cause cause when ipc request completed, provided only when [event] is
+     *   [IpcEvent.COMPLETED]
+     * @param elapsedRealtimeNanos nanoseconds since boot, including time spent in sleep
+     * @see [android.os.SystemClock.elapsedRealtimeNanos]
+     */
+    fun logIpcEvent(
+        packageName: String,
+        txnId: Int,
+        ipc: Int,
+        event: Int,
+        cause: Throwable?,
+        elapsedRealtimeNanos: Long,
+    )
+}
+
+/** Service connection events (for client). */
+@Target(AnnotationTarget.TYPE)
+@IntDef(
+    ServiceEvent.BIND_SERVICE,
+    ServiceEvent.UNBIND_SERVICE,
+    ServiceEvent.REBIND_SERVICE,
+    ServiceEvent.ON_SERVICE_CONNECTED,
+    ServiceEvent.ON_SERVICE_DISCONNECTED,
+    ServiceEvent.ON_BINDING_DIED,
+)
+@Retention(AnnotationRetention.SOURCE)
+annotation class ServiceEvent {
+    companion object {
+        /** Event of [android.content.Context.bindService] call. */
+        const val BIND_SERVICE = 0
+
+        /** Event of [android.content.Context.unbindService] call. */
+        const val UNBIND_SERVICE = 1
+
+        /** Event to rebind service. */
+        const val REBIND_SERVICE = 2
+
+        /** Event of [android.content.ServiceConnection.onServiceConnected] callback. */
+        const val ON_SERVICE_CONNECTED = 3
+
+        /** Event of [android.content.ServiceConnection.onServiceDisconnected] callback. */
+        const val ON_SERVICE_DISCONNECTED = 4
+
+        /** Event of [android.content.ServiceConnection.onBindingDied] callback. */
+        const val ON_BINDING_DIED = 5
+    }
+}
+
+/** Events of a ipc call. */
+@Target(AnnotationTarget.TYPE)
+@IntDef(IpcEvent.ENQUEUED, IpcEvent.REQUEST_SENT, IpcEvent.RESPONSE_RECEIVED, IpcEvent.COMPLETED)
+@Retention(AnnotationRetention.SOURCE)
+annotation class IpcEvent {
+    companion object {
+        /** Event of IPC request enqueued. */
+        const val ENQUEUED = 0
+
+        /** Event of IPC request has been sent to service. */
+        const val REQUEST_SENT = 1
+
+        /** Event of IPC response received from service. */
+        const val RESPONSE_RECEIVED = 2
+
+        /** Event of IPC request completed. */
+        const val COMPLETED = 3
+    }
+}
diff --git a/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/PermissionChecker.kt b/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/PermissionChecker.kt
new file mode 100644
index 0000000..da9c955
--- /dev/null
+++ b/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/PermissionChecker.kt
@@ -0,0 +1,43 @@
+/*
+ * 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.settingslib.ipc
+
+import android.app.Application
+import android.content.pm.PackageManager
+import androidx.collection.mutableIntIntMapOf
+
+/** Checker for permission. */
+fun interface PermissionChecker {
+    /**
+     * Checks permission.
+     *
+     * @param application application context
+     * @param myUid uid of current process
+     * @param callingUid uid of peer process
+     */
+    fun check(application: Application, myUid: Int, callingUid: Int): Boolean
+}
+
+/** Verifies apk signatures as permission check. */
+class SignatureChecker : PermissionChecker {
+    private val cache = mutableIntIntMapOf()
+
+    override fun check(application: Application, myUid: Int, callingUid: Int): Boolean =
+        cache.getOrPut(callingUid) {
+            application.packageManager.checkSignatures(myUid, callingUid)
+        } == PackageManager.SIGNATURE_MATCH
+}
diff --git a/packages/SettingsLib/aconfig/settingslib.aconfig b/packages/SettingsLib/aconfig/settingslib.aconfig
index 34b597b..79c3ff9 100644
--- a/packages/SettingsLib/aconfig/settingslib.aconfig
+++ b/packages/SettingsLib/aconfig/settingslib.aconfig
@@ -139,3 +139,13 @@
         purpose: PURPOSE_BUGFIX
     }
 }
+
+flag {
+    name: "audio_sharing_qs_dialog_improvement"
+    namespace: "cross_device_experiences"
+    description: "Gates whether to enable audio sharing qs dialog improvement"
+    bug: "360759048"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 1e58335..9d56c77 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -520,8 +520,6 @@
 
         if (android.webkit.Flags.updateServiceIpcWrapper()) {
             if (pm.hasSystemFeature(PackageManager.FEATURE_WEBVIEW)) {
-                // WebViewUpdateManager.getInstance() will not return null on devices with
-                // FEATURE_WEBVIEW.
                 provider = WebViewUpdateManager.getInstance().getDefaultWebViewPackage();
             }
         } else {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
index c6eb9fd..6dab224 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
@@ -18,6 +18,7 @@
 
 import android.bluetooth.BluetoothCsipSetCoordinator;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothLeBroadcastMetadata;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothUuid;
 import android.os.Build;
@@ -356,6 +357,8 @@
         final CachedBluetoothDeviceManager deviceManager = mBtManager.getCachedDeviceManager();
         preferredMainDevice = deviceManager.findDevice(bluetoothDeviceOfPreferredMainDevice);
         if (haveMultiMainDevicesInAllOfDevicesList) {
+            log("addMemberDevicesIntoMainDevice: haveMultiMainDevicesInAllOfDevicesList. "
+                    + "Combine them and also keep the preferred main device as main device.");
             // put another devices into main device.
             for (CachedBluetoothDevice deviceItem : topLevelOfGroupDevicesList) {
                 if (deviceItem.getDevice() == null || deviceItem.getDevice().equals(
@@ -376,6 +379,7 @@
                 preferredMainDevice.refresh();
                 hasChanged = true;
             }
+            syncAudioSharingSourceIfNeeded(preferredMainDevice);
         }
         if (hasChanged) {
             log("addMemberDevicesIntoMainDevice: After changed, CachedBluetoothDevice list: "
@@ -384,6 +388,41 @@
         return hasChanged;
     }
 
+    private void syncAudioSharingSourceIfNeeded(CachedBluetoothDevice mainDevice) {
+        boolean isAudioSharingEnabled = BluetoothUtils.isAudioSharingEnabled();
+        if (isAudioSharingEnabled) {
+            boolean hasBroadcastSource = BluetoothUtils.isBroadcasting(mBtManager)
+                    && BluetoothUtils.hasConnectedBroadcastSource(
+                    mainDevice, mBtManager);
+            if (hasBroadcastSource) {
+                LocalBluetoothLeBroadcast broadcast = mBtManager == null ? null
+                        : mBtManager.getProfileManager().getLeAudioBroadcastProfile();
+                BluetoothLeBroadcastMetadata metadata = broadcast == null ? null :
+                        broadcast.getLatestBluetoothLeBroadcastMetadata();
+                LocalBluetoothLeBroadcastAssistant assistant = mBtManager == null ? null
+                        : mBtManager.getProfileManager().getLeAudioBroadcastAssistantProfile();
+                if (metadata != null && assistant != null) {
+                    log("addMemberDevicesIntoMainDevice: sync audio sharing source after "
+                            + "combining the top level devices.");
+                    Set<CachedBluetoothDevice> deviceSet = new HashSet<>();
+                    deviceSet.add(mainDevice);
+                    deviceSet.addAll(mainDevice.getMemberDevice());
+                    Set<BluetoothDevice> sinksToSync = deviceSet.stream()
+                            .map(CachedBluetoothDevice::getDevice)
+                            .filter(device ->
+                                    !BluetoothUtils.hasConnectedBroadcastSourceForBtDevice(
+                                            device, mBtManager))
+                            .collect(Collectors.toSet());
+                    for (BluetoothDevice device : sinksToSync) {
+                        log("addMemberDevicesIntoMainDevice: sync audio sharing source to "
+                                + device.getAnonymizedAddress());
+                        assistant.addSource(device, metadata, /* isGroupOp= */ false);
+                    }
+                }
+            }
+        }
+    }
+
     private void log(String msg) {
         if (DEBUG) {
             Log.d(TAG, msg);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CsipDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CsipDeviceManagerTest.java
index 698eb81..b180b69 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CsipDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CsipDeviceManagerTest.java
@@ -18,31 +18,51 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
 
+import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothCsipSetCoordinator;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothLeBroadcastMetadata;
+import android.bluetooth.BluetoothLeBroadcastReceiveState;
 import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothStatusCodes;
 import android.content.Context;
+import android.os.Looper;
 import android.os.Parcel;
+import android.platform.test.flag.junit.SetFlagsRule;
+
+import com.android.settingslib.flags.Flags;
+import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
+
+import com.google.common.collect.ImmutableList;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
 
 import java.util.ArrayList;
 import java.util.List;
 
 @RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowBluetoothAdapter.class})
 public class CsipDeviceManagerTest {
     private final static String DEVICE_NAME_1 = "TestName_1";
     private final static String DEVICE_NAME_2 = "TestName_2";
@@ -59,6 +79,9 @@
     private final BluetoothClass DEVICE_CLASS_2 =
             createBtClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE);
 
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
     @Mock
     private LocalBluetoothManager mLocalBluetoothManager;
     @Mock
@@ -77,7 +100,12 @@
     private A2dpProfile mA2dpProfile;
     @Mock
     private LeAudioProfile mLeAudioProfile;
+    @Mock
+    private LocalBluetoothLeBroadcast mBroadcast;
+    @Mock
+    private LocalBluetoothLeBroadcastAssistant mAssistant;
 
+    private ShadowBluetoothAdapter mShadowBluetoothAdapter;
     private CachedBluetoothDevice mCachedDevice1;
     private CachedBluetoothDevice mCachedDevice2;
     private CachedBluetoothDevice mCachedDevice3;
@@ -101,6 +129,12 @@
         MockitoAnnotations.initMocks(this);
 
         mContext = RuntimeEnvironment.application;
+        mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
+        mShadowBluetoothAdapter.setEnabled(true);
+        mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
+                BluetoothStatusCodes.FEATURE_SUPPORTED);
+        mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
+                BluetoothStatusCodes.FEATURE_SUPPORTED);
         when(mDevice1.getAddress()).thenReturn(DEVICE_ADDRESS_1);
         when(mDevice2.getAddress()).thenReturn(DEVICE_ADDRESS_2);
         when(mDevice3.getAddress()).thenReturn(DEVICE_ADDRESS_3);
@@ -124,6 +158,8 @@
         when(mLocalProfileManager.getLeAudioProfile()).thenReturn(mLeAudioProfile);
         when(mLocalProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
         when(mLocalProfileManager.getHeadsetProfile()).thenReturn(mHfpProfile);
+        when(mLocalProfileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(mAssistant);
+        when(mLocalProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast);
 
         when(mLeAudioProfile.getConnectedGroupLeadDevice(anyInt())).thenReturn(null);
         mCachedDeviceManager = new CachedBluetoothDeviceManager(mContext, mLocalBluetoothManager);
@@ -307,6 +343,7 @@
         mCachedDevices.add(preferredDevice);
         mCachedDevices.add(mCachedDevice2);
         mCachedDevices.add(mCachedDevice3);
+        mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
 
         assertThat(mCsipDeviceManager.addMemberDevicesIntoMainDevice(GROUP1, preferredDevice))
                 .isTrue();
@@ -314,6 +351,36 @@
         assertThat(mCachedDevices.contains(mCachedDevice2)).isFalse();
         assertThat(mCachedDevices.contains(mCachedDevice3)).isTrue();
         assertThat(preferredDevice.getMemberDevice()).contains(mCachedDevice2);
+        verify(mAssistant, never()).addSource(any(BluetoothDevice.class),
+                any(BluetoothLeBroadcastMetadata.class), anyBoolean());
+    }
+
+    @Test
+    public void addMemberDevicesIntoMainDevice_preferredDeviceIsMainAndTwoMain_syncSource() {
+        // Condition: The preferredDevice is main and there is another main device in top list
+        // Expected Result: return true and there is the preferredDevice in top list
+        CachedBluetoothDevice preferredDevice = mCachedDevice1;
+        mCachedDevice1.getMemberDevice().clear();
+        mCachedDevices.clear();
+        mCachedDevices.add(preferredDevice);
+        mCachedDevices.add(mCachedDevice2);
+        mCachedDevices.add(mCachedDevice3);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+        when(mBroadcast.isEnabled(null)).thenReturn(true);
+        BluetoothLeBroadcastMetadata metadata = Mockito.mock(BluetoothLeBroadcastMetadata.class);
+        when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(metadata);
+        BluetoothLeBroadcastReceiveState state = Mockito.mock(
+                BluetoothLeBroadcastReceiveState.class);
+        when(state.getBisSyncState()).thenReturn(ImmutableList.of(1L));
+        when(mAssistant.getAllSources(mDevice2)).thenReturn(ImmutableList.of(state));
+
+        assertThat(mCsipDeviceManager.addMemberDevicesIntoMainDevice(GROUP1, preferredDevice))
+                .isTrue();
+        assertThat(mCachedDevices.contains(preferredDevice)).isTrue();
+        assertThat(mCachedDevices.contains(mCachedDevice2)).isFalse();
+        assertThat(mCachedDevices.contains(mCachedDevice3)).isTrue();
+        assertThat(preferredDevice.getMemberDevice()).contains(mCachedDevice2);
+        verify(mAssistant).addSource(mDevice1, metadata, /* isGroupOp= */ false);
     }
 
     @Test
@@ -341,6 +408,8 @@
         CachedBluetoothDevice preferredDevice = mCachedDevice2;
         BluetoothDevice expectedMainBluetoothDevice = preferredDevice.getDevice();
         mCachedDevice3.setGroupId(GROUP1);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+        when(mBroadcast.isEnabled(null)).thenReturn(false);
 
         assertThat(mCsipDeviceManager.addMemberDevicesIntoMainDevice(GROUP1, preferredDevice))
                 .isTrue();
@@ -351,8 +420,40 @@
         assertThat(mCachedDevices.contains(mCachedDevice3)).isFalse();
         assertThat(mCachedDevice1.getMemberDevice()).contains(mCachedDevice2);
         assertThat(mCachedDevice1.getMemberDevice()).contains(mCachedDevice3);
+        assertThat(mCachedDevice1.getDevice()).isEqualTo(expectedMainBluetoothDevice);
+        verify(mAssistant, never()).addSource(any(BluetoothDevice.class),
+                any(BluetoothLeBroadcastMetadata.class), anyBoolean());
+    }
+
+    @Test
+    public void addMemberDevicesIntoMainDevice_preferredDeviceIsMemberAndTwoMain_syncSource() {
+        // Condition: The preferredDevice is member and there are two main device in top list
+        // Expected Result: return true and there is the preferredDevice in top list
+        CachedBluetoothDevice preferredDevice = mCachedDevice2;
+        BluetoothDevice expectedMainBluetoothDevice = preferredDevice.getDevice();
+        mCachedDevice3.setGroupId(GROUP1);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+        when(mBroadcast.isEnabled(null)).thenReturn(true);
+        BluetoothLeBroadcastMetadata metadata = Mockito.mock(BluetoothLeBroadcastMetadata.class);
+        when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(metadata);
+        BluetoothLeBroadcastReceiveState state = Mockito.mock(
+                BluetoothLeBroadcastReceiveState.class);
+        when(state.getBisSyncState()).thenReturn(ImmutableList.of(1L));
+        when(mAssistant.getAllSources(mDevice1)).thenReturn(ImmutableList.of(state));
+
+        assertThat(mCsipDeviceManager.addMemberDevicesIntoMainDevice(GROUP1, preferredDevice))
+                .isTrue();
+        shadowOf(Looper.getMainLooper()).idle();
+        // expected main is mCachedDevice1 which is the main of preferredDevice, since system
+        // switch the relationship between preferredDevice and the main of preferredDevice
+        assertThat(mCachedDevices.contains(mCachedDevice1)).isTrue();
+        assertThat(mCachedDevices.contains(mCachedDevice2)).isFalse();
+        assertThat(mCachedDevices.contains(mCachedDevice3)).isFalse();
+        assertThat(mCachedDevice1.getMemberDevice()).contains(mCachedDevice2);
         assertThat(mCachedDevice1.getMemberDevice()).contains(mCachedDevice3);
         assertThat(mCachedDevice1.getDevice()).isEqualTo(expectedMainBluetoothDevice);
+        verify(mAssistant).addSource(mDevice2, metadata, /* isGroupOp= */ false);
+        verify(mAssistant).addSource(mDevice3, metadata, /* isGroupOp= */ false);
     }
 
     @Test
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/device_config_service.aconfig b/packages/SettingsProvider/src/com/android/providers/settings/device_config_service.aconfig
index 62401a1..aca26ec 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/device_config_service.aconfig
+++ b/packages/SettingsProvider/src/com/android/providers/settings/device_config_service.aconfig
@@ -91,3 +91,13 @@
         purpose: PURPOSE_BUGFIX
     }
 }
+
+flag {
+    name: "support_local_overrides_sysprops"
+    namespace: "core_experiments_team_internal"
+    description: "When DeviceConfig overrides are deleted, delete new storage overrides too."
+    bug: "366022906"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt
index 34eafde..d326f00 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt
@@ -830,7 +830,7 @@
             Image(
                 bitmap = it.asImageBitmap(),
                 contentDescription = null,
-                modifier = Modifier.size(SelectedUserImageSize),
+                modifier = Modifier.size(SelectedUserImageSize).sysuiResTag("user_icon"),
             )
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/decor/OverlayWindowTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/decor/OverlayWindowTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/PrivacyDotDecorProviderFactoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/decor/PrivacyDotDecorProviderFactoryTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/decor/PrivacyDotDecorProviderFactoryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/decor/PrivacyDotDecorProviderFactoryTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerDecorProviderFactoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/decor/RoundedCornerDecorProviderFactoryTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerDecorProviderFactoryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/decor/RoundedCornerDecorProviderFactoryTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/demomode/DemoModeControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/demomode/DemoModeControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/demomode/DemoModeControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/demomode/DemoModeControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/FaceWakeUpTriggersConfigTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/FaceWakeUpTriggersConfigTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/FaceWakeUpTriggersConfigTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/FaceWakeUpTriggersConfigTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/BiometricMessageInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/BiometricMessageInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/BiometricMessageInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/BiometricMessageInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricsAllowedInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricsAllowedInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricsAllowedInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricsAllowedInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthStatusInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthStatusInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthStatusInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthStatusInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/ui/viewmodel/UdfpsAccessibilityOverlayViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/ui/viewmodel/UdfpsAccessibilityOverlayViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/ui/viewmodel/UdfpsAccessibilityOverlayViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/ui/viewmodel/UdfpsAccessibilityOverlayViewModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/shared/FaceAuthReasonTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/shared/FaceAuthReasonTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/deviceentry/shared/FaceAuthReasonTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/shared/FaceAuthReasonTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/devicepolicy/DevicePolicyManagerExtTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/devicepolicy/DevicePolicyManagerExtTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/devicepolicy/DevicePolicyManagerExtTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/devicepolicy/DevicePolicyManagerExtTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DeviceStateRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DeviceStateRepositoryTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DeviceStateRepositoryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DeviceStateRepositoryTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayMetricsRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayMetricsRepositoryTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayMetricsRepositoryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayMetricsRepositoryTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogDelegateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogDelegateTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogDelegateTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogDelegateTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/AlwaysOnDisplayPolicyTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/doze/AlwaysOnDisplayPolicyTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/doze/AlwaysOnDisplayPolicyTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/doze/AlwaysOnDisplayPolicyTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/doze/DozeConfigurationTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/doze/DozeConfigurationTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/doze/DozeConfigurationUtil.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/doze/DozeConfigurationUtil.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/doze/DozeDockHandlerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/doze/DozeDockHandlerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/doze/DozeServiceFake.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/doze/DozeServiceFake.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuppressorTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/doze/DozeSuppressorTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuppressorTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/doze/DozeSuppressorTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapterTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapterTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapterTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapterTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/doze/DozeUiTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/doze/DozeUiTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/doze/DozeWallpaperStateTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/doze/DozeWallpaperStateTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dump/DumpHandlerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/dump/DumpHandlerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/DumpManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dump/DumpManagerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/dump/DumpManagerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/dump/DumpManagerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/DumpsysTableLoggerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dump/DumpsysTableLoggerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/dump/DumpsysTableLoggerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/dump/DumpsysTableLoggerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferFreezerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dump/LogBufferFreezerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferFreezerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/dump/LogBufferFreezerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/LogEulogizerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dump/LogEulogizerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/dump/LogEulogizerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/dump/LogEulogizerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/emergency/EmergencyActivityTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/emergency/EmergencyActivityTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/emergency/EmergencyActivityTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/emergency/EmergencyActivityTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/ConditionalRestarterTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/flags/ConditionalRestarterTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/flags/ConditionalRestarterTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/flags/ConditionalRestarterTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicDebugTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/flags/FeatureFlagsClassicDebugTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicDebugTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/flags/FeatureFlagsClassicDebugTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicReleaseTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/flags/FeatureFlagsClassicReleaseTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicReleaseTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/flags/FeatureFlagsClassicReleaseTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagCommandTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/flags/FlagCommandTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/flags/FlagCommandTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/flags/FlagCommandTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagDependenciesTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/flags/FlagDependenciesTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/flags/FlagDependenciesTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/flags/FlagDependenciesTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/flags/FlagManagerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/flags/FlagManagerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/NotOccludedConditionTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/flags/NotOccludedConditionTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/flags/NotOccludedConditionTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/flags/NotOccludedConditionTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/PluggedInConditionTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/flags/PluggedInConditionTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/flags/PluggedInConditionTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/flags/PluggedInConditionTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/RestartDozeListenerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/flags/RestartDozeListenerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/flags/RestartDozeListenerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/flags/RestartDozeListenerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/ScreenIdleConditionTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/flags/ScreenIdleConditionTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/flags/ScreenIdleConditionTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/flags/ScreenIdleConditionTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/fragments/FragmentServiceTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/fragments/FragmentServiceTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsGridLayoutTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/globalactions/GlobalActionsGridLayoutTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsGridLayoutTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/globalactions/GlobalActionsGridLayoutTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsLayoutTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/globalactions/GlobalActionsLayoutTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsLayoutTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/globalactions/GlobalActionsLayoutTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/ListGridLayoutTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/globalactions/ListGridLayoutTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/globalactions/ListGridLayoutTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/globalactions/ListGridLayoutTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/ShutdownUiTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/globalactions/ShutdownUiTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/globalactions/ShutdownUiTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/globalactions/ShutdownUiTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/data/repository/GlobalActionsRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/globalactions/data/repository/GlobalActionsRepositoryTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/globalactions/data/repository/GlobalActionsRepositoryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/globalactions/data/repository/GlobalActionsRepositoryTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/domain/interactor/GlobalActionsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/globalactions/domain/interactor/GlobalActionsInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/globalactions/domain/interactor/GlobalActionsInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/globalactions/domain/interactor/GlobalActionsInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/FakeSliderEventProducer.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/FakeSliderEventProducer.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/haptics/slider/FakeSliderEventProducer.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/FakeSliderEventProducer.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/inputdevice/data/repository/TutorialSchedulerRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/data/repository/TutorialSchedulerRepositoryTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/inputdevice/data/repository/TutorialSchedulerRepositoryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/data/repository/TutorialSchedulerRepositoryTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/inputdevice/data/repository/UserInputDeviceRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/data/repository/UserInputDeviceRepositoryTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/inputdevice/data/repository/UserInputDeviceRepositoryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/data/repository/UserInputDeviceRepositoryTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartableTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartableTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartableTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialNotificationCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialNotificationCoordinatorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialNotificationCoordinatorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialNotificationCoordinatorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/ui/KeyboardBacklightDialogCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/backlight/ui/KeyboardBacklightDialogCoordinatorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/ui/KeyboardBacklightDialogCoordinatorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/backlight/ui/KeyboardBacklightDialogCoordinatorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/docking/ui/viewmodel/KeyboardDockingIndicationViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/docking/ui/viewmodel/KeyboardDockingIndicationViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyboard/docking/ui/viewmodel/KeyboardDockingIndicationViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/docking/ui/viewmodel/KeyboardDockingIndicationViewModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/data/repository/ShortcutHelperStateRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/ShortcutHelperStateRepositoryTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/data/repository/ShortcutHelperStateRepositoryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/ShortcutHelperStateRepositoryTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/data/source/AppCategoriesShortcutsSourceTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/AppCategoriesShortcutsSourceTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/data/source/AppCategoriesShortcutsSourceTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/AppCategoriesShortcutsSourceTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/data/source/CurrentAppShortcutsSourceTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/CurrentAppShortcutsSourceTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/data/source/CurrentAppShortcutsSourceTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/CurrentAppShortcutsSourceTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/data/source/InputShortcutsSourceTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/InputShortcutsSourceTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/data/source/InputShortcutsSourceTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/InputShortcutsSourceTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/data/source/TestShortcuts.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/TestShortcuts.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/data/source/TestShortcuts.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/TestShortcuts.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyevent/domain/interactor/KeyEventInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyevent/domain/interactor/KeyEventInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyevent/domain/interactor/KeyEventInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyevent/domain/interactor/KeyEventInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyevent/domain/interactor/SysUIKeyEventHandlerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyevent/domain/interactor/SysUIKeyEventHandlerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyevent/domain/interactor/SysUIKeyEventHandlerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyevent/domain/interactor/SysUIKeyEventHandlerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/KeyguardIndicationTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/KeyguardIndicationTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ScreenLifecycleTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ScreenLifecycleTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/ScreenLifecycleTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ScreenLifecycleTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/WorkLockActivityTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/WorkLockActivityTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceConfigTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceConfigTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceConfigTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyEventRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyEventRepositoryTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyEventRepositoryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyEventRepositoryTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardSurfaceBehindRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardSurfaceBehindRepositoryImplTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardSurfaceBehindRepositoryImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardSurfaceBehindRepositoryImplTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/BurnInInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/BurnInInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/BurnInInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/BurnInInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/InWindowLauncherUnlockAnimationInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/InWindowLauncherUnlockAnimationInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/InWindowLauncherUnlockAnimationInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/InWindowLauncherUnlockAnimationInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardKeyEventInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardKeyEventInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardKeyEventInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardKeyEventInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/SwipeToDismissInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/SwipeToDismissInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/SwipeToDismissInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/SwipeToDismissInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/InWindowLauncherUnlockAnimationManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/binder/InWindowLauncherUnlockAnimationManagerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/InWindowLauncherUnlockAnimationManagerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/binder/InWindowLauncherUnlockAnimationManagerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinderTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinderTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinderTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardSurfaceBehindParamsApplierTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/binder/KeyguardSurfaceBehindParamsApplierTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardSurfaceBehindParamsApplierTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/binder/KeyguardSurfaceBehindParamsApplierTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/KeyguardBlueprintCommandListenerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/view/layout/KeyguardBlueprintCommandListenerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/KeyguardBlueprintCommandListenerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/view/layout/KeyguardBlueprintCommandListenerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSectionTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSectionTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSectionTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSectionTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/util/ActivityManagerWrapperMock.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/util/ActivityManagerWrapperMock.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/util/ActivityManagerWrapperMock.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/util/ActivityManagerWrapperMock.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/util/IndicationHelperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/util/IndicationHelperTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/util/IndicationHelperTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/util/IndicationHelperTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/util/KeyguardTransitionRunner.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/util/KeyguardTransitionRunner.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/util/KeyguardTransitionRunner.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/util/KeyguardTransitionRunner.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/lifecycle/ActivatableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/ActivatableTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/lifecycle/ActivatableTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/ActivatableTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/lifecycle/SysUiViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/SysUiViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/lifecycle/SysUiViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/SysUiViewModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/SessionTrackerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/log/SessionTrackerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/log/SessionTrackerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/log/SessionTrackerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/core/LoggerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/log/core/LoggerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/log/core/LoggerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/log/core/LoggerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/echo/LogcatEchoSettingsFormatTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/log/echo/LogcatEchoSettingsFormatTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/log/echo/LogcatEchoSettingsFormatTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/log/echo/LogcatEchoSettingsFormatTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/echo/LogcatEchoTrackerDebugTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/log/echo/LogcatEchoTrackerDebugTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/log/echo/LogcatEchoTrackerDebugTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/log/echo/LogcatEchoTrackerDebugTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/FakeLogProxy.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/log/table/FakeLogProxy.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/log/table/FakeLogProxy.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/log/table/FakeLogProxy.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/log/table/TableChangeTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/log/table/TableChangeTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/MediaTestUtils.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/MediaTestUtils.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/media/controls/MediaTestUtils.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/MediaTestUtils.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataCombineLatestTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataCombineLatestTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataCombineLatestTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataCombineLatestTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/shared/SmartspaceMediaDataTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/shared/SmartspaceMediaDataTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/media/controls/shared/SmartspaceMediaDataTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/shared/SmartspaceMediaDataTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/binder/SeekBarObserverTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/binder/SeekBarObserverTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/binder/SeekBarObserverTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/binder/SeekBarObserverTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/view/MediaCarouselScrollHandlerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/view/MediaCarouselScrollHandlerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/view/MediaCarouselScrollHandlerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/view/MediaCarouselScrollHandlerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/view/MediaViewHolderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/view/MediaViewHolderTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/view/MediaViewHolderTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/view/MediaViewHolderTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/util/MediaDataUtilsTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/util/MediaDataUtilsTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/media/controls/util/MediaDataUtilsTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/util/MediaDataUtilsTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaComplicationViewControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/dream/MediaComplicationViewControllerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaComplicationViewControllerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/media/dream/MediaComplicationViewControllerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/nearby/NearbyMediaDevicesManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/nearby/NearbyMediaDevicesManagerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/media/nearby/NearbyMediaDevicesManagerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/media/nearby/NearbyMediaDevicesManagerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/systemsounds/HomeSoundEffectControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/systemsounds/HomeSoundEffectControllerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/media/systemsounds/HomeSoundEffectControllerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/media/systemsounds/HomeSoundEffectControllerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerUtilsTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerUtilsTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerUtilsTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerUtilsTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLoggerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLoggerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLoggerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLoggerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverUiEventLoggerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverUiEventLoggerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverUiEventLoggerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverUiEventLoggerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLoggerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLoggerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLoggerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLoggerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLoggerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLoggerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLoggerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLoggerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLoggerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLoggerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLoggerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLoggerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/ActivityTaskManagerThumbnailLoaderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/appselector/data/ActivityTaskManagerThumbnailLoaderTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/ActivityTaskManagerThumbnailLoaderTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/appselector/data/ActivityTaskManagerThumbnailLoaderTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/BasicPackageManagerAppIconLoaderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/appselector/data/BasicPackageManagerAppIconLoaderTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/BasicPackageManagerAppIconLoaderTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/appselector/data/BasicPackageManagerAppIconLoaderTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/ShellRecentTaskListProviderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/appselector/data/ShellRecentTaskListProviderTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/ShellRecentTaskListProviderTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/appselector/data/ShellRecentTaskListProviderTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProviderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProviderTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProviderTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProviderTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/WindowMetricsProviderImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/appselector/view/WindowMetricsProviderImplTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/WindowMetricsProviderImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/appselector/view/WindowMetricsProviderImplTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/data/repository/MediaProjectionManagerRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/data/repository/MediaProjectionManagerRepositoryTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/mediaprojection/data/repository/MediaProjectionManagerRepositoryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/data/repository/MediaProjectionManagerRepositoryTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolverTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolverTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolverTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolverTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/ShareToAppPermissionDialogDelegateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/permission/ShareToAppPermissionDialogDelegateTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/ShareToAppPermissionDialogDelegateTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/permission/ShareToAppPermissionDialogDelegateTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/SystemCastPermissionDialogDelegateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/permission/SystemCastPermissionDialogDelegateTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/SystemCastPermissionDialogDelegateTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/permission/SystemCastPermissionDialogDelegateTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/taskswitcher/data/repository/ActivityTaskManagerTasksRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/taskswitcher/data/repository/ActivityTaskManagerTasksRepositoryTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/mediaprojection/taskswitcher/data/repository/ActivityTaskManagerTasksRepositoryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/taskswitcher/data/repository/ActivityTaskManagerTasksRepositoryTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/taskswitcher/data/repository/FakeTasksRepository.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/taskswitcher/data/repository/FakeTasksRepository.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/mediaprojection/taskswitcher/data/repository/FakeTasksRepository.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/taskswitcher/data/repository/FakeTasksRepository.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/taskswitcher/domain/interactor/TaskSwitchInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/taskswitcher/domain/interactor/TaskSwitchInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/mediaprojection/taskswitcher/domain/interactor/TaskSwitchInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/taskswitcher/domain/interactor/TaskSwitchInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/model/SysUiStateExtTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/model/SysUiStateExtTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/model/SysUiStateExtTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/model/SysUiStateExtTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/model/SysUiStateTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/model/SysUiStateTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/model/SysUiStateTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/model/SysUiStateTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/motion/ComposeMotionTestRuleHelper.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/motion/ComposeMotionTestRuleHelper.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/motion/ComposeMotionTestRuleHelper.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/motion/ComposeMotionTestRuleHelper.kt
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlags.kt b/packages/SystemUI/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlags.kt
index d7a4863b..7647cf6 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlags.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.bouncer.shared.flag
 
 import com.android.systemui.Flags
+import com.android.systemui.flags.RefactorFlagUtils
 import com.android.systemui.scene.shared.flag.SceneContainerFlag
 
 object ComposeBouncerFlags {
@@ -34,6 +35,18 @@
     }
 
     /**
+     * Called to ensure code is only run when the flag is enabled. This protects users from the
+     * unintended behaviors caused by accidentally running new logic, while also crashing on an eng
+     * build to ensure that the refactor author catches issues in testing.
+     */
+    @JvmStatic
+    fun isUnexpectedlyInLegacyMode() =
+        RefactorFlagUtils.isUnexpectedlyInLegacyMode(
+            isEnabled,
+            "SceneContainerFlag || ComposeBouncerFlag"
+        )
+
+    /**
      * Returns `true` if only compose bouncer is enabled and scene container framework is not
      * enabled.
      */
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
index d223657..73a8810 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerContainerViewModel.kt
@@ -47,21 +47,9 @@
             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)
-                            }
-                        }
+                        legacyInteractor.notifyKeyguardAuthenticatedPrimaryAuth(
+                            selectedUserInteractor.getSelectedUserId()
+                        )
                     }
                 }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt
index 60c5386..8495778 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt
@@ -164,7 +164,7 @@
     }
 
     fun runAfterKeyguardGone(runnable: Runnable) {
-        if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return
+        if (ComposeBouncerFlags.isUnexpectedlyInLegacyMode()) return
         setDismissAction(
             DismissAction.RunAfterKeyguardGone(
                 dismissAction = { runnable.run() },
@@ -176,18 +176,18 @@
     }
 
     fun setDismissAction(dismissAction: DismissAction) {
-        if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return
+        if (ComposeBouncerFlags.isUnexpectedlyInLegacyMode()) return
         repository.dismissAction.value.onCancelAction.run()
         repository.setDismissAction(dismissAction)
     }
 
     fun handleDismissAction() {
-        if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return
+        if (ComposeBouncerFlags.isUnexpectedlyInLegacyMode()) return
         repository.setDismissAction(DismissAction.None)
     }
 
     suspend fun setKeyguardDone(keyguardDoneTiming: KeyguardDone) {
-        if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return
+        if (ComposeBouncerFlags.isUnexpectedlyInLegacyMode()) return
         dismissInteractor.setKeyguardDone(keyguardDoneTiming)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
index ca94363..c089092 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
@@ -31,7 +31,6 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.settingslib.bluetooth.BluetoothCallback;
-import com.android.settingslib.bluetooth.BluetoothUtils;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.bluetooth.LocalBluetoothProfile;
@@ -72,7 +71,6 @@
     private final LocalBluetoothManager mLocalBluetoothManager;
     private final UserManager mUserManager;
     private final int mCurrentUser;
-    private final Context mContext;
     @GuardedBy("mConnectedDevices")
     private final List<CachedBluetoothDevice> mConnectedDevices = new ArrayList<>();
 
@@ -101,7 +99,6 @@
             @Main Looper mainLooper,
             @Nullable LocalBluetoothManager localBluetoothManager,
             @Nullable BluetoothAdapter bluetoothAdapter) {
-        mContext = context;
         mDumpManager = dumpManager;
         mLogger = logger;
         mBluetoothRepository = bluetoothRepository;
@@ -265,21 +262,9 @@
     }
 
     private Collection<CachedBluetoothDevice> getDevices() {
-        Collection<CachedBluetoothDevice> devices =
-                mLocalBluetoothManager != null
-                        ? mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy()
-                        : Collections.emptyList();
-        if (com.android.settingslib.flags.Flags.enableHideExclusivelyManagedBluetoothDevice()) {
-            // When the device is exclusively managed by its owner app it needs to be hidden.
-            devices =
-                    devices.stream()
-                            .filter(
-                                    device ->
-                                            !BluetoothUtils.isExclusivelyManagedBluetoothDevice(
-                                                    mContext, device.getDevice()))
-                            .toList();
-        }
-        return devices;
+        return mLocalBluetoothManager != null
+                ? mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy()
+                : Collections.emptyList();
     }
 
     private void updateConnected() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
index 93071bd..2588f1f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
@@ -14,10 +14,6 @@
 
 package com.android.systemui.statusbar.policy;
 
-import static android.platform.test.flag.junit.FlagsParameterization.allCombinationsOf;
-
-import static com.android.settingslib.flags.Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE;
-
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.assertEquals;
@@ -25,7 +21,6 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
@@ -35,11 +30,7 @@
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.platform.test.annotations.DisableFlags;
-import android.platform.test.annotations.EnableFlags;
-import android.platform.test.flag.junit.FlagsParameterization;
+import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 
@@ -65,31 +56,16 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.Executor;
 
-import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
-import platform.test.runner.parameterized.Parameters;
-
-@RunWith(ParameterizedAndroidJunit4.class)
+@RunWith(AndroidTestingRunner.class)
 @RunWithLooper
 @SmallTest
 public class BluetoothControllerImplTest extends SysuiTestCase {
 
-    @Parameters(name = "{0}")
-    public static List<FlagsParameterization> getParams() {
-        return allCombinationsOf(FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE);
-    }
-
-    private static final String TEST_EXCLUSIVE_MANAGER = "com.test.manager";
-
-    @Mock
-    private PackageManager mPackageManager;
-
     private UserTracker mUserTracker;
     private LocalBluetoothManager mMockBluetoothManager;
     private CachedBluetoothDeviceManager mMockDeviceManager;
@@ -102,21 +78,14 @@
 
     private FakeExecutor mBackgroundExecutor;
 
-    public BluetoothControllerImplTest(FlagsParameterization flags) {
-        super();
-        mSetFlagsRule.setFlagsParameterization(flags);
-    }
-
     @Before
     public void setup() throws Exception {
-        MockitoAnnotations.initMocks(this);
         mTestableLooper = TestableLooper.get(this);
         mMockBluetoothManager = mDependency.injectMockDependency(LocalBluetoothManager.class);
         mDevices = new ArrayList<>();
         mUserTracker = mock(UserTracker.class);
         mMockDeviceManager = mock(CachedBluetoothDeviceManager.class);
         mMockAdapter = mock(BluetoothAdapter.class);
-        mContext.setMockPackageManager(mPackageManager);
         when(mMockDeviceManager.getCachedDevicesCopy()).thenReturn(mDevices);
         when(mMockBluetoothManager.getCachedDeviceManager()).thenReturn(mMockDeviceManager);
         mMockLocalAdapter = mock(LocalBluetoothAdapter.class);
@@ -146,7 +115,6 @@
         CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
         when(device.isConnected()).thenReturn(true);
         when(device.getMaxConnectionState()).thenReturn(BluetoothProfile.STATE_CONNECTED);
-        when(device.getDevice()).thenReturn(mock(BluetoothDevice.class));
 
         mDevices.add(device);
         when(mMockLocalAdapter.getConnectionState())
@@ -172,12 +140,10 @@
     public void getConnectedDevices_onlyReturnsConnected() {
         CachedBluetoothDevice device1Disconnected = mock(CachedBluetoothDevice.class);
         when(device1Disconnected.isConnected()).thenReturn(false);
-        when(device1Disconnected.getDevice()).thenReturn(mock(BluetoothDevice.class));
         mDevices.add(device1Disconnected);
 
         CachedBluetoothDevice device2Connected = mock(CachedBluetoothDevice.class);
         when(device2Connected.isConnected()).thenReturn(true);
-        when(device2Connected.getDevice()).thenReturn(mock(BluetoothDevice.class));
         mDevices.add(device2Connected);
 
         mBluetoothControllerImpl.onDeviceAdded(device1Disconnected);
@@ -189,46 +155,6 @@
     }
 
     @Test
-    @EnableFlags(FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
-    public void getConnectedDevice_exclusivelyManagedDevice_doNotReturn()
-            throws PackageManager.NameNotFoundException {
-        CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
-        when(cachedDevice.isConnected()).thenReturn(true);
-        BluetoothDevice device = mock(BluetoothDevice.class);
-        when(device.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
-                TEST_EXCLUSIVE_MANAGER.getBytes());
-        when(cachedDevice.getDevice()).thenReturn(device);
-        doReturn(new ApplicationInfo()).when(mPackageManager).getApplicationInfo(
-                TEST_EXCLUSIVE_MANAGER, 0);
-
-        mDevices.add(cachedDevice);
-        mBluetoothControllerImpl.onDeviceAdded(cachedDevice);
-
-        assertThat(mBluetoothControllerImpl.getConnectedDevices()).isEmpty();
-    }
-
-    @Test
-    @DisableFlags(FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
-    public void getConnectedDevice_exclusivelyManagedDevice_returnsConnected()
-            throws PackageManager.NameNotFoundException {
-        CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
-        when(cachedDevice.isConnected()).thenReturn(true);
-        BluetoothDevice device = mock(BluetoothDevice.class);
-        when(device.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
-                TEST_EXCLUSIVE_MANAGER.getBytes());
-        when(cachedDevice.getDevice()).thenReturn(device);
-        doReturn(new ApplicationInfo()).when(mPackageManager).getApplicationInfo(
-                TEST_EXCLUSIVE_MANAGER, 0);
-
-        mDevices.add(cachedDevice);
-        mBluetoothControllerImpl.onDeviceAdded(cachedDevice);
-
-        assertThat(mBluetoothControllerImpl.getConnectedDevices()).hasSize(1);
-        assertThat(mBluetoothControllerImpl.getConnectedDevices().get(0))
-                .isEqualTo(cachedDevice);
-    }
-
-    @Test
     public void testOnBluetoothStateChange_updatesBluetoothState() {
         mBluetoothControllerImpl.onBluetoothStateChanged(BluetoothAdapter.STATE_OFF);
 
@@ -259,7 +185,6 @@
 
         assertFalse(mBluetoothControllerImpl.isBluetoothConnected());
         CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
-        when(device.getDevice()).thenReturn(mock(BluetoothDevice.class));
         mDevices.add(device);
         when(device.isConnected()).thenReturn(true);
         when(device.getMaxConnectionState()).thenReturn(BluetoothProfile.STATE_CONNECTED);
@@ -478,7 +403,6 @@
     private CachedBluetoothDevice createBluetoothDevice(
             int profile, boolean isConnected, boolean isActive) {
         CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
-        when(device.getDevice()).thenReturn(mock(BluetoothDevice.class));
         mDevices.add(device);
         when(device.isActiveDevice(profile)).thenReturn(isActive);
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModelTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/TestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/util/TestUtils.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/util/TestUtils.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/util/TestUtils.kt
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 439bca0..a13ce65 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -370,6 +370,13 @@
                   String propertyName = "next_boot." + makeAconfigFlagPropertyName(
                       actualNamespace, actualFlagName);
 
+                  if (Flags.supportLocalOverridesSysprops()) {
+                    // Don't propagate if there is a local override.
+                    String overrideName = actualNamespace + ":" + actualFlagName;
+                    if (DeviceConfig.getProperty(NAMESPACE_LOCAL_OVERRIDES, overrideName) != null) {
+                      continue;
+                    }
+                  }
                   setProperty(propertyName, flagValue);
               }
 
@@ -388,6 +395,42 @@
                 if (enableAconfigStorageDaemon()) {
                     setLocalOverridesInNewStorage(properties);
                 }
+
+                if (Flags.supportLocalOverridesSysprops()) {
+                  String overridesNamespace = properties.getNamespace();
+                  for (String key : properties.getKeyset()) {
+                    String realNamespace = key.split(":")[0];
+                    String realFlagName = key.split(":")[1];
+                    String aconfigPropertyName =
+                        makeAconfigFlagPropertyName(realNamespace, realFlagName);
+                    if (aconfigPropertyName == null) {
+                      logErr("unable to construct system property for " + realNamespace + "/"
+                        + key);
+                      return;
+                    }
+
+                    if (properties.getString(key, null) == null) {
+                      String deviceConfigValue =
+                              DeviceConfig.getProperty(realNamespace, realFlagName);
+                      String stagedDeviceConfigValue =
+                              DeviceConfig.getProperty(NAMESPACE_REBOOT_STAGING,
+                                              realNamespace + "*" + realFlagName);
+
+                      setProperty(aconfigPropertyName, deviceConfigValue);
+                      if (stagedDeviceConfigValue == null) {
+                        setProperty("next_boot." + aconfigPropertyName, deviceConfigValue);
+                      } else {
+                        setProperty("next_boot." + aconfigPropertyName, stagedDeviceConfigValue);
+                      }
+                    } else {
+                      // Otherwise, propagate the override to sysprops.
+                      setProperty(aconfigPropertyName, properties.getString(key, null));
+                      // If there's a staged value, make sure it's the override value.
+                      setProperty("next_boot." + aconfigPropertyName,
+                                properties.getString(key, null));
+                    }
+                  }
+                }
         });
     }
 
diff --git a/services/core/java/com/android/server/appop/AttributedOp.java b/services/core/java/com/android/server/appop/AttributedOp.java
index 430be03..314664b 100644
--- a/services/core/java/com/android/server/appop/AttributedOp.java
+++ b/services/core/java/com/android/server/appop/AttributedOp.java
@@ -110,7 +110,8 @@
 
         mAppOpsService.mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid,
                 parent.packageName, persistentDeviceId, tag, uidState, flags, accessTime,
-                AppOpsManager.ATTRIBUTION_FLAGS_NONE, AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE);
+                AppOpsManager.ATTRIBUTION_FLAGS_NONE, AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE,
+                DiscreteRegistry.ACCESS_TYPE_NOTE_OP);
     }
 
     /**
@@ -254,7 +255,7 @@
         if (isStarted) {
             mAppOpsService.mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid,
                     parent.packageName, persistentDeviceId, tag, uidState, flags, startTime,
-                    attributionFlags, attributionChainId);
+                    attributionFlags, attributionChainId, DiscreteRegistry.ACCESS_TYPE_START_OP);
         }
     }
 
@@ -290,12 +291,17 @@
      * stopping in the HistoricalRegistry, but does not delete it.
      *
      * @param triggeredByUidStateChange If {@code true}, then this method operates as usual, except
-     * that {@link AppOpsService#mActiveWatchers} will not be notified. This is currently only
-     * used in {@link #onUidStateChanged(int)}, for the purpose of restarting (i.e.,
-     * finishing then immediately starting again in the new uid state) the AttributedOp. In this
-     * case, the caller is responsible for guaranteeing that either the AttributedOp is started
-     * again or all {@link AppOpsService#mActiveWatchers} are notified that the AttributedOp is
-     * finished.
+     *                                  that {@link AppOpsService#mActiveWatchers} will not be
+     *                                  notified. This is currently only
+     *                                  used in {@link #onUidStateChanged(int)}, for the purpose of
+     *                                  restarting (i.e.,
+     *                                  finishing then immediately starting again in the new uid
+     *                                  state) the AttributedOp. In this
+     *                                  case, the caller is responsible for guaranteeing that either
+     *                                  the AttributedOp is started
+     *                                  again or all {@link AppOpsService#mActiveWatchers} are
+     *                                  notified that the AttributedOp is
+     *                                  finished.
      */
     @SuppressWarnings("GuardedBy") // Lock is held on mAppOpsService
     private void finishOrPause(@NonNull IBinder clientId, boolean triggeredByUidStateChange,
@@ -335,7 +341,9 @@
             mAppOpsService.mHistoricalRegistry.increaseOpAccessDuration(parent.op, parent.uid,
                     parent.packageName, persistentDeviceId, tag, event.getUidState(),
                     event.getFlags(), finishedEvent.getNoteTime(), finishedEvent.getDuration(),
-                    event.getAttributionFlags(), event.getAttributionChainId());
+                    event.getAttributionFlags(), event.getAttributionChainId(),
+                    isPausing ? DiscreteRegistry.ACCESS_TYPE_PAUSE_OP
+                            : DiscreteRegistry.ACCESS_TYPE_FINISH_OP);
 
             if (!isPausing) {
                 mAppOpsService.mInProgressStartOpEventPool.release(event);
@@ -443,7 +451,7 @@
             mAppOpsService.mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid,
                     parent.packageName, persistentDeviceId, tag, event.getUidState(),
                     event.getFlags(), startTime, event.getAttributionFlags(),
-                    event.getAttributionChainId());
+                    event.getAttributionChainId(), DiscreteRegistry.ACCESS_TYPE_RESUME_OP);
             if (shouldSendActive) {
                 mAppOpsService.scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid,
                         parent.packageName, tag, event.getVirtualDeviceId(), true,
@@ -864,12 +872,12 @@
         }
 
         InProgressStartOpEvent acquire(long startTime, long elapsedTime, @NonNull IBinder clientId,
-                @Nullable String attributionTag, int virtualDeviceId,  @NonNull Runnable onDeath,
+                @Nullable String attributionTag, int virtualDeviceId, @NonNull Runnable onDeath,
                 int proxyUid, @Nullable String proxyPackageName,
                 @Nullable String proxyAttributionTag, @Nullable String proxyDeviceId,
-                @AppOpsManager.UidState int uidState,
-                @AppOpsManager.OpFlags int flags, @AppOpsManager.AttributionFlags
-                int attributionFlags, int attributionChainId) throws RemoteException {
+                @AppOpsManager.UidState int uidState, @AppOpsManager.OpFlags int flags,
+                @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId)
+                throws RemoteException {
 
             InProgressStartOpEvent recycled = acquire();
 
diff --git a/services/core/java/com/android/server/appop/DiscreteRegistry.java b/services/core/java/com/android/server/appop/DiscreteRegistry.java
index 2ce4623..7f161f6 100644
--- a/services/core/java/com/android/server/appop/DiscreteRegistry.java
+++ b/services/core/java/com/android/server/appop/DiscreteRegistry.java
@@ -32,13 +32,23 @@
 import static android.app.AppOpsManager.OP_FLAG_SELF;
 import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED;
 import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXY;
+import static android.app.AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION;
+import static android.app.AppOpsManager.OP_MONITOR_LOCATION;
 import static android.app.AppOpsManager.OP_NONE;
 import static android.app.AppOpsManager.OP_PHONE_CALL_CAMERA;
 import static android.app.AppOpsManager.OP_PHONE_CALL_MICROPHONE;
+import static android.app.AppOpsManager.OP_PROCESS_OUTGOING_CALLS;
+import static android.app.AppOpsManager.OP_READ_ICC_SMS;
+import static android.app.AppOpsManager.OP_READ_SMS;
 import static android.app.AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO;
 import static android.app.AppOpsManager.OP_RECEIVE_SANDBOX_TRIGGER_AUDIO;
 import static android.app.AppOpsManager.OP_RECORD_AUDIO;
 import static android.app.AppOpsManager.OP_RESERVED_FOR_TESTING;
+import static android.app.AppOpsManager.OP_SEND_SMS;
+import static android.app.AppOpsManager.OP_SMS_FINANCIAL_TRANSACTIONS;
+import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
+import static android.app.AppOpsManager.OP_WRITE_ICC_SMS;
+import static android.app.AppOpsManager.OP_WRITE_SMS;
 import static android.app.AppOpsManager.flagsToString;
 import static android.app.AppOpsManager.getUidStateName;
 import static android.companion.virtual.VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT;
@@ -46,6 +56,7 @@
 import static java.lang.Long.min;
 import static java.lang.Math.max;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.AppOpsManager;
@@ -62,6 +73,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.util.XmlUtils;
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
@@ -72,6 +84,8 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.text.SimpleDateFormat;
 import java.time.Duration;
 import java.time.Instant;
@@ -125,7 +139,6 @@
  * relies on {@link HistoricalRegistry} for controlling that no calls are allowed until then. All
  * outside calls are going through {@link HistoricalRegistry}, where
  * {@link HistoricalRegistry#isPersistenceInitializedMLocked()} check is done.
- *
  */
 
 final class DiscreteRegistry {
@@ -142,11 +155,40 @@
             + OP_PHONE_CALL_MICROPHONE + "," + OP_PHONE_CALL_CAMERA + ","
             + OP_RECEIVE_AMBIENT_TRIGGER_AUDIO + "," + OP_RECEIVE_SANDBOX_TRIGGER_AUDIO
             + "," + OP_RESERVED_FOR_TESTING;
+    private static final int[] sDiscreteOpsToLog =
+            new int[]{OP_FINE_LOCATION, OP_COARSE_LOCATION, OP_EMERGENCY_LOCATION, OP_CAMERA,
+                    OP_RECORD_AUDIO, OP_PHONE_CALL_MICROPHONE, OP_PHONE_CALL_CAMERA,
+                    OP_RECEIVE_AMBIENT_TRIGGER_AUDIO, OP_RECEIVE_SANDBOX_TRIGGER_AUDIO, OP_READ_SMS,
+                    OP_WRITE_SMS, OP_SEND_SMS, OP_READ_ICC_SMS, OP_WRITE_ICC_SMS,
+                    OP_SMS_FINANCIAL_TRANSACTIONS, OP_SYSTEM_ALERT_WINDOW, OP_MONITOR_LOCATION,
+                    OP_MONITOR_HIGH_POWER_LOCATION, OP_PROCESS_OUTGOING_CALLS,
+            };
     private static final long DEFAULT_DISCRETE_HISTORY_CUTOFF = Duration.ofDays(7).toMillis();
     private static final long MAXIMUM_DISCRETE_HISTORY_CUTOFF = Duration.ofDays(30).toMillis();
     private static final long DEFAULT_DISCRETE_HISTORY_QUANTIZATION =
             Duration.ofMinutes(1).toMillis();
 
+    static final int ACCESS_TYPE_NOTE_OP =
+            FrameworkStatsLog.APP_OP_ACCESS_TRACKED__ACCESS_TYPE__NOTE_OP;
+    static final int ACCESS_TYPE_START_OP =
+            FrameworkStatsLog.APP_OP_ACCESS_TRACKED__ACCESS_TYPE__START_OP;
+    static final int ACCESS_TYPE_FINISH_OP =
+            FrameworkStatsLog.APP_OP_ACCESS_TRACKED__ACCESS_TYPE__FINISH_OP;
+    static final int ACCESS_TYPE_PAUSE_OP =
+            FrameworkStatsLog.APP_OP_ACCESS_TRACKED__ACCESS_TYPE__PAUSE_OP;
+    static final int ACCESS_TYPE_RESUME_OP =
+            FrameworkStatsLog.APP_OP_ACCESS_TRACKED__ACCESS_TYPE__RESUME_OP;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"ACCESS_TYPE_"}, value = {
+            ACCESS_TYPE_NOTE_OP,
+            ACCESS_TYPE_START_OP,
+            ACCESS_TYPE_FINISH_OP,
+            ACCESS_TYPE_PAUSE_OP,
+            ACCESS_TYPE_RESUME_OP
+    })
+    public @interface AccessType {}
+
     private static long sDiscreteHistoryCutoff;
     private static long sDiscreteHistoryQuantization;
     private static int[] sDiscreteOps;
@@ -255,7 +297,23 @@
     void recordDiscreteAccess(int uid, String packageName, @NonNull String deviceId, int op,
             @Nullable String attributionTag, @AppOpsManager.OpFlags int flags,
             @AppOpsManager.UidState int uidState, long accessTime, long accessDuration,
-            @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) {
+            @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId,
+            @AccessType int accessType) {
+        if (shouldLogAccess(op)) {
+            int firstChar = 0;
+            if (attributionTag != null && attributionTag.startsWith(packageName)) {
+                firstChar = packageName.length();
+                if (firstChar < attributionTag.length() && attributionTag.charAt(firstChar)
+                        == '.') {
+                    firstChar++;
+                }
+            }
+            FrameworkStatsLog.write(FrameworkStatsLog.APP_OP_ACCESS_TRACKED, uid, op, accessType,
+                    uidState, flags, attributionFlags,
+                    attributionTag == null ? null : attributionTag.substring(firstChar),
+                    attributionChainId);
+        }
+
         if (!isDiscreteOp(op, flags)) {
             return;
         }
@@ -388,7 +446,7 @@
                                 if (event == null
                                         || event.mAttributionChainId == ATTRIBUTION_CHAIN_ID_NONE
                                         || (event.mAttributionFlags & ATTRIBUTION_FLAG_TRUSTED)
-                                                == 0) {
+                                        == 0) {
                                     continue;
                                 }
 
@@ -1523,6 +1581,11 @@
         return true;
     }
 
+    private static boolean shouldLogAccess(int op) {
+        return Flags.appopAccessTrackingLoggingEnabled()
+                && ArrayUtils.contains(sDiscreteOpsToLog, op);
+    }
+
     private static long discretizeTimeStamp(long timeStamp) {
         return timeStamp / sDiscreteHistoryQuantization * sDiscreteHistoryQuantization;
 
@@ -1530,7 +1593,7 @@
 
     private static long discretizeDuration(long duration) {
         return duration == -1 ? -1 : (duration + sDiscreteHistoryQuantization - 1)
-                        / sDiscreteHistoryQuantization * sDiscreteHistoryQuantization;
+                / sDiscreteHistoryQuantization * sDiscreteHistoryQuantization;
     }
 
     void setDebugMode(boolean debugMode) {
diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java
index fffb108..6b02538 100644
--- a/services/core/java/com/android/server/appop/HistoricalRegistry.java
+++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java
@@ -474,7 +474,8 @@
     void incrementOpAccessedCount(int op, int uid, @NonNull String packageName,
             @NonNull String deviceId, @Nullable String attributionTag, @UidState int uidState,
             @OpFlags int flags, long accessTime,
-            @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) {
+            @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId,
+            @DiscreteRegistry.AccessType int accessType) {
         synchronized (mInMemoryLock) {
             if (mMode == AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) {
                 if (!isPersistenceInitializedMLocked()) {
@@ -487,7 +488,7 @@
 
                 mDiscreteRegistry.recordDiscreteAccess(uid, packageName, deviceId, op,
                         attributionTag, flags, uidState, accessTime, -1, attributionFlags,
-                        attributionChainId);
+                        attributionChainId, accessType);
             }
         }
     }
@@ -510,7 +511,8 @@
     void increaseOpAccessDuration(int op, int uid, @NonNull String packageName,
             @NonNull String deviceId, @Nullable String attributionTag, @UidState int uidState,
             @OpFlags int flags, long eventStartTime, long increment,
-            @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) {
+            @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId,
+            @DiscreteRegistry.AccessType int accessType) {
         synchronized (mInMemoryLock) {
             if (mMode == AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) {
                 if (!isPersistenceInitializedMLocked()) {
@@ -522,7 +524,7 @@
                         attributionTag, uidState, flags, increment);
                 mDiscreteRegistry.recordDiscreteAccess(uid, packageName, deviceId, op,
                         attributionTag, flags, uidState, eventStartTime, increment,
-                        attributionFlags, attributionChainId);
+                        attributionFlags, attributionChainId, accessType);
             }
         }
     }
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index be6fa14..1316df1 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -856,8 +856,9 @@
                     params.appPackageName, SYSTEM_UID);
             if (ps != null
                     && PackageArchiver.isArchived(ps.getUserStateOrDefault(userId))
-                    && PackageArchiver.getResponsibleInstallerPackage(ps)
-                            .equals(requestedInstallerPackageName)) {
+                    && TextUtils.equals(
+                        PackageArchiver.getResponsibleInstallerPackage(ps),
+                        requestedInstallerPackageName)) {
                 params.installFlags |= PackageManager.INSTALL_UNARCHIVE;
             }
         }
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BstatsCpuTimesValidationTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BstatsCpuTimesValidationTest.java
index e4ab227..38fc6a9 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BstatsCpuTimesValidationTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BstatsCpuTimesValidationTest.java
@@ -39,11 +39,11 @@
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
+import android.hardware.display.DisplayManager;
 import android.os.BatteryManager;
 import android.os.BatteryStats;
 import android.os.Bundle;
 import android.os.IBinder;
-import android.os.PowerManager;
 import android.os.Process;
 import android.os.SystemClock;
 import android.platform.test.ravenwood.RavenwoodRule;
@@ -52,10 +52,10 @@
 import android.util.DebugUtils;
 import android.util.KeyValueListParser;
 import android.util.Log;
+import android.view.Display;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.LargeTest;
-import androidx.test.runner.AndroidJUnit4;
 import androidx.test.uiautomator.UiDevice;
 
 import com.android.frameworks.coretests.aidl.ICmdCallback;
@@ -66,7 +66,6 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TestName;
-import org.junit.runner.RunWith;
 
 import java.util.Arrays;
 import java.util.concurrent.CountDownLatch;
@@ -103,6 +102,7 @@
 
     private static final int GENERAL_TIMEOUT_MS = 4000;
     private static final int GENERAL_INTERVAL_MS = 200;
+    private static final int SCREEN_STATE_CHANGE_TIMEOUT_MS = 10000;
 
     private static final int WORK_DURATION_MS = 2000;
 
@@ -110,6 +110,7 @@
     private static String sOriginalBatteryStatsConsts;
 
     private static Context sContext;
+    private static Display sDisplay;
     private static UiDevice sUiDevice;
     private static int sTestPkgUid;
     private static boolean sCpuFreqTimesAvailable;
@@ -131,6 +132,10 @@
         sTestPkgUid = sContext.getPackageManager().getPackageUid(TEST_PKG, 0);
         executeCmd("cmd deviceidle whitelist +" + TEST_PKG);
         checkCpuTimesAvailability();
+        DisplayManager displayManager = sContext.getSystemService(DisplayManager.class);
+        if (displayManager != null) {
+            sDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
+        }
     }
 
     @AfterClass
@@ -833,12 +838,12 @@
         executeCmd("input keyevent KEYCODE_WAKEUP");
         executeCmd("wm dismiss-keyguard");
         assertKeyguardUnLocked();
-        assertScreenInteractive(true);
+        assertScreenState(true);
     }
 
     private void screenoff() throws Exception {
         executeCmd("input keyevent KEYCODE_SLEEP");
-        assertScreenInteractive(false);
+        assertScreenState(false);
     }
 
     private void forceStop() throws Exception {
@@ -854,12 +859,15 @@
         );
     }
 
-    private void assertScreenInteractive(boolean interactive) throws Exception {
-        final PowerManager powerManager =
-                (PowerManager) sContext.getSystemService(Context.POWER_SERVICE);
-        assertDelayedCondition("Unexpected screen interactive state", () ->
-                interactive == powerManager.isInteractive() ? null : "expected=" + interactive
-        );
+    private void assertScreenState(boolean expectedOn) throws Exception {
+        if (sDisplay == null) {
+            return;
+        }
+
+        assertDelayedCondition("Unexpected screen-on state",
+                () -> expectedOn == Display.isOnState(sDisplay.getState())
+                        ? null : "expected=" + expectedOn,
+                SCREEN_STATE_CHANGE_TIMEOUT_MS, GENERAL_INTERVAL_MS);
     }
 
     private void assertDelayedCondition(String errMsgPrefix, ExpectedCondition condition)
diff --git a/services/tests/servicestests/src/com/android/server/appop/DiscreteAppOpPersistenceTest.java b/services/tests/servicestests/src/com/android/server/appop/DiscreteAppOpPersistenceTest.java
index bc3a5ca..2ff0c62 100644
--- a/services/tests/servicestests/src/com/android/server/appop/DiscreteAppOpPersistenceTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/DiscreteAppOpPersistenceTest.java
@@ -86,7 +86,8 @@
         int attributionChainId = AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE;
 
         mDiscreteRegistry.recordDiscreteAccess(uid, packageName, deviceId, op, null, opFlags,
-                uidState, accessTime, duration, attributionFlags, attributionChainId);
+                uidState, accessTime, duration, attributionFlags, attributionChainId,
+                DiscreteRegistry.ACCESS_TYPE_FINISH_OP);
 
         // Verify in-memory object is correct
         fetchDiscreteOpsAndValidate(uid, packageName, op, deviceId, null, accessTime,
@@ -117,7 +118,8 @@
         int attributionChainId = 10;
 
         mDiscreteRegistry.recordDiscreteAccess(uid, packageName, deviceId, op, null, opFlags,
-                uidState, accessTime, duration, attributionFlags, attributionChainId);
+                uidState, accessTime, duration, attributionFlags, attributionChainId,
+                DiscreteRegistry.ACCESS_TYPE_START_OP);
 
         fetchDiscreteOpsAndValidate(uid, packageName, op, deviceId, null, accessTime,
                 duration, uidState, opFlags, attributionFlags, attributionChainId);