Merge "Add APIs to control the external display state" into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index e394857..7005349 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -19,7 +19,7 @@
// Add java_aconfig_libraries to here to add them to the core framework
srcs: [
":android.security.flags-aconfig-java{.generated_srcjars}",
- ":com.android.hardware.camera2-aconfig-java{.generated_srcjars}",
+ ":camera_platform_flags_core_java_lib{.generated_srcjars}",
":com.android.window.flags.window-aconfig-java{.generated_srcjars}",
":com.android.text.flags-aconfig-java{.generated_srcjars}",
],
@@ -34,15 +34,9 @@
}
// Camera
-aconfig_declarations {
- name: "com.android.hardware.camera2-aconfig",
- package: "com.android.hardware.camera2",
- srcs: ["core/java/android/hardware/camera2/camera_platform.aconfig"],
-}
-
java_aconfig_library {
- name: "com.android.hardware.camera2-aconfig-java",
- aconfig_declarations: "com.android.hardware.camera2-aconfig",
+ name: "camera_platform_flags_core_java_lib",
+ aconfig_declarations: "camera_platform_flags",
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3dd69e4..1665cc1 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -223,6 +223,7 @@
import com.android.org.conscrypt.TrustedCertificateStore;
import com.android.server.am.MemInfoDumpProto;
+import dalvik.annotation.optimization.NeverCompile;
import dalvik.system.AppSpecializationHooks;
import dalvik.system.CloseGuard;
import dalvik.system.VMDebug;
@@ -1496,6 +1497,7 @@
}
}
+ @NeverCompile
@Override
public void dumpMemInfo(ParcelFileDescriptor pfd, Debug.MemoryInfo mem, boolean checkin,
boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
@@ -1510,6 +1512,7 @@
}
}
+ @NeverCompile
private void dumpMemInfo(PrintWriter pw, Debug.MemoryInfo memInfo, boolean checkin,
boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable) {
long nativeMax = Debug.getNativeHeapSize() / 1024;
@@ -1666,6 +1669,7 @@
}
}
+ @NeverCompile
@Override
public void dumpMemInfoProto(ParcelFileDescriptor pfd, Debug.MemoryInfo mem,
boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
@@ -1679,6 +1683,7 @@
}
}
+ @NeverCompile
private void dumpMemInfo(ProtoOutputStream proto, Debug.MemoryInfo memInfo,
boolean dumpFullInfo, boolean dumpDalvik,
boolean dumpSummaryOnly, boolean dumpUnreachable) {
@@ -3020,6 +3025,7 @@
pw.println(String.format(format, objs));
}
+ @NeverCompile
public static void dumpMemInfoTable(PrintWriter pw, Debug.MemoryInfo memInfo, boolean checkin,
boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
int pid, String processName,
@@ -3349,6 +3355,7 @@
/**
* Dump mem info data to proto.
*/
+ @NeverCompile
public static void dumpMemInfoTable(ProtoOutputStream proto, Debug.MemoryInfo memInfo,
boolean dumpDalvik, boolean dumpSummaryOnly,
long nativeMax, long nativeAllocated, long nativeFree,
diff --git a/core/java/android/hardware/camera2/camera_platform.aconfig b/core/java/android/hardware/camera2/camera_platform.aconfig
deleted file mode 100644
index 67f6300..0000000
--- a/core/java/android/hardware/camera2/camera_platform.aconfig
+++ /dev/null
@@ -1,8 +0,0 @@
-package: "com.android.hardware.camera2"
-
-flag {
- namespace: "camera_platform"
- name: "initial_test_flag"
- description: "Flag infrastructure test flag"
- bug: "292631208"
-}
diff --git a/core/java/android/hardware/radio/UniqueProgramIdentifier.aidl b/core/java/android/hardware/radio/UniqueProgramIdentifier.aidl
new file mode 100644
index 0000000..2ed2bcc
--- /dev/null
+++ b/core/java/android/hardware/radio/UniqueProgramIdentifier.aidl
@@ -0,0 +1,20 @@
+/**
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio;
+
+/** @hide */
+parcelable UniqueProgramIdentifier;
diff --git a/core/java/android/hardware/radio/UniqueProgramIdentifier.java b/core/java/android/hardware/radio/UniqueProgramIdentifier.java
new file mode 100644
index 0000000..ea8948e
--- /dev/null
+++ b/core/java/android/hardware/radio/UniqueProgramIdentifier.java
@@ -0,0 +1,163 @@
+/**
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+/**
+ * Identifier that can uniquely identifies a program.
+ *
+ * This is a transport class used for internal communication between
+ * Broadcast Radio Service and Radio Manager. Do not use it directly.
+ *
+ * @hide
+ */
+public final class UniqueProgramIdentifier implements Parcelable {
+
+ @NonNull private final ProgramSelector.Identifier mPrimaryId;
+ @NonNull private final ProgramSelector.Identifier[] mCriticalSecondaryIds;
+
+ /**
+ * Check whether some secondary identifier is needed to uniquely specify a program for
+ * a given primary identifier type
+ *
+ * @param type primary identifier type {@link ProgramSelector.IdentifierType}
+ * @return whether some secondary identifier is needed to uniquely specify a program.
+ */
+ public static boolean requireCriticalSecondaryIds(@ProgramSelector.IdentifierType int type) {
+ return type == ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT || type
+ == ProgramSelector.IDENTIFIER_TYPE_DAB_SID_EXT;
+ }
+
+ public UniqueProgramIdentifier(ProgramSelector selector) {
+ Objects.requireNonNull(selector, "Program selector can not be null");
+ mPrimaryId = selector.getPrimaryId();
+ switch (mPrimaryId.getType()) {
+ case ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT:
+ case ProgramSelector.IDENTIFIER_TYPE_DAB_SID_EXT:
+ ProgramSelector.Identifier ensembleId = null;
+ ProgramSelector.Identifier frequencyId = null;
+ ProgramSelector.Identifier[] secondaryIds = selector.getSecondaryIds();
+ for (int i = 0; i < secondaryIds.length; i++) {
+ if (ensembleId == null && secondaryIds[i].getType()
+ == ProgramSelector.IDENTIFIER_TYPE_DAB_ENSEMBLE) {
+ ensembleId = selector.getSecondaryIds()[i];
+ } else if (frequencyId == null && secondaryIds[i].getType()
+ == ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY) {
+ frequencyId = secondaryIds[i];
+ }
+ if (ensembleId != null && frequencyId != null) {
+ break;
+ }
+ }
+ if (ensembleId == null) {
+ if (frequencyId == null) {
+ mCriticalSecondaryIds = new ProgramSelector.Identifier[]{};
+ } else {
+ mCriticalSecondaryIds = new ProgramSelector.Identifier[]{frequencyId};
+ }
+ } else if (frequencyId == null) {
+ mCriticalSecondaryIds = new ProgramSelector.Identifier[]{ensembleId};
+ } else {
+ mCriticalSecondaryIds = new ProgramSelector.Identifier[]{ensembleId,
+ frequencyId};
+ }
+ break;
+ default:
+ mCriticalSecondaryIds = new ProgramSelector.Identifier[]{};
+ }
+
+ }
+
+ public UniqueProgramIdentifier(ProgramSelector.Identifier primaryId) {
+ mPrimaryId = primaryId;
+ mCriticalSecondaryIds = new ProgramSelector.Identifier[]{};
+ }
+
+ @NonNull
+ public ProgramSelector.Identifier getPrimaryId() {
+ return mPrimaryId;
+ }
+
+ @NonNull
+ public List<ProgramSelector.Identifier> getCriticalSecondaryIds() {
+ return List.of(mCriticalSecondaryIds);
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ return new StringBuilder("UniqueProgramIdentifier(primary=").append(mPrimaryId)
+ .append(", criticalSecondary=")
+ .append(Arrays.toString(mCriticalSecondaryIds)).append(")")
+ .toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mPrimaryId, Arrays.hashCode(mCriticalSecondaryIds));
+ }
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
+ if (this == obj) return true;
+ if (!(obj instanceof UniqueProgramIdentifier)) return false;
+ UniqueProgramIdentifier other = (UniqueProgramIdentifier) obj;
+ return other.mPrimaryId.equals(mPrimaryId)
+ && Arrays.equals(other.mCriticalSecondaryIds, mCriticalSecondaryIds);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ private UniqueProgramIdentifier(Parcel in) {
+ mPrimaryId = in.readTypedObject(ProgramSelector.Identifier.CREATOR);
+ mCriticalSecondaryIds = in.createTypedArray(ProgramSelector.Identifier.CREATOR);
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeTypedObject(mPrimaryId, 0);
+ dest.writeTypedArray(mCriticalSecondaryIds, 0);
+ if (Stream.of(mCriticalSecondaryIds).anyMatch(Objects::isNull)) {
+ throw new IllegalArgumentException(
+ "criticalSecondaryIds list must not contain nulls");
+ }
+ }
+
+ @NonNull
+ public static final Parcelable.Creator<UniqueProgramIdentifier> CREATOR =
+ new Parcelable.Creator<UniqueProgramIdentifier>() {
+ public UniqueProgramIdentifier createFromParcel(Parcel in) {
+ return new UniqueProgramIdentifier(in);
+ }
+
+ public UniqueProgramIdentifier[] newArray(int size) {
+ return new UniqueProgramIdentifier[size];
+ }
+ };
+}
diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/ProgramSelectorTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/ProgramSelectorTest.java
index ae43a1c..b1cf9c2 100644
--- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/ProgramSelectorTest.java
+++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/ProgramSelectorTest.java
@@ -437,8 +437,8 @@
@Test
public void writeToParcel_forProgramSelector() {
- ProgramSelector selectorExpected =
- getFmSelector(/* secondaryIds= */ null, /* vendorIds= */ null);
+ ProgramSelector selectorExpected = getDabSelector(new ProgramSelector.Identifier[]{
+ DAB_ENSEMBLE_IDENTIFIER, DAB_FREQUENCY_IDENTIFIER}, /* vendorIds= */ null);
Parcel parcel = Parcel.obtain();
selectorExpected.writeToParcel(parcel, /* flags= */ 0);
diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/UniqueProgramIdentifierTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/UniqueProgramIdentifierTest.java
new file mode 100644
index 0000000..b36367b
--- /dev/null
+++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/UniqueProgramIdentifierTest.java
@@ -0,0 +1,187 @@
+/**
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio;
+
+import android.annotation.Nullable;
+import android.os.Parcel;
+
+import com.google.common.truth.Expect;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+public final class UniqueProgramIdentifierTest {
+ private static final ProgramSelector.Identifier FM_IDENTIFIER = new ProgramSelector.Identifier(
+ ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY, /* value= */ 88_500);
+
+ private static final ProgramSelector.Identifier DAB_DMB_SID_EXT_IDENTIFIER_1 =
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT,
+ /* value= */ 0xA000000111L);
+ private static final ProgramSelector.Identifier DAB_ENSEMBLE_IDENTIFIER =
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_ENSEMBLE,
+ /* value= */ 0x1001);
+ private static final ProgramSelector.Identifier DAB_FREQUENCY_IDENTIFIER =
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY,
+ /* value= */ 220352);
+ private static final ProgramSelector.Identifier DAB_SCID_IDENTIFIER =
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_SCID,
+ /* value= */ 0x101);
+
+ @Rule
+ public final Expect expect = Expect.create();
+
+ @Test
+ public void getPrimaryId_forUniqueProgramIdentifier() {
+ ProgramSelector dabSelector = getDabSelector(new ProgramSelector.Identifier[]{
+ DAB_ENSEMBLE_IDENTIFIER, DAB_FREQUENCY_IDENTIFIER}, /* vendorIds= */ null);
+ UniqueProgramIdentifier dabIdentifier = new UniqueProgramIdentifier(dabSelector);
+
+ expect.withMessage("Primary id of DAB unique identifier")
+ .that(dabIdentifier.getPrimaryId()).isEqualTo(DAB_DMB_SID_EXT_IDENTIFIER_1);
+ }
+
+ @Test
+ public void getCriticalSecondaryIds_forDabUniqueProgramIdentifier() {
+ ProgramSelector dabSelector = getDabSelector(new ProgramSelector.Identifier[]{
+ DAB_ENSEMBLE_IDENTIFIER, DAB_FREQUENCY_IDENTIFIER, DAB_SCID_IDENTIFIER},
+ /* vendorIds= */ null);
+ UniqueProgramIdentifier dabIdentifier = new UniqueProgramIdentifier(dabSelector);
+
+ expect.withMessage("Critical secondary ids of DAB unique identifier")
+ .that(dabIdentifier.getCriticalSecondaryIds()).containsExactly(
+ DAB_ENSEMBLE_IDENTIFIER, DAB_FREQUENCY_IDENTIFIER);
+ }
+
+ @Test
+ public void getCriticalSecondaryIds_forFmUniqueProgramIdentifier() {
+ UniqueProgramIdentifier fmUniqueIdentifier = new UniqueProgramIdentifier(
+ new ProgramSelector(ProgramSelector.PROGRAM_TYPE_FM, FM_IDENTIFIER,
+ new ProgramSelector.Identifier[]{new ProgramSelector.Identifier(
+ ProgramSelector.IDENTIFIER_TYPE_RDS_PI, /* value= */ 0x1003)},
+ /* vendorIds= */ null));
+
+ expect.withMessage("Empty critical secondary id list of FM unique identifier")
+ .that(fmUniqueIdentifier.getCriticalSecondaryIds()).isEmpty();
+ }
+
+ @Test
+ public void toString_forUniqueProgramIdentifier() {
+ ProgramSelector dabSelector = getDabSelector(new ProgramSelector.Identifier[]{
+ DAB_ENSEMBLE_IDENTIFIER, DAB_FREQUENCY_IDENTIFIER}, /* vendorIds= */ null);
+ UniqueProgramIdentifier dabIdentifier = new UniqueProgramIdentifier(dabSelector);
+
+ String identifierString = dabIdentifier.toString();
+
+ expect.withMessage("Primary id in DAB unique identifier")
+ .that(identifierString).contains(DAB_DMB_SID_EXT_IDENTIFIER_1.toString());
+ expect.withMessage("Ensemble id in DAB unique identifier")
+ .that(identifierString).contains(DAB_ENSEMBLE_IDENTIFIER.toString());
+ expect.withMessage("Frequency id in DAB unique identifier")
+ .that(identifierString).contains(DAB_FREQUENCY_IDENTIFIER.toString());
+ }
+
+ @Test
+ public void hashCode_withTheSameUniqueProgramIdentifier_equals() {
+ ProgramSelector dabSelector1 = getDabSelector(new ProgramSelector.Identifier[]{
+ DAB_ENSEMBLE_IDENTIFIER, DAB_FREQUENCY_IDENTIFIER}, /* vendorIds= */ null);
+ ProgramSelector dabSelector2 = getDabSelector(new ProgramSelector.Identifier[]{
+ DAB_FREQUENCY_IDENTIFIER, DAB_ENSEMBLE_IDENTIFIER}, /* vendorIds= */ null);
+ UniqueProgramIdentifier dabIdentifier1 = new UniqueProgramIdentifier(dabSelector1);
+ UniqueProgramIdentifier dabIdentifier2 = new UniqueProgramIdentifier(dabSelector2);
+
+ expect.withMessage("Hash code of the same DAB unique identifiers")
+ .that(dabIdentifier1.hashCode()).isEqualTo(dabIdentifier2.hashCode());
+ }
+
+ @Test
+ public void equals_withIdsForUniqueProgramIdentifier_returnsTrue() {
+ ProgramSelector dabSelector1 = getDabSelector(new ProgramSelector.Identifier[]{
+ DAB_ENSEMBLE_IDENTIFIER, DAB_FREQUENCY_IDENTIFIER}, /* vendorIds= */ null);
+ ProgramSelector dabSelector2 = getDabSelector(new ProgramSelector.Identifier[]{
+ DAB_FREQUENCY_IDENTIFIER, DAB_ENSEMBLE_IDENTIFIER}, /* vendorIds= */ null);
+ UniqueProgramIdentifier dabIdentifier1 = new UniqueProgramIdentifier(dabSelector1);
+ UniqueProgramIdentifier dabIdentifier2 = new UniqueProgramIdentifier(dabSelector2);
+
+ expect.withMessage("The same DAB unique identifiers")
+ .that(dabIdentifier1).isEqualTo(dabIdentifier2);
+ }
+
+ @Test
+ public void equals_withDifferentPrimaryIdsForUniqueProgramIdentifier_returnsFalse() {
+ ProgramSelector dabSelector1 = getDabSelector(new ProgramSelector.Identifier[]{
+ DAB_ENSEMBLE_IDENTIFIER, DAB_FREQUENCY_IDENTIFIER}, /* vendorIds= */ null);
+ UniqueProgramIdentifier dabIdentifier1 = new UniqueProgramIdentifier(dabSelector1);
+ UniqueProgramIdentifier fmUniqueIdentifier = new UniqueProgramIdentifier(FM_IDENTIFIER);
+
+ expect.withMessage("Unique identifier with different primary ids")
+ .that(dabIdentifier1).isNotEqualTo(fmUniqueIdentifier);
+ }
+
+ @Test
+ public void equals_withDifferentSecondaryIdsForUniqueProgramIdentifier_returnsFalse() {
+ ProgramSelector dabSelector1 = getDabSelector(new ProgramSelector.Identifier[]{
+ DAB_ENSEMBLE_IDENTIFIER, DAB_FREQUENCY_IDENTIFIER}, /* vendorIds= */ null);
+ ProgramSelector.Identifier dabFreqIdentifier2 = new ProgramSelector.Identifier(
+ ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY, /* value= */ 222064);
+ ProgramSelector dabSelector2 = getDabSelector(new ProgramSelector.Identifier[]{
+ DAB_ENSEMBLE_IDENTIFIER, dabFreqIdentifier2}, /* vendorIds= */ null);
+ UniqueProgramIdentifier dabIdentifier1 = new UniqueProgramIdentifier(dabSelector1);
+ UniqueProgramIdentifier dabIdentifier2 = new UniqueProgramIdentifier(dabSelector2);
+
+ expect.withMessage("DAB unique identifier with different secondary ids")
+ .that(dabIdentifier1).isNotEqualTo(dabIdentifier2);
+ }
+
+ @Test
+ public void describeContents_forUniqueProgramIdentifier() {
+ UniqueProgramIdentifier fmUniqueIdentifier = new UniqueProgramIdentifier(FM_IDENTIFIER);
+
+ expect.withMessage("FM unique identifier contents")
+ .that(fmUniqueIdentifier.describeContents()).isEqualTo(0);
+ }
+
+ @Test
+ public void newArray_forUniqueProgramIdentifier() {
+ int createArraySize = 3;
+ UniqueProgramIdentifier[] identifiers = UniqueProgramIdentifier.CREATOR.newArray(
+ createArraySize);
+
+ expect.withMessage("Unique identifiers").that(identifiers).hasLength(createArraySize);
+ }
+
+ @Test
+ public void writeToParcel_forUniqueProgramIdentifier() {
+ ProgramSelector dabSelector = getDabSelector(new ProgramSelector.Identifier[]{
+ DAB_ENSEMBLE_IDENTIFIER, DAB_FREQUENCY_IDENTIFIER}, /* vendorIds= */ null);
+ UniqueProgramIdentifier dabIdentifier = new UniqueProgramIdentifier(dabSelector);
+ Parcel parcel = Parcel.obtain();
+
+ dabIdentifier.writeToParcel(parcel, /* flags= */ 0);
+ parcel.setDataPosition(0);
+
+ UniqueProgramIdentifier identifierFromParcel = UniqueProgramIdentifier.CREATOR
+ .createFromParcel(parcel);
+ expect.withMessage("Unique identifier created from parcel")
+ .that(identifierFromParcel).isEqualTo(dabIdentifier);
+ }
+
+ private ProgramSelector getDabSelector(@Nullable ProgramSelector.Identifier[] secondaryIds,
+ @Nullable long[] vendorIds) {
+ return new ProgramSelector(ProgramSelector.PROGRAM_TYPE_DAB, DAB_DMB_SID_EXT_IDENTIFIER_1,
+ secondaryIds, vendorIds);
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt
index 4dc98e4..050d1e9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt
@@ -141,13 +141,13 @@
private fun setupMaximizeMenu() {
val maximizeMenuView = maximizeMenu?.mWindowViewHost?.view ?: return
- maximizeMenuView.findViewById<Button>(
+ maximizeMenuView.requireViewById<Button>(
R.id.maximize_menu_maximize_button
).setOnClickListener(onClickListener)
- maximizeMenuView.findViewById<Button>(
+ maximizeMenuView.requireViewById<Button>(
R.id.maximize_menu_snap_right_button
).setOnClickListener(onClickListener)
- maximizeMenuView.findViewById<Button>(
+ maximizeMenuView.requireViewById<Button>(
R.id.maximize_menu_snap_left_button
).setOnClickListener(onClickListener)
}
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index b472982..2077af8 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -135,7 +135,10 @@
aconfig_declarations {
name: "systemui_aconfig_flags",
package: "com.android.systemui.aconfig",
- srcs: ["src/com/android/systemui/aconfig/systemui.aconfig"],
+ srcs: [
+ "src/com/android/systemui/aconfig/systemui.aconfig",
+ "src/com/android/systemui/accessibility/aconfig/accessibility.aconfig",
+ ],
}
java_aconfig_library {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/aconfig/accessibility.aconfig b/packages/SystemUI/src/com/android/systemui/accessibility/aconfig/accessibility.aconfig
new file mode 100644
index 0000000..91c5551
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/aconfig/accessibility.aconfig
@@ -0,0 +1,7 @@
+package: "com.android.systemui.aconfig"
+flag {
+ name: "floating_menu_overlaps_nav_bars_flag"
+ namespace: "accessibility"
+ description: "Adjusts bounds to allow the floating menu to render on top of navigation bars."
+ bug: "283768342"
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java
index 47770fa..f29077d 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java
@@ -38,6 +38,7 @@
import androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate;
import com.android.internal.accessibility.dialog.AccessibilityTarget;
+import com.android.systemui.aconfig.Flags;
import java.util.ArrayList;
import java.util.Collections;
@@ -284,6 +285,22 @@
void updateMenuMoveToTucked(boolean isMoveToTucked) {
mIsMoveToTucked = isMoveToTucked;
mMenuViewModel.updateMenuMoveToTucked(isMoveToTucked);
+
+ if (Flags.floatingMenuOverlapsNavBarsFlag()) {
+ if (isMoveToTucked) {
+ final float halfWidth = getMenuWidth() / 2.0f;
+ final boolean isOnLeftSide = mMenuAnimationController.isOnLeftSide();
+ final Rect clipBounds = new Rect(
+ (int) (!isOnLeftSide ? 0 : halfWidth),
+ 0,
+ (int) (!isOnLeftSide ? halfWidth : getMenuWidth()),
+ getMenuHeight()
+ );
+ setClipBounds(clipBounds);
+ } else {
+ setClipBounds(null);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewAppearance.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewAppearance.java
index 3cd250f..3822936 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewAppearance.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewAppearance.java
@@ -35,6 +35,7 @@
import androidx.annotation.DimenRes;
import com.android.systemui.R;
+import com.android.systemui.aconfig.Flags;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -154,8 +155,10 @@
final int margin = getMenuMargin();
final Rect draggableBounds = new Rect(getWindowAvailableBounds());
- // Initializes start position for mapping the translation of the menu view.
- draggableBounds.offsetTo(/* newLeft= */ 0, /* newTop= */ 0);
+ if (!Flags.floatingMenuOverlapsNavBarsFlag()) {
+ // Initializes start position for mapping the translation of the menu view.
+ draggableBounds.offsetTo(/* newLeft= */ 0, /* newTop= */ 0);
+ }
draggableBounds.top += margin;
draggableBounds.right -= getMenuWidth();
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java
index c52ecc5..cc18c30 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java
@@ -24,6 +24,7 @@
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
+import com.android.systemui.aconfig.Flags;
import com.android.systemui.util.settings.SecureSettings;
/**
@@ -77,8 +78,15 @@
params.receiveInsetsIgnoringZOrder = true;
params.privateFlags |= PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION;
params.windowAnimations = android.R.style.Animation_Translucent;
- params.setFitInsetsTypes(
- WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout());
+ // Insets are configured to allow the menu to display over navigation and system bars.
+ if (Flags.floatingMenuOverlapsNavBarsFlag()) {
+ params.setFitInsetsTypes(0);
+ params.layoutInDisplayCutoutMode =
+ WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+ } else {
+ params.setFitInsetsTypes(
+ WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout());
+ }
return params;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/CredentialPasswordView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/CredentialPasswordView.kt
index 6c5cc48..a7ecf38 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/CredentialPasswordView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/CredentialPasswordView.kt
@@ -52,7 +52,7 @@
titleView.ellipsize = TextUtils.TruncateAt.MARQUEE
titleView.marqueeRepeatLimit = -1
// select to enable marquee unless a screen reader is enabled
- titleView.isSelected = accessibilityManager.shouldMarquee()
+ titleView.isSelected = accessibilityManager?.shouldMarquee() ?: false
} else {
titleView.isSingleLine = false
titleView.ellipsize = null
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/BaseScreenSharePermissionDialog.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/BaseScreenSharePermissionDialog.kt
index 7859fa0..8dd25bc 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/BaseScreenSharePermissionDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/BaseScreenSharePermissionDialog.kt
@@ -121,7 +121,7 @@
private fun createOptionsView(@LayoutRes layoutId: Int?) {
if (layoutId == null) return
- val stub = findViewById<View>(R.id.options_stub) as ViewStub
+ val stub = requireViewById<View>(R.id.options_stub) as ViewStub
stub.layoutResource = layoutId
stub.inflate()
}
@@ -144,8 +144,8 @@
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
val inflater = LayoutInflater.from(parent.context)
val view = inflater.inflate(R.layout.screen_share_dialog_spinner_item_text, parent, false)
- val titleTextView = view.findViewById<TextView>(android.R.id.text1)
- val errorTextView = view.findViewById<TextView>(android.R.id.text2)
+ val titleTextView = view.requireViewById<TextView>(android.R.id.text1)
+ val errorTextView = view.requireViewById<TextView>(android.R.id.text2)
titleTextView.text = getItem(position)
errorTextView.text = options[position].spinnerDisabledText
if (isEnabled(position)) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotDetectionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotDetectionControllerTest.kt
index 08b5d2b..16091b2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotDetectionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotDetectionControllerTest.kt
@@ -170,8 +170,8 @@
private class ComponentInfoFlagMatcher(
@PackageManager.ComponentInfoFlagsBits val mask: Int, val value: Int
): ArgumentMatcher<PackageManager.ComponentInfoFlags> {
- override fun matches(flags: PackageManager.ComponentInfoFlags): Boolean {
- return (mask.toLong() and flags.value) == value.toLong()
+ override fun matches(flags: PackageManager.ComponentInfoFlags?): Boolean {
+ return flags != null && (mask.toLong() and flags.value) == value.toLong()
}
override fun toString(): String{
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
index 69575a9..7e0632b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
@@ -36,7 +36,7 @@
*
* Generic T is nullable because implicitly bounded by Any?.
*/
-fun <T> eq(obj: T): T = Mockito.eq<T>(obj)
+fun <T> eq(obj: T): T = Mockito.eq<T>(obj) ?: obj
/**
* Returns Mockito.any() as nullable type to avoid java.lang.IllegalStateException when
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 714ff68..b941aaf 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -193,6 +193,7 @@
"power_optimization_flags_lib",
"notification_flags_lib",
"pm_flags_lib",
+ "camera_platform_flags_core_java_lib",
],
javac_shard_size: 50,
javacflags: [