Merge "Golden update change auto-generated from Scuba: invocation I73200010267927138" into main
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/ModifierExt.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/ModifierExt.kt
new file mode 100644
index 0000000..e883a4a
--- /dev/null
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/ModifierExt.kt
@@ -0,0 +1,27 @@
+/*
+ * 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.spa.framework.compose
+
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.semantics.contentDescription
+import androidx.compose.ui.semantics.semantics
+
+/** Sets the content description of this node. */
+fun Modifier.contentDescription(contentDescription: String?) =
+    if (contentDescription != null) this.semantics {
+        this.contentDescription = contentDescription
+    } else this
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCard.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCard.kt
index f5cbe8f..d08d97e 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCard.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCard.kt
@@ -48,10 +48,9 @@
 import androidx.compose.ui.graphics.takeOrElse
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.semantics.contentDescription
-import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.unit.dp
 import com.android.settingslib.spa.debug.UiModePreviews
+import com.android.settingslib.spa.framework.compose.contentDescription
 import com.android.settingslib.spa.framework.theme.SettingsDimension
 import com.android.settingslib.spa.framework.theme.SettingsShape.CornerExtraLarge
 import com.android.settingslib.spa.framework.theme.SettingsShape.CornerExtraSmall
@@ -191,8 +190,7 @@
 private fun Button(button: CardButton, color: Color) {
     TextButton(
         onClick = button.onClick,
-        modifier =
-            Modifier.semantics { button.contentDescription?.let { this.contentDescription = it } }
+        modifier = Modifier.contentDescription(button.contentDescription),
     ) {
         Text(text = button.text, color = color)
     }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt
index 56d75d8..23a8e78 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt
@@ -28,6 +28,7 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
@@ -41,7 +42,8 @@
     title: String,
     subTitle: @Composable () -> Unit,
     modifier: Modifier = Modifier,
-    icon: (@Composable () -> Unit)? = null,
+    titleContentDescription: String? = null,
+    icon: @Composable (() -> Unit)? = null,
     enabled: () -> Boolean = { true },
     paddingStart: Dp = SettingsDimension.itemPaddingStart,
     paddingEnd: Dp = SettingsDimension.itemPaddingEnd,
@@ -51,6 +53,7 @@
     Row(
         modifier = modifier
             .fillMaxWidth()
+            .semantics(mergeDescendants = true) {}
             .padding(end = paddingEnd),
         verticalAlignment = Alignment.CenterVertically,
     ) {
@@ -58,6 +61,7 @@
         BaseIcon(icon, alphaModifier, paddingStart)
         Titles(
             title = title,
+            titleContentDescription = titleContentDescription,
             subTitle = subTitle,
             modifier = alphaModifier
                 .weight(1f)
@@ -87,9 +91,14 @@
 
 // Extracts a scope to avoid frequent recompose outside scope.
 @Composable
-private fun Titles(title: String, subTitle: @Composable () -> Unit, modifier: Modifier) {
+private fun Titles(
+    title: String,
+    titleContentDescription: String?,
+    subTitle: @Composable () -> Unit,
+    modifier: Modifier,
+) {
     Column(modifier) {
-        SettingsTitle(title)
+        SettingsTitle(title, titleContentDescription)
         subTitle()
     }
 }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt
index 194ed81..e9b3ba2 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt
@@ -32,6 +32,8 @@
     title: String,
     summary: () -> String,
     modifier: Modifier = Modifier,
+    titleContentDescription: String? = null,
+    summaryContentDescription: () -> String? = { null },
     singleLineSummary: Boolean = false,
     icon: @Composable (() -> Unit)? = null,
     enabled: () -> Boolean = { true },
@@ -42,9 +44,11 @@
 ) {
     BaseLayout(
         title = title,
+        titleContentDescription = titleContentDescription,
         subTitle = {
             SettingsBody(
                 body = summary(),
+                contentDescription = summaryContentDescription(),
                 maxLines = if (singleLineSummary) 1 else Int.MAX_VALUE,
             )
         },
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/Preference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/Preference.kt
index 3acf075..4ad4c14 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/Preference.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/Preference.kt
@@ -64,12 +64,24 @@
     val title: String
 
     /**
+     * The content description of [title].
+     */
+    val titleContentDescription: String?
+        get() = null
+
+    /**
      * The summary of this [Preference].
      */
     val summary: () -> String
         get() = { "" }
 
     /**
+     * The content description of [summary].
+     */
+    val summaryContentDescription: () -> String?
+        get() = { null }
+
+    /**
      * The icon of this [Preference].
      *
      * Default is `null` which means no icon.
@@ -112,7 +124,9 @@
     EntryHighlight {
         BasePreference(
             title = model.title,
+            titleContentDescription = model.titleContentDescription,
             summary = model.summary,
+            summaryContentDescription = model.summaryContentDescription,
             singleLineSummary = singleLineSummary,
             modifier = modifier,
             icon = model.icon,
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Switch.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Switch.kt
index 5155406..2fac576 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Switch.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Switch.kt
@@ -21,8 +21,7 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.semantics.contentDescription
-import androidx.compose.ui.semantics.semantics
+import com.android.settingslib.spa.framework.compose.contentDescription
 import com.android.settingslib.spa.framework.util.wrapOnSwitchWithLog
 
 @Composable
@@ -37,9 +36,7 @@
         Switch(
             checked = checked,
             onCheckedChange = wrapOnSwitchWithLog(onCheckedChange),
-            modifier = if (contentDescription != null) Modifier.semantics {
-                this.contentDescription = contentDescription
-            } else Modifier,
+            modifier = Modifier.contentDescription(contentDescription),
             enabled = changeable(),
             interactionSource = interactionSource,
         )
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Text.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Text.kt
index a59b95a..d423d9f 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Text.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Text.kt
@@ -30,16 +30,23 @@
 import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
+import com.android.settingslib.spa.framework.compose.contentDescription
 import com.android.settingslib.spa.framework.theme.SettingsDimension
 import com.android.settingslib.spa.framework.theme.SettingsOpacity.alphaForEnabled
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.framework.theme.toMediumWeight
 
 @Composable
-fun SettingsTitle(title: String, useMediumWeight: Boolean = false) {
+fun SettingsTitle(
+    title: String,
+    contentDescription: String? = null,
+    useMediumWeight: Boolean = false,
+) {
     Text(
         text = title,
-        modifier = Modifier.padding(vertical = SettingsDimension.paddingTiny),
+        modifier = Modifier
+            .padding(vertical = SettingsDimension.paddingTiny)
+            .contentDescription(contentDescription),
         color = MaterialTheme.colorScheme.onSurface,
         style = MaterialTheme.typography.titleMedium.withWeight(useMediumWeight),
     )
@@ -81,11 +88,13 @@
 @Composable
 fun SettingsBody(
     body: String,
+    contentDescription: String? = null,
     maxLines: Int = Int.MAX_VALUE,
 ) {
     if (body.isNotEmpty()) {
         Text(
             text = body,
+            modifier = Modifier.contentDescription(contentDescription),
             color = MaterialTheme.colorScheme.onSurfaceVariant,
             style = MaterialTheme.typography.bodyMedium,
             overflow = TextOverflow.Ellipsis,
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/PreferenceTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/PreferenceTest.kt
index 8c363db..5ef3329 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/PreferenceTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/PreferenceTest.kt
@@ -29,6 +29,7 @@
 import androidx.compose.ui.test.assertIsDisplayed
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.test.onRoot
 import androidx.compose.ui.test.performClick
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
@@ -93,11 +94,10 @@
             }
         }
 
-        val summaryNode = composeTestRule.onNodeWithText(LONG_SUMMARY)
         try {
             // There is no assertHeightIsAtMost, so use the assertHeightIsAtLeast and catch the
             // expected exception.
-            summaryNode.assertHeightIsAtLeast(lineHeightDp.times(2))
+            composeTestRule.onRoot().assertHeightIsAtLeast(lineHeightDp.times(5))
         } catch (e: AssertionError) {
             assertThat(e).hasMessageThat().contains("height")
             return
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 1bd93e4..b8bfeda 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -4727,9 +4727,14 @@
         }
 
         if ((code == OP_CAMERA) && isAutomotive()) {
-            if ((Flags.cameraPrivacyAllowlist())
-                    && (mSensorPrivacyManager.isCameraPrivacyEnabled(packageName))) {
-                return true;
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                if ((Flags.cameraPrivacyAllowlist())
+                        && (mSensorPrivacyManager.isCameraPrivacyEnabled(packageName))) {
+                    return true;
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
             }
         }
 
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 91860a6..390a7cf 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -4805,6 +4805,14 @@
                                 topActivity.getSyncTransaction());
                     }
                     lastParentBeforePip.moveToFront("movePinnedActivityToOriginalTask");
+                    // If the reparent is not included in transition, make sure the visibility of
+                    // task is still updated by core. Otherwise if the task is collected (e.g.
+                    // rotation change) after leaving this scope, the visibility operation will be
+                    // put in sync transaction, then it is not synced with reparent.
+                    if (com.android.window.flags.Flags.removePrepareSurfaceInPlacement()
+                            && lastParentBeforePip.mSyncState == SYNC_STATE_NONE) {
+                        lastParentBeforePip.prepareSurfaces();
+                    }
                 }
                 if (isPip2ExperimentEnabled) {
                     super.setWindowingMode(windowingMode);