Merge "Camera: Enable request processor during 'onCaptureSessionStart'" into udc-qpr-dev
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index 03d7450..1ed06b4 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -82,6 +82,7 @@
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_SCROLL_FLING;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLASHSCREEN_AVD;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLASHSCREEN_EXIT_ANIM;
+import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_DOUBLE_TAP_DIVIDER;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_ENTER;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_EXIT;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_RESIZE;
@@ -272,7 +273,9 @@
public static final int CUJ_IME_INSETS_SHOW_ANIMATION = 80;
public static final int CUJ_IME_INSETS_HIDE_ANIMATION = 81;
- private static final int LAST_CUJ = CUJ_IME_INSETS_HIDE_ANIMATION;
+ public static final int CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER = 82;
+
+ private static final int LAST_CUJ = CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER;
private static final int NO_STATSD_LOGGING = -1;
// Used to convert CujType to InteractionType enum value for statsd logging.
@@ -364,6 +367,7 @@
CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_EXPAND_FROM_STATUS_BAR] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_EXPAND_FROM_STATUS_BAR;
CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_IME_INSETS_SHOW_ANIMATION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_SHOW_ANIMATION;
CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_IME_INSETS_HIDE_ANIMATION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_HIDE_ANIMATION;
+ CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_DOUBLE_TAP_DIVIDER;
}
private static class InstanceHolder {
@@ -466,6 +470,7 @@
CUJ_SHADE_EXPAND_FROM_STATUS_BAR,
CUJ_IME_INSETS_SHOW_ANIMATION,
CUJ_IME_INSETS_HIDE_ANIMATION,
+ CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER,
})
@Retention(RetentionPolicy.SOURCE)
public @interface CujType {
@@ -1083,6 +1088,8 @@
return "IME_INSETS_SHOW_ANIMATION";
case CUJ_IME_INSETS_HIDE_ANIMATION:
return "IME_INSETS_HIDE_ANIMATION";
+ case CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER:
+ return "SPLIT_SCREEN_DOUBLE_TAP_DIVIDER";
}
return "UNKNOWN";
}
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 31d6f16..c7226f6 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -5342,7 +5342,7 @@
fingerprint and face. If a dual-modality device only enrolled a single biometric and
experiences high FRR (above threshold), system notification will be sent to encourage user
to enroll the other eligible biometric. -->
- <fraction name="config_biometricNotificationFrrThreshold">30%</fraction>
+ <fraction name="config_biometricNotificationFrrThreshold">25%</fraction>
<!-- The component name for the default profile supervisor, which can be set as a profile owner
even after user setup is complete. The defined component should be used for supervision purposes
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
index 1e6e503..0112e32 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
@@ -518,8 +518,11 @@
return WindowAreaComponent.STATUS_UNSUPPORTED;
}
- if (mCurrentDeviceState == mConcurrentDisplayState
- || !ArrayUtils.contains(mCurrentSupportedDeviceStates, mConcurrentDisplayState)
+ if (mCurrentDeviceState == mConcurrentDisplayState) {
+ return WindowAreaComponent.STATUS_ACTIVE;
+ }
+
+ if (!ArrayUtils.contains(mCurrentSupportedDeviceStates, mConcurrentDisplayState)
|| isDeviceFolded()) {
return WindowAreaComponent.STATUS_UNAVAILABLE;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 5d7e532..755dba0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -24,6 +24,7 @@
import static android.view.WindowManager.DOCKED_RIGHT;
import static android.view.WindowManager.DOCKED_TOP;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_SPLIT_SCREEN_RESIZE;
import static com.android.wm.shell.common.split.DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_END;
import static com.android.wm.shell.common.split.DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_START;
@@ -661,10 +662,22 @@
set.setDuration(FLING_SWITCH_DURATION);
set.addListener(new AnimatorListenerAdapter() {
@Override
+ public void onAnimationStart(Animator animation) {
+ InteractionJankMonitorUtils.beginTracing(CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER,
+ mContext, getDividerLeash(), null /*tag*/);
+ }
+
+ @Override
public void onAnimationEnd(Animator animation) {
mDividePosition = dividerPos;
updateBounds(mDividePosition);
finishCallback.accept(insets);
+ InteractionJankMonitorUtils.endTracing(CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ InteractionJankMonitorUtils.cancelTracing(CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER);
}
});
set.start();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index f60f8db..765edd7 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -1948,6 +1948,9 @@
cacheName = Settings.System.ALARM_ALERT_CACHE;
}
if (cacheName != null) {
+ if (!isValidAudioUri(name, value)) {
+ return false;
+ }
final File cacheFile = new File(
getRingtoneCacheDir(owningUserId), cacheName);
cacheFile.delete();
@@ -1980,6 +1983,34 @@
}
}
+ private boolean isValidAudioUri(String name, String uri) {
+ if (uri != null) {
+ Uri audioUri = Uri.parse(uri);
+ if (Settings.AUTHORITY.equals(
+ ContentProvider.getAuthorityWithoutUserId(audioUri.getAuthority()))) {
+ // Don't accept setting the default uri to self-referential URIs like
+ // Settings.System.DEFAULT_RINGTONE_URI, which is an alias to the value of this
+ // setting.
+ return false;
+ }
+ final String mimeType = getContext().getContentResolver().getType(audioUri);
+ if (mimeType == null) {
+ Slog.e(LOG_TAG,
+ "mutateSystemSetting for setting: " + name + " URI: " + audioUri
+ + " ignored: failure to find mimeType (no access from this context?)");
+ return false;
+ }
+ if (!(mimeType.startsWith("audio/") || mimeType.equals("application/ogg")
+ || mimeType.equals("application/x-flac"))) {
+ Slog.e(LOG_TAG,
+ "mutateSystemSetting for setting: " + name + " URI: " + audioUri
+ + " ignored: associated mimeType: " + mimeType + " is not an audio type");
+ return false;
+ }
+ }
+ return true;
+ }
+
private boolean hasWriteSecureSettingsPermission() {
// Write secure settings is a more protected permission. If caller has it we are good.
return getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DemotingTestWithoutBugDetector.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DemotingTestWithoutBugDetector.kt
index 09762b0..2fc56c9 100644
--- a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DemotingTestWithoutBugDetector.kt
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DemotingTestWithoutBugDetector.kt
@@ -43,7 +43,9 @@
if (node.qualifiedName in DEMOTING_ANNOTATION_BUG_ID) {
if (!containsBugId(node)) {
val location = context.getLocation(node)
- val message = "Please attach a bug id to track demoted test"
+ val message =
+ """Please attach a bug id to track demoted test, """ +
+ """e.g. @FlakyTest(bugId = 123)"""
context.report(ISSUE, node, location, message)
}
}
@@ -51,7 +53,8 @@
if (node.qualifiedName == DEMOTING_ANNOTATION_IGNORE) {
if (!containsBugString(node)) {
val location = context.getLocation(node)
- val message = "Please attach a bug (e.g. b/123) to track demoted test"
+ val message =
+ """Please attach a bug to track demoted test, e.g. @Ignore("b/123")"""
context.report(ISSUE, node, location, message)
}
}
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DemotingTestWithoutBugDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DemotingTestWithoutBugDetectorTest.kt
index a1e6f92..ee6e0ce 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DemotingTestWithoutBugDetectorTest.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DemotingTestWithoutBugDetectorTest.kt
@@ -98,7 +98,7 @@
.run()
.expect(
"""
- src/test/pkg/TestClass.java:4: Warning: Please attach a bug id to track demoted test [DemotingTestWithoutBug]
+ src/test/pkg/TestClass.java:4: Warning: Please attach a bug id to track demoted test, e.g. @FlakyTest(bugId = 123) [DemotingTestWithoutBug]
@FlakyTest
~~~~~~~~~~
0 errors, 1 warnings
@@ -126,7 +126,7 @@
.run()
.expect(
"""
- src/test/pkg/TestClass.java:4: Warning: Please attach a bug id to track demoted test [DemotingTestWithoutBug]
+ src/test/pkg/TestClass.java:4: Warning: Please attach a bug id to track demoted test, e.g. @FlakyTest(bugId = 123) [DemotingTestWithoutBug]
@FlakyTest
~~~~~~~~~~
0 errors, 1 warnings
@@ -181,7 +181,7 @@
.run()
.expect(
"""
- src/test/pkg/TestClass.java:4: Warning: Please attach a bug id to track demoted test [DemotingTestWithoutBug]
+ src/test/pkg/TestClass.java:4: Warning: Please attach a bug id to track demoted test, e.g. @FlakyTest(bugId = 123) [DemotingTestWithoutBug]
@Platinum(devices = "foo,bar")
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0 errors, 1 warnings
@@ -236,7 +236,7 @@
.run()
.expect(
"""
- src/test/pkg/TestClass.java:4: Warning: Please attach a bug (e.g. b/123) to track demoted test [DemotingTestWithoutBug]
+ src/test/pkg/TestClass.java:4: Warning: Please attach a bug to track demoted test, e.g. @Ignore("b/123") [DemotingTestWithoutBug]
@Ignore
~~~~~~~
0 errors, 1 warnings
@@ -264,7 +264,7 @@
.run()
.expect(
"""
- src/test/pkg/TestClass.java:4: Warning: Please attach a bug (e.g. b/123) to track demoted test [DemotingTestWithoutBug]
+ src/test/pkg/TestClass.java:4: Warning: Please attach a bug to track demoted test, e.g. @Ignore("b/123") [DemotingTestWithoutBug]
@Ignore("Not ready")
~~~~~~~~~~~~~~~~~~~~
0 errors, 1 warnings
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
index 33e453c..823bd2d 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
@@ -23,6 +23,7 @@
import android.view.SurfaceControl;
import com.android.systemui.shared.recents.ISystemUiProxy;
+// Next ID: 29
oneway interface IOverviewProxy {
void onActiveNavBarRegionChanges(in Region activeRegion) = 11;
@@ -56,6 +57,13 @@
void onAssistantVisibilityChanged(float visibility) = 14;
/**
+ * Sent when the assistant has been invoked with the given type (defined in AssistManager) and
+ * should be shown. This method should be used if SystemUiProxy#setAssistantOverridesRequested
+ * was previously called including this invocation type.
+ */
+ void onAssistantOverrideInvoked(int invocationType) = 28;
+
+ /**
* Sent when some system ui state changes.
*/
void onSystemUiStateChanged(int stateFlags) = 16;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index 4b31498..dc34ef7 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -67,6 +67,15 @@
oneway void startAssistant(in Bundle bundle) = 13;
/**
+ * Indicates that the given Assist invocation types should be handled by Launcher via
+ * OverviewProxy#onAssistantOverrideInvoked and should not be invoked by SystemUI.
+ *
+ * @param invocationTypes The invocation types that will henceforth be handled via
+ * OverviewProxy (Launcher); other invocation types should be handled by SysUI.
+ */
+ oneway void setAssistantOverridesRequested(in int[] invocationTypes) = 53;
+
+ /**
* Notifies that the accessibility button in the system's navigation area has been clicked
*/
oneway void notifyAccessibilityButtonClicked(int displayId) = 15;
@@ -135,5 +144,5 @@
*/
oneway void onStatusBarTrackpadEvent(in MotionEvent event) = 52;
- // Next id = 53
+ // Next id = 54
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 590056f..165bb6c 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -44,6 +44,7 @@
import dagger.Lazy;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import javax.inject.Inject;
@@ -136,6 +137,7 @@
protected final Context mContext;
private final AssistDisclosure mAssistDisclosure;
private final PhoneStateMonitor mPhoneStateMonitor;
+ private final OverviewProxyService mOverviewProxyService;
private final UiController mUiController;
protected final Lazy<SysUiState> mSysUiState;
protected final AssistLogger mAssistLogger;
@@ -164,6 +166,9 @@
private final CommandQueue mCommandQueue;
protected final AssistUtils mAssistUtils;
+ // Invocation types that should be sent over OverviewProxy instead of handled here.
+ private int[] mAssistOverrideInvocationTypes;
+
@Inject
public AssistManager(
DeviceProvisionedController controller,
@@ -184,6 +189,7 @@
mCommandQueue = commandQueue;
mAssistUtils = assistUtils;
mAssistDisclosure = new AssistDisclosure(context, uiHandler);
+ mOverviewProxyService = overviewProxyService;
mPhoneStateMonitor = phoneStateMonitor;
mAssistLogger = assistLogger;
mUserTracker = userTracker;
@@ -197,7 +203,7 @@
mSysUiState = sysUiState;
- overviewProxyService.addCallback(new OverviewProxyService.OverviewProxyListener() {
+ mOverviewProxyService.addCallback(new OverviewProxyService.OverviewProxyListener() {
@Override
public void onAssistantProgress(float progress) {
// Progress goes from 0 to 1 to indicate how close the assist gesture is to
@@ -260,6 +266,20 @@
}
public void startAssist(Bundle args) {
+ if (shouldOverrideAssist(args)) {
+ try {
+ if (mOverviewProxyService.getProxy() == null) {
+ Log.w(TAG, "No OverviewProxyService to invoke assistant override");
+ return;
+ }
+ mOverviewProxyService.getProxy().onAssistantOverrideInvoked(
+ args.getInt(INVOCATION_TYPE_KEY));
+ } catch (RemoteException e) {
+ Log.w(TAG, "Unable to invoke assistant via OverviewProxyService override", e);
+ }
+ return;
+ }
+
final ComponentName assistComponent = getAssistInfo();
if (assistComponent == null) {
return;
@@ -283,6 +303,24 @@
startAssistInternal(args, assistComponent, isService);
}
+ private boolean shouldOverrideAssist(Bundle args) {
+ if (args == null || !args.containsKey(INVOCATION_TYPE_KEY)) {
+ return false;
+ }
+
+ int invocationType = args.getInt(INVOCATION_TYPE_KEY);
+ return mAssistOverrideInvocationTypes != null && Arrays.stream(
+ mAssistOverrideInvocationTypes).anyMatch(override -> override == invocationType);
+ }
+
+ /**
+ * @param invocationTypes The invocation types that will henceforth be handled via
+ * OverviewProxy (Launcher); other invocation types should be handled by this class.
+ */
+ public void setAssistantOverridesRequested(int[] invocationTypes) {
+ mAssistOverrideInvocationTypes = invocationTypes;
+ }
+
/** Called when the user is performing an assistant invocation action (e.g. Active Edge) */
public void onInvocationProgress(int type, float progress) {
mUiController.onInvocationProgress(type, progress);
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
index 8225c47..c6f73ef 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
@@ -453,6 +453,11 @@
}
@Override
+ public void setAssistantOverridesRequested(int[] invocationTypes) {
+ mAssistManagerLazy.get().setAssistantOverridesRequested(invocationTypes);
+ }
+
+ @Override
public void onNavigationModeChanged(int mode) {
mNavBarMode = mode;
updateAssistantAvailability();
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index ae0ab84..555269d 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -394,6 +394,11 @@
}
@Override
+ public void setAssistantOverridesRequested(int[] invocationTypes) {
+ mAssistManagerLazy.get().setAssistantOverridesRequested(invocationTypes);
+ }
+
+ @Override
public void onHomeRotationEnabled(boolean enabled) {
mView.getRotationButtonController().setHomeRotationEnabled(enabled);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 1e82d44..3a64a6a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -326,6 +326,12 @@
}
@Override
+ public void setAssistantOverridesRequested(int[] invocationTypes) {
+ verifyCallerAndClearCallingIdentityPostMain("setAssistantOverridesRequested", () ->
+ notifyAssistantOverrideRequested(invocationTypes));
+ }
+
+ @Override
public void notifyAccessibilityButtonClicked(int displayId) {
verifyCallerAndClearCallingIdentity("notifyAccessibilityButtonClicked", () ->
AccessibilityManager.getInstance(mContext)
@@ -908,6 +914,12 @@
}
}
+ private void notifyAssistantOverrideRequested(int[] invocationTypes) {
+ for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
+ mConnectionCallbacks.get(i).setAssistantOverridesRequested(invocationTypes);
+ }
+ }
+
public void notifyAssistantVisibilityChanged(float visibility) {
try {
if (mOverviewProxy != null) {
@@ -1051,6 +1063,7 @@
default void onAssistantProgress(@FloatRange(from = 0.0, to = 1.0) float progress) {}
default void onAssistantGestureCompletion(float velocity) {}
default void startAssistant(Bundle bundle) {}
+ default void setAssistantOverridesRequested(int[] invocationTypes) {}
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
index c1b905a..91547a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
@@ -144,13 +144,24 @@
}
}
- private fun removeHun(animate: Boolean) {
- if (!headsUpManager.isAlerting(notificationKey)) {
- return
- }
+ private val headsUpNotificationRow: ExpandableNotificationRow? get() {
+ val summaryEntry = notificationEntry.parent?.summary
+ return when {
+ headsUpManager.isAlerting(notificationKey) -> notification
+ summaryEntry == null -> null
+ headsUpManager.isAlerting(summaryEntry.key) -> summaryEntry.row
+ else -> null
+ }
+ }
+
+ private fun removeHun(animate: Boolean) {
+ val row = headsUpNotificationRow ?: return
+
+ // TODO: b/297247841 - Call on the row we're removing, which may differ from notification.
HeadsUpUtil.setNeedsHeadsUpDisappearAnimationAfterClick(notification, animate)
- headsUpManager.removeNotification(notificationKey, true /* releaseImmediately */, animate)
+
+ headsUpManager.removeNotification(row.entry.key, true /* releaseImmediately */, animate)
}
override fun onLaunchAnimationCancelled(newKeyguardOccludedState: Boolean?) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index b2d26d9..90e10a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -497,14 +497,14 @@
return stackHeight / stackEndHeight;
}
- private boolean hasNonDismissableNotifs(StackScrollAlgorithmState algorithmState) {
+ private boolean hasNonClearableNotifs(StackScrollAlgorithmState algorithmState) {
for (int i = 0; i < algorithmState.visibleChildren.size(); i++) {
View child = algorithmState.visibleChildren.get(i);
if (!(child instanceof ExpandableNotificationRow)) {
continue;
}
final ExpandableNotificationRow row = (ExpandableNotificationRow) child;
- if (!row.canViewBeDismissed()) {
+ if (!row.canViewBeCleared()) {
return true;
}
}
@@ -579,7 +579,7 @@
((FooterView.FooterViewState) viewState).hideContent =
isShelfShowing || noSpaceForFooter
|| (ambientState.isClearAllInProgress()
- && !hasNonDismissableNotifs(algorithmState));
+ && !hasNonClearableNotifs(algorithmState));
}
} else {
if (view instanceof EmptyShadeView) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt
index e66eb70..470d340 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt
@@ -1,5 +1,6 @@
package com.android.systemui.statusbar.notification
+import android.app.Notification.GROUP_ALERT_SUMMARY
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.testing.TestableLooper.RunWithLooper
@@ -7,20 +8,26 @@
import com.android.internal.jank.InteractionJankMonitor
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
import com.android.systemui.statusbar.notification.data.repository.NotificationExpansionRepository
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.NotificationTestHelper
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
import com.android.systemui.statusbar.policy.HeadsUpUtil
+import com.android.systemui.tests.R
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertTrue
import kotlinx.coroutines.test.TestScope
+import org.junit.Assert.assertNotSame
+import org.junit.Assert.assertSame
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.never
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import org.mockito.junit.MockitoJUnit
@@ -118,6 +125,35 @@
}
@Test
+ fun testAlertingSummaryHunRemovedOnNonAlertingChildLaunch() {
+ val GROUP_KEY = "test_group_key"
+
+ val summary = NotificationEntryBuilder().setGroup(mContext, GROUP_KEY).setId(0).apply {
+ modifyNotification(mContext).setSmallIcon(R.drawable.ic_person)
+ }.build()
+ assertNotSame(summary.key, notification.entry.key)
+
+ notificationTestHelper.createRow(summary)
+
+ GroupEntryBuilder().setKey(GROUP_KEY).setSummary(summary).addChild(notification.entry)
+ .build()
+ assertSame(summary, notification.entry.parent?.summary)
+
+ `when`(headsUpManager.isAlerting(notificationKey)).thenReturn(false)
+ `when`(headsUpManager.isAlerting(summary.key)).thenReturn(true)
+
+ assertNotSame(GROUP_ALERT_SUMMARY, summary.sbn.notification.groupAlertBehavior)
+ assertNotSame(GROUP_ALERT_SUMMARY, notification.entry.sbn.notification.groupAlertBehavior)
+
+ controller.onLaunchAnimationEnd(isExpandingFullyAbove = true)
+
+ verify(headsUpManager).removeNotification(
+ summary.key, true /* releaseImmediately */, false /* animate */)
+ verify(headsUpManager, never()).removeNotification(
+ notification.entry.key, true /* releaseImmediately */, false /* animate */)
+ }
+
+ @Test
fun testNotificationIsExpandingDuringAnimation() {
controller.onIntentStarted(willAnimate = true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index 1ab2b38..b7574a3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -269,6 +269,10 @@
return generateRow(notification, PKG, UID, USER_HANDLE, mDefaultInflationFlags);
}
+ public ExpandableNotificationRow createRow(NotificationEntry entry) throws Exception {
+ return generateRow(entry, mDefaultInflationFlags);
+ }
+
/**
* Create a row with the specified content views inflated in addition to the default.
*
@@ -538,18 +542,6 @@
@InflationFlag int extraInflationFlags,
int importance)
throws Exception {
- // NOTE: This flag is read when the ExpandableNotificationRow is inflated, so it needs to be
- // set, but we do not want to override an existing value that is needed by a specific test.
- mFeatureFlags.setDefault(Flags.IMPROVED_HUN_ANIMATIONS);
-
- LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
- mContext.LAYOUT_INFLATER_SERVICE);
- mRow = (ExpandableNotificationRow) inflater.inflate(
- R.layout.status_bar_notification_row,
- null /* root */,
- false /* attachToRoot */);
- ExpandableNotificationRow row = mRow;
-
final NotificationChannel channel =
new NotificationChannel(
notification.getChannelId(),
@@ -569,6 +561,25 @@
.setChannel(channel)
.build();
+ return generateRow(entry, extraInflationFlags);
+ }
+
+ private ExpandableNotificationRow generateRow(
+ NotificationEntry entry,
+ @InflationFlag int extraInflationFlags)
+ throws Exception {
+ // NOTE: This flag is read when the ExpandableNotificationRow is inflated, so it needs to be
+ // set, but we do not want to override an existing value that is needed by a specific test.
+ mFeatureFlags.setDefault(Flags.IMPROVED_HUN_ANIMATIONS);
+
+ LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
+ mContext.LAYOUT_INFLATER_SERVICE);
+ mRow = (ExpandableNotificationRow) inflater.inflate(
+ R.layout.status_bar_notification_row,
+ null /* root */,
+ false /* attachToRoot */);
+ ExpandableNotificationRow row = mRow;
+
entry.setRow(row);
mIconManager.createIcons(entry);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
index 987861d..42f7b52 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
@@ -14,6 +14,8 @@
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
+import com.android.systemui.statusbar.notification.row.FooterView
+import com.android.systemui.statusbar.notification.row.FooterView.FooterViewState
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Expect
@@ -47,6 +49,7 @@
private val emptyShadeView = EmptyShadeView(context, /* attrs= */ null).apply {
layout(/* l= */ 0, /* t= */ 0, /* r= */ 100, /* b= */ 100)
}
+ private val footerView = FooterView(context, /*attrs=*/null)
private val ambientState = AmbientState(
context,
dumpManager,
@@ -325,6 +328,57 @@
}
@Test
+ fun resetViewStates_noSpaceForFooter_footerHidden() {
+ ambientState.isShadeExpanded = true
+ ambientState.stackEndHeight = 0f // no space for the footer in the stack
+ hostView.addView(footerView)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, 0)
+
+ assertThat((footerView.viewState as FooterViewState).hideContent).isTrue()
+ }
+
+ @Test
+ fun resetViewStates_clearAllInProgress_hasNonClearableRow_footerVisible() {
+ whenever(notificationRow.canViewBeCleared()).thenReturn(false)
+ ambientState.isClearAllInProgress = true
+ ambientState.isShadeExpanded = true
+ ambientState.stackEndHeight = 1000f // plenty space for the footer in the stack
+ hostView.addView(footerView)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, 0)
+
+ assertThat(footerView.viewState.hidden).isFalse()
+ assertThat((footerView.viewState as FooterViewState).hideContent).isFalse()
+ }
+
+ @Test
+ fun resetViewStates_clearAllInProgress_allRowsClearable_footerHidden() {
+ whenever(notificationRow.canViewBeCleared()).thenReturn(true)
+ ambientState.isClearAllInProgress = true
+ ambientState.isShadeExpanded = true
+ ambientState.stackEndHeight = 1000f // plenty space for the footer in the stack
+ hostView.addView(footerView)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, 0)
+
+ assertThat((footerView.viewState as FooterViewState).hideContent).isTrue()
+ }
+
+ @Test
+ fun resetViewStates_clearAllInProgress_allRowsRemoved_emptyShade_footerHidden() {
+ ambientState.isClearAllInProgress = true
+ ambientState.isShadeExpanded = true
+ ambientState.stackEndHeight = 1000f // plenty space for the footer in the stack
+ hostView.removeAllViews() // remove all rows
+ hostView.addView(footerView)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, 0)
+
+ assertThat((footerView.viewState as FooterViewState).hideContent).isTrue()
+ }
+
+ @Test
fun getGapForLocation_onLockscreen_returnsSmallGap() {
val gap = stackScrollAlgorithm.getGapForLocation(
/* fractionToShade= */ 0f, /* onKeyguard= */ true)
diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java
index 496bdf4..0eb459f 100644
--- a/services/core/java/com/android/server/audio/SpatializerHelper.java
+++ b/services/core/java/com/android/server/audio/SpatializerHelper.java
@@ -541,7 +541,6 @@
}
loglogi("addCompatibleAudioDevice: dev=" + ada);
final AdiDeviceState deviceState = findDeviceStateForAudioDeviceAttributes(ada);
- initSAState(deviceState);
AdiDeviceState updatedDevice = null; // non-null on update.
if (deviceState != null) {
if (forceEnable && !deviceState.isSAEnabled()) {
diff --git a/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java b/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java
index 54b34de..3d1b162 100644
--- a/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java
+++ b/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java
@@ -45,12 +45,12 @@
private static final String TAG = "AuthenticationStatsCollector";
// The minimum number of attempts that will calculate the FRR and trigger the notification.
- private static final int MINIMUM_ATTEMPTS = 500;
+ private static final int MINIMUM_ATTEMPTS = 150;
// Upload the data every 50 attempts (average number of daily authentications).
private static final int AUTHENTICATION_UPLOAD_INTERVAL = 50;
// The maximum number of eligible biometric enrollment notification can be sent.
@VisibleForTesting
- static final int MAXIMUM_ENROLLMENT_NOTIFICATIONS = 2;
+ static final int MAXIMUM_ENROLLMENT_NOTIFICATIONS = 1;
@NonNull private final Context mContext;