diff options
99 files changed, 1076 insertions, 747 deletions
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 40069aa00106..526a213a6003 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -165,6 +165,16 @@ package android.hardware.usb { package android.media { + public class AudioDeviceVolumeManager { + method @FlaggedApi("android.media.audio.unify_absolute_volume_management") @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.BLUETOOTH_STACK}) public void setDeviceAbsoluteMultiVolumeBehavior(@NonNull android.media.AudioDeviceAttributes, @NonNull java.util.List<android.media.VolumeInfo>, @NonNull java.util.concurrent.Executor, @NonNull android.media.AudioDeviceVolumeManager.OnAudioDeviceVolumeChangedListener); + method @FlaggedApi("android.media.audio.unify_absolute_volume_management") @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.BLUETOOTH_STACK}) public void setDeviceAbsoluteVolumeBehavior(@NonNull android.media.AudioDeviceAttributes, @NonNull android.media.VolumeInfo, @NonNull java.util.concurrent.Executor, @NonNull android.media.AudioDeviceVolumeManager.OnAudioDeviceVolumeChangedListener); + } + + @FlaggedApi("android.media.audio.unify_absolute_volume_management") public static interface AudioDeviceVolumeManager.OnAudioDeviceVolumeChangedListener { + method public void onAudioDeviceVolumeAdjusted(@NonNull android.media.AudioDeviceAttributes, @NonNull android.media.VolumeInfo, int, int); + method public void onAudioDeviceVolumeChanged(@NonNull android.media.AudioDeviceAttributes, @NonNull android.media.VolumeInfo); + } + public class AudioManager { method public void adjustStreamVolumeForUid(int, int, int, @NonNull String, int, int, int); method public void adjustSuggestedStreamVolumeForUid(int, int, int, @NonNull String, int, int, int); diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 0903d2293d67..c4347f05f4a3 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -3080,6 +3080,21 @@ public final class SurfaceControl implements Parcelable { } /** + * Changes the default ApplyToken. + * + * ApplyToken is used to determine the order in which Transactions are applied. + * Transactions applied with the same ApplyToken will be applied in the order + * they were queued in SurfaceFlinger. Transactions are sent via binder so the + * caller should be aware of the order in which binder calls are executed in + * SurfaceFlinger. This along with the ApplyToken will determine the order + * in which Transactions are applied. Transactions with different apply tokens + * will be applied in arbitrary order regardless of when they were queued in + * SurfaceFlinger. + * + * Caller must keep track of the previous ApplyToken if they want to restore it. + * + * Note each buffer producer should have its own ApplyToken in order to ensure + * that Transactions are not delayed by Transactions from other buffer producers. * * @hide */ @@ -3088,6 +3103,7 @@ public final class SurfaceControl implements Parcelable { } /** + * Returns the default ApplyToken. * * @hide */ @@ -3096,8 +3112,10 @@ public final class SurfaceControl implements Parcelable { } /** - * Apply the transaction, clearing it's state, and making it usable + * Apply the transaction, clearing its state, and making it usable * as a new transaction. + * + * This method will also increment the transaction ID for debugging purposes. */ public void apply() { apply(/*sync*/ false); @@ -3116,7 +3134,7 @@ public final class SurfaceControl implements Parcelable { /** - * Clear the transaction object, without applying it. + * Clear the transaction object, without applying it. The transction ID is preserved. * * @hide */ @@ -3375,6 +3393,9 @@ public final class SurfaceControl implements Parcelable { * If two siblings share the same Z order the ordering is undefined. Surfaces * with a negative Z will be placed below the parent surface. * + * Calling setLayer after setRelativeLayer will reset the relative layer + * in the same transaction. + * * @param sc The SurfaceControl to set the Z order on * @param z The Z-order * @return This Transaction. @@ -3392,6 +3413,22 @@ public final class SurfaceControl implements Parcelable { } /** + * Set the Z-order for a given SurfaceControl, relative to the specified SurfaceControl. + * The SurfaceControl with a negative z will be placed below the relativeTo + * SurfaceControl and the SurfaceControl with a positive z will be placed above the + * relativeTo SurfaceControl. + * + * Calling setLayer will reset the relative layer. Calling setRelativeLayer after setLayer + * will override the setLayer call. + * + * If a layer is set to be relative to a layer that is destroyed, the layer will be + * offscreen until setLayer is called or setRelativeLayer is called with a valid + * SurfaceControl. + * + * @param sc The SurfaceControl to set the Z order on + * @param relativeTo The SurfaceControl to set the Z order relative to + * @param z The Z-order + * @return This Transaction. * @hide */ public Transaction setRelativeLayer(SurfaceControl sc, SurfaceControl relativeTo, int z) { @@ -3405,6 +3442,9 @@ public final class SurfaceControl implements Parcelable { } /** + * The hint from the buffer producer as to what portion of the layer is + * transparent. + * * @hide */ public Transaction setTransparentRegionHint(SurfaceControl sc, Region transparentRegion) { @@ -3438,6 +3478,10 @@ public final class SurfaceControl implements Parcelable { } /** + * Sets the input channel for a given SurfaceControl. The position and order of the + * SurfaceControl in conjunction with the touchable region in the InputWindowHandle + * determines the hit region. + * * @hide */ public Transaction setInputWindowInfo(SurfaceControl sc, InputWindowHandle handle) { @@ -3549,6 +3593,8 @@ public final class SurfaceControl implements Parcelable { * surface. If no crop is specified and the surface has no buffer, the surface bounds is * only constrained by the size of its parent bounds. * + * To unset the crop, pass in an invalid Rect (0, 0, -1, -1) + * * @param sc SurfaceControl to set crop of. * @param crop Bounds of the crop to apply. * @hide @@ -3578,6 +3624,8 @@ public final class SurfaceControl implements Parcelable { * surface. If no crop is specified and the surface has no buffer, the surface bounds is * only constrained by the size of its parent bounds. * + * To unset the crop, pass in an invalid Rect (0, 0, -1, -1) + * * @param sc SurfaceControl to set crop of. * @param crop Bounds of the crop to apply. * @return this This transaction for chaining @@ -3625,6 +3673,8 @@ public final class SurfaceControl implements Parcelable { * surface. If no crop is specified and the surface has no buffer, the surface bounds is * only constrained by the size of its parent bounds. * + * To unset the crop, pass in an invalid Rect (0, 0, -1, -1) + * * @param sc SurfaceControl to set crop of. * @param crop Bounds of the crop to apply. * @return this This transaction for chaining @@ -3643,7 +3693,12 @@ public final class SurfaceControl implements Parcelable { } /** - * Sets the corner radius of a {@link SurfaceControl}. + * Sets the corner radius of a {@link SurfaceControl}. This corner radius is applied to the + * SurfaceControl and its children. The API expects a crop to be set on the SurfaceControl + * to ensure that the corner radius is applied to the correct region. If the crop does not + * intersect with the SurfaceControl's visible content, the corner radius will not be + * applied. + * * @param sc SurfaceControl * @param cornerRadius Corner radius in pixels. * @return Itself. @@ -3753,6 +3808,9 @@ public final class SurfaceControl implements Parcelable { } /** + * Associates a layer with a display. The layer will be drawn on the display with the + * specified layer stack. If the layer is not a root layer, this call has no effect. + * * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.O) @@ -3791,6 +3849,7 @@ public final class SurfaceControl implements Parcelable { /** * Fills the surface with the specified color. + * * @param color A float array with three values to represent r, g, b in range [0..1]. An * invalid color will remove the color fill. * @hide @@ -3809,8 +3868,9 @@ public final class SurfaceControl implements Parcelable { /** * Removes color fill. - * @hide - */ + * + * @hide + */ public Transaction unsetColor(SurfaceControl sc) { checkPreconditions(sc); if (SurfaceControlRegistry.sCallStackDebuggingEnabled) { @@ -3898,6 +3958,8 @@ public final class SurfaceControl implements Parcelable { } /** + * Sets the surface to render contents of the display to. + * * @hide */ public Transaction setDisplaySurface(IBinder displayToken, Surface surface) { @@ -3916,6 +3978,9 @@ public final class SurfaceControl implements Parcelable { } /** + * Sets the layer stack of the display. + * + * All layers with the same layer stack will be drawn on this display. * @hide */ public Transaction setDisplayLayerStack(IBinder displayToken, int layerStack) { diff --git a/core/java/android/window/DesktopModeFlags.java b/core/java/android/window/DesktopModeFlags.java index 50b7bb8ce9da..4aeedbb72903 100644 --- a/core/java/android/window/DesktopModeFlags.java +++ b/core/java/android/window/DesktopModeFlags.java @@ -104,9 +104,12 @@ public enum DesktopModeFlags { ENABLE_MODALS_FULLSCREEN_WITH_PERMISSIONS(Flags::enableModalsFullscreenWithPermission, false), ENABLE_OPAQUE_BACKGROUND_FOR_TRANSPARENT_WINDOWS( Flags::enableOpaqueBackgroundForTransparentWindows, false), + ENABLE_QUICKSWITCH_DESKTOP_SPLIT_BUGFIX(Flags::enableQuickswitchDesktopSplitBugfix, true), ENABLE_RESIZING_METRICS(Flags::enableResizingMetrics, true), ENABLE_RESTORE_TO_PREVIOUS_SIZE_FROM_DESKTOP_IMMERSIVE( Flags::enableRestoreToPreviousSizeFromDesktopImmersive, true), + ENABLE_START_LAUNCH_TRANSITION_FROM_TASKBAR_BUGFIX( + Flags::enableStartLaunchTransitionFromTaskbarBugfix, true), ENABLE_TASKBAR_OVERFLOW(Flags::enableTaskbarOverflow, false), ENABLE_TASK_RESIZING_KEYBOARD_SHORTCUTS(Flags::enableTaskResizingKeyboardShortcuts, true), ENABLE_TASK_STACK_OBSERVER_IN_SHELL(Flags::enableTaskStackObserverInShell, true), @@ -120,6 +123,8 @@ public enum DesktopModeFlags { ENABLE_WINDOWING_TRANSITION_HANDLERS_OBSERVERS( Flags::enableWindowingTransitionHandlersObservers, false), EXCLUDE_CAPTION_FROM_APP_BOUNDS(Flags::excludeCaptionFromAppBounds, false), + IGNORE_ASPECT_RATIO_RESTRICTIONS_FOR_RESIZEABLE_FREEFORM_ACTIVITIES( + Flags::ignoreAspectRatioRestrictionsForResizeableFreeformActivities, true), INCLUDE_TOP_TRANSPARENT_FULLSCREEN_TASK_IN_DESKTOP_HEURISTIC( Flags::includeTopTransparentFullscreenTaskInDesktopHeuristic, true) // go/keep-sorted end diff --git a/core/java/android/window/TransitionFilter.java b/core/java/android/window/TransitionFilter.java index 61fc6226f822..d8d20119a602 100644 --- a/core/java/android/window/TransitionFilter.java +++ b/core/java/android/window/TransitionFilter.java @@ -31,8 +31,6 @@ import android.os.Parcel; import android.os.Parcelable; import android.view.WindowManager; -import com.android.window.flags.Flags; - /** * A parcelable filter that can be used for rerouting transitions to a remote. This is a local * representation so that the transition system doesn't need to make blocking queries over @@ -261,9 +259,7 @@ public final class TransitionFilter implements Parcelable { // only applies to activity/task && (change.getTaskInfo() != null || change.getActivityComponent() != null)) { - final TransitionInfo.AnimationOptions opts = - Flags.moveAnimationOptionsToChange() ? change.getAnimationOptions() - : info.getAnimationOptions(); + final TransitionInfo.AnimationOptions opts = change.getAnimationOptions(); if (opts != null) { boolean canActuallyOverride = change.getTaskInfo() == null || opts.getOverrideTaskTransition(); diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java index 4f34aa36a204..32175f122d61 100644 --- a/core/java/android/window/TransitionInfo.java +++ b/core/java/android/window/TransitionInfo.java @@ -57,8 +57,6 @@ import android.view.Surface; import android.view.SurfaceControl; import android.view.WindowManager; -import com.android.window.flags.Flags; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -220,10 +218,6 @@ public final class TransitionInfo implements Parcelable { private final ArrayList<Change> mChanges = new ArrayList<>(); private final ArrayList<Root> mRoots = new ArrayList<>(); - // TODO(b/327332488): Clean-up usages after the flag is fully enabled. - @Deprecated - private AnimationOptions mOptions; - /** This is only a BEST-EFFORT id used for log correlation. DO NOT USE for any real work! */ private int mDebugId = -1; @@ -238,7 +232,6 @@ public final class TransitionInfo implements Parcelable { mFlags = in.readInt(); in.readTypedList(mChanges, Change.CREATOR); in.readTypedList(mRoots, Root.CREATOR); - mOptions = in.readTypedObject(AnimationOptions.CREATOR); mDebugId = in.readInt(); mTrack = in.readInt(); } @@ -250,7 +243,6 @@ public final class TransitionInfo implements Parcelable { dest.writeInt(mFlags); dest.writeTypedList(mChanges); dest.writeTypedList(mRoots, flags); - dest.writeTypedObject(mOptions, flags); dest.writeInt(mDebugId); dest.writeInt(mTrack); } @@ -286,18 +278,6 @@ public final class TransitionInfo implements Parcelable { mRoots.add(other); } - /** - * @deprecated Set {@link AnimationOptions} to change. This method is only used if - * {@link Flags#FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE} is disabled. - */ - @Deprecated - public void setAnimationOptions(@Nullable AnimationOptions options) { - if (Flags.moveAnimationOptionsToChange()) { - return; - } - mOptions = options; - } - public @TransitionType int getType() { return mType; } @@ -360,16 +340,6 @@ public final class TransitionInfo implements Parcelable { } /** - * @deprecated Use {@link Change#getAnimationOptions()} instead. This method is called only - * if {@link Flags#FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE} is disabled. - */ - @Deprecated - @Nullable - public AnimationOptions getAnimationOptions() { - return mOptions; - } - - /** * @return the list of {@link Change}s in this transition. The list is sorted top-to-bottom * in Z (meaning index 0 is the top-most container). */ @@ -455,9 +425,6 @@ public final class TransitionInfo implements Parcelable { StringBuilder sb = new StringBuilder(); sb.append("{id=").append(mDebugId).append(" t=").append(transitTypeToString(mType)) .append(" f=0x").append(Integer.toHexString(mFlags)).append(" trk=").append(mTrack); - if (mOptions != null) { - sb.append(" opt=").append(mOptions); - } sb.append(" r=["); for (int i = 0; i < mRoots.size(); ++i) { if (i > 0) { @@ -656,8 +623,6 @@ public final class TransitionInfo implements Parcelable { for (int i = 0; i < mRoots.size(); ++i) { out.mRoots.add(mRoots.get(i).localRemoteCopy()); } - // Doesn't have any native stuff, so no need for actual copy - out.mOptions = mOptions; return out; } @@ -860,9 +825,6 @@ public final class TransitionInfo implements Parcelable { * Sets {@link AnimationOptions} to override animation. */ public void setAnimationOptions(@Nullable AnimationOptions options) { - if (!Flags.moveAnimationOptionsToChange()) { - return; - } mAnimationOptions = options; } diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig index f6ed50e866fd..f77a36676b3d 100644 --- a/core/java/android/window/flags/lse_desktop_experience.aconfig +++ b/core/java/android/window/flags/lse_desktop_experience.aconfig @@ -788,3 +788,10 @@ flag { description: "Show recent apps in the taskbar overflow." bug: "368119679" } + +flag { + name: "enable_projected_display_desktop_mode" + namespace: "lse_desktop_experience" + description: "Enable Desktop Mode on Projected Mode devices but constrained to the external display." + bug: "384568161" +}
\ No newline at end of file diff --git a/core/java/android/window/flags/windowing_sdk.aconfig b/core/java/android/window/flags/windowing_sdk.aconfig index 54d0eeffc9bb..6e45d3dc659f 100644 --- a/core/java/android/window/flags/windowing_sdk.aconfig +++ b/core/java/android/window/flags/windowing_sdk.aconfig @@ -62,16 +62,6 @@ flag { flag { namespace: "windowing_sdk" - name: "move_animation_options_to_change" - description: "Move AnimationOptions from TransitionInfo to each Change" - bug: "327332488" - metadata { - purpose: PURPOSE_BUGFIX - } -} - -flag { - namespace: "windowing_sdk" name: "rear_display_disable_force_desktop_system_decorations" description: "Block system decorations from being added to a rear display when desktop mode is forced" bug: "346103150" diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java index eb59d6efdeff..7ab9e2e65b76 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java @@ -705,8 +705,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { } private static boolean isOverlayTransitionSupported() { - return Flags.moveAnimationOptionsToChange() - && Flags.activityEmbeddingOverlayPresentationFlag(); + return Flags.activityEmbeddingOverlayPresentationFlag(); } @NonNull diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java index f269b3831aab..78f5154c0ecb 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java @@ -364,7 +364,7 @@ class ActivityEmbeddingAnimationRunner { @NonNull SurfaceControl.Transaction finishTransaction, @NonNull List<ActivityEmbeddingAnimationAdapter> adapters) { for (ActivityEmbeddingAnimationAdapter adapter : adapters) { - final int backgroundColor = getTransitionBackgroundColorIfSet(info, adapter.mChange, + final int backgroundColor = getTransitionBackgroundColorIfSet(adapter.mChange, adapter.mAnimation, 0 /* defaultColor */); if (backgroundColor != 0) { // We only need to show one color. @@ -436,8 +436,8 @@ class ActivityEmbeddingAnimationRunner { final TransitionInfo.AnimationOptions options = boundsAnimationChange .getAnimationOptions(); if (options != null) { - final Animation overrideAnimation = mAnimationSpec.loadCustomAnimationFromOptions( - options, TRANSIT_CHANGE); + final Animation overrideAnimation = + mAnimationSpec.loadCustomAnimation(options, TRANSIT_CHANGE); if (overrideAnimation != null) { overrideShowBackdrop = overrideAnimation.getShowBackdrop(); } @@ -447,7 +447,7 @@ class ActivityEmbeddingAnimationRunner { // There are two animations in the array. The first one is for the start leash // (snapshot), and the second one is for the end leash (TaskFragment). final Animation[] animations = - mAnimationSpec.createChangeBoundsChangeAnimations(info, change, parentBounds); + mAnimationSpec.createChangeBoundsChangeAnimations(change, parentBounds); // Jump cut if either animation has zero for duration. for (Animation animation : animations) { if (shouldUseJumpCutForAnimation(animation)) { @@ -500,12 +500,10 @@ class ActivityEmbeddingAnimationRunner { // window without bounds change. animation = ActivityEmbeddingAnimationSpec.createNoopAnimation(change); } else if (TransitionUtil.isClosingType(change.getMode())) { - animation = - mAnimationSpec.createChangeBoundsCloseAnimation(info, change, parentBounds); + animation = mAnimationSpec.createChangeBoundsCloseAnimation(change, parentBounds); shouldShowBackgroundColor = false; } else { - animation = - mAnimationSpec.createChangeBoundsOpenAnimation(info, change, parentBounds); + animation = mAnimationSpec.createChangeBoundsOpenAnimation(change, parentBounds); shouldShowBackgroundColor = false; } if (shouldUseJumpCutForAnimation(animation)) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java index 77799e99607b..2b9eda40cdbb 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java @@ -42,7 +42,6 @@ import android.view.animation.TranslateAnimation; import android.window.TransitionInfo; import com.android.internal.policy.TransitionAnimation; -import com.android.window.flags.Flags; import com.android.wm.shell.shared.TransitionUtil; /** Animation spec for ActivityEmbedding transition. */ @@ -94,9 +93,10 @@ class ActivityEmbeddingAnimationSpec { /** Animation for window that is opening in a change transition. */ @NonNull - Animation createChangeBoundsOpenAnimation(@NonNull TransitionInfo info, - @NonNull TransitionInfo.Change change, @NonNull Rect parentBounds) { - final Animation customAnimation = loadCustomAnimation(info, change, TRANSIT_CHANGE); + Animation createChangeBoundsOpenAnimation(@NonNull TransitionInfo.Change change, + @NonNull Rect parentBounds) { + final Animation customAnimation = + loadCustomAnimation(change.getAnimationOptions(), TRANSIT_CHANGE); if (customAnimation != null) { return customAnimation; } @@ -126,9 +126,10 @@ class ActivityEmbeddingAnimationSpec { /** Animation for window that is closing in a change transition. */ @NonNull - Animation createChangeBoundsCloseAnimation(@NonNull TransitionInfo info, - @NonNull TransitionInfo.Change change, @NonNull Rect parentBounds) { - final Animation customAnimation = loadCustomAnimation(info, change, TRANSIT_CHANGE); + Animation createChangeBoundsCloseAnimation(@NonNull TransitionInfo.Change change, + @NonNull Rect parentBounds) { + final Animation customAnimation = + loadCustomAnimation(change.getAnimationOptions(), TRANSIT_CHANGE); if (customAnimation != null) { return customAnimation; } @@ -162,12 +163,13 @@ class ActivityEmbeddingAnimationSpec { * the second one is for the end leash. */ @NonNull - Animation[] createChangeBoundsChangeAnimations(@NonNull TransitionInfo info, - @NonNull TransitionInfo.Change change, @NonNull Rect parentBounds) { + Animation[] createChangeBoundsChangeAnimations(@NonNull TransitionInfo.Change change, + @NonNull Rect parentBounds) { // TODO(b/293658614): Support more complicated animations that may need more than a noop // animation as the start leash. final Animation noopAnimation = createNoopAnimation(change); - final Animation customAnimation = loadCustomAnimation(info, change, TRANSIT_CHANGE); + final Animation customAnimation = + loadCustomAnimation(change.getAnimationOptions(), TRANSIT_CHANGE); if (customAnimation != null) { return new Animation[]{noopAnimation, customAnimation}; } @@ -221,7 +223,8 @@ class ActivityEmbeddingAnimationSpec { Animation loadOpenAnimation(@NonNull TransitionInfo info, @NonNull TransitionInfo.Change change, @NonNull Rect wholeAnimationBounds) { final boolean isEnter = TransitionUtil.isOpeningType(change.getMode()); - final Animation customAnimation = loadCustomAnimation(info, change, change.getMode()); + final Animation customAnimation = + loadCustomAnimation(change.getAnimationOptions(), change.getMode()); final Animation animation; if (customAnimation != null) { animation = customAnimation; @@ -248,7 +251,8 @@ class ActivityEmbeddingAnimationSpec { Animation loadCloseAnimation(@NonNull TransitionInfo info, @NonNull TransitionInfo.Change change, @NonNull Rect wholeAnimationBounds) { final boolean isEnter = TransitionUtil.isOpeningType(change.getMode()); - final Animation customAnimation = loadCustomAnimation(info, change, change.getMode()); + final Animation customAnimation = + loadCustomAnimation(change.getAnimationOptions(), change.getMode()); final Animation animation; if (customAnimation != null) { animation = customAnimation; @@ -280,20 +284,8 @@ class ActivityEmbeddingAnimationSpec { } @Nullable - private Animation loadCustomAnimation(@NonNull TransitionInfo info, - @NonNull TransitionInfo.Change change, @WindowManager.TransitionType int mode) { - final TransitionInfo.AnimationOptions options; - if (Flags.moveAnimationOptionsToChange()) { - options = change.getAnimationOptions(); - } else { - options = info.getAnimationOptions(); - } - return loadCustomAnimationFromOptions(options, mode); - } - - @Nullable - Animation loadCustomAnimationFromOptions(@Nullable TransitionInfo.AnimationOptions options, - @WindowManager.TransitionType int mode) { + Animation loadCustomAnimation(@Nullable TransitionInfo.AnimationOptions options, + @WindowManager.TransitionType int mode) { if (options == null || options.getType() != ANIM_CUSTOM) { return null; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java index 55ed5fa4b56f..3a95333309ac 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java @@ -40,7 +40,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; -import com.android.window.flags.Flags; import com.android.wm.shell.shared.TransitionUtil; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.Transitions; @@ -123,9 +122,6 @@ public class ActivityEmbeddingController implements Transitions.TransitionHandle } private boolean shouldAnimateAnimationOptions(@NonNull TransitionInfo info) { - if (!Flags.moveAnimationOptionsToChange()) { - return shouldAnimateAnimationOptions(info.getAnimationOptions()); - } for (TransitionInfo.Change change : info.getChanges()) { if (!shouldAnimateAnimationOptions(change.getAnimationOptions())) { // If any of override animation is not supported, don't animate the transition. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java index 87a4115ccd3a..df82091ef002 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java @@ -227,7 +227,13 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged /** Hides the IME for Bubbles when the device is locked. */ public void hideImeForBubblesWhenLocked(int displayId) { PerDisplay pd = mImePerDisplay.get(displayId); - pd.setImeInputTargetRequestedVisibility(false, pd.getImeSourceControl().getImeStatsToken()); + InsetsSourceControl imeSourceControl = pd.getImeSourceControl(); + if (imeSourceControl != null) { + ImeTracker.Token imeStatsToken = imeSourceControl.getImeStatsToken(); + if (imeStatsToken != null) { + pd.setImeInputTargetRequestedVisibility(false, imeStatsToken); + } + } } /** An implementation of {@link IDisplayWindowInsetsController} for a given display id. */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt index 45adfe4112a6..ca870d2b6988 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt @@ -1079,7 +1079,8 @@ class DesktopTasksController( ) } - private fun startLaunchTransition( + @VisibleForTesting + fun startLaunchTransition( transitionType: Int, wct: WindowContainerTransaction, launchingTaskId: Int?, @@ -1087,34 +1088,52 @@ class DesktopTasksController( displayId: Int = DEFAULT_DISPLAY, unminimizeReason: UnminimizeReason = UnminimizeReason.UNKNOWN, ): IBinder { + // TODO: b/397619806 - Consolidate sharable logic with [handleFreeformTaskLaunch]. + var launchTransaction = wct val taskIdToMinimize = addAndGetMinimizeChanges( displayId, - wct, + launchTransaction, newTaskId = launchingTaskId, launchingNewIntent = launchingTaskId == null, ) val exitImmersiveResult = desktopImmersiveController.exitImmersiveIfApplicable( - wct = wct, + wct = launchTransaction, displayId = displayId, excludeTaskId = launchingTaskId, reason = DesktopImmersiveController.ExitReason.TASK_LAUNCH, ) + var deskIdToActivate: Int? = null + if ( + DesktopExperienceFlags.ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING.isTrue && + !isDesktopModeShowing(displayId) + ) { + deskIdToActivate = + checkNotNull( + launchingTaskId?.let { taskRepository.getDeskIdForTask(it) } + ?: getDefaultDeskId(displayId) + ) + val activateDeskWct = WindowContainerTransaction() + addDeskActivationChanges(deskIdToActivate, activateDeskWct) + // Desk activation must be handled before app launch-related transactions. + activateDeskWct.merge(launchTransaction, /* transfer= */ true) + launchTransaction = activateDeskWct + } val t = if (remoteTransition == null) { desktopMixedTransitionHandler.startLaunchTransition( transitionType = transitionType, - wct = wct, + wct = launchTransaction, taskId = launchingTaskId, minimizingTaskId = taskIdToMinimize, exitingImmersiveTask = exitImmersiveResult.asExit()?.exitingTask, ) } else if (taskIdToMinimize == null) { val remoteTransitionHandler = OneShotRemoteHandler(mainExecutor, remoteTransition) - transitions.startTransition(transitionType, wct, remoteTransitionHandler).also { - remoteTransitionHandler.setTransition(it) - } + transitions + .startTransition(transitionType, launchTransaction, remoteTransitionHandler) + .also { remoteTransitionHandler.setTransition(it) } } else { val remoteTransitionHandler = DesktopWindowLimitRemoteHandler( @@ -1123,9 +1142,9 @@ class DesktopTasksController( remoteTransition, taskIdToMinimize, ) - transitions.startTransition(transitionType, wct, remoteTransitionHandler).also { - remoteTransitionHandler.setTransition(it) - } + transitions + .startTransition(transitionType, launchTransaction, remoteTransitionHandler) + .also { remoteTransitionHandler.setTransition(it) } } if (taskIdToMinimize != null) { addPendingMinimizeTransition(t, taskIdToMinimize, MinimizeReason.TASK_LIMIT) @@ -1133,6 +1152,24 @@ class DesktopTasksController( if (launchingTaskId != null && taskRepository.isMinimizedTask(launchingTaskId)) { addPendingUnminimizeTransition(t, displayId, launchingTaskId, unminimizeReason) } + if ( + DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue && + deskIdToActivate != null + ) { + if (DesktopExperienceFlags.ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING.isTrue) { + desksTransitionObserver.addPendingTransition( + DeskTransition.ActivateDesk( + token = t, + displayId = displayId, + deskId = deskIdToActivate, + ) + ) + } + + desktopModeEnterExitTransitionListener?.onEnterDesktopModeTransitionStarted( + FREEFORM_ANIMATION_DURATION + ) + } exitImmersiveResult.asExit()?.runOnTransitionStart?.invoke(t) return t } @@ -2704,10 +2741,9 @@ class DesktopTasksController( activateDesk(deskId, remoteTransition) } - /** Activates the given desk. */ - fun activateDesk(deskId: Int, remoteTransition: RemoteTransition? = null) { + /** Activates the given desk but without starting a transition. */ + fun addDeskActivationChanges(deskId: Int, wct: WindowContainerTransaction) { val displayId = taskRepository.getDisplayForDesk(deskId) - val wct = WindowContainerTransaction() if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { prepareForDeskActivation(displayId, wct) desksOrganizer.activateDesk(wct, deskId) @@ -2720,6 +2756,13 @@ class DesktopTasksController( } else { bringDesktopAppsToFront(displayId, wct) } + } + + /** Activates the given desk. */ + fun activateDesk(deskId: Int, remoteTransition: RemoteTransition? = null) { + val displayId = taskRepository.getDisplayForDesk(deskId) + val wct = WindowContainerTransaction() + addDeskActivationChanges(deskId, wct) val transitionType = transitionType(remoteTransition) val handler = diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java index 743bd052995e..347dcff86529 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java @@ -40,7 +40,6 @@ import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; import com.android.internal.protolog.ProtoLog; -import com.android.window.flags.Flags; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.activityembedding.ActivityEmbeddingController; import com.android.wm.shell.common.ComponentUtils; @@ -439,9 +438,6 @@ public class DefaultMixedHandler implements MixedTransitionHandler, for (int i = 0; i < info.getRootCount(); ++i) { out.addRoot(info.getRoot(i)); } - if (!Flags.moveAnimationOptionsToChange()) { - out.setAnimationOptions(info.getAnimationOptions()); - } return out; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java index 01428e60582e..e9c6adec75d7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java @@ -539,7 +539,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { cornerRadius = 0; } - backgroundColorForTransition = getTransitionBackgroundColorIfSet(info, change, a, + backgroundColorForTransition = getTransitionBackgroundColorIfSet(change, a, backgroundColorForTransition); if (!isTask && a.getExtensionEdges() != 0x0) { @@ -606,12 +606,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { mTransactionPool, mMainExecutor, animRelOffset, cornerRadius, clipRect); - final TransitionInfo.AnimationOptions options; - if (Flags.moveAnimationOptionsToChange()) { - options = change.getAnimationOptions(); - } else { - options = info.getAnimationOptions(); - } + final TransitionInfo.AnimationOptions options = change.getAnimationOptions(); if (options != null) { attachThumbnail(animations, onAnimFinish, change, options, cornerRadius); } @@ -834,12 +829,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { final boolean isOpeningType = TransitionUtil.isOpeningType(type); final boolean enter = TransitionUtil.isOpeningType(changeMode); final boolean isTask = change.getTaskInfo() != null; - final TransitionInfo.AnimationOptions options; - if (Flags.moveAnimationOptionsToChange()) { - options = change.getAnimationOptions(); - } else { - options = info.getAnimationOptions(); - } + final TransitionInfo.AnimationOptions options = change.getAnimationOptions(); final int overrideType = options != null ? options.getType() : ANIM_NONE; final int userId = options != null ? options.getUserId() : UserHandle.USER_CURRENT; final Rect endBounds = TransitionUtil.isClosingType(changeMode) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java index 4feb4753096e..7984bcedc4e5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java @@ -58,7 +58,6 @@ import android.window.TransitionInfo; import com.android.internal.R; import com.android.internal.policy.TransitionAnimation; import com.android.internal.protolog.ProtoLog; -import com.android.window.flags.Flags; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.shared.TransitionUtil; @@ -78,12 +77,7 @@ public class TransitionAnimationHelper { final boolean isFreeform = isTask && change.getTaskInfo().isFreeform(); final boolean isCoveredByOpaqueFullscreenChange = isCoveredByOpaqueFullscreenChange(info, change); - final TransitionInfo.AnimationOptions options; - if (Flags.moveAnimationOptionsToChange()) { - options = change.getAnimationOptions(); - } else { - options = info.getAnimationOptions(); - } + final TransitionInfo.AnimationOptions options = change.getAnimationOptions(); final int overrideType = options != null ? options.getType() : ANIM_NONE; int animAttr = 0; boolean translucent = false; @@ -279,16 +273,10 @@ public class TransitionAnimationHelper { * the given transition animation. */ @ColorInt - public static int getTransitionBackgroundColorIfSet(@NonNull TransitionInfo info, - @NonNull TransitionInfo.Change change, @NonNull Animation a, - @ColorInt int defaultColor) { + public static int getTransitionBackgroundColorIfSet(@NonNull TransitionInfo.Change change, + @NonNull Animation a, @ColorInt int defaultColor) { if (!a.getShowBackdrop()) { return defaultColor; - } - if (!Flags.moveAnimationOptionsToChange() && info.getAnimationOptions() != null - && info.getAnimationOptions().getBackgroundColor() != 0) { - // If available use the background color provided through AnimationOptions - return info.getAnimationOptions().getBackgroundColor(); } else if (a.getBackdropColor() != 0) { // Otherwise fallback on the background color provided through the animation // definition. diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunnerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunnerTests.java index 94dc774a6737..d4d8d93abf7d 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunnerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunnerTests.java @@ -39,7 +39,6 @@ import android.animation.Animator; import android.annotation.NonNull; import android.graphics.Point; import android.graphics.Rect; -import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; @@ -77,7 +76,6 @@ public class ActivityEmbeddingAnimationRunnerTests extends ActivityEmbeddingAnim doNothing().when(mController).onAnimationFinished(any()); } - @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) @Test public void testStartAnimation() { final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN, 0) @@ -103,7 +101,6 @@ public class ActivityEmbeddingAnimationRunnerTests extends ActivityEmbeddingAnim verify(mController).onAnimationFinished(mTransition); } - @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) @Test public void testChangesBehindStartingWindow() { final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN, 0) @@ -118,7 +115,6 @@ public class ActivityEmbeddingAnimationRunnerTests extends ActivityEmbeddingAnim assertEquals(0, animator.getDuration()); } - @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) @Test public void testTransitionTypeDragResize() { final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_TASK_FRAGMENT_DRAG_RESIZE, 0) @@ -133,25 +129,6 @@ public class ActivityEmbeddingAnimationRunnerTests extends ActivityEmbeddingAnim assertEquals(0, animator.getDuration()); } - @DisableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) - @Test - public void testInvalidCustomAnimation_disableAnimationOptionsPerChange() { - final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN, 0) - .addChange(createChange(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY, TRANSIT_OPEN)) - .build(); - info.setAnimationOptions(TransitionInfo.AnimationOptions - .makeCustomAnimOptions("packageName", 0 /* enterResId */, 0 /* exitResId */, - 0 /* backgroundColor */, false /* overrideTaskTransition */)); - final Animator animator = mAnimRunner.createAnimator( - info, mStartTransaction, mFinishTransaction, - () -> mFinishCallback.onTransitionFinished(null /* wct */), - new ArrayList<>()); - - // An invalid custom animation is equivalent to jump-cut. - assertEquals(0, animator.getDuration()); - } - - @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) @Test public void testInvalidCustomAnimation_enableAnimationOptionsPerChange() { final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN, 0) @@ -169,36 +146,6 @@ public class ActivityEmbeddingAnimationRunnerTests extends ActivityEmbeddingAnim assertEquals(0, animator.getDuration()); } - @DisableFlags(Flags.FLAG_ACTIVITY_EMBEDDING_OVERLAY_PRESENTATION_FLAG) - @Test - public void testCalculateParentBounds_flagDisabled() { - final Rect parentBounds = new Rect(0, 0, 2000, 2000); - final Rect primaryBounds = new Rect(); - final Rect secondaryBounds = new Rect(); - parentBounds.splitVertically(primaryBounds, secondaryBounds); - - final TransitionInfo.Change change = createChange(0 /* flags */); - change.setStartAbsBounds(secondaryBounds); - - final TransitionInfo.Change boundsAnimationChange = createChange(0 /* flags */); - boundsAnimationChange.setStartAbsBounds(primaryBounds); - boundsAnimationChange.setEndAbsBounds(primaryBounds); - final Rect actualParentBounds = new Rect(); - - calculateParentBounds(change, boundsAnimationChange, actualParentBounds); - - assertEquals(parentBounds, actualParentBounds); - - actualParentBounds.setEmpty(); - - boundsAnimationChange.setStartAbsBounds(secondaryBounds); - boundsAnimationChange.setEndAbsBounds(primaryBounds); - - calculateParentBounds(boundsAnimationChange, boundsAnimationChange, actualParentBounds); - - assertEquals(parentBounds, actualParentBounds); - } - // TODO(b/243518738): Rewrite with TestParameter @EnableFlags(Flags.FLAG_ACTIVITY_EMBEDDING_OVERLAY_PRESENTATION_FLAG) @Test diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingControllerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingControllerTests.java index 9f29ef71930a..53a13d0d4ffd 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingControllerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingControllerTests.java @@ -32,8 +32,6 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import android.animation.Animator; import android.animation.ValueAnimator; import android.graphics.Rect; -import android.platform.test.annotations.DisableFlags; -import android.platform.test.annotations.EnableFlags; import android.view.SurfaceControl; import android.window.TransitionInfo; @@ -41,7 +39,6 @@ import androidx.test.annotation.UiThreadTest; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import com.android.window.flags.Flags; import com.android.wm.shell.transition.TransitionInfoBuilder; import org.junit.Before; @@ -69,13 +66,11 @@ public class ActivityEmbeddingControllerTests extends ActivityEmbeddingAnimation any()); } - @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) @Test public void testInstantiate() { verify(mShellInit).addInitCallback(any(), any()); } - @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) @Test public void testOnInit() { mController.onInit(); @@ -83,7 +78,6 @@ public class ActivityEmbeddingControllerTests extends ActivityEmbeddingAnimation verify(mTransitions).addHandler(mController); } - @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) @Test public void testSetAnimScaleSetting() { mController.setAnimScaleSetting(1.0f); @@ -92,7 +86,6 @@ public class ActivityEmbeddingControllerTests extends ActivityEmbeddingAnimation verify(mAnimSpec).setAnimScaleSetting(1.0f); } - @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) @Test public void testStartAnimation_containsNonActivityEmbeddingChange() { final TransitionInfo.Change nonEmbeddedOpen = createChange(0 /* flags */); @@ -129,7 +122,6 @@ public class ActivityEmbeddingControllerTests extends ActivityEmbeddingAnimation assertFalse(info2.getChanges().contains(nonEmbeddedClose)); } - @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) @Test public void testStartAnimation_containsOnlyFillTaskActivityEmbeddingChange() { final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN, 0) @@ -146,7 +138,6 @@ public class ActivityEmbeddingControllerTests extends ActivityEmbeddingAnimation verifyNoMoreInteractions(mFinishCallback); } - @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) @Test public void testStartAnimation_containsActivityEmbeddingSplitChange() { // Change that occupies only part of the Task. @@ -164,7 +155,6 @@ public class ActivityEmbeddingControllerTests extends ActivityEmbeddingAnimation verifyNoMoreInteractions(mFinishTransaction); } - @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) @Test public void testStartAnimation_containsChangeEnterActivityEmbeddingSplit() { // Change that is entering ActivityEmbedding split. @@ -181,7 +171,6 @@ public class ActivityEmbeddingControllerTests extends ActivityEmbeddingAnimation verifyNoMoreInteractions(mFinishTransaction); } - @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) @Test public void testStartAnimation_containsChangeExitActivityEmbeddingSplit() { // Change that is exiting ActivityEmbedding split. @@ -198,27 +187,6 @@ public class ActivityEmbeddingControllerTests extends ActivityEmbeddingAnimation verifyNoMoreInteractions(mFinishTransaction); } - @DisableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) - @Test - public void testShouldAnimate_containsAnimationOptions_disableAnimOptionsPerChange() { - final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_CLOSE, 0) - .addChange(createEmbeddedChange(EMBEDDED_RIGHT_BOUNDS, TASK_BOUNDS, TASK_BOUNDS)) - .build(); - - info.setAnimationOptions(TransitionInfo.AnimationOptions - .makeCustomAnimOptions("packageName", 0 /* enterResId */, 0 /* exitResId */, - 0 /* backgroundColor */, false /* overrideTaskTransition */)); - assertTrue(mController.shouldAnimate(info)); - - info.setAnimationOptions(TransitionInfo.AnimationOptions - .makeSceneTransitionAnimOptions()); - assertFalse(mController.shouldAnimate(info)); - - info.setAnimationOptions(TransitionInfo.AnimationOptions.makeCrossProfileAnimOptions()); - assertFalse(mController.shouldAnimate(info)); - } - - @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) @Test public void testShouldAnimate_containsAnimationOptions_enableAnimOptionsPerChange() { final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_CLOSE, 0) @@ -239,7 +207,6 @@ public class ActivityEmbeddingControllerTests extends ActivityEmbeddingAnimation assertFalse(mController.shouldAnimate(info)); } - @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) @UiThreadTest @Test public void testMergeAnimation() { @@ -278,7 +245,6 @@ public class ActivityEmbeddingControllerTests extends ActivityEmbeddingAnimation verify(mFinishCallback).onTransitionFinished(any()); } - @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) @Test public void testOnAnimationFinished() { // Should not call finish when there is no transition. diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt index 2e63c4f51792..785fb3e875b8 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt @@ -2477,8 +2477,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() controller.moveTaskToFront(task.taskId, unminimizeReason = UnminimizeReason.UNKNOWN) val wct = getLatestDesktopMixedTaskWct(type = TRANSIT_OPEN) - assertThat(wct.hierarchyOps).hasSize(1) - wct.assertLaunchTaskAt(0, task.taskId, WINDOWING_MODE_FREEFORM) + wct.assertLaunchTask(task.taskId, WINDOWING_MODE_FREEFORM) } @Test @@ -6306,6 +6305,61 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() assertThat(taskRepository.getNumberOfDesks(DEFAULT_DISPLAY)).isEqualTo(currentDeskCount + 1) } + @Test + @EnableFlags( + Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY, + Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER, + ) + fun startLaunchTransition_desktopNotShowing_movesWallpaperToFront() { + val launchingTask = createFreeformTask() + val wct = WindowContainerTransaction() + wct.reorder(launchingTask.token, /* onTop= */ true) + whenever( + desktopMixedTransitionHandler.startLaunchTransition( + eq(TRANSIT_OPEN), + any(), + anyOrNull(), + anyOrNull(), + anyOrNull(), + ) + ) + .thenReturn(Binder()) + + controller.startLaunchTransition(TRANSIT_OPEN, wct, launchingTaskId = null) + + val latestWct = getLatestDesktopMixedTaskWct(type = TRANSIT_OPEN) + val launchingTaskReorderIndex = latestWct.indexOfReorder(launchingTask, toTop = true) + val wallpaperReorderIndex = latestWct.indexOfReorder(wallpaperToken, toTop = true) + assertThat(launchingTaskReorderIndex).isNotEqualTo(-1) + assertThat(wallpaperReorderIndex).isNotEqualTo(-1) + assertThat(launchingTaskReorderIndex).isGreaterThan(wallpaperReorderIndex) + } + + @Test + @EnableFlags( + Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY, + Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER, + ) + fun startLaunchTransition_desktopShowing_doesNotReorderWallpaper() { + val wct = WindowContainerTransaction() + whenever( + desktopMixedTransitionHandler.startLaunchTransition( + eq(TRANSIT_OPEN), + any(), + anyOrNull(), + anyOrNull(), + anyOrNull(), + ) + ) + .thenReturn(Binder()) + + setUpFreeformTask() + controller.startLaunchTransition(TRANSIT_OPEN, wct, launchingTaskId = null) + + val latestWct = getLatestDesktopMixedTaskWct(type = TRANSIT_OPEN) + assertNull(latestWct.hierarchyOps.find { op -> op.container == wallpaperToken.asBinder() }) + } + private class RunOnStartTransitionCallback : ((IBinder) -> Unit) { var invocations = 0 private set @@ -6692,13 +6746,20 @@ private fun WindowContainerTransaction.assertWithoutHop( } private fun WindowContainerTransaction.indexOfReorder( - task: RunningTaskInfo, + token: WindowContainerToken, toTop: Boolean? = null, ): Int { - val hop = hierarchyOps.singleOrNull(ReorderPredicate(task.token, toTop)) ?: return -1 + val hop = hierarchyOps.singleOrNull(ReorderPredicate(token, toTop)) ?: return -1 return hierarchyOps.indexOf(hop) } +private fun WindowContainerTransaction.indexOfReorder( + task: RunningTaskInfo, + toTop: Boolean? = null, +): Int { + return indexOfReorder(task.token, toTop) +} + private class ReorderPredicate(val token: WindowContainerToken, val toTop: Boolean? = null) : ((WindowContainerTransaction.HierarchyOp) -> Boolean) { override fun invoke(hop: WindowContainerTransaction.HierarchyOp): Boolean = @@ -6816,6 +6877,17 @@ private fun WindowContainerTransaction.assertPendingIntentAt(index: Int, intent: assertThat(op.pendingIntent?.intent?.categories).isEqualTo(intent.categories) } +private fun WindowContainerTransaction.assertLaunchTask(taskId: Int, windowingMode: Int) { + val keyLaunchWindowingMode = "android.activity.windowingMode" + + assertHop { hop -> + hop.type == HIERARCHY_OP_TYPE_LAUNCH_TASK && + hop.launchOptions?.getInt(LAUNCH_KEY_TASK_ID) == taskId && + hop.launchOptions?.getInt(keyLaunchWindowingMode, WINDOWING_MODE_UNDEFINED) == + windowingMode + } +} + private fun WindowContainerTransaction.assertLaunchTaskAt( index: Int, taskId: Int, diff --git a/media/java/android/media/AudioDeviceVolumeManager.java b/media/java/android/media/AudioDeviceVolumeManager.java index 892a8612d74a..56d3df3b2555 100644 --- a/media/java/android/media/AudioDeviceVolumeManager.java +++ b/media/java/android/media/AudioDeviceVolumeManager.java @@ -16,6 +16,9 @@ package android.media; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; +import static android.media.audio.Flags.FLAG_UNIFY_ABSOLUTE_VOLUME_MANAGEMENT; + import static com.android.media.flags.Flags.FLAG_ENABLE_AUDIO_INPUT_DEVICE_ROUTING_AND_VOLUME_CONTROL; import android.Manifest; @@ -91,6 +94,8 @@ public class AudioDeviceVolumeManager { * @see #setDeviceAbsoluteVolumeBehavior(AudioDeviceAttributes, VolumeInfo, boolean, Executor, * OnAudioDeviceVolumeChangedListener) */ + @SystemApi(client = MODULE_LIBRARIES) + @FlaggedApi(FLAG_UNIFY_ABSOLUTE_VOLUME_MANAGEMENT) public interface OnAudioDeviceVolumeChangedListener { /** * Called the device for the given audio device has changed. @@ -203,6 +208,30 @@ public class AudioDeviceVolumeManager { * volume updates to apply on that device * @param device the audio device set to absolute volume mode * @param volume the type of volume this device responds to + * @param executor the Executor used for receiving volume updates through the listener + * @param vclistener the callback for volume updates + */ + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(anyOf = { android.Manifest.permission.MODIFY_AUDIO_ROUTING, + android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED, + android.Manifest.permission.BLUETOOTH_PRIVILEGED, + android.Manifest.permission.BLUETOOTH_STACK}) + @FlaggedApi(FLAG_UNIFY_ABSOLUTE_VOLUME_MANAGEMENT) + public void setDeviceAbsoluteVolumeBehavior( + @NonNull AudioDeviceAttributes device, + @NonNull VolumeInfo volume, + @NonNull @CallbackExecutor Executor executor, + @NonNull OnAudioDeviceVolumeChangedListener vclistener) { + setDeviceAbsoluteVolumeBehavior(device, volume, /*handlesVolumeAdjustment=*/false, executor, + vclistener); + } + + /** + * @hide + * Configures a device to use absolute volume model, and registers a listener for receiving + * volume updates to apply on that device + * @param device the audio device set to absolute volume mode + * @param volume the type of volume this device responds to * @param handlesVolumeAdjustment whether the controller handles volume adjustments separately * from volume changes. If true, adjustments from {@link AudioManager#adjustStreamVolume} * will be sent via {@link OnAudioDeviceVolumeChangedListener#onAudioDeviceVolumeAdjusted}. @@ -210,7 +239,7 @@ public class AudioDeviceVolumeManager { * @param vclistener the callback for volume updates */ @RequiresPermission(anyOf = { android.Manifest.permission.MODIFY_AUDIO_ROUTING, - android.Manifest.permission.BLUETOOTH_PRIVILEGED }) + android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void setDeviceAbsoluteVolumeBehavior( @NonNull AudioDeviceAttributes device, @NonNull VolumeInfo volume, @@ -229,6 +258,30 @@ public class AudioDeviceVolumeManager { * registers a listener for receiving volume updates to apply on that device * @param device the audio device set to absolute multi-volume mode * @param volumes the list of volumes the given device responds to + * @param executor the Executor used for receiving volume updates through the listener + * @param vclistener the callback for volume updates + */ + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(anyOf = { android.Manifest.permission.MODIFY_AUDIO_ROUTING, + android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED, + android.Manifest.permission.BLUETOOTH_PRIVILEGED, + android.Manifest.permission.BLUETOOTH_STACK}) + @FlaggedApi(FLAG_UNIFY_ABSOLUTE_VOLUME_MANAGEMENT) + public void setDeviceAbsoluteMultiVolumeBehavior( + @NonNull AudioDeviceAttributes device, + @NonNull List<VolumeInfo> volumes, + @NonNull @CallbackExecutor Executor executor, + @NonNull OnAudioDeviceVolumeChangedListener vclistener) { + setDeviceAbsoluteMultiVolumeBehavior(device, volumes, /*handlesVolumeAdjustment=*/false, + executor, vclistener); + } + + /** + * @hide + * Configures a device to use absolute volume model applied to different volume types, and + * registers a listener for receiving volume updates to apply on that device + * @param device the audio device set to absolute multi-volume mode + * @param volumes the list of volumes the given device responds to * @param handlesVolumeAdjustment whether the controller handles volume adjustments separately * from volume changes. If true, adjustments from {@link AudioManager#adjustStreamVolume} * will be sent via {@link OnAudioDeviceVolumeChangedListener#onAudioDeviceVolumeAdjusted}. @@ -236,7 +289,7 @@ public class AudioDeviceVolumeManager { * @param vclistener the callback for volume updates */ @RequiresPermission(anyOf = { android.Manifest.permission.MODIFY_AUDIO_ROUTING, - android.Manifest.permission.BLUETOOTH_PRIVILEGED }) + android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void setDeviceAbsoluteMultiVolumeBehavior( @NonNull AudioDeviceAttributes device, @NonNull List<VolumeInfo> volumes, diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java index 69e99c616910..94199df4b9f8 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java @@ -662,10 +662,10 @@ public class CachedBluetoothDeviceManagerTest { @Test @RequiresFlagsEnabled( com.android.settingslib.flags.Flags.FLAG_HEARING_DEVICE_SET_CONNECTION_STATUS_REPORT) - public void onDeviceUnpaired_hearingDevice_callReportConnectionStatus() { + public void onDeviceUnpaired_containsHearingAidInfo_callReportConnectionStatus() { when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); - when(mCachedDevice1.getProfiles()).thenReturn( - ImmutableList.of(mHapClientProfile, mHearingAidProfile)); + mCachedDevice1.setHearingAidInfo( + new HearingAidInfo.Builder().setHiSyncId(HISYNCID1).build()); mCachedDeviceManager.onDeviceUnpaired(mCachedDevice1); diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt index f8bcb81dc073..bc75b1dad40c 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt @@ -22,19 +22,8 @@ import android.util.Log import android.util.LruCache import android.util.MathUtils import androidx.annotation.VisibleForTesting -import java.lang.Float.max -import java.lang.Float.min import kotlin.math.roundToInt -private const val TAG_WGHT = "wght" -private const val TAG_ITAL = "ital" - -private const val FONT_WEIGHT_DEFAULT_VALUE = 400f -private const val FONT_ITALIC_MAX = 1f -private const val FONT_ITALIC_MIN = 0f -private const val FONT_ITALIC_ANIMATION_STEP = 0.1f -private const val FONT_ITALIC_DEFAULT_VALUE = 0f - /** Caches for font interpolation */ interface FontCache { val animationFrameCount: Int @@ -91,11 +80,8 @@ class FontCacheImpl(override val animationFrameCount: Int = DEFAULT_FONT_CACHE_M class FontInterpolator(val fontCache: FontCache = FontCacheImpl()) { /** Linear interpolate the font variation settings. */ fun lerp(start: Font, end: Font, progress: Float, linearProgress: Float): Font { - if (progress == 0f) { - return start - } else if (progress == 1f) { - return end - } + if (progress <= 0f) return start + if (progress >= 1f) return end val startAxes = start.axes ?: EMPTY_AXES val endAxes = end.axes ?: EMPTY_AXES @@ -110,7 +96,7 @@ class FontInterpolator(val fontCache: FontCache = FontCacheImpl()) { InterpKey(start, end, (linearProgress * fontCache.animationFrameCount).roundToInt()) fontCache.get(iKey)?.let { if (DEBUG) { - Log.d(LOG_TAG, "[$progress] Interp. cache hit for $iKey") + Log.d(LOG_TAG, "[$progress, $linearProgress] Interp. cache hit for $iKey") } return it } @@ -121,37 +107,16 @@ class FontInterpolator(val fontCache: FontCache = FontCacheImpl()) { // and also pre-fill the missing axes value with default value from 'fvar' table. val newAxes = lerp(startAxes, endAxes) { tag, startValue, endValue -> - when (tag) { - TAG_WGHT -> - MathUtils.lerp( - startValue ?: FONT_WEIGHT_DEFAULT_VALUE, - endValue ?: FONT_WEIGHT_DEFAULT_VALUE, - progress, - ) - TAG_ITAL -> - adjustItalic( - MathUtils.lerp( - startValue ?: FONT_ITALIC_DEFAULT_VALUE, - endValue ?: FONT_ITALIC_DEFAULT_VALUE, - progress, - ) - ) - else -> { - require(startValue != null && endValue != null) { - "Unable to interpolate due to unknown default axes value : $tag" - } - MathUtils.lerp(startValue, endValue, progress) - } - } + MathUtils.lerp(startValue, endValue, progress) } // Check if we already make font for this axes. This is typically happens if the animation - // happens backward. + // happens backward and is being linearly interpolated. val vKey = VarFontKey(start, newAxes) fontCache.get(vKey)?.let { fontCache.put(iKey, it) if (DEBUG) { - Log.d(LOG_TAG, "[$progress] Axis cache hit for $vKey") + Log.d(LOG_TAG, "[$progress, $linearProgress] Axis cache hit for $vKey") } return it } @@ -164,14 +129,14 @@ class FontInterpolator(val fontCache: FontCache = FontCacheImpl()) { fontCache.put(vKey, newFont) // Cache misses are likely to create memory leaks, so this is logged at error level. - Log.e(LOG_TAG, "[$progress] Cache MISS for $iKey / $vKey") + Log.e(LOG_TAG, "[$progress, $linearProgress] Cache MISS for $iKey / $vKey") return newFont } private fun lerp( start: Array<FontVariationAxis>, end: Array<FontVariationAxis>, - filter: (tag: String, left: Float?, right: Float?) -> Float, + filter: (tag: String, left: Float, right: Float) -> Float, ): List<FontVariationAxis> { // Safe to modify result of Font#getAxes since it returns cloned object. start.sortBy { axis -> axis.tag } @@ -191,39 +156,37 @@ class FontInterpolator(val fontCache: FontCache = FontCacheImpl()) { else -> tagA.compareTo(tagB) } - val axis = + val tag = + when { + comp == 0 -> tagA!! + comp < 0 -> tagA!! + else -> tagB!! + } + + val axisDefinition = GSFAxes.getAxis(tag) + require(comp == 0 || axisDefinition != null) { + "Unable to interpolate due to unknown default axes value: $tag" + } + + val axisValue = when { - comp == 0 -> { - val v = filter(tagA!!, start[i++].styleValue, end[j++].styleValue) - FontVariationAxis(tagA, v) - } - comp < 0 -> { - val v = filter(tagA!!, start[i++].styleValue, null) - FontVariationAxis(tagA, v) - } - else -> { // comp > 0 - val v = filter(tagB!!, null, end[j++].styleValue) - FontVariationAxis(tagB, v) - } + comp == 0 -> filter(tag, start[i++].styleValue, end[j++].styleValue) + comp < 0 -> filter(tag, start[i++].styleValue, axisDefinition!!.defaultValue) + else -> filter(tag, axisDefinition!!.defaultValue, end[j++].styleValue) } - result.add(axis) + // Round axis value to valid intermediate steps. This improves the cache hit rate. + val step = axisDefinition?.animationStep ?: DEFAULT_ANIMATION_STEP + result.add(FontVariationAxis(tag, (axisValue / step).roundToInt() * step)) } return result } - // For the performance reasons, we animate italic with FONT_ITALIC_ANIMATION_STEP. This helps - // Cache hit ratio in the Skia glyph cache. - private fun adjustItalic(value: Float) = - coerceInWithStep(value, FONT_ITALIC_MIN, FONT_ITALIC_MAX, FONT_ITALIC_ANIMATION_STEP) - - private fun coerceInWithStep(v: Float, min: Float, max: Float, step: Float) = - (v.coerceIn(min, max) / step).toInt() * step - companion object { private const val LOG_TAG = "FontInterpolator" private val DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG) private val EMPTY_AXES = arrayOf<FontVariationAxis>() + private const val DEFAULT_ANIMATION_STEP = 1f // Returns true if given two font instance can be interpolated. fun canInterpolate(start: Font, end: Font) = diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/FontVariationUtils.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/FontVariationUtils.kt index 9545bda80b2d..9a746870c6ff 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/FontVariationUtils.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/FontVariationUtils.kt @@ -1,12 +1,20 @@ -package com.android.systemui.animation +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -object GSFAxes { - const val WEIGHT = "wght" - const val WIDTH = "wdth" - const val SLANT = "slnt" - const val ROUND = "ROND" - const val OPTICAL_SIZE = "opsz" -} +package com.android.systemui.animation class FontVariationUtils { private var mWeight = -1 @@ -46,20 +54,20 @@ class FontVariationUtils { } var resultString = "" if (mWeight >= 0) { - resultString += "'${GSFAxes.WEIGHT}' $mWeight" + resultString += "'${GSFAxes.WEIGHT.tag}' $mWeight" } if (mWidth >= 0) { resultString += - (if (resultString.isBlank()) "" else ", ") + "'${GSFAxes.WIDTH}' $mWidth" + (if (resultString.isBlank()) "" else ", ") + "'${GSFAxes.WIDTH.tag}' $mWidth" } if (mOpticalSize >= 0) { resultString += (if (resultString.isBlank()) "" else ", ") + - "'${GSFAxes.OPTICAL_SIZE}' $mOpticalSize" + "'${GSFAxes.OPTICAL_SIZE.tag}' $mOpticalSize" } if (mRoundness >= 0) { resultString += - (if (resultString.isBlank()) "" else ", ") + "'${GSFAxes.ROUND}' $mRoundness" + (if (resultString.isBlank()) "" else ", ") + "'${GSFAxes.ROUND.tag}' $mRoundness" } return if (isUpdated) resultString else "" } diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/GSFAxes.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/GSFAxes.kt new file mode 100644 index 000000000000..f4e03613169a --- /dev/null +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/GSFAxes.kt @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.animation + +data class AxisDefinition( + val tag: String, + val minValue: Float, + val defaultValue: Float, + val maxValue: Float, + val animationStep: Float, +) + +object GSFAxes { + val WEIGHT = + AxisDefinition( + tag = "wght", + minValue = 1f, + defaultValue = 400f, + maxValue = 1000f, + animationStep = 10f, + ) + + val WIDTH = + AxisDefinition( + tag = "wdth", + minValue = 25f, + defaultValue = 100f, + maxValue = 151f, + animationStep = 1f, + ) + + val SLANT = + AxisDefinition( + tag = "slnt", + minValue = 0f, + defaultValue = 0f, + maxValue = -10f, + animationStep = 0.1f, + ) + + val ROUND = + AxisDefinition( + tag = "ROND", + minValue = 0f, + defaultValue = 0f, + maxValue = 100f, + animationStep = 1f, + ) + + val GRADE = + AxisDefinition( + tag = "GRAD", + minValue = 0f, + defaultValue = 0f, + maxValue = 100f, + animationStep = 1f, + ) + + val OPTICAL_SIZE = + AxisDefinition( + tag = "opsz", + minValue = 6f, + defaultValue = 18f, + maxValue = 144f, + animationStep = 1f, + ) + + // Not a GSF Axis, but present for FontInterpolator compatibility + val ITALIC = + AxisDefinition( + tag = "ITAL", + minValue = 0f, + defaultValue = 0f, + maxValue = 1f, + animationStep = 0.1f, + ) + + private val AXIS_MAP = + listOf(WEIGHT, WIDTH, SLANT, ROUND, GRADE, OPTICAL_SIZE, ITALIC) + .map { def -> def.tag.toLowerCase() to def } + .toMap() + + fun getAxis(axis: String): AxisDefinition? = AXIS_MAP[axis.toLowerCase()] +} diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockController.kt index 004d1aa1fe93..ac1c5a8dfaf3 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockController.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockController.kt @@ -130,39 +130,25 @@ class FlexClockController(private val clockCtx: ClockContext) : ClockController private val FONT_AXES = listOf( - ClockFontAxis( - key = GSFAxes.WEIGHT, + GSFAxes.WEIGHT.toClockAxis( type = AxisType.Float, - minValue = 25f, currentValue = 400f, - maxValue = 1000f, name = "Weight", description = "Glyph Weight", ), - ClockFontAxis( - key = GSFAxes.WIDTH, + GSFAxes.WIDTH.toClockAxis( type = AxisType.Float, - minValue = 25f, currentValue = 85f, - maxValue = 151f, name = "Width", description = "Glyph Width", ), - ClockFontAxis( - key = GSFAxes.ROUND, + GSFAxes.ROUND.toClockAxis( type = AxisType.Boolean, - minValue = 0f, - currentValue = 0f, - maxValue = 100f, name = "Round", description = "Glyph Roundness", ), - ClockFontAxis( - key = GSFAxes.SLANT, + GSFAxes.SLANT.toClockAxis( type = AxisType.Boolean, - minValue = 0f, - currentValue = 0f, - maxValue = -10f, name = "Slant", description = "Glyph Slant", ), @@ -170,10 +156,10 @@ class FlexClockController(private val clockCtx: ClockContext) : ClockController private val LEGACY_FLEX_SETTINGS = listOf( - ClockFontAxisSetting(GSFAxes.WEIGHT, 600f), - ClockFontAxisSetting(GSFAxes.WIDTH, 100f), - ClockFontAxisSetting(GSFAxes.ROUND, 100f), - ClockFontAxisSetting(GSFAxes.SLANT, 0f), + GSFAxes.WEIGHT.toClockAxisSetting(600f), + GSFAxes.WIDTH.toClockAxisSetting(100f), + GSFAxes.ROUND.toClockAxisSetting(100f), + GSFAxes.SLANT.toClockAxisSetting(0f), ) } } diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt index b2dbd6552955..b4c2f5de290f 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt @@ -132,7 +132,7 @@ class FlexClockFaceController(clockCtx: ClockContext, private val isLargeClock: if (!isLargeClock) { axes = axes.map { axis -> - if (axis.key == GSFAxes.WIDTH && axis.value > SMALL_CLOCK_MAX_WDTH) { + if (axis.key == GSFAxes.WIDTH.tag && axis.value > SMALL_CLOCK_MAX_WDTH) { axis.copy(value = SMALL_CLOCK_MAX_WDTH) } else { axis diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FontUtils.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FontUtils.kt new file mode 100644 index 000000000000..212b1e29d1b8 --- /dev/null +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FontUtils.kt @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.shared.clocks + +import com.android.systemui.animation.AxisDefinition +import com.android.systemui.plugins.clocks.AxisType +import com.android.systemui.plugins.clocks.ClockFontAxis +import com.android.systemui.plugins.clocks.ClockFontAxisSetting + +fun AxisDefinition.toClockAxis( + type: AxisType, + currentValue: Float? = null, + name: String, + description: String, +): ClockFontAxis { + return ClockFontAxis( + key = this.tag, + type = type, + maxValue = this.maxValue, + minValue = this.minValue, + currentValue = currentValue ?: this.defaultValue, + name = name, + description = description, + ) +} + +fun AxisDefinition.toClockAxisSetting(value: Float? = null): ClockFontAxisSetting { + return ClockFontAxisSetting(this.tag, value ?: this.defaultValue) +} diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt index 54be4d81ea06..b7ce20ec32d1 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt @@ -49,6 +49,7 @@ import com.android.systemui.shared.clocks.DigitTranslateAnimator import com.android.systemui.shared.clocks.DimensionParser import com.android.systemui.shared.clocks.FLEX_CLOCK_ID import com.android.systemui.shared.clocks.FontTextStyle +import com.android.systemui.shared.clocks.toClockAxisSetting import java.lang.Thread import kotlin.math.max import kotlin.math.min @@ -585,25 +586,25 @@ open class SimpleDigitalClockTextView( val FIDGET_INTERPOLATOR = PathInterpolator(0.26873f, 0f, 0.45042f, 1f) val FIDGET_DISTS = mapOf( - GSFAxes.WEIGHT to Pair(200f, 500f), - GSFAxes.WIDTH to Pair(30f, 75f), - GSFAxes.ROUND to Pair(0f, 50f), - GSFAxes.SLANT to Pair(0f, -5f), + GSFAxes.WEIGHT.tag to Pair(200f, 500f), + GSFAxes.WIDTH.tag to Pair(30f, 75f), + GSFAxes.ROUND.tag to Pair(0f, 50f), + GSFAxes.SLANT.tag to Pair(0f, -5f), ) val AOD_COLOR = Color.WHITE - val LS_WEIGHT_AXIS = ClockFontAxisSetting(GSFAxes.WEIGHT, 400f) - val AOD_WEIGHT_AXIS = ClockFontAxisSetting(GSFAxes.WEIGHT, 200f) - val WIDTH_AXIS = ClockFontAxisSetting(GSFAxes.WIDTH, 85f) - val ROUND_AXIS = ClockFontAxisSetting(GSFAxes.ROUND, 0f) - val SLANT_AXIS = ClockFontAxisSetting(GSFAxes.SLANT, 0f) + val LS_WEIGHT_AXIS = GSFAxes.WEIGHT.toClockAxisSetting(400f) + val AOD_WEIGHT_AXIS = GSFAxes.WEIGHT.toClockAxisSetting(200f) + val WIDTH_AXIS = GSFAxes.WIDTH.toClockAxisSetting(85f) + val ROUND_AXIS = GSFAxes.ROUND.toClockAxisSetting(0f) + val SLANT_AXIS = GSFAxes.SLANT.toClockAxisSetting(0f) // Axes for Legacy version of the Flex Clock - val FLEX_LS_WEIGHT_AXIS = ClockFontAxisSetting(GSFAxes.WEIGHT, 600f) - val FLEX_AOD_LARGE_WEIGHT_AXIS = ClockFontAxisSetting(GSFAxes.WEIGHT, 74f) - val FLEX_AOD_SMALL_WEIGHT_AXIS = ClockFontAxisSetting(GSFAxes.WEIGHT, 133f) - val FLEX_LS_WIDTH_AXIS = ClockFontAxisSetting(GSFAxes.WIDTH, 100f) - val FLEX_AOD_WIDTH_AXIS = ClockFontAxisSetting(GSFAxes.WIDTH, 43f) - val FLEX_ROUND_AXIS = ClockFontAxisSetting(GSFAxes.ROUND, 100f) + val FLEX_LS_WEIGHT_AXIS = GSFAxes.WEIGHT.toClockAxisSetting(600f) + val FLEX_AOD_LARGE_WEIGHT_AXIS = GSFAxes.WEIGHT.toClockAxisSetting(74f) + val FLEX_AOD_SMALL_WEIGHT_AXIS = GSFAxes.WEIGHT.toClockAxisSetting(133f) + val FLEX_LS_WIDTH_AXIS = GSFAxes.WIDTH.toClockAxisSetting(100f) + val FLEX_AOD_WIDTH_AXIS = GSFAxes.WIDTH.toClockAxisSetting(43f) + val FLEX_ROUND_AXIS = GSFAxes.ROUND.toClockAxisSetting(100f) } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/animation/FontVariationUtilsTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/animation/FontVariationUtilsTest.kt index f44769d522eb..8d3640d8d809 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/animation/FontVariationUtilsTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/animation/FontVariationUtilsTest.kt @@ -21,7 +21,7 @@ class FontVariationUtilsTest : SysuiTestCase() { roundness = 100, ) Assert.assertEquals( - "'${GSFAxes.WEIGHT}' 100, '${GSFAxes.WIDTH}' 100, '${GSFAxes.ROUND}' 100", + "'${GSFAxes.WEIGHT.tag}' 100, '${GSFAxes.WIDTH.tag}' 100, '${GSFAxes.ROUND.tag}' 100", initFvar, ) val updatedFvar = @@ -32,7 +32,8 @@ class FontVariationUtilsTest : SysuiTestCase() { roundness = 100, ) Assert.assertEquals( - "'${GSFAxes.WEIGHT}' 200, '${GSFAxes.WIDTH}' 100, '${GSFAxes.OPTICAL_SIZE}' 0, '${GSFAxes.ROUND}' 100", + "'${GSFAxes.WEIGHT.tag}' 200, '${GSFAxes.WIDTH.tag}' 100," + + " '${GSFAxes.OPTICAL_SIZE.tag}' 0, '${GSFAxes.ROUND.tag}' 100", updatedFvar, ) } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorControllerTest.kt index a1772e3f62ed..510167d10db4 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorControllerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorControllerTest.kt @@ -10,6 +10,7 @@ import com.android.systemui.coroutines.collectLastValue import com.android.systemui.jank.interactionJankMonitor import com.android.systemui.kosmos.testScope import com.android.systemui.res.R +import com.android.systemui.statusbar.notification.collection.GroupEntry import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder import com.android.systemui.statusbar.notification.data.repository.NotificationLaunchAnimationRepository @@ -165,7 +166,10 @@ class NotificationTransitionAnimatorControllerTest : SysuiTestCase() { .setSummary(summary) .addChild(notification.entry) .build() - assertSame(summary, notification.entry.parent?.summary) + + val parentSummary = if (notification.entry.parent is GroupEntry) + (notification.entry.parent as GroupEntry).summary else null + assertSame(summary, parentSummary) `when`(headsUpManager.isHeadsUpEntry(notificationKey)).thenReturn(false) `when`(headsUpManager.isHeadsUpEntry(summary.key)).thenReturn(true) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt index 99bd4fc549a8..d9c91771043b 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt @@ -26,6 +26,7 @@ import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder import com.android.systemui.statusbar.notification.collection.ListEntry import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.getAttachState import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner @@ -409,7 +410,7 @@ private fun buildSection( ): NotifSection { return NotifSection(object : NotifSectioner("Section $index (bucket=$bucket)", bucket) { - override fun isInSection(entry: ListEntry?): Boolean { + override fun isInSection(entry: PipelineEntry?): Boolean { throw NotImplementedError("This should never be called") } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt index e6fbc725af04..4a05804f663a 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt @@ -24,6 +24,7 @@ import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder import com.android.systemui.statusbar.notification.collection.ListEntry import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.ShadeListBuilder import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderEntryListener import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderGroupListener @@ -40,6 +41,7 @@ import org.mockito.kotlin.spy import org.mockito.kotlin.times import org.mockito.kotlin.verify import org.mockito.kotlin.verifyNoMoreInteractions +import java.nio.channels.Pipe @SmallTest @RunWith(AndroidJUnit4::class) @@ -198,7 +200,7 @@ class RenderStageManagerTest : SysuiTestCase() { ) private class FakeNotifViewRenderer : NotifViewRenderer { - override fun onRenderList(notifList: List<ListEntry>) {} + override fun onRenderList(notifList: List<PipelineEntry>) {} override fun getGroupController(group: GroupEntry): NotifGroupController = mock() diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java index 9ebb15f43307..c82243934b8b 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java @@ -19,6 +19,7 @@ package com.android.systemui.shared.recents.utilities; import static android.app.StatusBarManager.NAVBAR_BACK_DISMISS_IME; import static android.app.StatusBarManager.NAVBAR_IME_SWITCHER_BUTTON_VISIBLE; import static android.app.StatusBarManager.NAVBAR_IME_VISIBLE; +import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import android.annotation.TargetApi; import android.app.StatusBarManager.NavbarFlags; @@ -35,6 +36,8 @@ import android.util.DisplayMetrics; import android.view.Surface; import android.view.WindowManager; +import com.android.systemui.shared.recents.model.Task; + /* Common code */ public class Utilities { @@ -165,4 +168,10 @@ public class Utilities { float densityRatio = (float) densityDpi / DisplayMetrics.DENSITY_DEFAULT; return (size / densityRatio); } + + /** Whether a task is in freeform mode. */ + public static boolean isFreeformTask(Task task) { + return task != null && task.getKey() != null + && task.getKey().windowingMode == WINDOWING_MODE_FREEFORM; + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorController.kt index 383227d2b3aa..ab40582afc10 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorController.kt @@ -21,6 +21,7 @@ import android.view.ViewGroup import com.android.internal.jank.InteractionJankMonitor import com.android.systemui.animation.ActivityTransitionAnimator import com.android.systemui.animation.TransitionAnimator +import com.android.systemui.statusbar.notification.collection.GroupEntry import com.android.systemui.statusbar.notification.domain.interactor.NotificationLaunchAnimationInteractor import com.android.systemui.statusbar.notification.headsup.HeadsUpManager import com.android.systemui.statusbar.notification.headsup.HeadsUpUtil @@ -157,8 +158,8 @@ class NotificationTransitionAnimatorController( private val headsUpNotificationRow: ExpandableNotificationRow? get() { - val summaryEntry = notificationEntry.parent?.summary - + val pipelineParent = notificationEntry.parent + val summaryEntry = (pipelineParent as? GroupEntry)?.summary return when { headsUpManager.isHeadsUpEntry(notificationKey) -> notification summaryEntry == null -> null diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java index c6775d6dc051..31bcf2bc819b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java @@ -26,6 +26,7 @@ import com.android.internal.util.ContrastColorUtil; import com.android.systemui.res.R; import com.android.systemui.statusbar.notification.collection.EntryAdapter; import com.android.systemui.statusbar.notification.collection.ListEntry; +import com.android.systemui.statusbar.notification.collection.PipelineEntry; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.util.Compile; @@ -80,7 +81,7 @@ public class NotificationUtils { private static final boolean INCLUDE_HASH_CODE_IN_LIST_ENTRY_LOG_KEY = false; /** Get the notification key, reformatted for logging, for the (optional) entry */ - public static String logKey(ListEntry entry) { + public static String logKey(PipelineEntry entry) { if (entry == null) { return "null"; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.kt index 432bac49fa9b..2c29e30f9660 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.kt @@ -17,10 +17,10 @@ package com.android.systemui.statusbar.notification import android.service.notification.StatusBarNotification -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry /** Get the notification key, reformatted for logging, for the (optional) entry */ -val ListEntry?.logKey: String? +val PipelineEntry?.logKey: String? get() = this?.let { NotificationUtils.logKey(it) } /** Get the notification key, reformatted for logging, for the (optional) sbn */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/BundleEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/BundleEntry.java index 24ab6959b9e1..35a28288c631 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/BundleEntry.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/BundleEntry.java @@ -29,26 +29,54 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.android.systemui.statusbar.notification.icon.IconPack; +import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import java.util.List; /** - * Abstract class to represent notification section bundled by AI. + * Class to represent notifications bundled by classification. */ public class BundleEntry extends PipelineEntry { - private final String mKey; private final BundleEntryAdapter mEntryAdapter; // TODO (b/389839319): implement the row private ExpandableNotificationRow mRow; public BundleEntry(String key) { - mKey = key; + super(key); mEntryAdapter = new BundleEntryAdapter(); } + @Nullable + @Override + public NotificationEntry getRepresentativeEntry() { + return null; + } + + @Nullable + @Override + public NotifSection getSection() { + return null; + } + + @Override + public int getSectionIndex() { + return 0; + } + + @Nullable + @Override + public PipelineEntry getParent() { + return null; + } + + @Override + public boolean wasAttachedInPreviousPass() { + return false; + } + @VisibleForTesting public BundleEntryAdapter getEntryAdapter() { return mEntryAdapter; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java index 918843cedd2e..8726e83d7ddf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java @@ -75,6 +75,7 @@ public class GroupEntry extends ListEntry { return mChildren; } + // TODO(b/394483200) Change ROOT_ENTRY to PipelineEntry public static final GroupEntry ROOT_ENTRY = new GroupEntry("<root>", 0); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt index b5fce4163bb0..4a1b9568c714 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt @@ -21,14 +21,14 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter /** - * Stores the state that [ShadeListBuilder] assigns to this [ListEntry] + * Stores the state that [ShadeListBuilder] assigns to this [PipelineEntry] */ data class ListAttachState private constructor( /** * Null if not attached to the current shade list. If top-level, then the shade list root. If * part of a group, then that group's GroupEntry. */ - var parent: GroupEntry?, + var parent: PipelineEntry?, /** * The section that this ListEntry was sorted into. If the child of the group, this will be the diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java index f6a572ec6ce6..60b75b1fd8c8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java @@ -39,14 +39,14 @@ public class ListDumper { * entry to be in its current state (ie: filter, lifeExtender) */ public static String dumpTree( - List<ListEntry> entries, + List<PipelineEntry> entries, NotificationInteractionTracker interactionTracker, boolean includeRecordKeeping, String indent) { StringBuilder sb = new StringBuilder(); final String childEntryIndent = indent + INDENT; for (int topEntryIndex = 0; topEntryIndex < entries.size(); topEntryIndex++) { - ListEntry entry = entries.get(topEntryIndex); + PipelineEntry entry = entries.get(topEntryIndex); dumpEntry(entry, Integer.toString(topEntryIndex), indent, @@ -106,7 +106,7 @@ public class ListDumper { } private static void dumpEntry( - ListEntry entry, + PipelineEntry entry, String index, String indent, StringBuilder sb, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java index c8e3be4e57b4..697d0a06cf9d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java @@ -21,28 +21,18 @@ import android.annotation.UptimeMillisLong; import androidx.annotation.Nullable; -import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection; - /** * Abstract superclass for top-level entries, i.e. things that can appear in the final notification * list shown to users. In practice, this means either GroupEntries or NotificationEntries. */ public abstract class ListEntry extends PipelineEntry { - private final String mKey; private final long mCreationTime; - private final ListAttachState mPreviousAttachState = ListAttachState.create(); - private final ListAttachState mAttachState = ListAttachState.create(); - protected ListEntry(String key, long creationTime) { - mKey = key; + super(key); mCreationTime = creationTime; } - public String getKey() { - return mKey; - } - /** * The SystemClock.uptimeMillis() when this object was created. In general, this means the * moment when NotificationManager notifies our listener about the existence of this entry. @@ -64,34 +54,22 @@ public abstract class ListEntry extends PipelineEntry { */ public abstract @Nullable NotificationEntry getRepresentativeEntry(); - @Nullable public GroupEntry getParent() { + @Nullable public PipelineEntry getParent() { return mAttachState.getParent(); } - void setParent(@Nullable GroupEntry parent) { + void setParent(@Nullable PipelineEntry parent) { mAttachState.setParent(parent); } - @Nullable public GroupEntry getPreviousParent() { + @Nullable public PipelineEntry getPreviousParent() { return mPreviousAttachState.getParent(); } - @Nullable public NotifSection getSection() { - return mAttachState.getSection(); - } - public int getSectionIndex() { return mAttachState.getSection() != null ? mAttachState.getSection().getIndex() : -1; } - ListAttachState getAttachState() { - return mAttachState; - } - - ListAttachState getPreviousAttachState() { - return mPreviousAttachState; - } - /** * Stores the current attach state into {@link #getPreviousAttachState()}} and then starts a * fresh attach state (all entries will be null/default-initialized). @@ -100,11 +78,4 @@ public abstract class ListEntry extends PipelineEntry { mPreviousAttachState.clone(mAttachState); mAttachState.reset(); } - - /** - * True if this entry was attached in the last pass, else false. - */ - public boolean wasAttachedInPreviousPass() { - return getPreviousAttachState().getParent() != null; - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java index 698a56363465..e5b72d459069 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java @@ -305,8 +305,10 @@ public final class NotificationEntry extends ListEntry { if (isTopLevelEntry() || getParent() == null) { return null; } - if (NotificationEntry.this.getParent().getSummary() != null) { - return NotificationEntry.this.getParent().getSummary().mEntryAdapter; + if (NotificationEntry.this.getParent() instanceof GroupEntry parentGroupEntry) { + if (parentGroupEntry.getSummary() != null) { + return parentGroupEntry.getSummary().mEntryAdapter; + } } return null; } @@ -588,7 +590,7 @@ public final class NotificationEntry extends ListEntry { * Get the children that are actually attached to this notification's row. * * TODO: Seems like most callers here should probably be using - * {@link GroupMembershipManager#getChildren(ListEntry)} + * {@link GroupMembershipManager#getChildren(PipelineEntry)} */ public @Nullable List<NotificationEntry> getAttachedNotifChildren() { if (row == null) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/PipelineEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/PipelineEntry.java index c5a479180329..78652ccda1d1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/PipelineEntry.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/PipelineEntry.java @@ -16,8 +16,74 @@ package com.android.systemui.statusbar.notification.collection; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection; + /** * Class to represent a notification, group, or bundle in the pipeline. */ public abstract class PipelineEntry { + + final String mKey; + final ListAttachState mAttachState = ListAttachState.create(); + final ListAttachState mPreviousAttachState = ListAttachState.create(); + + public PipelineEntry(String key) { + this.mKey = key; + } + + /** + * Key of the representative entry. + */ + public @NonNull String getKey() { + return mKey; + } + + /** + * @return The representative NotificationEntry: + * for NotificationEntry, return itself + * for GroupEntry, return the summary NotificationEntry, or null if it does not exist + * for BundleEntry, return null + */ + public abstract @Nullable NotificationEntry getRepresentativeEntry(); + + /** + * @return NotifSection that ShadeListBuilder assigned to this PipelineEntry. + */ + @Nullable public NotifSection getSection() { + return mAttachState.getSection(); + } + + /** + * @return True if this entry was attached in the last pass, else false. + */ + public boolean wasAttachedInPreviousPass() { + return getPreviousAttachState().getParent() != null; + } + + /** + * @return Index of section assigned to this entry. + */ + public abstract int getSectionIndex(); + + /** + * @return Parent PipelineEntry + */ + public abstract @Nullable PipelineEntry getParent(); + + /** + * @return Current state that ShadeListBuilder assigned to this PipelineEntry. + */ + final ListAttachState getAttachState() { + return mAttachState; + } + + /** + * @return Previous state that ShadeListBuilder assigned to this PipelineEntry. + */ + final ListAttachState getPreviousAttachState() { + return mPreviousAttachState; + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java index ac11c15e8bf8..bb84ab8f421a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java @@ -100,15 +100,15 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { private final DumpManager mDumpManager; // used exclusivly by ShadeListBuilder#notifySectionEntriesUpdated // TODO replace temp with collection pool for readability - private final ArrayList<ListEntry> mTempSectionMembers = new ArrayList<>(); + private final ArrayList<PipelineEntry> mTempSectionMembers = new ArrayList<>(); private NotifPipelineFlags mFlags; private final boolean mAlwaysLogList; - private List<ListEntry> mNotifList = new ArrayList<>(); - private List<ListEntry> mNewNotifList = new ArrayList<>(); + private List<PipelineEntry> mNotifList = new ArrayList<>(); + private List<PipelineEntry> mNewNotifList = new ArrayList<>(); private final SemiStableSort mSemiStableSort = new SemiStableSort(); - private final StableOrder<ListEntry> mStableOrder = this::getStableOrderRank; + private final StableOrder<PipelineEntry> mStableOrder = this::getStableOrderRank; private final PipelineState mPipelineState = new PipelineState(); private final Map<String, GroupEntry> mGroups = new ArrayMap<>(); private Collection<NotificationEntry> mAllEntries = Collections.emptyList(); @@ -133,8 +133,8 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { mOnBeforeRenderListListeners = new NamedListenerSet<>(); @Nullable private OnRenderListListener mOnRenderListListener; - private List<ListEntry> mReadOnlyNotifList = Collections.unmodifiableList(mNotifList); - private List<ListEntry> mReadOnlyNewNotifList = Collections.unmodifiableList(mNewNotifList); + private List<PipelineEntry> mReadOnlyNotifList = Collections.unmodifiableList(mNotifList); + private List<PipelineEntry> mReadOnlyNewNotifList = Collections.unmodifiableList(mNewNotifList); private final NotifPipelineChoreographer mChoreographer; private int mConsecutiveReentrantRebuilds = 0; @@ -308,7 +308,7 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { } } - List<ListEntry> getShadeList() { + List<PipelineEntry> getShadeList() { Assert.isMainThread(); // NOTE: Accessing this method when the pipeline is running is generally going to provide // incorrect results, and indicates a poorly behaved component of the pipeline. @@ -493,7 +493,7 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { Trace.beginSection("ShadeListBuilder.notifySectionEntriesUpdated"); mTempSectionMembers.clear(); for (NotifSection section : mNotifSections) { - for (ListEntry entry : mNotifList) { + for (PipelineEntry entry : mNotifList) { if (section == entry.getSection()) { mTempSectionMembers.add(entry); } @@ -514,11 +514,11 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { */ private void applyNewNotifList() { mNotifList.clear(); - List<ListEntry> emptyList = mNotifList; + List<PipelineEntry> emptyList = mNotifList; mNotifList = mNewNotifList; mNewNotifList = emptyList; - List<ListEntry> readOnlyNotifList = mReadOnlyNotifList; + List<PipelineEntry> readOnlyNotifList = mReadOnlyNotifList; mReadOnlyNotifList = mReadOnlyNewNotifList; mReadOnlyNewNotifList = readOnlyNotifList; } @@ -538,12 +538,12 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { } private void filterNotifs( - Collection<? extends ListEntry> entries, - List<ListEntry> out, + Collection<? extends PipelineEntry> entries, + List<PipelineEntry> out, List<NotifFilter> filters) { Trace.beginSection("ShadeListBuilder.filterNotifs"); final long now = mSystemClock.uptimeMillis(); - for (ListEntry entry : entries) { + for (PipelineEntry entry : entries) { if (entry instanceof GroupEntry) { final GroupEntry groupEntry = (GroupEntry) entry; @@ -576,11 +576,11 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { Trace.endSection(); } - private void groupNotifs(List<ListEntry> entries, List<ListEntry> out) { + private void groupNotifs(List<PipelineEntry> entries, List<PipelineEntry> out) { Trace.beginSection("ShadeListBuilder.groupNotifs"); - for (ListEntry listEntry : entries) { + for (PipelineEntry PipelineEntry : entries) { // since grouping hasn't happened yet, all notifs are NotificationEntries - NotificationEntry entry = (NotificationEntry) listEntry; + NotificationEntry entry = (NotificationEntry) PipelineEntry; if (entry.getSbn().isGroup()) { final String topLevelKey = entry.getSbn().getGroupKey(); @@ -631,14 +631,14 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { Trace.endSection(); } - private void stabilizeGroupingNotifs(List<ListEntry> topLevelList) { + private void stabilizeGroupingNotifs(List<PipelineEntry> topLevelList) { if (getStabilityManager().isEveryChangeAllowed()) { return; } Trace.beginSection("ShadeListBuilder.stabilizeGroupingNotifs"); for (int i = 0; i < topLevelList.size(); i++) { - final ListEntry tle = topLevelList.get(i); + final PipelineEntry tle = topLevelList.get(i); if (tle instanceof GroupEntry) { // maybe put children back into their old group (including moving back to top-level) GroupEntry groupEntry = (GroupEntry) tle; @@ -667,13 +667,13 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { /** * Returns true if the group change was suppressed, else false */ - private boolean maybeSuppressGroupChange(NotificationEntry entry, List<ListEntry> out) { - final GroupEntry prevParent = entry.getPreviousAttachState().getParent(); + private boolean maybeSuppressGroupChange(NotificationEntry entry, List<PipelineEntry> out) { + final PipelineEntry prevParent = entry.getPreviousAttachState().getParent(); if (prevParent == null) { // New entries are always allowed. return false; } - final GroupEntry assignedParent = entry.getParent(); + final PipelineEntry assignedParent = entry.getParent(); if (prevParent == assignedParent) { // Nothing to change. return false; @@ -691,21 +691,22 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { entry.setParent(prevParent); if (prevParent == ROOT_ENTRY) { out.add(entry); - } else { - prevParent.addChild(entry); + } else if (prevParent instanceof GroupEntry) { + ((GroupEntry) prevParent).addChild(entry); if (!mGroups.containsKey(prevParent.getKey())) { - mGroups.put(prevParent.getKey(), prevParent); + mGroups.put(prevParent.getKey(), (GroupEntry) prevParent); } } + // TODO(b/394483200): Revisit group stability for BundleEntry return true; } return false; } - private void promoteNotifs(List<ListEntry> list) { + private void promoteNotifs(List<PipelineEntry> list) { Trace.beginSection("ShadeListBuilder.promoteNotifs"); for (int i = 0; i < list.size(); i++) { - final ListEntry tle = list.get(i); + final PipelineEntry tle = list.get(i); if (tle instanceof GroupEntry) { final GroupEntry group = (GroupEntry) tle; @@ -725,7 +726,7 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { Trace.endSection(); } - private void pruneIncompleteGroups(List<ListEntry> shadeList) { + private void pruneIncompleteGroups(List<PipelineEntry> shadeList) { Trace.beginSection("ShadeListBuilder.pruneIncompleteGroups"); // Any group which lost a child on this run to stability is exempt from being pruned or // having its summary promoted, regardless of how many children it has @@ -742,7 +743,7 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { // Iterate backwards, so that we can remove elements without affecting indices of // yet-to-be-accessed entries. for (int i = shadeList.size() - 1; i >= 0; i--) { - final ListEntry tle = shadeList.get(i); + final PipelineEntry tle = shadeList.get(i); if (tle instanceof GroupEntry) { final GroupEntry group = (GroupEntry) tle; @@ -793,7 +794,7 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { Trace.endSection(); } - private void pruneGroupAtIndexAndPromoteSummary(List<ListEntry> shadeList, + private void pruneGroupAtIndexAndPromoteSummary(List<PipelineEntry> shadeList, GroupEntry group, int index) { // Validate that the group has no children checkArgument(group.getChildren().isEmpty(), "group should have no children"); @@ -801,7 +802,7 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { NotificationEntry summary = group.getSummary(); summary.setParent(ROOT_ENTRY); // The list may be sorted; replace the group with the summary, in its place - ListEntry oldEntry = shadeList.set(index, summary); + PipelineEntry oldEntry = shadeList.set(index, summary); // Validate that the replaced entry was the group entry checkState(oldEntry == group); @@ -812,10 +813,10 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { "SUMMARY with no children @ " + mPipelineState.getStateName()); } - private void pruneGroupAtIndexAndPromoteAnyChildren(List<ListEntry> shadeList, + private void pruneGroupAtIndexAndPromoteAnyChildren(List<PipelineEntry> shadeList, GroupEntry group, int index) { // REMOVE the GroupEntry at this index - ListEntry oldEntry = shadeList.remove(index); + PipelineEntry oldEntry = shadeList.remove(index); // Validate that the replaced entry was the group entry checkState(oldEntry == group); @@ -868,14 +869,14 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { * top level (ungrouped) notifications. */ @NonNull - private Set<String> getGroupsWithChildrenLostToStability(List<ListEntry> shadeList) { + private Set<String> getGroupsWithChildrenLostToStability(List<PipelineEntry> shadeList) { if (getStabilityManager().isEveryChangeAllowed()) { return Collections.emptySet(); } ArraySet<String> groupsWithChildrenLostToStability = new ArraySet<>(); for (int i = 0; i < shadeList.size(); i++) { - final ListEntry tle = shadeList.get(i); - final GroupEntry suppressedParent = + final PipelineEntry tle = shadeList.get(i); + final PipelineEntry suppressedParent = tle.getAttachState().getSuppressedChanges().getParent(); if (suppressedParent != null) { // This top-level-entry was supposed to be attached to this group, @@ -892,9 +893,10 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { * * These groups will be exempt from appearing without any children. */ - private void addGroupsWithChildrenLostToPromotion(List<ListEntry> shadeList, Set<String> out) { + private void addGroupsWithChildrenLostToPromotion(List<PipelineEntry> shadeList, + Set<String> out) { for (int i = 0; i < shadeList.size(); i++) { - final ListEntry tle = shadeList.get(i); + final PipelineEntry tle = shadeList.get(i); if (tle.getAttachState().getPromoter() != null) { // This top-level-entry was part of a group, but was promoted out of it. final String groupKey = tle.getRepresentativeEntry().getSbn().getGroupKey(); @@ -910,7 +912,7 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { * These groups will be exempt from appearing without any children. */ private void addGroupsWithChildrenLostToFiltering(Set<String> out) { - for (ListEntry tle : mAllEntries) { + for (PipelineEntry tle : mAllEntries) { StatusBarNotification sbn = tle.getRepresentativeEntry().getSbn(); if (sbn.isGroup() && !sbn.getNotification().isGroupSummary() @@ -921,14 +923,14 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { } /** - * If a ListEntry was added to the shade list and then later removed (e.g. because it was a + * If a PipelineEntry was added to the shade list and then later removed (e.g. because it was a * group that was broken up), this method will erase any bookkeeping traces of that addition * and/or check that they were already erased. * * Before calling this method, the entry must already have been removed from its parent. If * it's a group, its summary must be null and its children must be empty. */ - private void annulAddition(ListEntry entry, List<ListEntry> shadeList) { + private void annulAddition(PipelineEntry entry, List<PipelineEntry> shadeList) { // This function does very little, but if any of its assumptions are violated (and it has a // lot of them), it will put the system into an inconsistent state. So we check all of them @@ -956,9 +958,11 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { throw new IllegalStateException( "Cannot nullify group " + ge.getKey() + ": still has children"); } - } else if (entry instanceof NotificationEntry) { - if (entry == entry.getParent().getSummary() - || entry.getParent().getChildren().contains(entry)) { + } else if (entry instanceof NotificationEntry + && entry.getParent() instanceof GroupEntry) { + GroupEntry parentGroupEntry = (GroupEntry) entry.getParent(); + if (entry == parentGroupEntry.getSummary() + || parentGroupEntry.getChildren().contains(entry)) { throw new IllegalStateException("Cannot nullify addition of child " + entry.getKey() + ": it's still attached to its parent."); } @@ -973,14 +977,14 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { * This can happen if the entry is removed from a group that was broken up or if the entry was * filtered out during any of the filtering steps. */ - private void annulAddition(ListEntry entry) { + private void annulAddition(PipelineEntry entry) { entry.getAttachState().detach(); } private void assignSections() { Trace.beginSection("ShadeListBuilder.assignSections"); // Assign sections to top-level elements and their children - for (ListEntry entry : mNotifList) { + for (PipelineEntry entry : mNotifList) { NotifSection section = applySections(entry); if (entry instanceof GroupEntry) { GroupEntry parent = (GroupEntry) entry; @@ -1001,7 +1005,7 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { private void sortWithSemiStableSort() { // Sort each group's children boolean allSorted = true; - for (ListEntry entry : mNotifList) { + for (PipelineEntry entry : mNotifList) { if (entry instanceof GroupEntry) { GroupEntry parent = (GroupEntry) entry; allSorted &= sortGroupChildren(parent.getRawChildren()); @@ -1010,7 +1014,7 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { // Sort each section within the top level list mNotifList.sort(mTopLevelComparator); if (!getStabilityManager().isEveryChangeAllowed()) { - for (List<ListEntry> subList : getSectionSubLists(mNotifList)) { + for (List<PipelineEntry> subList : getSectionSubLists(mNotifList)) { allSorted &= mSemiStableSort.stabilizeTo(subList, mStableOrder, mNewNotifList); } applyNewNotifList(); @@ -1022,7 +1026,7 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { } } - private Iterable<List<ListEntry>> getSectionSubLists(List<ListEntry> entries) { + private Iterable<List<PipelineEntry>> getSectionSubLists(List<PipelineEntry> entries) { return ShadeListBuilderHelper.INSTANCE.getSectionSubLists(entries); } @@ -1057,12 +1061,12 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { /** * Assign the index of each notification relative to the total order */ - private void assignIndexes(List<ListEntry> notifList) { + private void assignIndexes(List<PipelineEntry> notifList) { if (notifList.size() == 0) return; NotifSection currentSection = requireNonNull(notifList.get(0).getSection()); int sectionMemberIndex = 0; for (int i = 0; i < notifList.size(); i++) { - final ListEntry entry = notifList.get(i); + final PipelineEntry entry = notifList.get(i); NotifSection section = requireNonNull(entry.getSection()); if (section.getIndex() != currentSection.getIndex()) { sectionMemberIndex = 0; @@ -1099,7 +1103,7 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { Trace.endSection(); } - private void logAttachStateChanges(ListEntry entry) { + private void logAttachStateChanges(PipelineEntry entry) { final ListAttachState curr = entry.getAttachState(); final ListAttachState prev = entry.getPreviousAttachState(); @@ -1115,8 +1119,8 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { mLogger.logParentChanged(mIterationCount, prev.getParent(), curr.getParent()); } - GroupEntry currSuppressedParent = curr.getSuppressedChanges().getParent(); - GroupEntry prevSuppressedParent = prev.getSuppressedChanges().getParent(); + PipelineEntry currSuppressedParent = curr.getSuppressedChanges().getParent(); + PipelineEntry prevSuppressedParent = prev.getSuppressedChanges().getParent(); if (currSuppressedParent != null && (prevSuppressedParent == null || !prevSuppressedParent.getKey().equals(currSuppressedParent.getKey()))) { mLogger.logParentChangeSuppressedStarted( @@ -1210,7 +1214,7 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { @Nullable private NotifComparator getSectionComparator( - @NonNull ListEntry o1, @NonNull ListEntry o2) { + @NonNull PipelineEntry o1, @NonNull PipelineEntry o2) { final NotifSection section = o1.getSection(); if (section != o2.getSection()) { throw new RuntimeException("Entry ordering should only be done within sections"); @@ -1221,7 +1225,7 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { return null; } - private final Comparator<ListEntry> mTopLevelComparator = (o1, o2) -> { + private final Comparator<PipelineEntry> mTopLevelComparator = (o1, o2) -> { int cmp = Integer.compare( o1.getSectionIndex(), o2.getSectionIndex()); @@ -1264,7 +1268,7 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { }; @Nullable - private Integer getStableOrderRank(ListEntry entry) { + private Integer getStableOrderRank(PipelineEntry entry) { if (getStabilityManager().isEntryReorderingAllowed(entry)) { // let the stability manager constrain or allow reordering return null; @@ -1323,7 +1327,7 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { return null; } - private NotifSection applySections(ListEntry entry) { + private NotifSection applySections(PipelineEntry entry) { final NotifSection newSection = findSection(entry); final ListAttachState prevAttachState = entry.getPreviousAttachState(); @@ -1346,7 +1350,7 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { return finalSection; } - private void setEntrySection(ListEntry entry, NotifSection finalSection) { + private void setEntrySection(PipelineEntry entry, NotifSection finalSection) { entry.getAttachState().setSection(finalSection); NotificationEntry representativeEntry = entry.getRepresentativeEntry(); if (representativeEntry != null) { @@ -1358,7 +1362,7 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { } @NonNull - private NotifSection findSection(ListEntry entry) { + private NotifSection findSection(PipelineEntry entry) { for (int i = 0; i < mNotifSections.size(); i++) { NotifSection section = mNotifSections.get(i); if (section.getSectioner().isInSection(entry)) { @@ -1428,10 +1432,10 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { mChoreographer.schedule(); } - private static int countChildren(List<ListEntry> entries) { + private static int countChildren(List<PipelineEntry> entries) { int count = 0; for (int i = 0; i < entries.size(); i++) { - final ListEntry entry = entries.get(i); + final PipelineEntry entry = entries.get(i); if (entry instanceof GroupEntry) { count += ((GroupEntry) entry).getChildren().size(); } @@ -1439,7 +1443,7 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { return count; } - private void dispatchOnBeforeTransformGroups(List<ListEntry> entries) { + private void dispatchOnBeforeTransformGroups(List<PipelineEntry> entries) { Trace.beginSection("ShadeListBuilder.dispatchOnBeforeTransformGroups"); mOnBeforeTransformGroupsListeners.forEachTraced(listener -> { listener.onBeforeTransformGroups(entries); @@ -1447,7 +1451,7 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { Trace.endSection(); } - private void dispatchOnBeforeSort(List<ListEntry> entries) { + private void dispatchOnBeforeSort(List<PipelineEntry> entries) { Trace.beginSection("ShadeListBuilder.dispatchOnBeforeSort"); mOnBeforeSortListeners.forEachTraced(listener -> { listener.onBeforeSort(entries); @@ -1455,7 +1459,7 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { Trace.endSection(); } - private void dispatchOnBeforeFinalizeFilter(List<ListEntry> entries) { + private void dispatchOnBeforeFinalizeFilter(List<PipelineEntry> entries) { Trace.beginSection("ShadeListBuilder.dispatchOnBeforeFinalizeFilter"); mOnBeforeFinalizeFilterListeners.forEachTraced(listener -> { listener.onBeforeFinalizeFilter(entries); @@ -1463,7 +1467,7 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { Trace.endSection(); } - private void dispatchOnBeforeRenderList(List<ListEntry> entries) { + private void dispatchOnBeforeRenderList(List<PipelineEntry> entries) { Trace.beginSection("ShadeListBuilder.dispatchOnBeforeRenderList"); mOnBeforeRenderListListeners.forEachTraced(listener -> { listener.onBeforeRenderList(entries); @@ -1508,13 +1512,13 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { * @param entries A read-only view into the current notif list. Note that this list is * backed by the live list and will change in response to new pipeline runs. */ - void onRenderList(@NonNull List<ListEntry> entries); + void onRenderList(@NonNull List<PipelineEntry> entries); } private static final NotifSectioner DEFAULT_SECTIONER = new NotifSectioner("UnknownSection", NotificationPriorityBucketKt.BUCKET_UNKNOWN) { @Override - public boolean isInSection(ListEntry entry) { + public boolean isInSection(PipelineEntry entry) { return true; } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SuppressedAttachState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SuppressedAttachState.kt index 584563b6c388..c9429547a518 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SuppressedAttachState.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SuppressedAttachState.kt @@ -19,7 +19,7 @@ package com.android.systemui.statusbar.notification.collection import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection /** - * Stores the suppressed state that [ShadeListBuilder] assigned to this [ListEntry] before the + * Stores the suppressed state that [ShadeListBuilder] assigned to this [PipelineEntry] before the * VisualStabilityManager suppressed group and section changes. */ data class SuppressedAttachState private constructor( @@ -35,7 +35,7 @@ data class SuppressedAttachState private constructor( * - Root if suppressing group change to top-level * - GroupEntry if suppressing group change to a different group */ - var parent: GroupEntry?, + var parent: PipelineEntry?, /** * Whether the ListEntry would have been pruned had its group change not been suppressed. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BundleCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BundleCoordinator.kt index 244c5946c21e..e6d5f4120a20 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BundleCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BundleCoordinator.kt @@ -20,7 +20,7 @@ import android.app.NotificationChannel.NEWS_ID import android.app.NotificationChannel.PROMOTIONS_ID import android.app.NotificationChannel.RECS_ID import android.app.NotificationChannel.SOCIAL_MEDIA_ID -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner @@ -48,7 +48,7 @@ class BundleCoordinator @Inject constructor( val newsSectioner = object : NotifSectioner("News", BUCKET_NEWS) { - override fun isInSection(entry: ListEntry): Boolean { + override fun isInSection(entry: PipelineEntry): Boolean { return entry.representativeEntry?.channel?.id == NEWS_ID } @@ -59,7 +59,7 @@ class BundleCoordinator @Inject constructor( val socialSectioner = object : NotifSectioner("Social", BUCKET_SOCIAL) { - override fun isInSection(entry: ListEntry): Boolean { + override fun isInSection(entry: PipelineEntry): Boolean { return entry.representativeEntry?.channel?.id == SOCIAL_MEDIA_ID } @@ -70,7 +70,7 @@ class BundleCoordinator @Inject constructor( val recsSectioner = object : NotifSectioner("Recommendations", BUCKET_RECS) { - override fun isInSection(entry: ListEntry): Boolean { + override fun isInSection(entry: PipelineEntry): Boolean { return entry.representativeEntry?.channel?.id == RECS_ID } @@ -81,7 +81,7 @@ class BundleCoordinator @Inject constructor( val promoSectioner = object : NotifSectioner("Promotions", BUCKET_PROMO) { - override fun isInSection(entry: ListEntry): Boolean { + override fun isInSection(entry: PipelineEntry): Boolean { return entry.representativeEntry?.channel?.id == PROMOTIONS_ID } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinator.java index 9df4bf4af4e8..afba85b49c30 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinator.java @@ -25,6 +25,7 @@ import androidx.annotation.Nullable; import com.android.systemui.dagger.qualifiers.Application; import com.android.systemui.statusbar.notification.collection.ListEntry; +import com.android.systemui.statusbar.notification.collection.PipelineEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope; @@ -96,7 +97,7 @@ public class ColorizedFgsCoordinator implements Coordinator { private final NotifSectioner mNotifSectioner = new NotifSectioner("ColorizedSectioner", NotificationPriorityBucketKt.BUCKET_FOREGROUND_SERVICE) { @Override - public boolean isInSection(ListEntry entry) { + public boolean isInSection(PipelineEntry entry) { NotificationEntry notificationEntry = entry.getRepresentativeEntry(); if (notificationEntry != null) { return isRichOngoing(notificationEntry); @@ -117,7 +118,7 @@ public class ColorizedFgsCoordinator implements Coordinator { private final NotifComparator mOngoingComparator = new NotifComparator( "OngoingComparator") { @Override - public int compare(@NonNull ListEntry o1, @NonNull ListEntry o2) { + public int compare(@NonNull PipelineEntry o1, @NonNull PipelineEntry o2) { return Integer.compare( getSortKey(o1.getRepresentativeEntry()), getSortKey(o2.getRepresentativeEntry()) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt index af2c1979ff77..248b5286803f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt @@ -16,7 +16,8 @@ package com.android.systemui.statusbar.notification.collection.coordinator -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.GroupEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.SortBySectionTimeFlag @@ -61,6 +62,7 @@ class ConversationCoordinator @Inject constructor( originalGroup == null -> null originalGroup == promoted.parent -> null originalGroup.parent == null -> null + originalGroup !is GroupEntry -> summary.key originalGroup.summary != summary -> null originalGroup.children.any { it.channel == summary.channel } -> null else -> summary.key @@ -74,7 +76,7 @@ class ConversationCoordinator @Inject constructor( override fun shouldPromoteToTopLevel(entry: NotificationEntry): Boolean { val shouldPromote = entry.channel?.isImportantConversation == true if (shouldPromote) { - val summary = entry.parent?.summary + val summary = (entry.parent as? GroupEntry)?.summary if (summary != null && entry.channel == summary.channel) { promotedEntriesToSummaryOfSameChannel[entry] = summary } @@ -85,14 +87,14 @@ class ConversationCoordinator @Inject constructor( val priorityPeopleSectioner = object : NotifSectioner("Priority People", BUCKET_PRIORITY_PEOPLE) { - override fun isInSection(entry: ListEntry): Boolean { + override fun isInSection(entry: PipelineEntry): Boolean { return getPeopleType(entry) == TYPE_IMPORTANT_PERSON } } // TODO(b/330193582): Rename to just "People" val peopleAlertingSectioner = object : NotifSectioner("People(alerting)", BUCKET_PEOPLE) { - override fun isInSection(entry: ListEntry): Boolean { + override fun isInSection(entry: PipelineEntry): Boolean { if (SortBySectionTimeFlag.isEnabled) { return highPriorityProvider.isHighPriorityConversation(entry) || isConversation(entry) @@ -111,7 +113,7 @@ class ConversationCoordinator @Inject constructor( val peopleSilentSectioner = object : NotifSectioner("People(silent)", BUCKET_PEOPLE) { // Because the peopleAlertingSectioner is above this one, it will claim all conversations that are alerting. // All remaining conversations must be silent. - override fun isInSection(entry: ListEntry): Boolean { + override fun isInSection(entry: PipelineEntry): Boolean { SortBySectionTimeFlag.assertInLegacyMode() return isConversation(entry) } @@ -132,17 +134,17 @@ class ConversationCoordinator @Inject constructor( pipeline.addOnBeforeRenderListListener(onBeforeRenderListListener) } - private fun isConversation(entry: ListEntry): Boolean = + private fun isConversation(entry: PipelineEntry): Boolean = getPeopleType(entry) != TYPE_NON_PERSON @PeopleNotificationType - private fun getPeopleType(entry: ListEntry): Int = + private fun getPeopleType(entry: PipelineEntry): Int = entry.representativeEntry?.let { peopleNotificationIdentifier.getPeopleNotificationType(it) } ?: TYPE_NON_PERSON private val notifComparator: NotifComparator = object : NotifComparator("People") { - override fun compare(entry1: ListEntry, entry2: ListEntry): Int { + override fun compare(entry1: PipelineEntry, entry2: PipelineEntry): Int { val type1 = getPeopleType(entry1) val type2 = getPeopleType(entry2) return type2.compareTo(type1) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinator.kt index 034a4fd2af72..e4ec76c68e6f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinator.kt @@ -17,7 +17,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator import com.android.systemui.statusbar.notification.collection.GroupEntry -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.NotifLiveDataStoreImpl import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.NotificationEntry @@ -43,12 +43,12 @@ internal constructor(private val notifLiveDataStoreImpl: NotifLiveDataStoreImpl) d.dump("notifLiveDataStoreImpl", notifLiveDataStoreImpl) } - private fun onAfterRenderList(entries: List<ListEntry>) { + private fun onAfterRenderList(entries: List<PipelineEntry>) { val flatEntryList = flattenedEntryList(entries) notifLiveDataStoreImpl.setActiveNotifList(flatEntryList) } - private fun flattenedEntryList(entries: List<ListEntry>) = + private fun flattenedEntryList(entries: List<PipelineEntry>) = mutableListOf<NotificationEntry>().also { list -> entries.forEach { entry -> when (entry) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt index 0a9dddc1c75e..6bed0cf054af 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt @@ -17,7 +17,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator import com.android.systemui.statusbar.notification.collection.GroupEntry -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope import com.android.systemui.statusbar.notification.collection.provider.NotificationDismissibilityProviderImpl @@ -37,7 +37,7 @@ constructor( pipeline.addOnBeforeRenderListListener(::onBeforeRenderListListener) } - private fun onBeforeRenderListListener(entries: List<ListEntry>) { + private fun onBeforeRenderListListener(entries: List<PipelineEntry>) { val isLocked = !keyguardStateController.isUnlocked val nonDismissableEntryKeys = mutableSetOf<String>() markNonDismissibleEntries(nonDismissableEntryKeys, entries, isLocked) @@ -54,7 +54,7 @@ constructor( */ private fun markNonDismissibleEntries( markedKeys: MutableSet<String>, - entries: List<ListEntry>, + entries: List<PipelineEntry>, isLocked: Boolean ): Boolean { var anyNonDismissableEntries = false diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinator.kt index 02bf3b3be537..2f0701f96f28 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinator.kt @@ -18,7 +18,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator import android.util.ArrayMap import com.android.systemui.statusbar.notification.collection.GroupEntry -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope import com.android.systemui.statusbar.notification.collection.render.NotifGroupController @@ -34,7 +34,7 @@ class GroupCountCoordinator @Inject constructor() : Coordinator { pipeline.addOnAfterRenderGroupListener(::onAfterRenderGroup) } - private fun onBeforeFinalizeFilter(entries: List<ListEntry>) { + private fun onBeforeFinalizeFilter(entries: List<PipelineEntry>) { // save untruncated child counts to our internal map untruncatedChildCounts.clear() entries.asSequence().filterIsInstance<GroupEntry>().forEach { groupEntry -> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupWhenCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupWhenCoordinator.kt index f253100b3661..d0411b56d92d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupWhenCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupWhenCoordinator.kt @@ -18,7 +18,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator import android.util.ArrayMap import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.statusbar.notification.collection.GroupEntry -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator @@ -52,7 +52,7 @@ constructor( pipeline.addPreRenderInvalidator(invalidator) } - private fun onBeforeFinalizeFilterListener(entries: List<ListEntry>) { + private fun onBeforeFinalizeFilterListener(entries: List<PipelineEntry>) { cancelListInvalidation() notificationGroupTimes.clear() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinator.kt index b200136b1b43..9045aac6ea6f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinator.kt @@ -18,7 +18,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator import android.util.ArraySet import com.android.systemui.Dumpable import com.android.systemui.dump.DumpManager -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope @@ -113,7 +113,7 @@ class GutsCoordinator @Inject constructor( } } - private fun isCurrentlyShowingGuts(entry: ListEntry) = + private fun isCurrentlyShowingGuts(entry: PipelineEntry) = notifsWithOpenGuts.contains(entry.key) private fun closeGutsAndEndLifetimeExtension(entry: NotificationEntry) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt index eb5a3703bcfb..611e0ef77fac 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt @@ -27,7 +27,7 @@ import com.android.systemui.statusbar.chips.notification.domain.interactor.Statu import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips import com.android.systemui.statusbar.notification.NotifPipelineFlags import com.android.systemui.statusbar.notification.collection.GroupEntry -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.NotifCollection import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.NotificationEntry @@ -103,7 +103,7 @@ constructor( mNotifPipeline = pipeline mHeadsUpManager.addListener(mOnHeadsUpChangedListener) pipeline.addCollectionListener(mNotifCollectionListener) - pipeline.addOnBeforeTransformGroupsListener(::onBeforeTransformGroups) + pipeline.addOnBeforeTransformGroupsListener { onBeforeTransformGroups() } pipeline.addOnBeforeFinalizeFilterListener(::onBeforeFinalizeFilter) pipeline.addPromoter(mNotifPromoter) pipeline.addNotificationLifetimeExtender(mLifetimeExtender) @@ -170,7 +170,7 @@ constructor( * Once the pipeline starts running, we can look through posted entries and quickly process any * that don't have groups, and thus will never gave a group heads up edge case. */ - fun onBeforeTransformGroups(list: List<ListEntry>) { + fun onBeforeTransformGroups() { mNow = mSystemClock.currentTimeMillis() if (mPostedEntries.isEmpty()) { return @@ -191,7 +191,7 @@ constructor( * we know that stability and [NotifPromoter]s have been applied, so we can use the location of * notifications in this list to determine what kind of group heads up behavior should happen. */ - fun onBeforeFinalizeFilter(list: List<ListEntry>) = + fun onBeforeFinalizeFilter(list: List<PipelineEntry>) = mHeadsUpManager.modifyHuns { hunMutator -> // Nothing to do if there are no other adds/updates if (mPostedEntries.isEmpty()) { @@ -410,7 +410,7 @@ constructor( ) .firstOrNull() - private fun getGroupLocationsByKey(list: List<ListEntry>): Map<String, GroupLocation> = + private fun getGroupLocationsByKey(list: List<PipelineEntry>): Map<String, GroupLocation> = mutableMapOf<String, GroupLocation>().also { map -> list.forEach { topLevelEntry -> when (topLevelEntry) { @@ -833,13 +833,13 @@ constructor( val sectioner = object : NotifSectioner("HeadsUp", BUCKET_HEADS_UP) { - override fun isInSection(entry: ListEntry): Boolean = + override fun isInSection(entry: PipelineEntry): Boolean = // TODO: This check won't notice if a child of the group is going to HUN... isGoingToShowHunNoRetract(entry) override fun getComparator(): NotifComparator { return object : NotifComparator("HeadsUp") { - override fun compare(o1: ListEntry, o2: ListEntry): Int = + override fun compare(o1: PipelineEntry, o2: PipelineEntry): Int = mHeadsUpManager.compare(o1.representativeEntry, o2.representativeEntry) } } @@ -867,7 +867,7 @@ constructor( private fun isSticky(entry: NotificationEntry) = mHeadsUpManager.isSticky(entry.key) - private fun isEntryBinding(entry: ListEntry): Boolean { + private fun isEntryBinding(entry: PipelineEntry): Boolean { val bindingUntil = mEntriesBindingUntil[entry.key] return bindingUntil != null && bindingUntil >= mNow } @@ -875,12 +875,12 @@ constructor( /** * Whether the notification is already heads up or binding so that it can imminently heads up */ - private fun isAttemptingToShowHun(entry: ListEntry) = + private fun isAttemptingToShowHun(entry: PipelineEntry) = mHeadsUpManager.isHeadsUpEntry(entry.key) || isEntryBinding(entry) || isHeadsUpAnimatingAway(entry) - private fun isHeadsUpAnimatingAway(entry: ListEntry): Boolean { + private fun isHeadsUpAnimatingAway(entry: PipelineEntry): Boolean { if (!GroupHunAnimationFix.isEnabled) return false return entry.representativeEntry?.row?.isHeadsUpAnimatingAway ?: false } @@ -891,7 +891,7 @@ constructor( * returns `true` even if the update would (in isolation of its group) cause the heads up to be * retracted. This is important for not retracting transferred group heads ups. */ - private fun isGoingToShowHunNoRetract(entry: ListEntry) = + private fun isGoingToShowHunNoRetract(entry: PipelineEntry) = mPostedEntries[entry.key]?.calculateShouldBeHeadsUpNoRetract ?: isAttemptingToShowHun(entry) /** @@ -900,7 +900,7 @@ constructor( * strict because any update which would revoke the heads up supersedes the current heads * up/binding state. */ - private fun isGoingToShowHunStrict(entry: ListEntry) = + private fun isGoingToShowHunStrict(entry: PipelineEntry) = mPostedEntries[entry.key]?.calculateShouldBeHeadsUpStrict ?: isAttemptingToShowHun(entry) private fun endNotifLifetimeExtensionIfExtended(entry: NotificationEntry) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/LockScreenMinimalismCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/LockScreenMinimalismCoordinator.kt index e2328497d9ea..56deb18df9ab 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/LockScreenMinimalismCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/LockScreenMinimalismCoordinator.kt @@ -27,7 +27,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.notification.collection.GroupEntry -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope @@ -176,7 +176,7 @@ constructor( } } - private fun pickOutTopUnseenNotifs(list: List<ListEntry>) { + private fun pickOutTopUnseenNotifs(list: List<PipelineEntry>) { if (NotificationMinimalism.isUnexpectedlyInLegacyMode()) return if (!minimalismEnabled) return // Only ever elevate a top unseen notification on keyguard, not even locked shade @@ -224,7 +224,7 @@ constructor( val topOngoingSectioner = object : NotifSectioner("TopOngoing", BUCKET_TOP_ONGOING) { - override fun isInSection(entry: ListEntry): Boolean { + override fun isInSection(entry: PipelineEntry): Boolean { if (NotificationMinimalism.isUnexpectedlyInLegacyMode()) return false if (!minimalismEnabled) return false return entry.anyEntry { notificationEntry -> @@ -235,7 +235,7 @@ constructor( val topUnseenSectioner = object : NotifSectioner("TopUnseen", BUCKET_TOP_UNSEEN) { - override fun isInSection(entry: ListEntry): Boolean { + override fun isInSection(entry: PipelineEntry): Boolean { if (NotificationMinimalism.isUnexpectedlyInLegacyMode()) return false if (!minimalismEnabled) return false return entry.anyEntry { notificationEntry -> @@ -244,7 +244,7 @@ constructor( } } - private fun ListEntry.anyEntry(predicate: (NotificationEntry?) -> Boolean) = + private fun PipelineEntry.anyEntry(predicate: (NotificationEntry?) -> Boolean) = when { predicate(representativeEntry) -> true this !is GroupEntry -> false diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/OriginalUnseenKeyguardCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/OriginalUnseenKeyguardCoordinator.kt index de6f2576ff19..660ee401b369 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/OriginalUnseenKeyguardCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/OriginalUnseenKeyguardCoordinator.kt @@ -30,6 +30,7 @@ import com.android.systemui.scene.domain.interactor.SceneInteractor import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.statusbar.expansionChanges +import com.android.systemui.statusbar.notification.collection.GroupEntry import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope @@ -313,7 +314,7 @@ constructor( unseenNotifications.contains(entry) -> false // Don't apply the filter to (non-promoted) group summaries // - summary will be pruned if necessary, depending on if children are filtered - entry.parent?.summary == entry -> false + (entry.parent as? GroupEntry)?.summary == entry -> false // Check that the entry satisfies certain characteristics that would bypass the // filter shouldIgnoreUnseenCheck(entry) -> false diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java index 2ecce1f02ef6..20c6736b74c8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java @@ -35,7 +35,7 @@ import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.statusbar.notification.collection.GroupEntry; -import com.android.systemui.statusbar.notification.collection.ListEntry; +import com.android.systemui.statusbar.notification.collection.PipelineEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.ShadeListBuilder; @@ -232,9 +232,10 @@ public class PreparationCoordinator implements Coordinator { */ @Override public boolean shouldFilterOut(NotificationEntry entry, long now) { - final GroupEntry parent = requireNonNull(entry.getParent()); - Boolean isMemberOfDelayedGroup = mIsDelayedGroupCache.get(parent); - if (isMemberOfDelayedGroup == null) { + final PipelineEntry pipelineEntryParent = requireNonNull(entry.getParent()); + Boolean isMemberOfDelayedGroup = mIsDelayedGroupCache.get(pipelineEntryParent); + if (isMemberOfDelayedGroup == null && pipelineEntryParent instanceof GroupEntry) { + GroupEntry parent = (GroupEntry) pipelineEntryParent; isMemberOfDelayedGroup = shouldWaitForGroupToInflate(parent, now); mIsDelayedGroupCache.put(parent, isMemberOfDelayedGroup); } @@ -279,7 +280,7 @@ public class PreparationCoordinator implements Coordinator { } }; - private void purgeCaches(Collection<ListEntry> entries) { + private void purgeCaches(Collection<PipelineEntry> entries) { Set<String> wantedPackages = getPackages(entries); mAppIconProvider.purgeCache(wantedPackages); mNotificationIconStyleProvider.purgeCache(wantedPackages); @@ -288,9 +289,9 @@ public class PreparationCoordinator implements Coordinator { /** * Get all app packages present in {@param entries}. */ - private static @NonNull Set<String> getPackages(Collection<ListEntry> entries) { + private static @NonNull Set<String> getPackages(Collection<PipelineEntry> entries) { Set<String> packages = new HashSet<>(); - for (ListEntry entry : entries) { + for (PipelineEntry entry : entries) { NotificationEntry notificationEntry = entry.getRepresentativeEntry(); if (notificationEntry == null) { Log.wtf(TAG, "notification entry " + entry.getKey() @@ -302,9 +303,9 @@ public class PreparationCoordinator implements Coordinator { return packages; } - private void inflateAllRequiredViews(List<ListEntry> entries) { + private void inflateAllRequiredViews(List<PipelineEntry> entries) { for (int i = 0, size = entries.size(); i < size; i++) { - ListEntry entry = entries.get(i); + PipelineEntry entry = entries.get(i); if (entry instanceof GroupEntry) { GroupEntry groupEntry = (GroupEntry) entry; inflateRequiredGroupViews(groupEntry); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java index 69b069d792e3..26bc5b14d357 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java @@ -20,7 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import com.android.systemui.plugins.statusbar.StatusBarStateController; -import com.android.systemui.statusbar.notification.collection.ListEntry; +import com.android.systemui.statusbar.notification.collection.PipelineEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope; @@ -97,7 +97,7 @@ public class RankingCoordinator implements Coordinator { private final NotifSectioner mAlertingNotifSectioner = new NotifSectioner("Alerting", NotificationPriorityBucketKt.BUCKET_ALERTING) { @Override - public boolean isInSection(ListEntry entry) { + public boolean isInSection(PipelineEntry entry) { return mHighPriorityProvider.isHighPriority(entry); } @@ -115,7 +115,7 @@ public class RankingCoordinator implements Coordinator { private final NotifSectioner mSilentNotifSectioner = new NotifSectioner("Silent", NotificationPriorityBucketKt.BUCKET_SILENT) { @Override - public boolean isInSection(ListEntry entry) { + public boolean isInSection(PipelineEntry entry) { return !mHighPriorityProvider.isHighPriority(entry) && !entry.getRepresentativeEntry().isAmbient(); } @@ -128,7 +128,7 @@ public class RankingCoordinator implements Coordinator { @Nullable @Override - public void onEntriesUpdated(@NonNull List<ListEntry> entries) { + public void onEntriesUpdated(@NonNull List<PipelineEntry> entries) { mHasSilentEntries = false; for (int i = 0; i < entries.size(); i++) { if (entries.get(i).getRepresentativeEntry().getSbn().isClearable()) { @@ -144,7 +144,7 @@ public class RankingCoordinator implements Coordinator { private final NotifSectioner mMinimizedNotifSectioner = new NotifSectioner("Minimized", NotificationPriorityBucketKt.BUCKET_SILENT) { @Override - public boolean isInSection(ListEntry entry) { + public boolean isInSection(PipelineEntry entry) { return !mHighPriorityProvider.isHighPriority(entry) && entry.getRepresentativeEntry().isAmbient(); } @@ -157,7 +157,7 @@ public class RankingCoordinator implements Coordinator { @Nullable @Override - public void onEntriesUpdated(@NonNull List<ListEntry> entries) { + public void onEntriesUpdated(@NonNull List<PipelineEntry> entries) { mHasMinimizedEntries = false; for (int i = 0; i < entries.size(); i++) { if (entries.get(i).getRepresentativeEntry().getSbn().isClearable()) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAlertTimeCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAlertTimeCoordinator.kt index 4a7b7ca51ba2..930e52a8fd52 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAlertTimeCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAlertTimeCoordinator.kt @@ -17,7 +17,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator import android.util.ArrayMap import com.android.systemui.statusbar.notification.collection.GroupEntry -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope @@ -39,7 +39,7 @@ class RowAlertTimeCoordinator @Inject constructor() : Coordinator { pipeline.addOnAfterRenderEntryListener(::onAfterRenderEntry) } - private fun onBeforeFinalizeFilterListener(entries: List<ListEntry>) { + private fun onBeforeFinalizeFilterListener(entries: List<PipelineEntry>) { latestAlertTimeBySummary.clear() entries.asSequence().filterIsInstance<GroupEntry>().forEach { groupEntry -> val summary = checkNotNull(groupEntry.summary) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt index df8e56eb4102..a987c544bb50 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt @@ -20,7 +20,7 @@ import android.content.Context import com.android.systemui.res.R import com.android.systemui.shade.ShadeDisplayAware import com.android.systemui.statusbar.notification.AssistantFeedbackController -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope @@ -63,7 +63,7 @@ internal constructor( pipeline.addOnAfterRenderEntryListener(::onAfterRenderEntry) } - private fun onBeforeRenderList(list: List<ListEntry>) { + private fun onBeforeRenderList(list: List<PipelineEntry>) { entryToExpand = list.firstOrNull()?.representativeEntry?.takeIf { entry -> !mSectionStyleProvider.isMinimizedSection(entry.section!!) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt index 90916d1c77d8..db24e7d0604d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt @@ -32,7 +32,7 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTIO import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.notification.DynamicPrivacyController import com.android.systemui.statusbar.notification.collection.GroupEntry -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope @@ -155,7 +155,7 @@ constructor( } } - override fun onBeforeRenderList(entries: List<ListEntry>) { + override fun onBeforeRenderList(entries: List<PipelineEntry>) { if ( isKeyguardGoingAway || statusBarStateController.state == StatusBarState.KEYGUARD && @@ -220,13 +220,15 @@ constructor( } } -private fun extractAllRepresentativeEntries(entries: List<ListEntry>): Sequence<NotificationEntry> = +private fun extractAllRepresentativeEntries(entries: List<PipelineEntry>): Sequence<NotificationEntry> = entries.asSequence().flatMap(::extractAllRepresentativeEntries) -private fun extractAllRepresentativeEntries(listEntry: ListEntry): Sequence<NotificationEntry> = +private fun extractAllRepresentativeEntries( + pipelineEntry: PipelineEntry, +): Sequence<NotificationEntry> = sequence { - listEntry.representativeEntry?.let { yield(it) } - if (listEntry is GroupEntry) { - yieldAll(extractAllRepresentativeEntries(listEntry.children)) + pipelineEntry.representativeEntry?.let { yield(it) } + if (pipelineEntry is GroupEntry) { + yieldAll(extractAllRepresentativeEntries(pipelineEntry.children)) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinator.kt index 1c66db783a34..29a8eb0c25d9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinator.kt @@ -19,7 +19,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator import android.service.notification.NotificationListenerService import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener @@ -67,7 +67,7 @@ class ShadeEventCoordinator @Inject internal constructor( mShadeEmptiedCallback = callback } - private fun onBeforeRenderList(entries: List<ListEntry>) { + private fun onBeforeRenderList(entries: List<PipelineEntry>) { if (mEntryRemoved && entries.isEmpty()) { mLogger.logShadeEmptied() // TODO(b/206023518): This was bad. Do not copy this. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt index 1cb2366a16fe..53a73f4ced63 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt @@ -19,7 +19,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator import com.android.app.tracing.traceSection import com.android.server.notification.Flags.screenshareNotificationHiding import com.android.systemui.Flags.screenshareNotificationHidingBugFix -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManagerImpl @@ -50,14 +50,14 @@ internal constructor( groupExpansionManagerImpl.attach(pipeline) } - private fun onAfterRenderList(entries: List<ListEntry>) = + private fun onAfterRenderList(entries: List<PipelineEntry>) = traceSection("StackCoordinator.onAfterRenderList") { val notifStats = calculateNotifStats(entries) activeNotificationsInteractor.setNotifStats(notifStats) renderListInteractor.setRenderedList(entries) } - private fun calculateNotifStats(entries: List<ListEntry>): NotifStats { + private fun calculateNotifStats(entries: List<PipelineEntry>): NotifStats { var hasNonClearableAlertingNotifs = false var hasClearableAlertingNotifs = false var hasNonClearableSilentNotifs = false diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java index 49d5029bbc70..3e5655a9e925 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java @@ -39,7 +39,7 @@ import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractor; import com.android.systemui.shade.domain.interactor.ShadeInteractor; import com.android.systemui.statusbar.notification.VisibilityLocationProvider; import com.android.systemui.statusbar.notification.collection.GroupEntry; -import com.android.systemui.statusbar.notification.collection.ListEntry; +import com.android.systemui.statusbar.notification.collection.PipelineEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener; @@ -253,21 +253,20 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable { return false; } - final GroupEntry parent = entry.getParent(); + final PipelineEntry parent = entry.getParent(); if (parent == null) { return false; } - return isHeadsUpGroup(parent); } - private boolean isHeadsUpGroup(GroupEntry groupEntry) { - if (StabilizeHeadsUpGroup.isUnexpectedlyInLegacyMode()) { + private boolean isHeadsUpGroup(PipelineEntry pipelineEntry) { + if (!(pipelineEntry instanceof GroupEntry groupEntry)) { return false; } - if (groupEntry == null) { + if (StabilizeHeadsUpGroup.isUnexpectedlyInLegacyMode()) { return false; } @@ -370,7 +369,7 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable { } @Override - public boolean isEntryReorderingAllowed(@NonNull ListEntry entry) { + public boolean isEntryReorderingAllowed(@NonNull PipelineEntry entry) { if (StabilizeHeadsUpGroup.isEnabled()) { if (isEveryChangeAllowed()) { return true; @@ -403,7 +402,7 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable { private final OnBeforeRenderListListener mOnBeforeRenderListListener = new OnBeforeRenderListListener() { @Override - public void onBeforeRenderList(List<ListEntry> entries) { + public void onBeforeRenderList(List<PipelineEntry> entries) { if (StabilizeHeadsUpGroup.isUnexpectedlyInLegacyMode()) { return; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt index 465bc288cbc1..adcc3ec02f0c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt @@ -124,7 +124,7 @@ constructor( val parent = entry.parent ?: error("Entry must have a parent to determine if minimized") val isMinimizedSection = sectionStyleProvider.isMinimizedSection(section) val isTopLevelEntry = parent == GroupEntry.ROOT_ENTRY - val isGroupSummary = parent.summary == entry + val isGroupSummary = (parent as? GroupEntry)?.summary == entry return isMinimizedSection && (isTopLevelEntry || isGroupSummary) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnAfterRenderListListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnAfterRenderListListener.java index ac450c03b850..e3ab81c84bfc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnAfterRenderListListener.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnAfterRenderListListener.java @@ -18,7 +18,7 @@ package com.android.systemui.statusbar.notification.collection.listbuilder; import androidx.annotation.NonNull; -import com.android.systemui.statusbar.notification.collection.ListEntry; +import com.android.systemui.statusbar.notification.collection.PipelineEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import java.util.List; @@ -31,5 +31,5 @@ public interface OnAfterRenderListListener { * @param entries The current list of top-level entries. Note that this is a live view into the * current list and will change whenever the pipeline is rerun. */ - void onAfterRenderList(@NonNull List<ListEntry> entries); + void onAfterRenderList(@NonNull List<PipelineEntry> entries); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeFinalizeFilterListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeFinalizeFilterListener.java index 086661ea219b..3c4f4225388c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeFinalizeFilterListener.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeFinalizeFilterListener.java @@ -16,7 +16,7 @@ package com.android.systemui.statusbar.notification.collection.listbuilder; -import com.android.systemui.statusbar.notification.collection.ListEntry; +import com.android.systemui.statusbar.notification.collection.PipelineEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import java.util.List; @@ -30,5 +30,5 @@ public interface OnBeforeFinalizeFilterListener { * @param entries The current list of top-level entries. Note that this is a live view into the * current list and will change whenever the pipeline is rerun. */ - void onBeforeFinalizeFilter(List<ListEntry> entries); + void onBeforeFinalizeFilter(List<PipelineEntry> entries); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeRenderListListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeRenderListListener.java index 44a27a4b546a..6ceb7d5653f0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeRenderListListener.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeRenderListListener.java @@ -16,7 +16,7 @@ package com.android.systemui.statusbar.notification.collection.listbuilder; -import com.android.systemui.statusbar.notification.collection.ListEntry; +import com.android.systemui.statusbar.notification.collection.PipelineEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import java.util.List; @@ -30,5 +30,5 @@ public interface OnBeforeRenderListListener { * @param entries The current list of top-level entries. Note that this is a live view into the * current list and will change whenever the pipeline is rerun. */ - void onBeforeRenderList(List<ListEntry> entries); + void onBeforeRenderList(List<PipelineEntry> entries); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeSortListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeSortListener.java index 56cfe5cb3716..858cec1e80b5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeSortListener.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeSortListener.java @@ -16,7 +16,7 @@ package com.android.systemui.statusbar.notification.collection.listbuilder; -import com.android.systemui.statusbar.notification.collection.ListEntry; +import com.android.systemui.statusbar.notification.collection.PipelineEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import java.util.List; @@ -30,5 +30,5 @@ public interface OnBeforeSortListener { * @param entries The current list of top-level entries. Note that this is a live view into the * current list and will change whenever the pipeline is rerun. */ - void onBeforeSort(List<ListEntry> entries); + void onBeforeSort(List<PipelineEntry> entries); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeTransformGroupsListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeTransformGroupsListener.java index 0dc4df0da066..eb525c7c4505 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeTransformGroupsListener.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeTransformGroupsListener.java @@ -16,7 +16,7 @@ package com.android.systemui.statusbar.notification.collection.listbuilder; -import com.android.systemui.statusbar.notification.collection.ListEntry; +import com.android.systemui.statusbar.notification.collection.PipelineEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter; @@ -35,5 +35,5 @@ public interface OnBeforeTransformGroupsListener { * a live view into the current notif list and will change as the list moves through * the pipeline. */ - void onBeforeTransformGroups(List<ListEntry> list); + void onBeforeTransformGroups(List<PipelineEntry> list); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderHelper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderHelper.kt index d8f75f61c05a..0d8a64abd13d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderHelper.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderHelper.kt @@ -16,10 +16,10 @@ package com.android.systemui.statusbar.notification.collection.listbuilder -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry object ShadeListBuilderHelper { - fun getSectionSubLists(entries: List<ListEntry>): Iterable<List<ListEntry>> = + fun getSectionSubLists(entries: List<PipelineEntry>): Iterable<List<PipelineEntry>> = getContiguousSubLists(entries, minLength = 1) { it.sectionIndex } inline fun <T : Any, K : Any> getContiguousSubLists( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt index a8409d0c6fa0..8a9548f0b9d5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt @@ -23,7 +23,7 @@ import com.android.systemui.log.core.LogLevel.INFO import com.android.systemui.log.core.LogLevel.WARNING import com.android.systemui.statusbar.notification.NotifPipelineFlags import com.android.systemui.statusbar.notification.collection.GroupEntry -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.StateName import com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.getStateName @@ -152,9 +152,9 @@ class ShadeListBuilderLogger @Inject constructor( fun logEntryAttachStateChanged( buildId: Int, - entry: ListEntry, - prevParent: GroupEntry?, - newParent: GroupEntry? + entry: PipelineEntry, + prevParent: PipelineEntry?, + newParent: PipelineEntry? ) { buffer.log(TAG, INFO, { long1 = buildId.toLong() @@ -177,7 +177,7 @@ class ShadeListBuilderLogger @Inject constructor( }) } - fun logParentChanged(buildId: Int, prevParent: GroupEntry?, newParent: GroupEntry?) { + fun logParentChanged(buildId: Int, prevParent: PipelineEntry?, newParent: PipelineEntry?) { buffer.log(TAG, INFO, { long1 = buildId.toLong() str1 = prevParent?.logKey @@ -195,8 +195,8 @@ class ShadeListBuilderLogger @Inject constructor( fun logParentChangeSuppressedStarted( buildId: Int, - suppressedParent: GroupEntry?, - keepingParent: GroupEntry? + suppressedParent: PipelineEntry?, + keepingParent: PipelineEntry? ) { buffer.log(TAG, INFO, { long1 = buildId.toLong() @@ -209,8 +209,8 @@ class ShadeListBuilderLogger @Inject constructor( fun logParentChangeSuppressedStopped( buildId: Int, - previouslySuppressedParent: GroupEntry?, - previouslyKeptParent: GroupEntry? + previouslySuppressedParent: PipelineEntry?, + previouslyKeptParent: PipelineEntry? ) { buffer.log(TAG, INFO, { long1 = buildId.toLong() @@ -224,7 +224,7 @@ class ShadeListBuilderLogger @Inject constructor( fun logGroupPruningSuppressed( buildId: Int, - keepingParent: GroupEntry? + keepingParent: PipelineEntry? ) { buffer.log(TAG, INFO, { long1 = buildId.toLong() @@ -310,7 +310,7 @@ class ShadeListBuilderLogger @Inject constructor( val logRankInFinalList = Compile.IS_DEBUG && notifPipelineFlags.isDevLoggingEnabled() - fun logFinalList(entries: List<ListEntry>) { + fun logFinalList(entries: List<PipelineEntry>) { if (entries.isEmpty()) { buffer.log(TAG, DEBUG, {}, { "(empty list)" }) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifComparator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifComparator.java index f7bbd281ec51..f7c74c217cdf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifComparator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifComparator.java @@ -18,7 +18,7 @@ package com.android.systemui.statusbar.notification.collection.listbuilder.plugg import androidx.annotation.NonNull; -import com.android.systemui.statusbar.notification.collection.ListEntry; +import com.android.systemui.statusbar.notification.collection.PipelineEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import java.util.Comparator; @@ -29,7 +29,7 @@ import java.util.List; */ public abstract class NotifComparator extends Pluggable<NotifComparator> - implements Comparator<ListEntry> { + implements Comparator<PipelineEntry> { protected NotifComparator(String name) { super(name); @@ -41,5 +41,5 @@ public abstract class NotifComparator * @return a negative integer, zero, or a positive integer as the first argument is less than * equal to, or greater than the second (same as standard Comparator<> interface). */ - public abstract int compare(@NonNull ListEntry o1, @NonNull ListEntry o2); + public abstract int compare(@NonNull PipelineEntry o1, @NonNull PipelineEntry o2); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifSectioner.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifSectioner.java index 8c52c53ea6b2..4a856a55f185 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifSectioner.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifSectioner.java @@ -18,7 +18,7 @@ package com.android.systemui.statusbar.notification.collection.listbuilder.plugg import android.annotation.Nullable; -import com.android.systemui.statusbar.notification.collection.ListEntry; +import com.android.systemui.statusbar.notification.collection.PipelineEntry; import com.android.systemui.statusbar.notification.collection.ShadeListBuilder; import com.android.systemui.statusbar.notification.collection.render.NodeController; import com.android.systemui.statusbar.notification.collection.render.NodeSpec; @@ -52,11 +52,11 @@ public abstract class NotifSectioner extends Pluggable<NotifSectioner> { * However, this doesn't necessarily mean that your section will get called on each top-level * notification. The first section to return true determines the section of the notification. */ - public abstract boolean isInSection(ListEntry entry); + public abstract boolean isInSection(PipelineEntry entry); /** * Returns an optional {@link NotifComparator} to sort entries only in this section. - * {@link ListEntry} instances passed to this comparator are guaranteed to have this section, + * {@link PipelineEntry} instances passed to this comparator are guaranteed to have this section, * and this ordering will take precedence over any global comparators supplied to {@link * com.android.systemui.statusbar.notification.collection.NotifPipeline#setComparators(List)}. * @@ -80,5 +80,5 @@ public abstract class NotifSectioner extends Pluggable<NotifSectioner> { * Notify of children of this section being updated * @param entries of this section that are borrowed (must clone to store) */ - public void onEntriesUpdated(List<ListEntry> entries) {} + public void onEntriesUpdated(List<PipelineEntry> entries) {} } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifStabilityManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifStabilityManager.kt index 58bbca822164..e1e2bcff3e31 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifStabilityManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifStabilityManager.kt @@ -16,7 +16,7 @@ package com.android.systemui.statusbar.notification.collection.listbuilder.pluggable import com.android.systemui.statusbar.notification.collection.GroupEntry -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.NotificationEntry /** @@ -75,7 +75,7 @@ abstract class NotifStabilityManager protected constructor(name: String) : * being suppressed. However, if an order change is suppressed, that will be reported to ths * implementation by calling [onEntryReorderSuppressed] after ordering is complete. */ - abstract fun isEntryReorderingAllowed(entry: ListEntry): Boolean + abstract fun isEntryReorderingAllowed(entry: PipelineEntry): Boolean /** * Called by the pipeline to determine if every call to the other stability methods would @@ -100,7 +100,7 @@ object DefaultNotifStabilityManager : NotifStabilityManager("DefaultNotifStabili override fun isGroupChangeAllowed(entry: NotificationEntry): Boolean = true override fun isGroupPruneAllowed(entry: GroupEntry): Boolean = true override fun isSectionChangeAllowed(entry: NotificationEntry): Boolean = true - override fun isEntryReorderingAllowed(entry: ListEntry): Boolean = true + override fun isEntryReorderingAllowed(entry: PipelineEntry): Boolean = true override fun isEveryChangeAllowed(): Boolean = true override fun onEntryReorderSuppressed() {} } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt index 014ac549591e..ae2c70a284e9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt @@ -27,6 +27,7 @@ import com.android.systemui.log.core.LogLevel.ERROR import com.android.systemui.log.core.LogLevel.INFO import com.android.systemui.log.core.LogLevel.WARNING import com.android.systemui.log.core.LogLevel.WTF +import com.android.systemui.statusbar.notification.collection.GroupEntry import com.android.systemui.statusbar.notification.collection.NotifCollection import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason import com.android.systemui.statusbar.notification.collection.NotifCollection.FutureDismissal @@ -421,6 +422,14 @@ class NotifCollectionLogger @Inject constructor( }) } + private fun getParentLogKey(childEntry: NotificationEntry): String { + return if (childEntry.parent is GroupEntry) { + (childEntry.parent as? GroupEntry)?.summary?.logKey ?: "(null)" + } else { + "(null)" + } + } + fun logDismissAlreadyParentDismissedNotif( childEntry: NotificationEntry, childIndex: Int, @@ -430,7 +439,7 @@ class NotifCollectionLogger @Inject constructor( str1 = childEntry.logKey int1 = childIndex int2 = childCount - str2 = childEntry.parent?.summary?.logKey ?: "(null)" + str2 = getParentLogKey(childEntry) }, { "DISMISS Already Parent-Dismissed $str1 ($int1/$int2) with summary $str2" }) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java index 2e3ab926ad57..051bd3a99549 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java @@ -23,7 +23,7 @@ import android.app.NotificationManager; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.notification.collection.GroupEntry; -import com.android.systemui.statusbar.notification.collection.ListEntry; +import com.android.systemui.statusbar.notification.collection.PipelineEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; @@ -53,7 +53,7 @@ public class HighPriorityProvider { } /** - * @return true if the ListEntry is high priority, else false + * @return true if the PipelineEntry is high priority, else false * * A NotificationEntry is considered high priority if it: * - has importance greater than or equal to IMPORTANCE_DEFAULT @@ -67,12 +67,12 @@ public class HighPriorityProvider { * A GroupEntry is considered high priority if its representativeEntry (summary) or any of its * children are high priority. */ - public boolean isHighPriority(@Nullable ListEntry entry) { + public boolean isHighPriority(@Nullable PipelineEntry entry) { return isHighPriority(entry, /* allowImplicit = */ true); } /** - * @return true if the ListEntry is explicitly high priority, else false + * @return true if the PipelineEntry is explicitly high priority, else false * * A NotificationEntry is considered explicitly high priority if has importance greater than or * equal to IMPORTANCE_DEFAULT. @@ -80,11 +80,11 @@ public class HighPriorityProvider { * A GroupEntry is considered explicitly high priority if its representativeEntry (summary) or * any of its children are explicitly high priority. */ - public boolean isExplicitlyHighPriority(@Nullable ListEntry entry) { + public boolean isExplicitlyHighPriority(@Nullable PipelineEntry entry) { return isHighPriority(entry, /* allowImplicit= */ false); } - private boolean isHighPriority(@Nullable ListEntry entry, boolean allowImplicit) { + private boolean isHighPriority(@Nullable PipelineEntry entry, boolean allowImplicit) { if (entry == null) { return false; } @@ -100,9 +100,9 @@ public class HighPriorityProvider { } /** - * @return true if the ListEntry is high priority conversation, else false + * @return true if the PipelineEntry is high priority conversation, else false */ - public boolean isHighPriorityConversation(@NonNull ListEntry entry) { + public boolean isHighPriorityConversation(@NonNull PipelineEntry entry) { final NotificationEntry notifEntry = entry.getRepresentativeEntry(); if (notifEntry == null) { return false; @@ -119,7 +119,7 @@ public class HighPriorityProvider { return isNotificationEntryWithAtLeastOneImportantChild(entry); } - private boolean isNotificationEntryWithAtLeastOneImportantChild(@NonNull ListEntry entry) { + private boolean isNotificationEntryWithAtLeastOneImportantChild(@NonNull PipelineEntry entry) { if (!(entry instanceof GroupEntry)) { return false; } @@ -134,7 +134,7 @@ public class HighPriorityProvider { * Returns whether the given ListEntry has a high priority child or is in a group with a child * that's high priority */ - private boolean hasHighPriorityChild(ListEntry entry, boolean allowImplicit) { + private boolean hasHighPriorityChild(PipelineEntry entry, boolean allowImplicit) { if (NotificationBundleUi.isEnabled()) { GroupEntry representativeGroupEntry = null; if (entry instanceof GroupEntry) { @@ -142,9 +142,10 @@ public class HighPriorityProvider { } else if (entry instanceof NotificationEntry){ final NotificationEntry notificationEntry = entry.getRepresentativeEntry(); if (notificationEntry.getParent() != null - && notificationEntry.getParent().getSummary() != null - && notificationEntry.getParent().getSummary() == notificationEntry) { - representativeGroupEntry = notificationEntry.getParent(); + && notificationEntry.getParent() instanceof GroupEntry parent + && parent.getSummary() != null + && parent.getSummary() == notificationEntry) { + representativeGroupEntry = parent; } } return representativeGroupEntry != null && diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionStyleProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionStyleProvider.kt index ea9f29521459..f418bb639f49 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionStyleProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionStyleProvider.kt @@ -17,7 +17,7 @@ package com.android.systemui.statusbar.notification.collection.provider import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.SortBySectionTimeFlag import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner @@ -53,7 +53,7 @@ class SectionStyleProvider @Inject constructor( * Determine if the given entry is minimized. */ @JvmOverloads - fun isMinimized(entry: ListEntry, ifNotInSection: Boolean = true): Boolean { + fun isMinimized(entry: PipelineEntry, ifNotInSection: Boolean = true): Boolean { val section = entry.section ?: return ifNotInSection return isMinimizedSection(section) } @@ -77,7 +77,7 @@ class SectionStyleProvider @Inject constructor( * Determine if the given entry is silent. */ @JvmOverloads - fun isSilent(entry: ListEntry, ifNotInSection: Boolean = true): Boolean { + fun isSilent(entry: PipelineEntry, ifNotInSection: Boolean = true): Boolean { val section = entry.section ?: return ifNotInSection if (SortBySectionTimeFlag.isEnabled) { if (entry.section?.bucket == BUCKET_PEOPLE) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java index 16b98e20498a..b179a694dad7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java @@ -25,7 +25,7 @@ import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dump.DumpManager; import com.android.systemui.statusbar.notification.collection.EntryAdapter; import com.android.systemui.statusbar.notification.collection.GroupEntry; -import com.android.systemui.statusbar.notification.collection.ListEntry; +import com.android.systemui.statusbar.notification.collection.PipelineEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener; @@ -81,7 +81,7 @@ public class GroupExpansionManagerImpl implements GroupExpansionManager, Dumpabl } final Set<NotificationEntry> renderingSummaries = new HashSet<>(); - for (ListEntry entry : entries) { + for (PipelineEntry entry : entries) { if (entry instanceof GroupEntry) { renderingSummaries.add(entry.getRepresentativeEntry()); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java index 69267e5d9e55..3edbfafd7d33 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java @@ -22,6 +22,7 @@ import android.annotation.Nullable; import com.android.systemui.statusbar.notification.collection.EntryAdapter; import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.PipelineEntry; import java.util.List; @@ -78,5 +79,5 @@ public interface GroupMembershipManager { * @return list of the children */ @Nullable - List<NotificationEntry> getChildren(@NonNull ListEntry summary); + List<NotificationEntry> getChildren(@NonNull PipelineEntry summary); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java index 80a9f8adf8f3..a1a23e3a0b44 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java @@ -24,7 +24,7 @@ import androidx.annotation.Nullable; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.notification.collection.EntryAdapter; import com.android.systemui.statusbar.notification.collection.GroupEntry; -import com.android.systemui.statusbar.notification.collection.ListEntry; +import com.android.systemui.statusbar.notification.collection.PipelineEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.shared.NotificationBundleUi; @@ -48,8 +48,13 @@ public class GroupMembershipManagerImpl implements GroupMembershipManager { // The entry is not attached, so it doesn't count. return false; } + PipelineEntry pipelineEntry = entry.getParent(); + if (!(pipelineEntry instanceof GroupEntry groupEntry)) { + return false; + } + // If entry is a summary, its parent is a GroupEntry with summary = entry. - return entry.getParent().getSummary() == entry; + return groupEntry.getSummary() == entry; } @Override @@ -65,7 +70,10 @@ public class GroupMembershipManagerImpl implements GroupMembershipManager { if (isTopLevelEntry(entry) || entry.getParent() == null) { return null; } - return entry.getParent().getSummary(); + if (entry.getParent() instanceof GroupEntry parent) { + return parent.getSummary(); + } + return null; } @Nullable @@ -91,8 +99,9 @@ public class GroupMembershipManagerImpl implements GroupMembershipManager { @Nullable @Override - public List<NotificationEntry> getChildren(@NonNull ListEntry entry) { + public List<NotificationEntry> getChildren(@NonNull PipelineEntry entry) { NotificationBundleUi.assertInLegacyMode(); + if (entry instanceof GroupEntry) { return ((GroupEntry) entry).getChildren(); } @@ -100,8 +109,7 @@ public class GroupMembershipManagerImpl implements GroupMembershipManager { NotificationEntry representativeEntry = entry.getRepresentativeEntry(); if (representativeEntry != null && isGroupSummary(representativeEntry)) { // maybe we were actually passed the summary - GroupEntry parent = representativeEntry.getParent(); - if (parent != null) { + if (representativeEntry.getParent() instanceof GroupEntry parent) { return parent.getChildren(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt index 9fc4e4036b31..e17319484cce 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt @@ -18,12 +18,12 @@ package com.android.systemui.statusbar.notification.collection.render import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager import com.android.systemui.statusbar.notification.collection.GroupEntry -import com.android.systemui.statusbar.notification.collection.ListEntry import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection import com.android.systemui.statusbar.notification.collection.provider.SectionHeaderVisibilityProvider import com.android.systemui.util.Compile import com.android.app.tracing.traceSection +import com.android.systemui.statusbar.notification.collection.PipelineEntry /** * Converts a notif list (the output of the ShadeListBuilder) into a NodeSpec, an abstract @@ -45,7 +45,7 @@ class NodeSpecBuilder( fun buildNodeSpec( rootController: NodeController, - notifList: List<ListEntry> + notifList: List<PipelineEntry> ): NodeSpec = traceSection("NodeSpecBuilder.buildNodeSpec") { val root = NodeSpecImpl(null, rootController) @@ -100,7 +100,7 @@ class NodeSpecBuilder( return@traceSection root } - private fun buildNotifNode(parent: NodeSpec, entry: ListEntry): NodeSpec = when (entry) { + private fun buildNotifNode(parent: NodeSpec, entry: PipelineEntry): NodeSpec = when (entry) { is NotificationEntry -> NodeSpecImpl(parent, viewBarn.requireNodeController(entry)) is GroupEntry -> NodeSpecImpl(parent, viewBarn.requireNodeController(checkNotNull(entry.summary))) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewBarn.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewBarn.kt index fd91d5a2c082..56662f105e4a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewBarn.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewBarn.kt @@ -18,18 +18,18 @@ package com.android.systemui.statusbar.notification.collection.render import android.view.textclassifier.Log import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.NotificationEntry import javax.inject.Inject /** - * The ViewBarn is just a map from [ListEntry] to an instance of a [NodeController]. + * The ViewBarn is just a map from [PipelineEntry] to an instance of a [NodeController]. */ @SysUISingleton class NotifViewBarn @Inject constructor() { private val rowMap = mutableMapOf<String, NotifViewController>() - fun requireNodeController(entry: ListEntry): NodeController { + fun requireNodeController(entry: PipelineEntry): NodeController { if (DEBUG) { Log.d(TAG, "requireNodeController: ${entry.key}") } @@ -50,14 +50,14 @@ class NotifViewBarn @Inject constructor() { return rowMap[entry.key] ?: error("No view has been registered for entry: ${entry.key}") } - fun registerViewForEntry(entry: ListEntry, controller: NotifViewController) { + fun registerViewForEntry(entry: PipelineEntry, controller: NotifViewController) { if (DEBUG) { Log.d(TAG, "registerViewForEntry: ${entry.key}") } rowMap[entry.key] = controller } - fun removeViewForEntry(entry: ListEntry) { + fun removeViewForEntry(entry: PipelineEntry) { if (DEBUG) { Log.d(TAG, "removeViewForEntry: ${entry.key}") } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewRenderer.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewRenderer.kt index 8284022c7270..396d47e7096c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewRenderer.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewRenderer.kt @@ -17,7 +17,7 @@ package com.android.systemui.statusbar.notification.collection.render import com.android.systemui.statusbar.notification.collection.GroupEntry -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.NotificationEntry /** @@ -34,7 +34,7 @@ interface NotifViewRenderer { * also ensure that future calls to [getStackController], [getGroupController], and * [getRowController] will provide valid results. */ - fun onRenderList(notifList: List<ListEntry>) + fun onRenderList(notifList: List<PipelineEntry>) /** * Provides an interface for the pipeline to update individual groups. This will be called at diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt index 21e68376031c..93e844de79d9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt @@ -19,7 +19,7 @@ package com.android.systemui.statusbar.notification.collection.render import com.android.app.tracing.traceSection import com.android.systemui.dagger.SysUISingleton import com.android.systemui.statusbar.notification.collection.GroupEntry -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.PipelineDumpable import com.android.systemui.statusbar.notification.collection.PipelineDumper @@ -46,7 +46,7 @@ class RenderStageManager @Inject constructor() : PipelineDumpable { listBuilder.setOnRenderListListener(::onRenderList) } - private fun onRenderList(notifList: List<ListEntry>) { + private fun onRenderList(notifList: List<PipelineEntry>) { traceSection("RenderStageManager.onRenderList") { val viewRenderer = viewRenderer ?: return viewRenderer.onRenderList(notifList) @@ -85,7 +85,7 @@ class RenderStageManager @Inject constructor() : PipelineDumpable { dump("onAfterRenderEntryListeners", onAfterRenderEntryListeners) } - private fun dispatchOnAfterRenderList(entries: List<ListEntry>) { + private fun dispatchOnAfterRenderList(entries: List<PipelineEntry>) { traceSection("RenderStageManager.dispatchOnAfterRenderList") { onAfterRenderListListeners.forEach { listener -> listener.onAfterRenderList(entries) } } @@ -93,7 +93,7 @@ class RenderStageManager @Inject constructor() : PipelineDumpable { private fun dispatchOnAfterRenderGroups( viewRenderer: NotifViewRenderer, - entries: List<ListEntry>, + entries: List<PipelineEntry>, ) { traceSection("RenderStageManager.dispatchOnAfterRenderGroups") { if (onAfterRenderGroupListeners.isEmpty()) { @@ -110,7 +110,7 @@ class RenderStageManager @Inject constructor() : PipelineDumpable { private fun dispatchOnAfterRenderEntries( viewRenderer: NotifViewRenderer, - entries: List<ListEntry>, + entries: List<PipelineEntry>, ) { traceSection("RenderStageManager.dispatchOnAfterRenderEntries") { if (onAfterRenderEntryListeners.isEmpty()) { @@ -129,7 +129,7 @@ class RenderStageManager @Inject constructor() : PipelineDumpable { * Performs a forward, depth-first traversal of the list where the group's summary immediately * precedes the group's children. */ - private inline fun List<ListEntry>.forEachNotificationEntry( + private inline fun List<PipelineEntry>.forEachNotificationEntry( action: (NotificationEntry) -> Unit ) { forEach { entry -> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt index 72316bf14c9a..9532d6d89cf7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt @@ -22,7 +22,7 @@ import com.android.app.tracing.traceSection import com.android.systemui.shade.ShadeDisplayAware import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager import com.android.systemui.statusbar.notification.collection.GroupEntry -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.PipelineDumpable import com.android.systemui.statusbar.notification.collection.PipelineDumper @@ -76,7 +76,7 @@ constructor( private val viewRenderer = object : NotifViewRenderer { - override fun onRenderList(notifList: List<ListEntry>) { + override fun onRenderList(notifList: List<PipelineEntry>) { traceSection("ShadeViewManager.onRenderList") { viewDiffer.applySpec(specBuilder.buildNodeSpec(rootController, notifList)) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationListInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationListInteractor.kt index bde3c4d8c632..adc049e7cdf1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationListInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationListInteractor.kt @@ -29,7 +29,7 @@ import com.android.app.tracing.traceSection import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.statusbar.StatusBarIconView import com.android.systemui.statusbar.notification.collection.GroupEntry -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository @@ -57,11 +57,11 @@ constructor( /** * Sets the current list of rendered notification entries as displayed in the notification list. */ - fun setRenderedList(entries: List<ListEntry>) { + fun setRenderedList(entries: List<PipelineEntry>) { traceSection("RenderNotificationListInteractor.setRenderedList") { repository.activeNotifications.update { existingModels -> buildActiveNotificationsStore(existingModels, sectionStyleProvider, context) { - entries.forEach(::addListEntry) + entries.forEach(::addPipelineEntry) setRankingsMap(entries) } } @@ -89,11 +89,11 @@ private class ActiveNotificationsStoreBuilder( fun build(): ActiveNotificationsStore = builder.build() /** - * Convert a [ListEntry] into [ActiveNotificationEntryModel]s, and add them to the + * Convert a [PipelineEntry] into [ActiveNotificationEntryModel]s, and add them to the * [ActiveNotificationsStore]. Special care is taken to avoid re-allocating models if the result * would be identical to an existing model (at the expense of additional computations). */ - fun addListEntry(entry: ListEntry) { + fun addPipelineEntry(entry: PipelineEntry) { when (entry) { is GroupEntry -> { entry.summary?.let { summary -> @@ -116,11 +116,11 @@ private class ActiveNotificationsStoreBuilder( } } - fun setRankingsMap(entries: List<ListEntry>) { + fun setRankingsMap(entries: List<PipelineEntry>) { builder.setRankingsMap(flatMapToRankingsMap(entries)) } - fun flatMapToRankingsMap(entries: List<ListEntry>): Map<String, Int> { + fun flatMapToRankingsMap(entries: List<PipelineEntry>): Map<String, Int> { val result = ArrayMap<String, Int>() for (entry in entries) { if (entry is NotificationEntry) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt index c7548aae7131..5096894911c8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt @@ -19,7 +19,7 @@ import com.android.systemui.settings.UserTracker import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.SysuiStatusBarStateController -import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.PipelineEntry import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider import com.android.systemui.statusbar.policy.KeyguardStateController @@ -198,7 +198,7 @@ constructor( else -> false } - private fun shouldHideIfEntrySilent(entry: ListEntry): Boolean = + private fun shouldHideIfEntrySilent(entry: PipelineEntry): Boolean = when { // Show if explicitly high priority (not hidden) highPriorityProvider.isExplicitlyHighPriority(entry) -> false diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt index f755dbb48e1d..002230e4e516 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt @@ -20,6 +20,7 @@ import android.annotation.IntDef import android.service.notification.NotificationListenerService.Ranking import android.service.notification.StatusBarNotification import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.statusbar.notification.collection.GroupEntry import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.PeopleNotificationType @@ -117,8 +118,8 @@ class PeopleNotificationIdentifierImpl @Inject constructor( if (!entry.sbn.notification.isGroupSummary) { return TYPE_NON_PERSON; } - - return getPeopleTypeForChildList(entry.parent?.children) + val parent = entry.parent as? GroupEntry ?: return TYPE_NON_PERSON + return getPeopleTypeForChildList(parent.children) } else { if (!groupManager.isGroupSummary(entry)) { return TYPE_NON_PERSON diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index 6f7eade1c0f2..d2800d7c1b71 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -2182,7 +2182,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView R.dimen.notification_min_height); } mMaxSmallHeightWithSummarization = NotificationUtils.getFontScaledHeight(mContext, - com.android.internal.R.dimen.notification_collapsed_height_with_summarization); + com.android.internal.R.dimen.notification_min_height); mMaxExpandedHeight = NotificationUtils.getFontScaledHeight(mContext, R.dimen.notification_max_height); mMaxExpandedHeightForPromotedOngoing = NotificationUtils.getFontScaledHeight(mContext, diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt index 2e634390679a..c2a495d13c02 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt @@ -64,6 +64,12 @@ class FontInterpolatorTest : SysuiTestCase() { "'wght' 500, 'ital' 0.5, 'GRAD' 450", interp.lerp(startFont, endFont, 0.5f, 0.5f), ) + + // Ensure axes rounded correctly to nearest step + assertSameAxes( + "'wght' 490, 'ital' 0.5, 'GRAD' 446", + interp.lerp(startFont, endFont, 0.492f, 0.492f), + ) } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java index e8b50d580c33..81213caaa5f4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java @@ -130,7 +130,7 @@ public class ShadeListBuilderTest extends SysuiTestCase { private CollectionReadyForBuildListener mReadyForBuildListener; private List<NotificationEntryBuilder> mPendingSet = new ArrayList<>(); private List<NotificationEntry> mEntrySet = new ArrayList<>(); - private List<ListEntry> mBuiltList = new ArrayList<>(); + private List<PipelineEntry> mBuiltList = new ArrayList<>(); private TestableStabilityManager mStabilityManager; private TestableNotifFilter mFinalizeFilter; @@ -723,26 +723,26 @@ public class ShadeListBuilderTest extends SysuiTestCase { @Test public void testNotifSectionsChildrenUpdated() { - ArrayList<ListEntry> pkg1Entries = new ArrayList<>(); - ArrayList<ListEntry> pkg2Entries = new ArrayList<>(); - ArrayList<ListEntry> pkg3Entries = new ArrayList<>(); + ArrayList<PipelineEntry> pkg1Entries = new ArrayList<>(); + ArrayList<PipelineEntry> pkg2Entries = new ArrayList<>(); + ArrayList<PipelineEntry> pkg3Entries = new ArrayList<>(); final NotifSectioner pkg1Sectioner = spy(new PackageSectioner(PACKAGE_1) { @Override - public void onEntriesUpdated(List<ListEntry> entries) { + public void onEntriesUpdated(List<PipelineEntry> entries) { super.onEntriesUpdated(entries); pkg1Entries.addAll(entries); } }); final NotifSectioner pkg2Sectioner = spy(new PackageSectioner(PACKAGE_2) { @Override - public void onEntriesUpdated(List<ListEntry> entries) { + public void onEntriesUpdated(List<PipelineEntry> entries) { super.onEntriesUpdated(entries); pkg2Entries.addAll(entries); } }); final NotifSectioner pkg3Sectioner = spy(new PackageSectioner(PACKAGE_3) { @Override - public void onEntriesUpdated(List<ListEntry> entries) { + public void onEntriesUpdated(List<PipelineEntry> entries) { super.onEntriesUpdated(entries); pkg3Entries.addAll(entries); } @@ -2478,7 +2478,7 @@ public class ShadeListBuilderTest extends SysuiTestCase { mBuiltList.size()); for (int i = 0; i < expectedEntries.length; i++) { - ListEntry outEntry = mBuiltList.get(i); + PipelineEntry outEntry = mBuiltList.get(i); ExpectedEntry expectedEntry = expectedEntries[i]; if (expectedEntry instanceof ExpectedNotif) { @@ -2653,7 +2653,7 @@ public class ShadeListBuilderTest extends SysuiTestCase { } @Override - public int compare(@NonNull ListEntry o1, @NonNull ListEntry o2) { + public int compare(@NonNull PipelineEntry o1, @NonNull PipelineEntry o2) { boolean contains1 = mPreferredPackages.contains( o1.getRepresentativeEntry().getSbn().getPackageName()); boolean contains2 = mPreferredPackages.contains( @@ -2691,37 +2691,37 @@ public class ShadeListBuilderTest extends SysuiTestCase { } @Override - public boolean isInSection(ListEntry entry) { + public boolean isInSection(PipelineEntry entry) { return mPackages.contains(entry.getRepresentativeEntry().getSbn().getPackageName()); } } private static class RecordingOnBeforeTransformGroupsListener implements OnBeforeTransformGroupsListener { - List<ListEntry> mEntriesReceived; + List<PipelineEntry> mEntriesReceived; @Override - public void onBeforeTransformGroups(List<ListEntry> list) { + public void onBeforeTransformGroups(List<PipelineEntry> list) { mEntriesReceived = new ArrayList<>(list); } } private static class RecordingOnBeforeSortListener implements OnBeforeSortListener { - List<ListEntry> mEntriesReceived; + List<PipelineEntry> mEntriesReceived; @Override - public void onBeforeSort(List<ListEntry> list) { + public void onBeforeSort(List<PipelineEntry> list) { mEntriesReceived = new ArrayList<>(list); } } private static class RecordingOnBeforeRenderListener implements OnBeforeRenderListListener { - List<ListEntry> mEntriesReceived; + List<PipelineEntry> mEntriesReceived; @Override - public void onBeforeRenderList(List<ListEntry> list) { + public void onBeforeRenderList(List<PipelineEntry> list) { mEntriesReceived = new ArrayList<>(list); } } @@ -2800,7 +2800,7 @@ public class ShadeListBuilderTest extends SysuiTestCase { } @Override - public boolean isEntryReorderingAllowed(@NonNull ListEntry entry) { + public boolean isEntryReorderingAllowed(@NonNull PipelineEntry entry) { return mAllowEntryReodering; } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java index 562ac0c15a0b..804ec9f29926 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java @@ -56,7 +56,7 @@ public class NotificationEntryBuilder { private StatusBarNotification mSbn = null; /* ListEntry properties */ - private GroupEntry mParent; + private PipelineEntry mParent; private NotifSection mNotifSection; /* If set, use this creation time instead of mClock.uptimeMillis */ @@ -91,7 +91,7 @@ public class NotificationEntryBuilder { } /** Update an the parent on an existing entry */ - public static void setNewParent(NotificationEntry entry, GroupEntry parent) { + public static void setNewParent(NotificationEntry entry, PipelineEntry parent) { entry.setParent(parent); } @@ -135,7 +135,7 @@ public class NotificationEntryBuilder { /** * Sets the parent. */ - public NotificationEntryBuilder setParent(@Nullable GroupEntry parent) { + public NotificationEntryBuilder setParent(@Nullable PipelineEntry parent) { mParent = parent; return this; } diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index d800503c658e..b85967fa2bac 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -954,7 +954,8 @@ public class AudioService extends IAudioService.Stub /** * Stores information about a device using absolute volume behavior. */ - private static final class AbsoluteVolumeDeviceInfo { + private static final class AbsoluteVolumeDeviceInfo implements IBinder.DeathRecipient { + private final AudioService mParent; private final AudioDeviceAttributes mDevice; private final List<VolumeInfo> mVolumeInfos; private final IAudioDeviceVolumeDispatcher mCallback; @@ -962,16 +963,26 @@ public class AudioService extends IAudioService.Stub private @AudioManager.AbsoluteDeviceVolumeBehavior int mDeviceVolumeBehavior; private AbsoluteVolumeDeviceInfo( + AudioService parent, AudioDeviceAttributes device, List<VolumeInfo> volumeInfos, IAudioDeviceVolumeDispatcher callback, boolean handlesVolumeAdjustment, @AudioManager.AbsoluteDeviceVolumeBehavior int behavior) { + this.mParent = parent; this.mDevice = device; this.mVolumeInfos = volumeInfos; this.mCallback = callback; this.mHandlesVolumeAdjustment = handlesVolumeAdjustment; this.mDeviceVolumeBehavior = behavior; + + try { + this.mCallback.asBinder().linkToDeath(this, 0); + } catch (RemoteException | NullPointerException e) { + // NPE can be raised when mocking the callback object + Slog.w(TAG, "Exception: " + e + + "\nCannot listen to callback binder death for device " + mDevice); + } } /** @@ -991,6 +1002,25 @@ public class AudioService extends IAudioService.Stub } return null; } + + @Override + public void binderDied() { + if (mParent.removeAudioSystemDeviceOutFromAbsVolumeDevices(mDevice.getInternalType()) + != null) { + mParent.dispatchDeviceVolumeBehavior(mDevice, + AudioManager.DEVICE_VOLUME_BEHAVIOR_VARIABLE); + } + } + + public void unlinkToDeath() { + try { + mCallback.asBinder().unlinkToDeath(this, 0); + } catch (NullPointerException e) { + // NPE can be raised when mocking the callback object + Slog.w(TAG, "Exception: " + e + + "\nCannot unlink to death, null binder object for device " + mDevice); + } + } } // Devices for the which use the "absolute volume" concept (framework sends audio signal @@ -8142,16 +8172,16 @@ public class AudioService extends IAudioService.Stub int deviceOut = device.getInternalType(); if (register) { - AbsoluteVolumeDeviceInfo info = new AbsoluteVolumeDeviceInfo( + AbsoluteVolumeDeviceInfo info = new AbsoluteVolumeDeviceInfo(this, device, volumes, cb, handlesVolumeAdjustment, deviceVolumeBehavior); final AbsoluteVolumeDeviceInfo oldInfo = getAbsoluteVolumeDeviceInfo(deviceOut); + addAudioSystemDeviceOutToAbsVolumeDevices(deviceOut, info); boolean volumeBehaviorChanged = (oldInfo == null) || (oldInfo.mDeviceVolumeBehavior != deviceVolumeBehavior); if (volumeBehaviorChanged) { removeAudioSystemDeviceOutFromFullVolumeDevices(deviceOut); removeAudioSystemDeviceOutFromFixedVolumeDevices(deviceOut); - addAudioSystemDeviceOutToAbsVolumeDevices(deviceOut, info); dispatchDeviceVolumeBehavior(device, deviceVolumeBehavior); } @@ -8177,8 +8207,10 @@ public class AudioService extends IAudioService.Stub } } } else { - boolean wasAbsVol = removeAudioSystemDeviceOutFromAbsVolumeDevices(deviceOut) != null; - if (wasAbsVol) { + AbsoluteVolumeDeviceInfo deviceInfo = removeAudioSystemDeviceOutFromAbsVolumeDevices( + deviceOut); + if (deviceInfo != null) { + deviceInfo.unlinkToDeath(); dispatchDeviceVolumeBehavior(device, AudioManager.DEVICE_VOLUME_BEHAVIOR_VARIABLE); } } diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index a5058dd51a33..cf5fa9699ca9 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -540,9 +540,23 @@ public class BiometricService extends SystemService { DEFAULT_MANDATORY_BIOMETRICS_STATUS) && mMandatoryBiometricsRequirementsSatisfied.getOrDefault(userId, DEFAULT_MANDATORY_BIOMETRICS_REQUIREMENTS_SATISFIED_STATUS) - && getEnabledForApps(userId, TYPE_ANY_BIOMETRIC) - && (mFingerprintEnrolledForUser.getOrDefault(userId, false /* default */) - || mFaceEnrolledForUser.getOrDefault(userId, false /* default */)); + && getBiometricStatusForIdentityCheck(userId); + } + + private boolean getBiometricStatusForIdentityCheck(int userId) { + if (com.android.settings.flags.Flags.biometricsOnboardingEducation()) { + if (mFingerprintEnrolledForUser.getOrDefault(userId, false /* default */) + && getEnabledForApps(userId, TYPE_FINGERPRINT)) { + return true; + } else { + return mFaceEnrolledForUser.getOrDefault(userId, false /* default */) + && getEnabledForApps(userId, TYPE_FACE); + } + } else { + return (mFingerprintEnrolledForUser.getOrDefault(userId, false /* default */) + || mFaceEnrolledForUser.getOrDefault(userId, false /* default */)) + && getEnabledForApps(userId, TYPE_ANY_BIOMETRIC); + } } void notifyEnabledOnKeyguardCallbacks(int userId, int modality) { diff --git a/services/core/java/com/android/server/wm/AppCompatAspectRatioPolicy.java b/services/core/java/com/android/server/wm/AppCompatAspectRatioPolicy.java index 15c0789d777e..3535a96d9c45 100644 --- a/services/core/java/com/android/server/wm/AppCompatAspectRatioPolicy.java +++ b/services/core/java/com/android/server/wm/AppCompatAspectRatioPolicy.java @@ -36,8 +36,7 @@ import android.app.WindowConfiguration; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Rect; - -import com.android.window.flags.Flags; +import android.window.DesktopModeFlags; /** * Encapsulate app compat policy logic related to aspect ratio. @@ -298,7 +297,8 @@ class AppCompatAspectRatioPolicy { // Camera compat mode is an exception to this, where the activity is letterboxed // to an aspect ratio commonly found on phones, e.g. 16:9, to avoid issues like // stretching of the camera preview. - || (Flags.ignoreAspectRatioRestrictionsForResizeableFreeformActivities() + || (DesktopModeFlags + .IGNORE_ASPECT_RATIO_RESTRICTIONS_FOR_RESIZEABLE_FREEFORM_ACTIVITIES.isTrue() && task.getWindowingMode() == WINDOWING_MODE_FREEFORM && !mActivityRecord.shouldCreateAppCompatDisplayInsets() && !AppCompatCameraPolicy.shouldCameraCompatControlAspectRatio( diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 867b3a234f71..fd7d96a646ae 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -2032,23 +2032,18 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { if (mOverrideOptions == null) { return; } - - if (!Flags.moveAnimationOptionsToChange()) { - info.setAnimationOptions(mOverrideOptions); - } else { - final List<TransitionInfo.Change> changes = info.getChanges(); - for (int i = changes.size() - 1; i >= 0; --i) { - final WindowContainer<?> container = mTargets.get(i).mContainer; - if (container.asActivityRecord() != null - || shouldApplyAnimOptionsToTask(container.asTask())) { - changes.get(i).setAnimationOptions(mOverrideOptions); - // TODO(b/295805497): Extract mBackgroundColor from AnimationOptions. - changes.get(i).setBackgroundColor(mOverrideOptions.getBackgroundColor()); - } else if (shouldApplyAnimOptionsToEmbeddedTf(container.asTaskFragment())) { - // We only override AnimationOptions because backgroundColor should be from - // TaskFragmentAnimationParams. - changes.get(i).setAnimationOptions(mOverrideOptions); - } + final List<TransitionInfo.Change> changes = info.getChanges(); + for (int i = changes.size() - 1; i >= 0; --i) { + final WindowContainer<?> container = mTargets.get(i).mContainer; + if (container.asActivityRecord() != null + || shouldApplyAnimOptionsToTask(container.asTask())) { + changes.get(i).setAnimationOptions(mOverrideOptions); + // TODO(b/295805497): Extract mBackgroundColor from AnimationOptions. + changes.get(i).setBackgroundColor(mOverrideOptions.getBackgroundColor()); + } else if (shouldApplyAnimOptionsToEmbeddedTf(container.asTaskFragment())) { + // We only override AnimationOptions because backgroundColor should be from + // TaskFragmentAnimationParams. + changes.get(i).setAnimationOptions(mOverrideOptions); } } updateActivityTargetForCrossProfileAnimation(info); @@ -2939,9 +2934,6 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { final AnimationOptions animOptionsForActivityTransition = calculateAnimationOptionsForActivityTransition(type, sortedTargets); - if (!Flags.moveAnimationOptionsToChange() && animOptionsForActivityTransition != null) { - out.setAnimationOptions(animOptionsForActivityTransition); - } final ArraySet<WindowContainer> occludedAtEndContainers = new ArraySet<>(); // Convert all the resolved ChangeInfos into TransactionInfo.Change objects in order. @@ -3065,28 +3057,26 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { } AnimationOptions animOptions = null; - if (Flags.moveAnimationOptionsToChange()) { - if (activityRecord != null && animOptionsForActivityTransition != null) { - animOptions = animOptionsForActivityTransition; - } else if (Flags.activityEmbeddingOverlayPresentationFlag() - && isEmbeddedTaskFragment) { - final TaskFragmentAnimationParams params = taskFragment.getAnimationParams(); - if (params.hasOverrideAnimation()) { - // Only set AnimationOptions if there's any animation override. - // We use separated field for backgroundColor, and - // AnimationOptions#backgroundColor will be removed in long term. - animOptions = AnimationOptions.makeCustomAnimOptions( - taskFragment.getTask().getBasePackageName(), - params.getOpenAnimationResId(), params.getChangeAnimationResId(), - params.getCloseAnimationResId(), 0 /* backgroundColor */, - false /* overrideTaskTransition */); - animOptions.setUserId(taskFragment.getTask().mUserId); - } - } - if (animOptions != null) { - change.setAnimationOptions(animOptions); + if (activityRecord != null && animOptionsForActivityTransition != null) { + animOptions = animOptionsForActivityTransition; + } else if (Flags.activityEmbeddingOverlayPresentationFlag() + && isEmbeddedTaskFragment) { + final TaskFragmentAnimationParams params = taskFragment.getAnimationParams(); + if (params.hasOverrideAnimation()) { + // Only set AnimationOptions if there's any animation override. + // We use separated field for backgroundColor, and + // AnimationOptions#backgroundColor will be removed in long term. + animOptions = AnimationOptions.makeCustomAnimOptions( + taskFragment.getTask().getBasePackageName(), + params.getOpenAnimationResId(), params.getChangeAnimationResId(), + params.getCloseAnimationResId(), 0 /* backgroundColor */, + false /* overrideTaskTransition */); + animOptions.setUserId(taskFragment.getTask().mUserId); } } + if (animOptions != null) { + change.setAnimationOptions(animOptions); + } if (activityRecord != null) { change.setActivityComponent(activityRecord.mActivityComponent); diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java index 77ad7f7bac7f..c0cb09f9a7d7 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java @@ -82,8 +82,6 @@ import android.graphics.Color; import android.graphics.Point; import android.graphics.Rect; import android.os.IBinder; -import android.platform.test.annotations.DisableFlags; -import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; import android.util.ArrayMap; import android.util.ArraySet; @@ -104,7 +102,6 @@ import androidx.annotation.NonNull; import androidx.test.filters.SmallTest; import com.android.internal.graphics.ColorUtils; -import com.android.window.flags.Flags; import org.junit.Test; import org.junit.runner.RunWith; @@ -2012,21 +2009,6 @@ public class TransitionTests extends WindowTestsBase { assertEquals(expectedBackgroundColor, info.getChanges().get(1).getBackgroundColor()); } - @DisableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) - @Test - public void testOverrideAnimationOptionsToInfoIfNecessary_disableAnimOptionsPerChange() { - ActivityRecord r = initializeOverrideAnimationOptionsTest(); - TransitionInfo.AnimationOptions options = TransitionInfo.AnimationOptions - .makeCommonAnimOptions("testPackage"); - mTransition.setOverrideAnimation(options, r, null /* startCallback */, - null /* finishCallback */); - - mTransition.overrideAnimationOptionsToInfoIfNecessary(mInfo); - - assertEquals(options, mInfo.getAnimationOptions()); - } - - @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) @Test public void testOverrideAnimationOptionsToInfoIfNecessary_fromStyleAnimOptions() { ActivityRecord r = initializeOverrideAnimationOptionsTest(); @@ -2052,7 +2034,6 @@ public class TransitionTests extends WindowTestsBase { options, activityChange.getAnimationOptions()); } - @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) @Test public void testOverrideAnimationOptionsToInfoIfNecessary_sceneAnimOptions() { ActivityRecord r = initializeOverrideAnimationOptionsTest(); @@ -2078,7 +2059,6 @@ public class TransitionTests extends WindowTestsBase { options, activityChange.getAnimationOptions()); } - @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) @Test public void testOverrideAnimationOptionsToInfoIfNecessary_crossProfileAnimOptions() { ActivityRecord r = initializeOverrideAnimationOptionsTest(); @@ -2106,7 +2086,6 @@ public class TransitionTests extends WindowTestsBase { assertTrue(activityChange.hasFlags(FLAG_CROSS_PROFILE_OWNER_THUMBNAIL)); } - @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) @Test public void testOverrideAnimationOptionsToInfoIfNecessary_customAnimOptions() { ActivityRecord r = initializeOverrideAnimationOptionsTest(); @@ -2139,7 +2118,6 @@ public class TransitionTests extends WindowTestsBase { options.getBackgroundColor(), activityChange.getBackgroundColor()); } - @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) @Test public void testOverrideAnimationOptionsToInfoIfNecessary_haveTaskFragmentAnimParams() { ActivityRecord r = initializeOverrideAnimationOptionsTest(); @@ -2188,7 +2166,6 @@ public class TransitionTests extends WindowTestsBase { options.getBackgroundColor(), activityChange.getBackgroundColor()); } - @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) @Test public void testOverrideAnimationOptionsToInfoIfNecessary_customAnimOptionsWithTaskOverride() { ActivityRecord r = initializeOverrideAnimationOptionsTest(); @@ -2418,7 +2395,6 @@ public class TransitionTests extends WindowTestsBase { } @Test - @EnableFlags(Flags.FLAG_ENABLE_DISPLAY_FOCUS_IN_SHELL_TRANSITIONS) public void testMoveDisplayToTop() { // Set up two displays, each of which has a task. DisplayContent otherDisplay = createNewDisplay(); diff --git a/tools/aapt2/link/FlaggedResources_test.cpp b/tools/aapt2/link/FlaggedResources_test.cpp index adf711ecfcbb..7bea96c26990 100644 --- a/tools/aapt2/link/FlaggedResources_test.cpp +++ b/tools/aapt2/link/FlaggedResources_test.cpp @@ -169,4 +169,18 @@ TEST_F(FlaggedResourcesTest, EnabledXmlELementAttributeRemoved) { ASSERT_TRUE(output.contains("test.package.readWriteFlag")); } +TEST_F(FlaggedResourcesTest, ReadWriteFlagInPathFails) { + test::TestDiagnosticsImpl diag; + const std::string compiled_files_dir = GetTestPath("compiled"); + ASSERT_FALSE(CompileFile(GetTestPath("res/values/flag(!test.package.rwFlag)/bools.xml"), + R"(<resources> + <bool name="bool1">false</bool> + </resources>)", + compiled_files_dir, &diag, + {"--feature-flags", "test.package.rwFlag=false"})); + + ASSERT_TRUE(diag.GetLog().contains( + "Only read only flags may be used with resources: test.package.rwFlag")); +} + } // namespace aapt |