Merge "Fix keyguard on secondary displays" into main
diff --git a/nfc/api/current.txt b/nfc/api/current.txt
index f111327..e244520 100644
--- a/nfc/api/current.txt
+++ b/nfc/api/current.txt
@@ -228,20 +228,10 @@
method public final android.os.IBinder onBind(android.content.Intent);
method public abstract void onDeactivated(int);
method public abstract byte[] processCommandApdu(byte[], android.os.Bundle);
- method @FlaggedApi("android.nfc.nfc_read_polling_loop") public void processPollingFrames(@NonNull java.util.List<android.os.Bundle>);
+ method @FlaggedApi("android.nfc.nfc_read_polling_loop") public void processPollingFrames(@NonNull java.util.List<android.nfc.cardemulation.PollingFrame>);
method public final void sendResponseApdu(byte[]);
field public static final int DEACTIVATION_DESELECTED = 1; // 0x1
field public static final int DEACTIVATION_LINK_LOSS = 0; // 0x0
- field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final String KEY_POLLING_LOOP_DATA = "android.nfc.cardemulation.DATA";
- field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final String KEY_POLLING_LOOP_GAIN = "android.nfc.cardemulation.GAIN";
- field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final String KEY_POLLING_LOOP_TIMESTAMP = "android.nfc.cardemulation.TIMESTAMP";
- field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final String KEY_POLLING_LOOP_TYPE = "android.nfc.cardemulation.TYPE";
- field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_A = 65; // 0x0041 'A'
- field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_B = 66; // 0x0042 'B'
- field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_F = 70; // 0x0046 'F'
- field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_OFF = 88; // 0x0058 'X'
- field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_ON = 79; // 0x004f 'O'
- field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_UNKNOWN = 85; // 0x0055 'U'
field public static final String SERVICE_INTERFACE = "android.nfc.cardemulation.action.HOST_APDU_SERVICE";
field public static final String SERVICE_META_DATA = "android.nfc.cardemulation.host_apdu_service";
}
@@ -274,6 +264,23 @@
field public static final String SERVICE_META_DATA = "android.nfc.cardemulation.off_host_apdu_service";
}
+ @FlaggedApi("android.nfc.nfc_read_polling_loop") public final class PollingFrame implements android.os.Parcelable {
+ ctor public PollingFrame(int, @Nullable byte[], int, int);
+ method public int describeContents();
+ method @NonNull public byte[] getData();
+ method public int getGain();
+ method public int getTimestamp();
+ method public int getType();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.nfc.cardemulation.PollingFrame> CREATOR;
+ field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final int POLLING_LOOP_TYPE_A = 65; // 0x41
+ field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final int POLLING_LOOP_TYPE_B = 66; // 0x42
+ field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final int POLLING_LOOP_TYPE_F = 70; // 0x46
+ field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final int POLLING_LOOP_TYPE_OFF = 88; // 0x58
+ field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final int POLLING_LOOP_TYPE_ON = 79; // 0x4f
+ field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final int POLLING_LOOP_TYPE_UNKNOWN = 85; // 0x55
+ }
+
}
package android.nfc.tech {
diff --git a/nfc/java/android/nfc/NfcAdapter.java b/nfc/java/android/nfc/NfcAdapter.java
index c5b7582..e5752d1 100644
--- a/nfc/java/android/nfc/NfcAdapter.java
+++ b/nfc/java/android/nfc/NfcAdapter.java
@@ -38,6 +38,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
+import android.nfc.cardemulation.PollingFrame;
import android.nfc.tech.MifareClassic;
import android.nfc.tech.Ndef;
import android.nfc.tech.NfcA;
@@ -2799,7 +2800,8 @@
*/
@TestApi
@FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP)
- public void notifyPollingLoop(@NonNull Bundle frame) {
+ public void notifyPollingLoop(@NonNull PollingFrame pollingFrame) {
+ Bundle frame = pollingFrame.toBundle();
try {
if (sService == null) {
attemptDeadServiceRecovery(null);
diff --git a/nfc/java/android/nfc/cardemulation/HostApduService.java b/nfc/java/android/nfc/cardemulation/HostApduService.java
index 363788e..61037a2 100644
--- a/nfc/java/android/nfc/cardemulation/HostApduService.java
+++ b/nfc/java/android/nfc/cardemulation/HostApduService.java
@@ -244,85 +244,6 @@
public static final String KEY_DATA = "data";
/**
- * KEY_POLLING_LOOP_TYPE is the Bundle key for the type of
- * polling loop frame in the Bundle passed to {@link #processPollingFrames(List)}
- */
- @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
- public static final String KEY_POLLING_LOOP_TYPE = "android.nfc.cardemulation.TYPE";
-
- /**
- * POLLING_LOOP_TYPE_A is the value associated with the key
- * POLLING_LOOP_TYPE in the Bundle passed to {@link #processPollingFrames(List)}
- * when the polling loop is for NFC-A.
- */
- @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
- public static final char POLLING_LOOP_TYPE_A = 'A';
-
- /**
- * POLLING_LOOP_TYPE_B is the value associated with the key
- * POLLING_LOOP_TYPE in the Bundle passed to {@link #processPollingFrames(List)}
- * when the polling loop is for NFC-B.
- */
- @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
- public static final char POLLING_LOOP_TYPE_B = 'B';
-
- /**
- * POLLING_LOOP_TYPE_F is the value associated with the key
- * POLLING_LOOP_TYPE in the Bundle passed to {@link #processPollingFrames(List)}
- * when the polling loop is for NFC-F.
- */
- @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
- public static final char POLLING_LOOP_TYPE_F = 'F';
-
- /**
- * POLLING_LOOP_TYPE_ON is the value associated with the key
- * POLLING_LOOP_TYPE in the Bundle passed to {@link #processPollingFrames(List)}
- * when the polling loop turns on.
- */
- @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
- public static final char POLLING_LOOP_TYPE_ON = 'O';
-
- /**
- * POLLING_LOOP_TYPE_OFF is the value associated with the key
- * POLLING_LOOP_TYPE in the Bundle passed to {@link #processPollingFrames(List)}
- * when the polling loop turns off.
- */
- @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
- public static final char POLLING_LOOP_TYPE_OFF = 'X';
-
- /**
- * POLLING_LOOP_TYPE_UNKNOWN is the value associated with the key
- * POLLING_LOOP_TYPE in the Bundle passed to {@link #processPollingFrames(List)}
- * when the polling loop frame isn't recognized.
- */
- @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
- public static final char POLLING_LOOP_TYPE_UNKNOWN = 'U';
-
- /**
- * KEY_POLLING_LOOP_DATA is the Bundle key for the raw data of captured from
- * the polling loop frame in the Bundle passed to {@link #processPollingFrames(List)}
- * when the frame type isn't recognized.
- */
- @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
- public static final String KEY_POLLING_LOOP_DATA = "android.nfc.cardemulation.DATA";
-
- /**
- * KEY_POLLING_LOOP_GAIN is the Bundle key for the field strength of
- * the polling loop frame in the Bundle passed to {@link #processPollingFrames(List)}
- * when the frame type isn't recognized.
- */
- @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
- public static final String KEY_POLLING_LOOP_GAIN = "android.nfc.cardemulation.GAIN";
-
- /**
- * KEY_POLLING_LOOP_TIMESTAMP is the Bundle key for the timestamp of
- * the polling loop frame in the Bundle passed to {@link #processPollingFrames(List)}
- * when the frame type isn't recognized.
- */
- @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
- public static final String KEY_POLLING_LOOP_TIMESTAMP = "android.nfc.cardemulation.TIMESTAMP";
-
- /**
* @hide
*/
public static final String KEY_POLLING_LOOP_FRAMES_BUNDLE =
@@ -407,7 +328,12 @@
ArrayList<Bundle> frames =
msg.getData().getParcelableArrayList(KEY_POLLING_LOOP_FRAMES_BUNDLE,
Bundle.class);
- processPollingFrames(frames);
+ ArrayList<PollingFrame> pollingFrames =
+ new ArrayList<PollingFrame>(frames.size());
+ for (Bundle frame : frames) {
+ pollingFrames.add(new PollingFrame(frame));
+ }
+ processPollingFrames(pollingFrames);
break;
default:
super.handleMessage(msg);
@@ -482,7 +408,7 @@
* @param frame A description of the polling frame.
*/
@FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
- public void processPollingFrames(@NonNull List<Bundle> frame) {
+ public void processPollingFrames(@NonNull List<PollingFrame> frame) {
}
/**
diff --git a/nfc/java/android/nfc/cardemulation/PollingFrame.java b/nfc/java/android/nfc/cardemulation/PollingFrame.java
new file mode 100644
index 0000000..3383f3b
--- /dev/null
+++ b/nfc/java/android/nfc/cardemulation/PollingFrame.java
@@ -0,0 +1,243 @@
+/*
+ * 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.nfc.cardemulation;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HexFormat;
+import java.util.List;
+
+/**
+ * Polling Frames represent data about individual frames of an NFC polling loop. These frames will
+ * be deliverd to subclasses of {@link HostApduService} that have registered filters with
+ * {@link CardEmulation#registerPollingLoopFilterForService(ComponentName, String)} that match a
+ * given frame in a loop and will be delivered through calls to
+ * {@link HostApduService#processPollingFrames(List)}.
+ */
+@FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+public final class PollingFrame implements Parcelable{
+
+ /**
+ * @hide
+ */
+ @IntDef(prefix = { "POLLING_LOOP_TYPE_"}, value = { POLLING_LOOP_TYPE_A, POLLING_LOOP_TYPE_B,
+ POLLING_LOOP_TYPE_F, POLLING_LOOP_TYPE_OFF, POLLING_LOOP_TYPE_ON })
+ @Retention(RetentionPolicy.SOURCE)
+ @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+ public @interface PollingFrameType {}
+
+ /**
+ * POLLING_LOOP_TYPE_A is the value associated with the key
+ * POLLING_LOOP_TYPE in the Bundle passed to {@link HostApduService#processPollingFrames(List)}
+ * when the polling loop is for NFC-A.
+ */
+ @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+ public static final int POLLING_LOOP_TYPE_A = 'A';
+
+ /**
+ * POLLING_LOOP_TYPE_B is the value associated with the key
+ * POLLING_LOOP_TYPE in the Bundle passed to {@link HostApduService#processPollingFrames(List)}
+ * when the polling loop is for NFC-B.
+ */
+ @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+ public static final int POLLING_LOOP_TYPE_B = 'B';
+
+ /**
+ * POLLING_LOOP_TYPE_F is the value associated with the key
+ * POLLING_LOOP_TYPE in the Bundle passed to {@link HostApduService#processPollingFrames(List)}
+ * when the polling loop is for NFC-F.
+ */
+ @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+ public static final int POLLING_LOOP_TYPE_F = 'F';
+
+ /**
+ * POLLING_LOOP_TYPE_ON is the value associated with the key
+ * POLLING_LOOP_TYPE in the Bundle passed to {@link HostApduService#processPollingFrames(List)}
+ * when the polling loop turns on.
+ */
+ @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+ public static final int POLLING_LOOP_TYPE_ON = 'O';
+
+ /**
+ * POLLING_LOOP_TYPE_OFF is the value associated with the key
+ * POLLING_LOOP_TYPE in the Bundle passed to {@link HostApduService#processPollingFrames(List)}
+ * when the polling loop turns off.
+ */
+ @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+ public static final int POLLING_LOOP_TYPE_OFF = 'X';
+
+ /**
+ * POLLING_LOOP_TYPE_UNKNOWN is the value associated with the key
+ * POLLING_LOOP_TYPE in the Bundle passed to {@link HostApduService#processPollingFrames(List)}
+ * when the polling loop frame isn't recognized.
+ */
+ @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+ public static final int POLLING_LOOP_TYPE_UNKNOWN = 'U';
+
+ /**
+ * KEY_POLLING_LOOP_TYPE is the Bundle key for the type of
+ * polling loop frame in the Bundle included in MSG_POLLING_LOOP.
+ *
+ * @hide
+ */
+ @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+ public static final String KEY_POLLING_LOOP_TYPE = "android.nfc.cardemulation.TYPE";
+
+ /**
+ * KEY_POLLING_LOOP_DATA is the Bundle key for the raw data of captured from
+ * the polling loop frame in the Bundle included in MSG_POLLING_LOOP.
+ *
+ * @hide
+ */
+ @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+ public static final String KEY_POLLING_LOOP_DATA = "android.nfc.cardemulation.DATA";
+
+ /**
+ * KEY_POLLING_LOOP_GAIN is the Bundle key for the field strength of
+ * the polling loop frame in the Bundle included in MSG_POLLING_LOOP.
+ *
+ * @hide
+ */
+ @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+ public static final String KEY_POLLING_LOOP_GAIN = "android.nfc.cardemulation.GAIN";
+
+ /**
+ * KEY_POLLING_LOOP_TIMESTAMP is the Bundle key for the timestamp of
+ * the polling loop frame in the Bundle included in MSG_POLLING_LOOP.
+ *
+ * @hide
+ */
+ @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+ public static final String KEY_POLLING_LOOP_TIMESTAMP = "android.nfc.cardemulation.TIMESTAMP";
+
+
+ @PollingFrameType
+ private final int mType;
+ private final byte[] mData;
+ private final int mGain;
+ private final int mTimestamp;
+
+ public static final @NonNull Parcelable.Creator<PollingFrame> CREATOR =
+ new Parcelable.Creator<>() {
+ @Override
+ public PollingFrame createFromParcel(Parcel source) {
+ return new PollingFrame(source.readBundle());
+ }
+
+ @Override
+ public PollingFrame[] newArray(int size) {
+ return new PollingFrame[size];
+ }
+ };
+
+ PollingFrame(Bundle frame) {
+ mType = frame.getInt(KEY_POLLING_LOOP_TYPE);
+ byte[] data = frame.getByteArray(KEY_POLLING_LOOP_DATA);
+ mData = (data == null) ? new byte[0] : data;
+ mGain = frame.getByte(KEY_POLLING_LOOP_GAIN);
+ mTimestamp = frame.getInt(KEY_POLLING_LOOP_TIMESTAMP);
+ }
+
+ public PollingFrame(@PollingFrameType int type, @Nullable byte[] data,
+ int gain, int timestamp) {
+ mType = type;
+ mData = data == null ? new byte[0] : data;
+ mGain = gain;
+ mTimestamp = timestamp;
+ }
+
+ /**
+ * Returns the type of frame for this polling loop frame.
+ * The possible return values are:
+ * <ul>
+ * <li>{@link POLLING_LOOP_TYPE_ON}</li>
+ * <li>{@link POLLING_LOOP_TYPE_OFF}</li>
+ * <li>{@link POLLING_LOOP_TYPE_A}</li>
+ * <li>{@link POLLING_LOOP_TYPE_B}</li>
+ * <li>{@link POLLING_LOOP_TYPE_F}</li>
+ * </ul>
+ */
+ public @PollingFrameType int getType() {
+ return mType;
+ }
+
+ /**
+ * Returns the raw data from the polling type frame.
+ */
+ public @NonNull byte[] getData() {
+ return mData;
+ }
+
+ /**
+ * Returns the gain representing the field strength of the NFC field when this polling loop
+ * frame was observed.
+ */
+ public int getGain() {
+ return mGain;
+ }
+
+ /**
+ * Returns the timestamp of when the polling loop frame was observed in milliseconds. These
+ * timestamps are relative and not absolute and should only be used fro comparing the timing of
+ * frames relative to each other.
+ * @return the timestamp in milliseconds
+ */
+ public int getTimestamp() {
+ return mTimestamp;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeBundle(toBundle());
+ }
+
+ /**
+ *
+ * @hide
+ * @return a Bundle representing this frame
+ */
+ public Bundle toBundle() {
+ Bundle frame = new Bundle();
+ frame.putInt(KEY_POLLING_LOOP_TYPE, getType());
+ frame.putByte(KEY_POLLING_LOOP_GAIN, (byte) getGain());
+ frame.putByteArray(KEY_POLLING_LOOP_DATA, getData());
+ frame.putInt(KEY_POLLING_LOOP_TIMESTAMP, getTimestamp());
+ return frame;
+ }
+
+ @Override
+ public String toString() {
+ return "PollingFrame { Type: " + (char) getType()
+ + ", gain: " + getGain()
+ + ", timestamp: " + Integer.toUnsignedString(getTimestamp())
+ + ", data: [" + HexFormat.ofDelimiter(" ").formatHex(getData()) + "] }";
+ }
+}
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 4ed1965..acb1418 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -15,6 +15,16 @@
}
flag {
+ name: "udfps_view_performance"
+ namespace: "systemui"
+ description: "Decrease screen off blocking calls by waiting until the device is finished going to sleep before adding the udfps view."
+ bug: "225183106"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "notification_async_group_header_inflation"
namespace: "systemui"
description: "Inflates the notification group summary header views from the background thread."
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt
index 7b21d09..dd043db 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt
@@ -18,11 +18,14 @@
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import com.android.compose.animation.scene.SceneScope
+import com.android.compose.animation.scene.animateSceneFloatAsState
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.ui.viewmodel.LockscreenSceneViewModel
+import com.android.systemui.qs.ui.composable.QuickSettings
import com.android.systemui.scene.shared.model.Direction
import com.android.systemui.scene.shared.model.Edge
import com.android.systemui.scene.shared.model.SceneKey
@@ -87,10 +90,15 @@
}
@Composable
-private fun LockscreenScene(
+private fun SceneScope.LockscreenScene(
lockscreenContent: Lazy<LockscreenContent>,
modifier: Modifier = Modifier,
) {
+ animateSceneFloatAsState(
+ value = QuickSettings.SharedValues.SquishinessValues.LockscreenSceneStarting,
+ key = QuickSettings.SharedValues.TilesSquishiness,
+ )
+
lockscreenContent
.get()
.Content(
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt
index de8f2ec..5d0b9ba 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt
@@ -16,7 +16,6 @@
package com.android.systemui.qs.ui.composable
-import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
@@ -32,14 +31,12 @@
import com.android.compose.animation.scene.MovableElementScenePicker
import com.android.compose.animation.scene.SceneScope
import com.android.compose.animation.scene.TransitionState
+import com.android.compose.animation.scene.ValueKey
import com.android.compose.modifiers.thenIf
-import com.android.compose.theme.colorAttr
import com.android.systemui.qs.ui.adapter.QSSceneAdapter
import com.android.systemui.qs.ui.adapter.QSSceneAdapter.State.Companion.Collapsing
import com.android.systemui.qs.ui.adapter.QSSceneAdapter.State.Expanding
-import com.android.systemui.res.R
-import com.android.systemui.scene.ui.composable.Gone
-import com.android.systemui.scene.ui.composable.Lockscreen
+import com.android.systemui.qs.ui.adapter.QSSceneAdapter.State.Unsquishing
import com.android.systemui.scene.ui.composable.QuickSettings as QuickSettingsSceneKey
import com.android.systemui.scene.ui.composable.Shade
@@ -51,15 +48,24 @@
)
object Elements {
- // TODO RENAME
val Content =
ElementKey("QuickSettingsContent", scenePicker = MovableElementScenePicker(SCENES))
- val CollapsedGrid = ElementKey("QuickSettingsCollapsedGrid")
val FooterActions = ElementKey("QuickSettingsFooterActions")
}
+
+ object SharedValues {
+ val TilesSquishiness = ValueKey("QuickSettingsTileSquishiness")
+ object SquishinessValues {
+ val Default = 1f
+ val LockscreenSceneStarting = 0f
+ val GoneSceneStarting = 0.3f
+ }
+ }
}
-private fun SceneScope.stateForQuickSettingsContent(): QSSceneAdapter.State {
+private fun SceneScope.stateForQuickSettingsContent(
+ squishiness: Float = QuickSettings.SharedValues.SquishinessValues.Default
+): QSSceneAdapter.State {
return when (val transitionState = layoutState.transitionState) {
is TransitionState.Idle -> {
when (transitionState.currentScene) {
@@ -73,10 +79,10 @@
when {
fromScene == Shade && toScene == QuickSettingsSceneKey -> Expanding(progress)
fromScene == QuickSettingsSceneKey && toScene == Shade -> Collapsing(progress)
- toScene == Shade -> QSSceneAdapter.State.QQS
- toScene == QuickSettingsSceneKey -> QSSceneAdapter.State.QS
- toScene == Gone -> QSSceneAdapter.State.CLOSED
- toScene == Lockscreen -> QSSceneAdapter.State.CLOSED
+ fromScene == Shade || toScene == Shade -> Unsquishing(squishiness)
+ fromScene == QuickSettingsSceneKey || toScene == QuickSettingsSceneKey -> {
+ QSSceneAdapter.State.QS
+ }
else ->
error(
"Bad transition for QuickSettings: fromScene=$fromScene," +
@@ -90,14 +96,24 @@
/**
* This composable will show QuickSettingsContent in the correct state (as determined by its
* [SceneScope]).
+ *
+ * If adding to scenes not in:
+ * * QuickSettingsScene
+ * * ShadeScene
+ *
+ * amend:
+ * * [stateForQuickSettingsContent],
+ * * [QuickSettings.SCENES],
+ * * this doc.
*/
@Composable
fun SceneScope.QuickSettings(
qsSceneAdapter: QSSceneAdapter,
heightProvider: () -> Int,
modifier: Modifier = Modifier,
+ squishiness: Float = QuickSettings.SharedValues.SquishinessValues.Default,
) {
- val contentState = stateForQuickSettingsContent()
+ val contentState = stateForQuickSettingsContent(squishiness)
MovableElement(
key = QuickSettings.Elements.Content,
@@ -136,7 +152,7 @@
modifier.fillMaxWidth().thenIf(isCustomizing) { Modifier.fillMaxHeight() }
) {
AndroidView(
- modifier = Modifier.fillMaxWidth().background(colorAttr(R.attr.underSurface)),
+ modifier = Modifier.fillMaxWidth(),
factory = { _ ->
qsSceneAdapter.setState(state)
view
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
index d36345a3..66cef86 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
@@ -54,6 +54,7 @@
import androidx.compose.ui.unit.dp
import com.android.compose.animation.scene.SceneScope
import com.android.compose.animation.scene.TransitionState
+import com.android.compose.animation.scene.animateSceneFloatAsState
import com.android.compose.windowsizeclass.LocalWindowSizeClass
import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.compose.modifiers.sysuiResTag
@@ -128,6 +129,7 @@
remember(lifecycleOwner, viewModel) {
viewModel.getFooterActionsViewModel(lifecycleOwner)
}
+ animateSceneFloatAsState(value = 1f, key = QuickSettings.SharedValues.TilesSquishiness)
// ############## SCROLLING ################
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt
index f90f29d..9ca751e 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt
@@ -19,9 +19,12 @@
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import com.android.compose.animation.scene.SceneScope
+import com.android.compose.animation.scene.animateSceneFloatAsState
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.qs.ui.composable.QuickSettings
import com.android.systemui.scene.shared.model.Direction
import com.android.systemui.scene.shared.model.Edge
import com.android.systemui.scene.shared.model.SceneKey
@@ -63,6 +66,10 @@
override fun SceneScope.Content(
modifier: Modifier,
) {
+ animateSceneFloatAsState(
+ value = QuickSettings.SharedValues.SquishinessValues.GoneSceneStarting,
+ key = QuickSettings.SharedValues.TilesSquishiness,
+ )
Spacer(modifier.fillMaxSize())
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToShadeTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToShadeTransition.kt
index e71f996..48ab68a 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToShadeTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToShadeTransition.kt
@@ -1,11 +1,11 @@
package com.android.systemui.scene.ui.composable.transitions
import androidx.compose.animation.core.tween
-import com.android.compose.animation.scene.Edge
import com.android.compose.animation.scene.TransitionBuilder
import com.android.systemui.notifications.ui.composable.Notifications
import com.android.systemui.qs.ui.composable.QuickSettings
import com.android.systemui.shade.ui.composable.Shade
+import com.android.systemui.shade.ui.composable.ShadeHeader
import kotlin.time.Duration.Companion.milliseconds
fun TransitionBuilder.lockscreenToShadeTransition(
@@ -13,15 +13,12 @@
) {
spec = tween(durationMillis = DefaultDuration.times(durationScale).inWholeMilliseconds.toInt())
- fractionRange(end = 0.5f) {
- fade(Shade.Elements.BackgroundScrim)
- translate(
- QuickSettings.Elements.CollapsedGrid,
- Edge.Top,
- startsOutsideLayoutBounds = false,
- )
+ fractionRange(end = 0.5f) { fade(Shade.Elements.BackgroundScrim) }
+ translate(QuickSettings.Elements.Content, y = -ShadeHeader.Dimensions.CollapsedHeight * .66f)
+ fractionRange(start = 0.5f) {
+ fade(QuickSettings.Elements.Content)
+ fade(Notifications.Elements.NotificationScrim)
}
- fractionRange(start = 0.5f) { fade(Notifications.Elements.NotificationScrim) }
}
private val DefaultDuration = 500.milliseconds
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
index 25df3e4..8c6bf61 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
@@ -28,6 +28,7 @@
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
@@ -40,6 +41,7 @@
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.LowestZIndexScenePicker
import com.android.compose.animation.scene.SceneScope
+import com.android.compose.animation.scene.animateSceneFloatAsState
import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
@@ -73,7 +75,6 @@
object Shade {
object Elements {
- val QuickSettings = ElementKey("ShadeQuickSettings")
val MediaCarousel = ElementKey("ShadeMediaCarousel")
val BackgroundScrim =
ElementKey("ShadeBackgroundScrim", scenePicker = LowestZIndexScenePicker)
@@ -160,6 +161,8 @@
val density = LocalDensity.current
val layoutWidth = remember { mutableStateOf(0) }
val maxNotifScrimTop = remember { mutableStateOf(0f) }
+ val tileSquishiness by
+ animateSceneFloatAsState(value = 1f, key = QuickSettings.SharedValues.TilesSquishiness)
Box(
modifier =
@@ -190,7 +193,11 @@
)
QuickSettings(
viewModel.qsSceneAdapter,
- { viewModel.qsSceneAdapter.qqsHeight },
+ {
+ (viewModel.qsSceneAdapter.qqsHeight * tileSquishiness)
+ .roundToInt()
+ },
+ squishiness = tileSquishiness,
)
if (viewModel.isMediaVisible()) {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt
index f8573cc2..3c0ab24 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt
@@ -259,6 +259,37 @@
}
@Test
+ fun state_unsquishing() =
+ testScope.runTest {
+ val qsImpl by collectLastValue(underTest.qsImpl)
+ val squishiness = 0.342f
+
+ underTest.inflate(context)
+ runCurrent()
+ clearInvocations(qsImpl!!)
+
+ underTest.setState(QSSceneAdapter.State.Unsquishing(squishiness))
+ with(qsImpl!!) {
+ verify(this).setQsVisible(true)
+ verify(this)
+ .setQsExpansion(
+ /* expansion= */ 0f,
+ /* panelExpansionFraction= */ 1f,
+ /* proposedTranslation= */ 0f,
+ /* squishinessFraction= */ squishiness,
+ )
+ verify(this).setListening(true)
+ verify(this).setExpanded(true)
+ verify(this)
+ .setTransitionToFullShadeProgress(
+ /* isTransitioningToFullShade= */ false,
+ /* qsTransitionFraction= */ 1f,
+ /* qsSquishinessFraction = */ squishiness,
+ )
+ }
+ }
+
+ @Test
fun customizing_QS() =
testScope.runTest {
val customizing by collectLastValue(underTest.isCustomizing)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterTest.kt
index d1bc686..e281383 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterTest.kt
@@ -29,6 +29,12 @@
@EnabledOnRavenwood
@RunWith(AndroidJUnit4::class)
class QSSceneAdapterTest : SysuiTestCase() {
+
+ @Test
+ fun expanding_squishiness1() {
+ assertThat(QSSceneAdapter.State.Expanding(0.3f).squishiness).isEqualTo(1f)
+ }
+
@Test
fun expandingSpecialValues() {
assertThat(QSSceneAdapter.State.QQS).isEqualTo(QSSceneAdapter.State.Expanding(0f))
@@ -41,4 +47,11 @@
assertThat(Collapsing(collapsingProgress))
.isEqualTo(QSSceneAdapter.State.Expanding(1 - collapsingProgress))
}
+
+ @Test
+ fun unsquishing_expansionSameAsQQS() {
+ val squishiness = 0.6f
+ assertThat(QSSceneAdapter.State.Unsquishing(squishiness).expansion)
+ .isEqualTo(QSSceneAdapter.State.QQS.expansion)
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagDependenciesBase.kt b/packages/SystemUI/src/com/android/systemui/flags/FlagDependenciesBase.kt
index efbd59f..2fe1dd4 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagDependenciesBase.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/FlagDependenciesBase.kt
@@ -19,6 +19,7 @@
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
+import android.app.NotificationManager.IMPORTANCE_DEFAULT
import android.content.Context
import android.util.Log
import com.android.systemui.CoreStartable
@@ -150,7 +151,7 @@
val title = "Invalid flag dependencies: ${unmet.size}"
val details = unmet.joinToString("\n") { it.shortUnmetString() }
Log.e("FlagDependencies", "$title:\n$details")
- val channel = NotificationChannel("FLAGS", "Flags", NotificationManager.IMPORTANCE_DEFAULT)
+ val channel = NotificationChannel(CHANNEL_ID, CHANNEL_NAME, IMPORTANCE_DEFAULT)
val notification =
Notification.Builder(context, channel.id)
.setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
@@ -160,7 +161,18 @@
.setVisibility(Notification.VISIBILITY_PUBLIC)
.build()
notifManager.createNotificationChannel(channel)
- notifManager.notify("flags", 0, notification)
+ notifManager.notify(NOTIF_TAG, NOTIF_ID, notification)
+ }
+
+ override fun onCollected(all: List<FlagDependenciesBase.Dependency>) {
+ notifManager.cancel(NOTIF_TAG, NOTIF_ID)
+ }
+
+ companion object {
+ private const val CHANNEL_ID = "FLAGS"
+ private const val CHANNEL_NAME = "Flags"
+ private const val NOTIF_TAG = "FlagDependenciesNotifier"
+ private const val NOTIF_ID = 0
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java
index 8ff0e36..e5d970d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java
@@ -207,6 +207,9 @@
mFooterActionsViewBinder = footerActionsViewBinder;
mListeningAndVisibilityLifecycleOwner = new ListeningAndVisibilityLifecycleOwner();
mSceneContainerFlags = sceneContainerFlags;
+ if (mSceneContainerFlags.isEnabled()) {
+ mStatusBarState = StatusBarState.SHADE;
+ }
}
/**
@@ -506,10 +509,20 @@
}
}
- private boolean isKeyguardState() {
- // We want the freshest state here since otherwise we'll have some weirdness if earlier
- // listeners trigger updates
- return mStatusBarStateController.getCurrentOrUpcomingState() == KEYGUARD;
+ @VisibleForTesting
+ boolean isKeyguardState() {
+ if (mSceneContainerFlags.isEnabled()) {
+ return false;
+ } else {
+ // We want the freshest state here since otherwise we'll have some weirdness if earlier
+ // listeners trigger updates
+ return mStatusBarStateController.getCurrentOrUpcomingState() == KEYGUARD;
+ }
+ }
+
+ @VisibleForTesting
+ int getStatusBarState() {
+ return mStatusBarState;
}
private void updateShowCollapsedOnKeyguard() {
@@ -562,15 +575,17 @@
}
private void setKeyguardShowing(boolean keyguardShowing) {
- if (DEBUG) Log.d(TAG, "setKeyguardShowing " + keyguardShowing);
- mLastQSExpansion = -1;
+ if (!mSceneContainerFlags.isEnabled()) {
+ if (DEBUG) Log.d(TAG, "setKeyguardShowing " + keyguardShowing);
+ mLastQSExpansion = -1;
- if (mQSAnimator != null) {
- mQSAnimator.setOnKeyguard(keyguardShowing);
+ if (mQSAnimator != null) {
+ mQSAnimator.setOnKeyguard(keyguardShowing);
+ }
+
+ mFooter.setKeyguardShowing(keyguardShowing);
+ updateQsState();
}
-
- mFooter.setKeyguardShowing(keyguardShowing);
- updateQsState();
}
@Override
@@ -971,7 +986,7 @@
@Override
public void onStateChanged(int newState) {
- if (newState == mStatusBarState) {
+ if (mSceneContainerFlags.isEnabled() || newState == mStatusBarState) {
return;
}
mStatusBarState = newState;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt
index 6e4f72d..72a5c46 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt
@@ -84,18 +84,36 @@
*/
val qsHeight: Int
- sealed class State(
- val isVisible: Boolean,
- val expansion: Float,
- ) {
- data object CLOSED : State(false, 0f)
- data class Expanding(val progress: Float) : State(true, progress)
+ sealed interface State {
+
+ val isVisible: Boolean
+ val expansion: Float
+ val squishiness: Float
+
+ data object CLOSED : State {
+ override val isVisible = false
+ override val expansion = 0f
+ override val squishiness = 1f
+ }
+
+ /** State for expanding between QQS and QS */
+ data class Expanding(override val expansion: Float) : State {
+ override val isVisible = true
+ override val squishiness = 1f
+ }
+
+ /** State for appearing QQS from Lockscreen or Gone */
+ data class Unsquishing(override val squishiness: Float) : State {
+ override val isVisible = true
+ override val expansion = 0f
+ }
companion object {
// These are special cases of the expansion.
val QQS = Expanding(0f)
val QS = Expanding(1f)
+ /** Collapsing from QS to QQS. [progress] is 0f in QS and 1f in QQS. */
fun Collapsing(progress: Float) = Expanding(1f - progress)
}
}
@@ -232,7 +250,7 @@
setQsVisible(state.isVisible)
setExpanded(state.isVisible)
setListening(state.isVisible)
- setQsExpansion(state.expansion, 1f, 0f, 1f)
- setTransitionToFullShadeProgress(false, 1f, 1f)
+ setQsExpansion(state.expansion, 1f, 0f, state.squishiness)
+ setTransitionToFullShadeProgress(false, 1f, state.squishiness)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt
index 4ccb18f..8408c51 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt
@@ -29,6 +29,7 @@
import com.android.systemui.flags.FlagToken
import com.android.systemui.flags.Flags.SCENE_CONTAINER_ENABLED
import com.android.systemui.flags.RefactorFlagUtils
+import com.android.systemui.keyguard.shared.ComposeLockscreen
import com.android.systemui.media.controls.util.MediaInSceneContainerFlag
import dagger.Module
import dagger.Provides
@@ -45,6 +46,7 @@
sceneContainer() && // mainAconfigFlag
keyguardBottomAreaRefactor() &&
migrateClocksToBlueprint() &&
+ ComposeLockscreen.isEnabled &&
MediaInSceneContainerFlag.isEnabled &&
// NOTE: Changes should also be made in getSecondaryFlags and @EnableSceneContainer
ComposeFacade.isComposeAvailable()
@@ -65,6 +67,7 @@
sequenceOf(
FlagToken(FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR, keyguardBottomAreaRefactor()),
FlagToken(FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT, migrateClocksToBlueprint()),
+ ComposeLockscreen.token,
MediaInSceneContainerFlag.token,
// NOTE: Changes should also be made in isEnabled and @EnableSceneContainer
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java
index 563a3fe..8e72d06 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java
@@ -20,6 +20,7 @@
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import static com.android.systemui.statusbar.StatusBarState.SHADE;
+import static com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED;
import static com.google.common.truth.Truth.assertThat;
@@ -511,6 +512,28 @@
);
}
+ @Test
+ public void testSceneContainerFlagsEnabled_statusBarStateIsShade() {
+ when(mSceneContainerFlags.isEnabled()).thenReturn(true);
+
+ mUnderTest.onStateChanged(KEYGUARD);
+ assertThat(mUnderTest.getStatusBarState()).isEqualTo(SHADE);
+
+ mUnderTest.onStateChanged(SHADE_LOCKED);
+ assertThat(mUnderTest.getStatusBarState()).isEqualTo(SHADE);
+ }
+
+ @Test
+ public void testSceneContainerFlagsEnabled_isKeyguardState_alwaysFalse() {
+ when(mSceneContainerFlags.isEnabled()).thenReturn(true);
+
+ mUnderTest.onStateChanged(KEYGUARD);
+ assertThat(mUnderTest.isKeyguardState()).isFalse();
+
+ when(mStatusBarStateController.getCurrentOrUpcomingState()).thenReturn(KEYGUARD);
+ assertThat(mUnderTest.isKeyguardState()).isFalse();
+ }
+
private QSImpl instantiate() {
setupQsComponent();
setUpViews();
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt
index 43897c9..cceb3ff 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt
@@ -17,9 +17,10 @@
package com.android.systemui.flags
import android.platform.test.annotations.EnableFlags
+import com.android.systemui.Flags.FLAG_COMPOSE_LOCKSCREEN
import com.android.systemui.Flags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR
-import com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT
import com.android.systemui.Flags.FLAG_MEDIA_IN_SCENE_CONTAINER
+import com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT
import com.android.systemui.Flags.FLAG_SCENE_CONTAINER
/**
@@ -30,6 +31,7 @@
FLAG_SCENE_CONTAINER,
FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR,
FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT,
+ FLAG_COMPOSE_LOCKSCREEN,
FLAG_MEDIA_IN_SCENE_CONTAINER,
)
@Retention(AnnotationRetention.RUNTIME)
diff --git a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java
index 0bcb26d..252ea4b 100644
--- a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java
+++ b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java
@@ -222,7 +222,7 @@
}
final int uid = mPackageManagerInternal.getPackageUid(appPackageName, 0, userId);
- FrameworkStatsLog.write(FrameworkStatsLog.GRAMMATICAL_INFLECTION_CHANGED,
+ FrameworkStatsLog.write(FrameworkStatsLog.APPLICATION_GRAMMATICAL_INFLECTION_CHANGED,
FrameworkStatsLog.APPLICATION_GRAMMATICAL_INFLECTION_CHANGED__SOURCE_ID__OTHERS,
uid,
gender != GRAMMATICAL_GENDER_NOT_SPECIFIED,
@@ -266,8 +266,14 @@
try {
Configuration config = new Configuration();
+ int preValue = config.getGrammaticalGender();
config.setGrammaticalGender(grammaticalGender);
ActivityTaskManager.getService().updateConfiguration(config);
+ FrameworkStatsLog.write(FrameworkStatsLog.SYSTEM_GRAMMATICAL_INFLECTION_CHANGED,
+ FrameworkStatsLog.SYSTEM_GRAMMATICAL_INFLECTION_CHANGED__SOURCE_ID__SYSTEM,
+ userId,
+ grammaticalGender != GRAMMATICAL_GENDER_NOT_SPECIFIED,
+ preValue != GRAMMATICAL_GENDER_NOT_SPECIFIED);
} catch (RemoteException e) {
Log.w(TAG, "Can not update configuration", e);
}