diff options
176 files changed, 1954 insertions, 425 deletions
diff --git a/core/java/android/os/PerfettoTrackEventExtra.java b/core/java/android/os/PerfettoTrackEventExtra.java index 2848bcb8ad34..8a3a5be9c934 100644 --- a/core/java/android/os/PerfettoTrackEventExtra.java +++ b/core/java/android/os/PerfettoTrackEventExtra.java @@ -214,9 +214,6 @@ public final class PerfettoTrackEventExtra { * Initialize the builder for a new trace event. */ public Builder init(int traceType, PerfettoTrace.Category category) { - if (!category.isEnabled()) { - return this; - } mTraceType = traceType; mCategory = category; mEventName = ""; @@ -228,7 +225,7 @@ public final class PerfettoTrackEventExtra { mExtra.reset(); // Reset after on init in case the thread created builders without calling emit - return initInternal(this, null, true); + return initInternal(this, null, category.isEnabled()); } /** diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 89f66c010976..1210790668de 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -9357,6 +9357,16 @@ public final class Settings { "accessibility_autoclick_panel_position"; /** + * Setting that specifies whether autoclick type reverts to left click after performing + * an action when {@link #ACCESSIBILITY_AUTOCLICK_ENABLED} is set. + * + * @see #ACCESSIBILITY_AUTOCLICK_ENABLED + * @hide + */ + public static final String ACCESSIBILITY_AUTOCLICK_REVERT_TO_LEFT_CLICK = + "accessibility_autoclick_revert_to_left_click"; + + /** * Whether or not larger size icons are used for the pointer of mouse/trackpad for * accessibility. * (0 = false, 1 = true) diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index e157da72196a..9d0773f0a606 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -2071,26 +2071,40 @@ public final class ViewRootImpl implements ViewParent, */ @VisibleForTesting public @ForceDarkType.ForceDarkTypeDef int determineForceDarkType() { - if (forceInvertColor()) { - // Force invert ignores all developer opt-outs. - // We also ignore dark theme, since the app developer can override the user's preference - // for dark mode in configuration.uiMode. Instead, we assume that both force invert and - // the system's dark theme are enabled. - if (getUiModeManager().getForceInvertState() == UiModeManager.FORCE_INVERT_TYPE_DARK) { - return ForceDarkType.FORCE_INVERT_COLOR_DARK; - } - } - - boolean useAutoDark = getNightMode() == Configuration.UI_MODE_NIGHT_YES; - if (useAutoDark) { - boolean forceDarkAllowedDefault = - SystemProperties.getBoolean(ThreadedRenderer.DEBUG_FORCE_DARK, false); - TypedArray a = mContext.obtainStyledAttributes(R.styleable.Theme); - useAutoDark = a.getBoolean(R.styleable.Theme_isLightTheme, true) - && a.getBoolean(R.styleable.Theme_forceDarkAllowed, forceDarkAllowedDefault); + TypedArray a = mContext.obtainStyledAttributes(R.styleable.Theme); + try { + if (forceInvertColor()) { + // Force invert ignores all developer opt-outs. + // We also ignore dark theme, since the app developer can override the user's + // preference for dark mode in configuration.uiMode. Instead, we assume that both + // force invert and the system's dark theme are enabled. + if (getUiModeManager().getForceInvertState() == + UiModeManager.FORCE_INVERT_TYPE_DARK) { + final boolean isLightTheme = + a.getBoolean(R.styleable.Theme_isLightTheme, false); + // TODO: b/372558459 - Also check the background ColorDrawable color lightness + // TODO: b/368725782 - Use hwui color area detection instead of / in + // addition to these heuristics. + if (isLightTheme) { + return ForceDarkType.FORCE_INVERT_COLOR_DARK; + } else { + return ForceDarkType.NONE; + } + } + } + + boolean useAutoDark = getNightMode() == Configuration.UI_MODE_NIGHT_YES; + if (useAutoDark) { + boolean forceDarkAllowedDefault = + SystemProperties.getBoolean(ThreadedRenderer.DEBUG_FORCE_DARK, false); + useAutoDark = a.getBoolean(R.styleable.Theme_isLightTheme, true) + && a.getBoolean(R.styleable.Theme_forceDarkAllowed, + forceDarkAllowedDefault); + } + return useAutoDark ? ForceDarkType.FORCE_DARK : ForceDarkType.NONE; + } finally { a.recycle(); } - return useAutoDark ? ForceDarkType.FORCE_DARK : ForceDarkType.NONE; } private void updateForceDarkMode() { diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java index d267c9451d1a..e43fb48527a1 100644 --- a/core/java/android/view/accessibility/AccessibilityManager.java +++ b/core/java/android/view/accessibility/AccessibilityManager.java @@ -163,6 +163,9 @@ public final class AccessibilityManager { /** @hide */ public static final boolean AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT_DEFAULT = false; + /** @hide */ + public static final boolean AUTOCLICK_REVERT_TO_LEFT_CLICK_DEFAULT = true; + /** * Activity action: Launch UI to manage which accessibility service or feature is assigned * to the navigation bar Accessibility button. diff --git a/core/java/android/window/DesktopModeFlags.java b/core/java/android/window/DesktopModeFlags.java index 696b7b8bb965..1b8f73a7edb8 100644 --- a/core/java/android/window/DesktopModeFlags.java +++ b/core/java/android/window/DesktopModeFlags.java @@ -126,6 +126,8 @@ public enum DesktopModeFlags { ENABLE_TILE_RESIZING(Flags::enableTileResizing, true), ENABLE_TOP_VISIBLE_ROOT_TASK_PER_USER_TRACKING(Flags::enableTopVisibleRootTaskPerUserTracking, true), + ENABLE_VISUAL_INDICATOR_IN_TRANSITION_BUGFIX( + Flags::enableVisualIndicatorInTransitionBugfix, false), ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS(Flags::enableWindowingDynamicInitialBounds, true), ENABLE_WINDOWING_EDGE_DRAG_RESIZE(Flags::enableWindowingEdgeDragResize, true), ENABLE_WINDOWING_SCALED_RESIZING(Flags::enableWindowingScaledResizing, true), diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig index 09f458be9bfa..2f2a09a9fac3 100644 --- a/core/java/android/window/flags/lse_desktop_experience.aconfig +++ b/core/java/android/window/flags/lse_desktop_experience.aconfig @@ -864,4 +864,14 @@ flag { metadata { purpose: PURPOSE_BUGFIX } -}
\ No newline at end of file +} + +flag { + name: "enable_visual_indicator_in_transition_bugfix" + namespace: "lse_desktop_experience" + description: "Enables bugfix to move visual drop-zone indicator to transition root, so it can't be shown after the transition." + bug: "392826275" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java b/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java index b8503da2c09b..796ea8d1538f 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java +++ b/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java @@ -65,7 +65,7 @@ public class CoreDocument implements Serializable { // We also keep a more fine-grained BUILD number, exposed as // ID_API_LEVEL = DOCUMENT_API_LEVEL + BUILD - static final float BUILD = 0.2f; + static final float BUILD = 0.3f; @NonNull ArrayList<Operation> mOperations = new ArrayList<>(); @@ -411,7 +411,7 @@ public class CoreDocument implements Serializable { @Override public void serialize(MapSerializer serializer) { serializer - .add("type", "CoreDocument") + .addType("CoreDocument") .add("width", mWidth) .add("height", mHeight) .add("operations", mOperations); diff --git a/core/java/com/android/internal/widget/remotecompose/core/Operations.java b/core/java/com/android/internal/widget/remotecompose/core/Operations.java index 09ec40271f4d..9cbafab07a43 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/Operations.java +++ b/core/java/com/android/internal/widget/remotecompose/core/Operations.java @@ -100,6 +100,7 @@ import com.android.internal.widget.remotecompose.core.operations.layout.managers import com.android.internal.widget.remotecompose.core.operations.layout.managers.CollapsibleColumnLayout; import com.android.internal.widget.remotecompose.core.operations.layout.managers.CollapsibleRowLayout; import com.android.internal.widget.remotecompose.core.operations.layout.managers.ColumnLayout; +import com.android.internal.widget.remotecompose.core.operations.layout.managers.FitBoxLayout; import com.android.internal.widget.remotecompose.core.operations.layout.managers.RowLayout; import com.android.internal.widget.remotecompose.core.operations.layout.managers.StateLayout; import com.android.internal.widget.remotecompose.core.operations.layout.managers.TextLayout; @@ -231,6 +232,7 @@ public class Operations { public static final int LAYOUT_ROOT = 200; public static final int LAYOUT_CONTENT = 201; public static final int LAYOUT_BOX = 202; + public static final int LAYOUT_FIT_BOX = 176; public static final int LAYOUT_ROW = 203; public static final int LAYOUT_COLLAPSIBLE_ROW = 230; public static final int LAYOUT_COLUMN = 204; @@ -391,6 +393,7 @@ public class Operations { map.put(LAYOUT_ROOT, RootLayoutComponent::read); map.put(LAYOUT_CONTENT, LayoutComponentContent::read); map.put(LAYOUT_BOX, BoxLayout::read); + map.put(LAYOUT_FIT_BOX, FitBoxLayout::read); map.put(LAYOUT_COLUMN, ColumnLayout::read); map.put(LAYOUT_COLLAPSIBLE_COLUMN, CollapsibleColumnLayout::read); map.put(LAYOUT_ROW, RowLayout::read); diff --git a/core/java/com/android/internal/widget/remotecompose/core/PaintOperation.java b/core/java/com/android/internal/widget/remotecompose/core/PaintOperation.java index f355676be63e..c27ee3284b9c 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/PaintOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/PaintOperation.java @@ -17,11 +17,13 @@ package com.android.internal.widget.remotecompose.core; import android.annotation.NonNull; +import com.android.internal.widget.remotecompose.core.serialize.Serializable; + /** * PaintOperation interface, used for operations aimed at painting (while any operation _can_ paint, * this make it a little more explicit) */ -public abstract class PaintOperation extends Operation { +public abstract class PaintOperation extends Operation implements Serializable { @Override public void apply(@NonNull RemoteContext context) { diff --git a/core/java/com/android/internal/widget/remotecompose/core/Platform.java b/core/java/com/android/internal/widget/remotecompose/core/Platform.java index 6073de662cdb..3fff86c38b2e 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/Platform.java +++ b/core/java/com/android/internal/widget/remotecompose/core/Platform.java @@ -47,6 +47,14 @@ public interface Platform { int getImageHeight(@NonNull Object image); /** + * Returns true if the platform-specific image object has format ALPHA_8 + * + * @param image platform-specific image object + * @return whether or not the platform-specific image object has format ALPHA_8 + */ + boolean isAlpha8Image(@NonNull Object image); + + /** * Converts a platform-specific path object into a platform-independent float buffer * * @param path @@ -110,6 +118,11 @@ public interface Platform { } @Override + public boolean isAlpha8Image(@NonNull Object image) { + throw new UnsupportedOperationException(); + } + + @Override public float[] pathToFloatArray(@NonNull Object path) { throw new UnsupportedOperationException(); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java index e75bd30b381d..c249adf5bd58 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java +++ b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java @@ -98,6 +98,7 @@ import com.android.internal.widget.remotecompose.core.operations.layout.managers import com.android.internal.widget.remotecompose.core.operations.layout.managers.CollapsibleColumnLayout; import com.android.internal.widget.remotecompose.core.operations.layout.managers.CollapsibleRowLayout; import com.android.internal.widget.remotecompose.core.operations.layout.managers.ColumnLayout; +import com.android.internal.widget.remotecompose.core.operations.layout.managers.FitBoxLayout; import com.android.internal.widget.remotecompose.core.operations.layout.managers.RowLayout; import com.android.internal.widget.remotecompose.core.operations.layout.managers.StateLayout; import com.android.internal.widget.remotecompose.core.operations.layout.managers.TextLayout; @@ -281,13 +282,7 @@ public class RemoteComposeBuffer { int dstRight, int dstBottom, @Nullable String contentDescription) { - int imageId = mRemoteComposeState.dataGetId(image); - if (imageId == -1) { - imageId = mRemoteComposeState.cacheData(image); - byte[] data = mPlatform.imageToByteArray(image); // todo: potential npe - BitmapData.apply( - mBuffer, imageId, imageWidth, imageHeight, data); // todo: potential npe - } + int imageId = storeBitmap(image); int contentDescriptionId = 0; if (contentDescription != null) { contentDescriptionId = addText(contentDescription); @@ -443,16 +438,7 @@ public class RemoteComposeBuffer { float right, float bottom, @Nullable String contentDescription) { - int imageId = mRemoteComposeState.dataGetId(image); - if (imageId == -1) { - imageId = mRemoteComposeState.cacheData(image); - byte[] data = mPlatform.imageToByteArray(image); // todo: potential npe - int imageWidth = mPlatform.getImageWidth(image); - int imageHeight = mPlatform.getImageHeight(image); - - BitmapData.apply( - mBuffer, imageId, imageWidth, imageHeight, data); // todo: potential npe - } + int imageId = storeBitmap(image); addDrawBitmap(imageId, left, top, right, bottom, contentDescription); } @@ -523,15 +509,7 @@ public class RemoteComposeBuffer { int scaleType, float scaleFactor, @Nullable String contentDescription) { - int imageId = mRemoteComposeState.dataGetId(image); - if (imageId == -1) { - imageId = mRemoteComposeState.cacheData(image); - byte[] data = mPlatform.imageToByteArray(image); // todo: potential npe - int imageWidth = mPlatform.getImageWidth(image); - int imageHeight = mPlatform.getImageHeight(image); - - BitmapData.apply(mBuffer, imageId, imageWidth, imageHeight, data); // todo: potential pe - } + int imageId = storeBitmap(image); int contentDescriptionId = 0; if (contentDescription != null) { contentDescriptionId = addText(contentDescription); @@ -559,16 +537,7 @@ public class RemoteComposeBuffer { * @return id of the image useful with */ public int addBitmap(@NonNull Object image) { - int imageId = mRemoteComposeState.dataGetId(image); - if (imageId == -1) { - imageId = mRemoteComposeState.cacheData(image); - byte[] data = mPlatform.imageToByteArray(image); // tODO: potential npe - int imageWidth = mPlatform.getImageWidth(image); - int imageHeight = mPlatform.getImageHeight(image); - - BitmapData.apply(mBuffer, imageId, imageWidth, imageHeight, data); - } - return imageId; + return storeBitmap(image); } /** @@ -578,18 +547,7 @@ public class RemoteComposeBuffer { * @return id of the image useful with */ public int addBitmap(@NonNull Object image, @NonNull String name) { - int imageId = mRemoteComposeState.dataGetId(image); - if (imageId == -1) { - imageId = mRemoteComposeState.cacheData(image); - byte[] data = mPlatform.imageToByteArray(image); // todo: potential npe - int imageWidth = mPlatform.getImageWidth(image); - int imageHeight = mPlatform.getImageHeight(image); - - BitmapData.apply(mBuffer, imageId, imageWidth, imageHeight, data); - setBitmapName(imageId, name); - } - - return imageId; + return storeBitmap(image); } /** @@ -1393,7 +1351,7 @@ public class RemoteComposeBuffer { * @return the id of the command representing long */ public int addLong(long value) { - int id = mRemoteComposeState.cacheData(value); + int id = mRemoteComposeState.nextId(); LongConstant.apply(mBuffer, id, value); return id; } @@ -1405,7 +1363,7 @@ public class RemoteComposeBuffer { * @return the id */ public int addBoolean(boolean value) { - int id = mRemoteComposeState.cacheData(value); + int id = mRemoteComposeState.nextId(); BooleanConstant.apply(mBuffer, id, value); return id; } @@ -1821,33 +1779,14 @@ public class RemoteComposeBuffer { } /** - * This defines the name of the color given the id. - * - * @param id of the color - * @param name Name of the color - */ - public void setColorName(int id, @NonNull String name) { - NamedVariable.apply(mBuffer, id, NamedVariable.COLOR_TYPE, name); - } - - /** - * This defines the name of the string given the id - * - * @param id of the string - * @param name name of the string - */ - public void setStringName(int id, @NonNull String name) { - NamedVariable.apply(mBuffer, id, NamedVariable.STRING_TYPE, name); - } - - /** - * This defines the name of the float given the id + * This defines the name of a type of given object * * @param id of the float * @param name name of the float + * @param type the type of variable NamedVariable.COLOR_TYPE, STRING_TYPE, etc */ - public void setFloatName(int id, String name) { - NamedVariable.apply(mBuffer, id, NamedVariable.FLOAT_TYPE, name); + public void setNamedVariable(int id, @NonNull String name, int type) { + NamedVariable.apply(mBuffer, id, type, name); } /** @@ -2139,6 +2078,19 @@ public class RemoteComposeBuffer { } /** + * Add a fitbox start tag + * + * @param componentId component id + * @param animationId animation id + * @param horizontal horizontal alignment + * @param vertical vertical alignment + */ + public void addFitBoxStart(int componentId, int animationId, int horizontal, int vertical) { + mLastComponentId = getComponentId(componentId); + FitBoxLayout.apply(mBuffer, mLastComponentId, animationId, horizontal, vertical); + } + + /** * Add a row start tag * * @param componentId component id @@ -2439,4 +2391,35 @@ public class RemoteComposeBuffer { public void drawComponentContent() { DrawContent.apply(mBuffer); } + + /** + * Ensures the bitmap is stored. + * + * @param image the bitbap to store + * @return the id of the bitmap + */ + private int storeBitmap(Object image) { + int imageId = mRemoteComposeState.dataGetId(image); + if (imageId == -1) { + imageId = mRemoteComposeState.cacheData(image); + byte[] data = mPlatform.imageToByteArray(image); // todo: potential npe + short imageWidth = (short) mPlatform.getImageWidth(image); + short imageHeight = (short) mPlatform.getImageHeight(image); + if (mPlatform.isAlpha8Image(image)) { + BitmapData.apply( + mBuffer, + imageId, + BitmapData.TYPE_PNG_ALPHA_8, + imageWidth, + BitmapData.ENCODING_INLINE, + imageHeight, + data); // todo: potential npe + } else { + BitmapData.apply( + mBuffer, imageId, imageWidth, imageHeight, data); // todo: potential npe + } + } + + return imageId; + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java index 363b82bdf70c..83c06197db9c 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java +++ b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java @@ -27,6 +27,7 @@ import com.android.internal.widget.remotecompose.core.operations.utilities.IntMa import com.android.internal.widget.remotecompose.core.operations.utilities.NanMap; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; /** @@ -36,7 +37,7 @@ import java.util.HashMap; public class RemoteComposeState implements CollectionsAccess { public static final int START_ID = 42; // private static final int MAX_FLOATS = 500; - private static final int MAX_COLORS = 200; + private static int sMaxColors = 200; private static final int MAX_DATA = 1000; private final IntMap<Object> mIntDataMap = new IntMap<>(); @@ -52,7 +53,7 @@ public class RemoteComposeState implements CollectionsAccess { private final IntMap<Object> mPathMap = new IntMap<>(); private final IntMap<float[]> mPathData = new IntMap<>(); - private final boolean[] mColorOverride = new boolean[MAX_COLORS]; + private boolean[] mColorOverride = new boolean[sMaxColors]; @NonNull private final IntMap<ArrayAccess> mCollectionMap = new IntMap<>(); private final boolean[] mDataOverride = new boolean[MAX_DATA]; @@ -318,7 +319,7 @@ public class RemoteComposeState implements CollectionsAccess { * @param color */ public void updateColor(int id, int color) { - if (mColorOverride[id]) { + if (id < sMaxColors && mColorOverride[id]) { return; } mColorMap.put(id, color); @@ -342,6 +343,10 @@ public class RemoteComposeState implements CollectionsAccess { * @param color */ public void overrideColor(int id, int color) { + if (id >= sMaxColors) { + sMaxColors *= 2; + mColorOverride = Arrays.copyOf(mColorOverride, sMaxColors); + } mColorOverride[id] = true; mColorMap.put(id, color); updateListeners(id); diff --git a/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java b/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java index 622f0c8d12b7..c6b17e4116d6 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java +++ b/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java @@ -211,6 +211,14 @@ public abstract class RemoteContext { public abstract void clearNamedFloatOverride(String floatName); /** + * Set the value of a named long. This modifies the content of a LongConstant + * + * @param name the name of the float to override + * @param value Override the default float + */ + public abstract void setNamedLong(String name, long value); + + /** * Set the value of a named Object. This overrides the Object in the document * * @param dataName the name of the Object to override diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/BitmapData.java b/core/java/com/android/internal/widget/remotecompose/core/operations/BitmapData.java index 13e6f3859933..255d7a46e49e 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/BitmapData.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/BitmapData.java @@ -72,6 +72,9 @@ public class BitmapData extends Operation implements SerializableToString, Seria /** The data is encoded as RAW 8888 bit */ public static final short TYPE_RAW8888 = 3; + /** The data is encoded as PNG_8888 but decoded as ALPHA_8 */ + public static final short TYPE_PNG_ALPHA_8 = 4; + /** * create a bitmap structure * @@ -136,6 +139,15 @@ public class BitmapData extends Operation implements SerializableToString, Seria } /** + * The type of the image + * + * @return the type of the image + */ + public int getType() { + return mType; + } + + /** * Add the image to the document * * @param buffer document to write to @@ -195,6 +207,21 @@ public class BitmapData extends Operation implements SerializableToString, Seria int imageId = buffer.readInt(); int width = buffer.readInt(); int height = buffer.readInt(); + int type; + if (width > 0xffff) { + type = width >> 16; + width = width & 0xffff; + } else { + type = TYPE_PNG_8888; + } + + int encoding; + if (height > 0xffff) { + encoding = height >> 16; + height = height & 0xffff; + } else { + encoding = ENCODING_INLINE; + } if (width < 1 || height < 1 || height > MAX_IMAGE_DIMENSION @@ -202,7 +229,10 @@ public class BitmapData extends Operation implements SerializableToString, Seria throw new RuntimeException("Dimension of image is invalid " + width + "x" + height); } byte[] bitmap = buffer.readBuffer(); - operations.add(new BitmapData(imageId, width, height, bitmap)); + BitmapData bitmapData = new BitmapData(imageId, width, height, bitmap); + bitmapData.mType = (short) type; + bitmapData.mEncoding = (short) encoding; + operations.add(bitmapData); } /** @@ -244,7 +274,7 @@ public class BitmapData extends Operation implements SerializableToString, Seria @Override public void serialize(MapSerializer serializer) { serializer - .add("type", CLASS_NAME) + .addType(CLASS_NAME) .add("imageId", mImageId) .add("imageWidth", mImageWidth) .add("imageHeight", mImageHeight) @@ -275,6 +305,8 @@ public class BitmapData extends Operation implements SerializableToString, Seria return "TYPE_RAW8"; case TYPE_RAW8888: return "TYPE_RAW8888"; + case TYPE_PNG_ALPHA_8: + return "TYPE_PNG_ALPHA_8"; default: return "TYPE_INVALID"; } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/BitmapFontData.java b/core/java/com/android/internal/widget/remotecompose/core/operations/BitmapFontData.java index 078ce981d243..70bda6d1c0fa 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/BitmapFontData.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/BitmapFontData.java @@ -221,6 +221,6 @@ public class BitmapFontData extends Operation implements Serializable { @Override public void serialize(MapSerializer serializer) { - serializer.add("type", CLASS_NAME).add("id", mId); + serializer.addType(CLASS_NAME).add("id", mId); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ClickArea.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ClickArea.java index 00ac9c28f362..7a8373bf7c7d 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/ClickArea.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ClickArea.java @@ -237,7 +237,7 @@ public class ClickArea extends Operation @Override public void serialize(MapSerializer serializer) { serializer - .add("type", CLASS_NAME) + .addType(CLASS_NAME) .add("id", mId) .add("contentDescriptionId", mContentDescription) .add("left", mLeft, mOutLeft) diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ClipPath.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ClipPath.java index e7dc405b542e..03bdb70a9289 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/ClipPath.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ClipPath.java @@ -133,7 +133,7 @@ public class ClipPath extends PaintOperation implements Serializable { @Override public void serialize(MapSerializer serializer) { - serializer.add("type", CLASS_NAME).add("id", mId).add("regionOp", regionOpToString()); + serializer.addType(CLASS_NAME).add("id", mId).add("regionOp", regionOpToString()); } String regionOpToString() { diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ClipRect.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ClipRect.java index 1646146bd21d..8b1e96a691a6 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/ClipRect.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ClipRect.java @@ -118,6 +118,6 @@ public class ClipRect extends DrawBase4 { @Override public void serialize(MapSerializer serializer) { - serialize(serializer, "left", "top", "right", "bottom").add("type", CLASS_NAME); + serialize(serializer, "left", "top", "right", "bottom").addType(CLASS_NAME); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ColorConstant.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ColorConstant.java index 333ffaae8289..7b12f4a9cf15 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/ColorConstant.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ColorConstant.java @@ -133,7 +133,7 @@ public class ColorConstant extends Operation implements Serializable { @Override public void serialize(MapSerializer serializer) { serializer - .add("type", CLASS_NAME) + .addType(CLASS_NAME) .add("color", Utils.colorInt(mColor)) .add("colorId", mColorId); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ColorExpression.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ColorExpression.java index d5af7914607a..25323a8a818d 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/ColorExpression.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ColorExpression.java @@ -507,7 +507,7 @@ public class ColorExpression extends Operation implements VariableSupport, Seria @Override public void serialize(MapSerializer serializer) { - serializer.add("type", CLASS_NAME).add("id", mId); + serializer.addType(CLASS_NAME).add("id", mId); switch (mMode) { case COLOR_COLOR_INTERPOLATE: case ID_COLOR_INTERPOLATE: diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ComponentValue.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ComponentValue.java index cd13d2534266..5335e4fa76ca 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/ComponentValue.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ComponentValue.java @@ -171,7 +171,7 @@ public class ComponentValue extends Operation implements SerializableToString, S @Override public void serialize(MapSerializer serializer) { serializer - .add("type", CLASS_NAME) + .addType(CLASS_NAME) .add("valueId", mValueId) .add("componentValueType", typeToString(mType)) .add("componentId", mComponentID); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DataListFloat.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DataListFloat.java index fb3abdbb0626..20bebaa1ddb2 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DataListFloat.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DataListFloat.java @@ -148,8 +148,9 @@ public class DataListFloat extends Operation implements VariableSupport, ArrayAc return mValues.length; } + @SuppressWarnings("JdkImmutableCollections") @Override public void serialize(MapSerializer serializer) { - serializer.add("type", CLASS_NAME).add("id", mId).add("values", List.of(mValues)); + serializer.addType(CLASS_NAME).add("id", mId).add("values", List.of(mValues)); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DataListIds.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DataListIds.java index 58fd74fdcf3e..af660f3d42c9 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DataListIds.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DataListIds.java @@ -150,8 +150,9 @@ public class DataListIds extends Operation implements VariableSupport, ArrayAcce return 0; } + @SuppressWarnings("JdkImmutableCollections") @Override public void serialize(MapSerializer serializer) { - serializer.add("type", CLASS_NAME).add("id", mId).add("ids", List.of(mIds)); + serializer.addType(CLASS_NAME).add("id", mId).add("ids", List.of(mIds)); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawArc.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawArc.java index a427836b6c5f..5024164651f5 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawArc.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawArc.java @@ -141,6 +141,6 @@ public class DrawArc extends DrawBase6 { @Override public void serialize(MapSerializer serializer) { serialize(serializer, "left", "top", "right", "bottom", "startAngle", "sweepAngle") - .add("type", CLASS_NAME); + .addType(CLASS_NAME); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmap.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmap.java index 40d3bede0912..e3b53a125a63 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmap.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmap.java @@ -28,6 +28,7 @@ import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.VariableSupport; import com.android.internal.widget.remotecompose.core.WireBuffer; import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.serialize.MapSerializer; import java.util.List; @@ -185,4 +186,16 @@ public class DrawBitmap extends PaintOperation implements VariableSupport { public void paint(@NonNull PaintContext context) { context.drawBitmap(mId, mOutputLeft, mOutputTop, mOutputRight, mOutputBottom); } + + @Override + public void serialize(MapSerializer serializer) { + serializer + .addType(CLASS_NAME) + .add("imageId", mId) + .add("contentDescriptionId", mDescriptionId) + .add("left", mLeft, mOutputLeft) + .add("top", mTop, mOutputTop) + .add("right", mRight, mOutputRight) + .add("bottom", mBottom, mOutputBottom); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapFontText.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapFontText.java index 258988e8b00a..bff87fda2fd9 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapFontText.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapFontText.java @@ -28,6 +28,7 @@ import com.android.internal.widget.remotecompose.core.VariableSupport; import com.android.internal.widget.remotecompose.core.WireBuffer; import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation; +import com.android.internal.widget.remotecompose.core.serialize.MapSerializer; import java.util.List; @@ -229,4 +230,16 @@ public class DrawBitmapFontText extends PaintOperation implements VariableSuppor xPos = xPos2 + glyph.mMarginRight; } } + + @Override + public void serialize(MapSerializer serializer) { + serializer + .addType(CLASS_NAME) + .add("textId", mTextID) + .add("bitmapFontId", mBitmapFontID) + .add("start", mStart) + .add("end", mEnd) + .add("x", mX, mOutX) + .add("y", mY, mOutY); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapInt.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapInt.java index 013dd1ae9db8..39d85af900ee 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapInt.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapInt.java @@ -25,6 +25,7 @@ import com.android.internal.widget.remotecompose.core.WireBuffer; import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation; import com.android.internal.widget.remotecompose.core.semantics.AccessibleComponent; +import com.android.internal.widget.remotecompose.core.serialize.MapSerializer; import java.util.List; @@ -230,4 +231,20 @@ public class DrawBitmapInt extends PaintOperation implements AccessibleComponent mDstBottom, mContentDescId); } + + @Override + public void serialize(MapSerializer serializer) { + serializer + .addType(CLASS_NAME) + .add("imageId", mImageId) + .add("contentDescriptionId", mContentDescId) + .add("srcLeft", mSrcLeft) + .add("srcTop", mSrcTop) + .add("srcRight", mSrcRight) + .add("srcBottom", mSrcBottom) + .add("dstLeft", mDstLeft) + .add("dstTop", mDstTop) + .add("dstRight", mDstRight) + .add("dstBottom", mDstBottom); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapScaled.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapScaled.java index e1070f97d5aa..827e5692e132 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapScaled.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapScaled.java @@ -28,6 +28,7 @@ import com.android.internal.widget.remotecompose.core.documentation.Documentatio import com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation; import com.android.internal.widget.remotecompose.core.operations.utilities.ImageScaling; import com.android.internal.widget.remotecompose.core.semantics.AccessibleComponent; +import com.android.internal.widget.remotecompose.core.serialize.MapSerializer; import java.util.List; @@ -374,4 +375,46 @@ public class DrawBitmapScaled extends PaintOperation mContentDescId); context.restore(); } + + @Override + public void serialize(MapSerializer serializer) { + serializer + .addType(CLASS_NAME) + .add("imageId", mImageId) + .add("contentDescriptionId", mContentDescId) + .add("scaleType", getScaleTypeString()) + .add("mode", mMode) + .add("scaleFactor", mScaleFactor, mOutScaleFactor) + .add("srcLeft", mSrcLeft, mOutSrcLeft) + .add("srcTop", mSrcTop, mOutSrcTop) + .add("srcRight", mSrcRight, mOutSrcRight) + .add("srcBottom", mSrcBottom, mOutSrcBottom) + .add("dstLeft", mDstLeft, mOutDstLeft) + .add("dstTop", mDstTop, mOutDstTop) + .add("dstRight", mDstRight, mOutDstRight) + .add("dstBottom", mDstBottom, mOutDstBottom); + } + + private String getScaleTypeString() { + switch (mScaleType) { + case SCALE_NONE: + return "SCALE_NONE"; + case SCALE_INSIDE: + return "SCALE_INSIDE"; + case SCALE_FILL_WIDTH: + return "SCALE_FILL_WIDTH"; + case SCALE_FILL_HEIGHT: + return "SCALE_FILL_HEIGHT"; + case SCALE_FIT: + return "SCALE_FIT"; + case SCALE_CROP: + return "SCALE_CROP"; + case SCALE_FILL_BOUNDS: + return "SCALE_FILL_BOUNDS"; + case SCALE_FIXED_SCALE: + return "SCALE_FIXED_SCALE"; + default: + return "INVALID_SCALE_TYPE"; + } + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawCircle.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawCircle.java index dfc89b12de1e..538cbaf97a06 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawCircle.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawCircle.java @@ -112,6 +112,6 @@ public class DrawCircle extends DrawBase3 { @Override public void serialize(MapSerializer serializer) { - serialize(serializer, "cx", "cy", "radius").add("type", CLASS_NAME); + serialize(serializer, "cx", "cy", "radius").addType(CLASS_NAME); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawContent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawContent.java index e2e22acbeb8f..4d2a939eb948 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawContent.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawContent.java @@ -114,6 +114,6 @@ public class DrawContent extends PaintOperation implements Serializable { @Override public void serialize(MapSerializer serializer) { - serializer.add("type", CLASS_NAME); + serializer.addType(CLASS_NAME); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawLine.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawLine.java index 461dece02625..97e5057fb950 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawLine.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawLine.java @@ -140,6 +140,6 @@ public class DrawLine extends DrawBase4 implements SerializableToString { @Override public void serialize(MapSerializer serializer) { - serialize(serializer, "startX", "startY", "endX", "endY").add("type", CLASS_NAME); + serialize(serializer, "startX", "startY", "endX", "endY").addType(CLASS_NAME); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawOval.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawOval.java index d0a5adc0e737..5d619baa1328 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawOval.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawOval.java @@ -110,6 +110,6 @@ public class DrawOval extends DrawBase4 { @Override public void serialize(MapSerializer serializer) { - serialize(serializer, "left", "top", "right", "bottom").add("type", CLASS_NAME); + serialize(serializer, "left", "top", "right", "bottom").addType(CLASS_NAME); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawPath.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawPath.java index 3fd8bb440d82..6e299275fb24 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawPath.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawPath.java @@ -112,6 +112,6 @@ public class DrawPath extends PaintOperation implements Serializable { @Override public void serialize(MapSerializer serializer) { - serializer.add("type", CLASS_NAME).add("id", mId).add("start", mStart).add("end", mEnd); + serializer.addType(CLASS_NAME).add("id", mId).add("start", mStart).add("end", mEnd); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRect.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRect.java index f6aa30f5b5dd..15f3ced74652 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRect.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRect.java @@ -106,6 +106,6 @@ public class DrawRect extends DrawBase4 { @Override public void serialize(MapSerializer serializer) { - serialize(serializer, "left", "top", "right", "bottom").add("type", CLASS_NAME); + serialize(serializer, "left", "top", "right", "bottom").addType(CLASS_NAME); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRoundRect.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRoundRect.java index 67338c14a101..31d9b6ac124d 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRoundRect.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRoundRect.java @@ -127,6 +127,6 @@ public class DrawRoundRect extends DrawBase6 { @Override public void serialize(MapSerializer serializer) { serialize(serializer, "left", "top", "right", "bottom", "rx", "sweepAngle") - .add("type", CLASS_NAME); + .addType(CLASS_NAME); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawSector.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawSector.java index 78f64a5bcd44..19f16239b9f2 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawSector.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawSector.java @@ -128,6 +128,6 @@ public class DrawSector extends DrawBase6 { @Override public void serialize(MapSerializer serializer) { serialize(serializer, "left", "top", "right", "bottom", "startAngle", "sweepAngle") - .add("type", CLASS_NAME); + .addType(CLASS_NAME); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawText.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawText.java index 8adba1d2616a..ee1689c21fe3 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawText.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawText.java @@ -28,6 +28,7 @@ import com.android.internal.widget.remotecompose.core.VariableSupport; import com.android.internal.widget.remotecompose.core.WireBuffer; import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation; +import com.android.internal.widget.remotecompose.core.serialize.MapSerializer; import java.util.List; @@ -205,4 +206,17 @@ public class DrawText extends PaintOperation implements VariableSupport { public void paint(@NonNull PaintContext context) { context.drawTextRun(mTextID, mStart, mEnd, mContextStart, mContextEnd, mOutX, mOutY, mRtl); } + + @Override + public void serialize(MapSerializer serializer) { + serializer + .addType(CLASS_NAME) + .add("start", mStart) + .add("end", mEnd) + .add("contextStart", mContextStart) + .add("contextEnd", mContextEnd) + .add("x", mX, mOutX) + .add("y", mY, mOutY) + .add("rtl", mRtl); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextAnchored.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextAnchored.java index 92469d1834ba..1d917d565331 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextAnchored.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextAnchored.java @@ -244,7 +244,7 @@ public class DrawTextAnchored extends PaintOperation implements VariableSupport, @Override public void serialize(MapSerializer serializer) { serializer - .add("type", CLASS_NAME) + .addType(CLASS_NAME) .add("textId", mTextID) .add("x", mX, mOutX) .add("y", mY, mOutY) diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextOnPath.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextOnPath.java index 1f7910ede4b5..f382440360ed 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextOnPath.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextOnPath.java @@ -159,7 +159,7 @@ public class DrawTextOnPath extends PaintOperation implements VariableSupport, S @Override public void serialize(MapSerializer serializer) { serializer - .add("type", CLASS_NAME) + .addType(CLASS_NAME) .add("pathId", mPathId) .add("textId", mTextId) .add("vOffset", mVOffset, mOutVOffset) diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTweenPath.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTweenPath.java index e2883949022c..4ca995b59f1f 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTweenPath.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTweenPath.java @@ -28,6 +28,7 @@ import com.android.internal.widget.remotecompose.core.VariableSupport; import com.android.internal.widget.remotecompose.core.WireBuffer; import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation; +import com.android.internal.widget.remotecompose.core.serialize.MapSerializer; import java.util.List; @@ -171,4 +172,15 @@ public class DrawTweenPath extends PaintOperation implements VariableSupport { public void paint(@NonNull PaintContext context) { context.drawTweenPath(mPath1Id, mPath2Id, mOutTween, mOutStart, mOutStop); } + + @Override + public void serialize(MapSerializer serializer) { + serializer + .addType(CLASS_NAME) + .add("path1Id", mPath1Id) + .add("path2Id", mPath2Id) + .add("tween", mTween, mOutTween) + .add("start", mStart, mOutStart) + .add("stop", mStop, mOutStop); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/FloatConstant.java b/core/java/com/android/internal/widget/remotecompose/core/operations/FloatConstant.java index 7f3c3ed6bcff..233e246d3868 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/FloatConstant.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/FloatConstant.java @@ -123,6 +123,6 @@ public class FloatConstant extends Operation implements Serializable { @Override public void serialize(MapSerializer serializer) { - serializer.add("type", CLASS_NAME).add("id", mId).add("value", mValue); + serializer.addType(CLASS_NAME).add("id", mId).add("value", mValue); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/FloatExpression.java b/core/java/com/android/internal/widget/remotecompose/core/operations/FloatExpression.java index c1fa898ec619..eba201bfb216 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/FloatExpression.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/FloatExpression.java @@ -160,6 +160,9 @@ public class FloatExpression extends Operation implements VariableSupport, Seria mLastAnimatedValue = lastComputedValue; context.loadFloat(mId, lastComputedValue); context.needsRepaint(); + if (mFloatAnimation.isPropagate()) { + markDirty(); + } } } else if (mSpring != null) { float lastComputedValue = mSpring.get(t - mLastChange); @@ -169,8 +172,12 @@ public class FloatExpression extends Operation implements VariableSupport, Seria context.needsRepaint(); } } else { - float v = - mExp.eval(context.getCollectionsAccess(), mPreCalcValue, mPreCalcValue.length); + float v = 0; + try { + v = mExp.eval(context.getCollectionsAccess(), mPreCalcValue, mPreCalcValue.length); + } catch (Exception e) { + throw new RuntimeException(this.toString() + " len = " + mPreCalcValue.length, e); + } if (mFloatAnimation != null) { mFloatAnimation.setTargetValue(v); } @@ -344,7 +351,7 @@ public class FloatExpression extends Operation implements VariableSupport, Seria public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.EXPRESSION) - .add("type", CLASS_NAME) + .addType(CLASS_NAME) .add("id", mId) .addFloatExpressionSrc("srcValues", mSrcValue) .add("animation", mFloatAnimation); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/FloatFunctionCall.java b/core/java/com/android/internal/widget/remotecompose/core/operations/FloatFunctionCall.java index eccc00a18308..85592948438f 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/FloatFunctionCall.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/FloatFunctionCall.java @@ -32,8 +32,10 @@ import com.android.internal.widget.remotecompose.core.documentation.Documentatio import com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation; import com.android.internal.widget.remotecompose.core.operations.utilities.AnimatedFloatExpression; import com.android.internal.widget.remotecompose.core.operations.utilities.NanMap; +import com.android.internal.widget.remotecompose.core.serialize.MapSerializer; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** This provides the command to call a floatfunction defined in floatfunction */ @@ -182,4 +184,13 @@ public class FloatFunctionCall extends PaintOperation implements VariableSupport } mFunction.execute(remoteContext); } + + @Override + public void serialize(MapSerializer serializer) { + serializer + .addType(CLASS_NAME) + .add("id", mId) + .add("args", Collections.singletonList(mArgs)) + .add("outArgs", Collections.singletonList(mOutArgs)); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ImageAttribute.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ImageAttribute.java index fb4a5e4848c2..9ef1b3b1ad6a 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/ImageAttribute.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ImageAttribute.java @@ -26,7 +26,9 @@ import com.android.internal.widget.remotecompose.core.PaintContext; import com.android.internal.widget.remotecompose.core.PaintOperation; import com.android.internal.widget.remotecompose.core.WireBuffer; import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.serialize.MapSerializer; +import java.util.Collections; import java.util.List; /** Operation to extract meta Attributes from image data objects */ @@ -162,4 +164,25 @@ public class ImageAttribute extends PaintOperation { break; } } + + @Override + public void serialize(MapSerializer serializer) { + serializer + .addType(CLASS_NAME) + .add("id", mId) + .add("imageId", mImageId) + .add("args", Collections.singletonList(mArgs)) + .addType(typeToString()); + } + + private String typeToString() { + switch (mType) { + case IMAGE_WIDTH: + return "IMAGE_WIDTH"; + case IMAGE_HEIGHT: + return "IMAGE_HEIGHT"; + default: + return "INVALID_TYPE"; + } + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/IntegerExpression.java b/core/java/com/android/internal/widget/remotecompose/core/operations/IntegerExpression.java index 2a5260c0c9b1..53b3c89f3aa8 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/IntegerExpression.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/IntegerExpression.java @@ -233,7 +233,7 @@ public class IntegerExpression extends Operation implements VariableSupport, Ser public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.EXPRESSION) - .add("type", CLASS_NAME) + .addType(CLASS_NAME) .add("id", mId) .add("mask", mId) .addIntExpressionSrc("srcValues", mSrcValue, mMask); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRestore.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRestore.java index 64df19d8a04f..d2b38f42e966 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRestore.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRestore.java @@ -102,6 +102,6 @@ public class MatrixRestore extends PaintOperation implements Serializable { @Override public void serialize(MapSerializer serializer) { - serializer.add("type", CLASS_NAME); + serializer.addType(CLASS_NAME); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRotate.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRotate.java index 9c4df0b54d60..5990b4bdfad7 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRotate.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRotate.java @@ -114,6 +114,6 @@ public class MatrixRotate extends DrawBase3 { @Override public void serialize(MapSerializer serializer) { - serialize(serializer, "rotate", "pivotX", "pivotY").add("type", CLASS_NAME); + serialize(serializer, "rotate", "pivotX", "pivotY").addType(CLASS_NAME); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSave.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSave.java index 0e6de0db3b28..06da1565bf3a 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSave.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSave.java @@ -100,6 +100,6 @@ public class MatrixSave extends PaintOperation implements Serializable { @Override public void serialize(MapSerializer serializer) { - serializer.add("type", CLASS_NAME); + serializer.addType(CLASS_NAME); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixScale.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixScale.java index b6e5cbcf388a..20d406569223 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixScale.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixScale.java @@ -106,6 +106,6 @@ public class MatrixScale extends DrawBase4 { @Override public void serialize(MapSerializer serializer) { - serialize(serializer, "scaleX", "scaleY", "pivotX", "pivotY").add("type", CLASS_NAME); + serialize(serializer, "scaleX", "scaleY", "pivotX", "pivotY").addType(CLASS_NAME); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSkew.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSkew.java index f9a589c598aa..6d1c503c3284 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSkew.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSkew.java @@ -103,6 +103,6 @@ public class MatrixSkew extends DrawBase2 { @Override public void serialize(MapSerializer serializer) { - serialize(serializer, "skewX", "skewY").add("type", CLASS_NAME); + serialize(serializer, "skewX", "skewY").addType(CLASS_NAME); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixTranslate.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixTranslate.java index de783bfc7ae8..e21f13355679 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixTranslate.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixTranslate.java @@ -102,6 +102,6 @@ public class MatrixTranslate extends DrawBase2 { @Override public void serialize(MapSerializer serializer) { - serialize(serializer, "dx", "dy").add("type", CLASS_NAME); + serialize(serializer, "dx", "dy").addType(CLASS_NAME); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/NamedVariable.java b/core/java/com/android/internal/widget/remotecompose/core/operations/NamedVariable.java index 96628fd51225..9a880858b5a5 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/NamedVariable.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/NamedVariable.java @@ -25,7 +25,6 @@ import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.WireBuffer; import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; -import com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation; import com.android.internal.widget.remotecompose.core.serialize.MapSerializer; import com.android.internal.widget.remotecompose.core.serialize.Serializable; @@ -43,6 +42,8 @@ public class NamedVariable extends Operation implements Serializable { public static final int FLOAT_TYPE = 1; public static final int STRING_TYPE = 0; public static final int IMAGE_TYPE = 3; + public static final int INT_TYPE = 4; + public static final int LONG_TYPE = 5; public NamedVariable(int varId, int varType, @NonNull String name) { this.mVarId = varId; @@ -122,7 +123,7 @@ public class NamedVariable extends Operation implements Serializable { public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Data Operations", OP_CODE, CLASS_NAME) .description("Add a string name for an ID") - .field(DocumentedOperation.INT, "varId", "id to label") + .field(INT, "varId", "id to label") .field(INT, "varType", "The type of variable") .field(UTF8, "name", "String"); } @@ -141,7 +142,7 @@ public class NamedVariable extends Operation implements Serializable { @Override public void serialize(MapSerializer serializer) { serializer - .add("type", CLASS_NAME) + .addType(CLASS_NAME) .add("varId", mVarId) .add("varName", mVarName) .add("varType", typeToString()); @@ -157,6 +158,8 @@ public class NamedVariable extends Operation implements Serializable { return "STRING_TYPE"; case IMAGE_TYPE: return "IMAGE_TYPE"; + case INT_TYPE: + return "INT_TYPE"; default: return "INVALID_TYPE"; } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/PaintData.java b/core/java/com/android/internal/widget/remotecompose/core/operations/PaintData.java index 8389aa707ee6..70197c6d085d 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/PaintData.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/PaintData.java @@ -131,6 +131,6 @@ public class PaintData extends PaintOperation implements VariableSupport, Serial @Override public void serialize(MapSerializer serializer) { - serializer.add("type", CLASS_NAME).add("paintBundle", mPaintData); + serializer.addType(CLASS_NAME).add("paintBundle", mPaintData); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ParticlesLoop.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ParticlesLoop.java index 8d19c94df604..f9fdfdf09e35 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/ParticlesLoop.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ParticlesLoop.java @@ -33,6 +33,7 @@ import com.android.internal.widget.remotecompose.core.documentation.DocumentedOp import com.android.internal.widget.remotecompose.core.operations.layout.Container; import com.android.internal.widget.remotecompose.core.operations.utilities.AnimatedFloatExpression; import com.android.internal.widget.remotecompose.core.operations.utilities.NanMap; +import com.android.internal.widget.remotecompose.core.serialize.MapSerializer; import java.util.ArrayList; import java.util.List; @@ -292,4 +293,9 @@ public class ParticlesLoop extends PaintOperation implements VariableSupport, Co } } } + + @Override + public void serialize(MapSerializer serializer) { + serializer.addType(CLASS_NAME).add("id", mId); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/PathAppend.java b/core/java/com/android/internal/widget/remotecompose/core/operations/PathAppend.java index 8f353ce4a26b..8a747e134897 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/PathAppend.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/PathAppend.java @@ -258,9 +258,6 @@ public class PathAppend extends PaintOperation implements VariableSupport, Seria @Override public void serialize(MapSerializer serializer) { - serializer - .add("type", CLASS_NAME) - .add("id", mInstanceId) - .add("path", pathString(mFloatPath)); + serializer.addType(CLASS_NAME).add("id", mInstanceId).add("path", pathString(mFloatPath)); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/PathCreate.java b/core/java/com/android/internal/widget/remotecompose/core/operations/PathCreate.java index 7aa3390b53ee..78e3b9eac110 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/PathCreate.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/PathCreate.java @@ -242,9 +242,6 @@ public class PathCreate extends PaintOperation implements VariableSupport, Seria @Override public void serialize(MapSerializer serializer) { - serializer - .add("type", CLASS_NAME) - .add("id", mInstanceId) - .add("path", pathString(mFloatPath)); + serializer.addType(CLASS_NAME).add("id", mInstanceId).add("path", pathString(mFloatPath)); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/PathData.java b/core/java/com/android/internal/widget/remotecompose/core/operations/PathData.java index 9564f15209c7..cedc4f3b0e45 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/PathData.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/PathData.java @@ -243,9 +243,6 @@ public class PathData extends Operation implements VariableSupport, Serializable @Override public void serialize(MapSerializer serializer) { - serializer - .add("type", CLASS_NAME) - .add("id", mInstanceId) - .add("path", pathString(mFloatPath)); + serializer.addType(CLASS_NAME).add("id", mInstanceId).add("path", pathString(mFloatPath)); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/PathTween.java b/core/java/com/android/internal/widget/remotecompose/core/operations/PathTween.java index c5add57d4dd0..09b29e8c5e5c 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/PathTween.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/PathTween.java @@ -161,7 +161,7 @@ public class PathTween extends PaintOperation implements VariableSupport, Serial @Override public void serialize(MapSerializer serializer) { serializer - .add("type", CLASS_NAME) + .addType(CLASS_NAME) .add("outId", mOutId) .add("pathId1", mPathId1) .add("pathId2", mPathId2) diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentDescription.java b/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentDescription.java index a6a8a810d2ad..214d240a39fd 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentDescription.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentDescription.java @@ -133,6 +133,6 @@ public class RootContentDescription extends Operation @Override public void serialize(MapSerializer serializer) { - serializer.add("type", CLASS_NAME).add("contentDescriptionId", mContentDescription); + serializer.addType(CLASS_NAME).add("contentDescriptionId", mContentDescription); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ShaderData.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ShaderData.java index 5f6162b68e9e..013b6f64b91a 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/ShaderData.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ShaderData.java @@ -390,7 +390,7 @@ public class ShaderData extends Operation implements VariableSupport, Serializab @Override public void serialize(MapSerializer serializer) { serializer - .add("type", CLASS_NAME) + .addType(CLASS_NAME) .add("shaderTextId", mShaderTextId) .add("shaderID", mShaderID) .add("uniformRawFloatMap", mUniformRawFloatMap) diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TextAttribute.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TextAttribute.java index 3e72995de9db..36f25c6ce944 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/TextAttribute.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TextAttribute.java @@ -173,7 +173,7 @@ public class TextAttribute extends PaintOperation implements Serializable { @Override public void serialize(MapSerializer serializer) { serializer - .add("type", CLASS_NAME) + .addType(CLASS_NAME) .add("id", mId) .add("textId", mTextId) .add("measureType", typeToString()); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TextData.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TextData.java index 419e6d074479..67773d1d6187 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/TextData.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TextData.java @@ -136,6 +136,6 @@ public class TextData extends Operation implements SerializableToString, Seriali @Override public void serialize(MapSerializer serializer) { - serializer.add("type", CLASS_NAME).add("textId", mTextId).add("text", mText); + serializer.addType(CLASS_NAME).add("textId", mTextId).add("text", mText); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TextFromFloat.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TextFromFloat.java index 6b2f49be76f0..f22369f51ce9 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/TextFromFloat.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TextFromFloat.java @@ -215,7 +215,7 @@ public class TextFromFloat extends Operation implements VariableSupport, Seriali @Override public void serialize(MapSerializer serializer) { serializer - .add("type", CLASS_NAME) + .addType(CLASS_NAME) .add("textId", mTextId) .add("value", mValue, mOutValue) .add("digitsBefore", mDigitsBefore) diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookup.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookup.java index e8865c26db12..fa44bf165cd7 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookup.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookup.java @@ -156,7 +156,7 @@ public class TextLookup extends Operation implements VariableSupport, Serializab @Override public void serialize(MapSerializer serializer) { serializer - .add("type", CLASS_NAME) + .addType(CLASS_NAME) .add("textId", mTextId) .add("dataSetId", mDataSetId) .add("indexId", mIndex, mOutIndex); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookupInt.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookupInt.java index de2025569d46..5ec3290c445d 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookupInt.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookupInt.java @@ -149,7 +149,7 @@ public class TextLookupInt extends Operation implements VariableSupport, Seriali @Override public void serialize(MapSerializer serializer) { serializer - .add("type", CLASS_NAME) + .addType(CLASS_NAME) .add("textId", mTextId) .add("dataSetId", mDataSetId) .add("indexId", mIndex, mOutIndex); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TextMeasure.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TextMeasure.java index 58cd68e2a5db..3559d1dbe53b 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/TextMeasure.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TextMeasure.java @@ -27,6 +27,7 @@ import com.android.internal.widget.remotecompose.core.PaintContext; import com.android.internal.widget.remotecompose.core.PaintOperation; import com.android.internal.widget.remotecompose.core.WireBuffer; import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.serialize.MapSerializer; import java.util.List; @@ -161,4 +162,33 @@ public class TextMeasure extends PaintOperation { break; } } + + @Override + public void serialize(MapSerializer serializer) { + serializer + .addType(CLASS_NAME) + .add("id", mId) + .add("textId", mTextId) + .add("measureType", typeToString()); + } + + private String typeToString() { + int val = mType & 255; + switch (val) { + case MEASURE_WIDTH: + return "MEASURE_WIDTH"; + case MEASURE_HEIGHT: + return "MEASURE_HEIGHT"; + case MEASURE_LEFT: + return "MEASURE_LEFT"; + case MEASURE_TOP: + return "MEASURE_TOP"; + case MEASURE_RIGHT: + return "MEASURE_RIGHT"; + case MEASURE_BOTTOM: + return "MEASURE_BOTTOM"; + default: + return "INVALID_TYPE"; + } + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TextMerge.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TextMerge.java index 262916dd9d0c..1239b5648446 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/TextMerge.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TextMerge.java @@ -132,7 +132,7 @@ public class TextMerge extends Operation implements Serializable { @Override public void serialize(MapSerializer serializer) { serializer - .add("type", CLASS_NAME) + .addType(CLASS_NAME) .add("id", mTextId) .add("leftId", mSrcId1) .add("rightId", mSrcId2); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TimeAttribute.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TimeAttribute.java index afb84b56d7b0..fd9a2bf5e435 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/TimeAttribute.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TimeAttribute.java @@ -27,12 +27,14 @@ import com.android.internal.widget.remotecompose.core.PaintOperation; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.WireBuffer; import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.serialize.MapSerializer; import com.android.internal.widget.remotecompose.core.types.LongConstant; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.util.Arrays; +import java.util.Collections; import java.util.List; /** Operation to perform time related calculation */ @@ -292,4 +294,48 @@ public class TimeAttribute extends PaintOperation { break; } } + + @Override + public void serialize(MapSerializer serializer) { + serializer + .addType(CLASS_NAME) + .add("id", mId) + .add("timeId", mTimeId) + .addType(getTypeString()) + .add("args", Collections.singletonList(mArgs)); + } + + private String getTypeString() { + int val = mType & 255; + switch (val) { + case TIME_FROM_NOW_SEC: + return "TIME_FROM_NOW_SEC"; + case TIME_FROM_NOW_MIN: + return "TIME_FROM_NOW_MIN"; + case TIME_FROM_NOW_HR: + return "TIME_FROM_NOW_HR"; + case TIME_FROM_ARG_SEC: + return "TIME_FROM_ARG_SEC"; + case TIME_FROM_ARG_MIN: + return "TIME_FROM_ARG_MIN"; + case TIME_FROM_ARG_HR: + return "TIME_FROM_ARG_HR"; + case TIME_IN_SEC: + return "TIME_IN_SEC"; + case TIME_IN_MIN: + return "TIME_IN_MIN"; + case TIME_IN_HR: + return "TIME_IN_HR"; + case TIME_DAY_OF_MONTH: + return "TIME_DAY_OF_MONTH"; + case TIME_MONTH_VALUE: + return "TIME_MONTH_VALUE"; + case TIME_DAY_OF_WEEK: + return "TIME_DAY_OF_WEEK"; + case TIME_YEAR: + return "TIME_YEAR"; + default: + return "INVALID_TIME_TYPE"; + } + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TouchExpression.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TouchExpression.java index 2591a4c39778..f24672922367 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/TouchExpression.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TouchExpression.java @@ -716,9 +716,9 @@ public class TouchExpression extends Operation @Override public void serialize(MapSerializer serializer) { serializer - .add("type", CLASS_NAME) + .addType(CLASS_NAME) .add("id", mId) - .add("mDefValue", mDefValue, mOutDefValue) + .add("defValue", mDefValue, mOutDefValue) .add("min", mMin, mOutMin) .add("max", mMax, mOutMax) .add("mode", mMode) diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/AnimatableValue.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/AnimatableValue.java index 9dc2a49d26ef..b98a017addb3 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/AnimatableValue.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/AnimatableValue.java @@ -129,6 +129,6 @@ public class AnimatableValue implements Serializable { @Override public void serialize(MapSerializer serializer) { - serializer.add("type", "AnimatableValue").add("id", mId); + serializer.addType("AnimatableValue").add("id", mId); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/CanvasOperations.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/CanvasOperations.java index 3e7f1d304315..25a10ab7dbeb 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/CanvasOperations.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/CanvasOperations.java @@ -156,7 +156,7 @@ public class CanvasOperations extends PaintOperation @Override public void serialize(MapSerializer serializer) { - serializer.add("type", CLASS_NAME).add("list", mList); + serializer.addType(CLASS_NAME).add("list", mList); } /** diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierOperation.java index 8b13c13a3333..7ee14903ced5 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierOperation.java @@ -253,6 +253,6 @@ public class ClickModifierOperation extends PaintOperation @Override public void serialize(MapSerializer serializer) { - serializer.addTags(SerializeTags.MODIFIER).add("type", "ClickModifierOperation"); + serializer.addTags(SerializeTags.MODIFIER).addType("ClickModifierOperation"); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java index c73643682b55..b30dade828a7 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java @@ -57,8 +57,8 @@ public class Component extends PaintOperation protected float mHeight; @Nullable protected Component mParent; protected int mAnimationId = -1; - @NonNull public Visibility mVisibility = Visibility.VISIBLE; - @NonNull public Visibility mScheduledVisibility = Visibility.VISIBLE; + public int mVisibility = Visibility.VISIBLE; + public int mScheduledVisibility = Visibility.VISIBLE; @NonNull public ArrayList<Operation> mList = new ArrayList<>(); public PaintOperation mPreTranslate; // todo, can we initialize this here and make it NonNull? public boolean mNeedsMeasure = true; @@ -288,22 +288,42 @@ public class Component extends PaintOperation } /** - * Returns the intrinsic width of the layout + * Returns the min intrinsic width of the layout * * @param context * @return the width in pixels */ - public float intrinsicWidth(@Nullable RemoteContext context) { + public float minIntrinsicWidth(@Nullable RemoteContext context) { return getWidth(); } /** - * Returns the intrinsic height of the layout + * Returns the max intrinsic width of the layout + * + * @param context + * @return the width in pixels + */ + public float maxIntrinsicWidth(@Nullable RemoteContext context) { + return getWidth(); + } + + /** + * Returns the min intrinsic height of the layout + * + * @param context + * @return the height in pixels + */ + public float minIntrinsicHeight(@Nullable RemoteContext context) { + return getHeight(); + } + + /** + * Returns the max intrinsic height of the layout * * @param context * @return the height in pixels */ - public float intrinsicHeight(@Nullable RemoteContext context) { + public float maxIntrinsicHeight(@Nullable RemoteContext context) { return getHeight(); } @@ -338,10 +358,119 @@ public class Component extends PaintOperation // Nothing here } - public enum Visibility { - GONE, - VISIBLE, - INVISIBLE + public static class Visibility { + + public static final int GONE = 0; + public static final int VISIBLE = 1; + public static final int INVISIBLE = 2; + public static final int OVERRIDE_GONE = 16; + public static final int OVERRIDE_VISIBLE = 32; + public static final int OVERRIDE_INVISIBLE = 64; + public static final int CLEAR_OVERRIDE = 128; + + /** + * Returns a string representation of the field + * + * @param value + * @return + */ + public static String toString(int value) { + switch (value) { + case GONE: + return "GONE"; + case VISIBLE: + return "VISIBLE"; + case INVISIBLE: + return "INVISIBLE"; + } + if ((value >> 4) > 0) { + if ((value & OVERRIDE_GONE) == OVERRIDE_GONE) { + return "OVERRIDE_GONE"; + } + if ((value & OVERRIDE_VISIBLE) == OVERRIDE_VISIBLE) { + return "OVERRIDE_VISIBLE"; + } + if ((value & OVERRIDE_INVISIBLE) == OVERRIDE_INVISIBLE) { + return "OVERRIDE_INVISIBLE"; + } + } + return "" + value; + } + + /** + * Returns true if gone + * + * @param value + * @return + */ + public static boolean isGone(int value) { + if ((value >> 4) > 0) { + return (value & OVERRIDE_GONE) == OVERRIDE_GONE; + } + return value == GONE; + } + + /** + * Returns true if visible + * + * @param value + * @return + */ + public static boolean isVisible(int value) { + if ((value >> 4) > 0) { + return (value & OVERRIDE_VISIBLE) == OVERRIDE_VISIBLE; + } + return value == VISIBLE; + } + + /** + * Returns true if invisible + * + * @param value + * @return + */ + public static boolean isInvisible(int value) { + if ((value >> 4) > 0) { + return (value & OVERRIDE_INVISIBLE) == OVERRIDE_INVISIBLE; + } + return value == INVISIBLE; + } + + /** + * Returns true if the field has an override + * + * @param value + * @return + */ + public static boolean hasOverride(int value) { + return (value >> 4) > 0; + } + + /** + * Clear the override values + * + * @param value + * @return + */ + public static int clearOverride(int value) { + return value & 15; + } + + /** + * Add an override value + * + * @param value + * @param visibility + * @return + */ + public static int add(int value, int visibility) { + int v = value & 15; + v += visibility; + if ((v & CLEAR_OVERRIDE) == CLEAR_OVERRIDE) { + v = v & 15; + } + return v; + } } /** @@ -350,13 +479,28 @@ public class Component extends PaintOperation * @return */ public boolean isVisible() { - if (mVisibility != Visibility.VISIBLE || mParent == null) { - return mVisibility == Visibility.VISIBLE; - } - if (mParent != null) { // TODO: this is always true -- bbade@ - return mParent.isVisible(); + if (mParent == null || !Visibility.isVisible(mVisibility)) { + return Visibility.isVisible(mVisibility); } - return true; + return mParent.isVisible(); + } + + /** + * Returns true if the component is gone + * + * @return + */ + public boolean isGone() { + return Visibility.isGone(mVisibility); + } + + /** + * Returns true if the component is invisible + * + * @return + */ + public boolean isInvisible() { + return Visibility.isInvisible(mVisibility); } /** @@ -364,7 +508,7 @@ public class Component extends PaintOperation * * @param visibility can be VISIBLE, INVISIBLE or GONE */ - public void setVisibility(@NonNull Visibility visibility) { + public void setVisibility(int visibility) { if (visibility != mVisibility || visibility != mScheduledVisibility) { mScheduledVisibility = visibility; invalidateMeasure(); @@ -705,7 +849,7 @@ public class Component extends PaintOperation + "] " + textContent() + " Visibility (" - + mVisibility + + Visibility.toString(mVisibility) + ") "; } @@ -732,7 +876,7 @@ public class Component extends PaintOperation + ", " + mHeight + "] " - + mVisibility; + + Visibility.toString(mVisibility); // + " [" + mNeedsMeasure + ", " + mNeedsRepaint + "]" serializer.append(indent, content); } @@ -966,7 +1110,7 @@ public class Component extends PaintOperation if (applyAnimationAsNeeded(context)) { return; } - if (mVisibility == Visibility.GONE || mVisibility == Visibility.INVISIBLE) { + if (isGone() || isInvisible()) { return; } paintingComponent(context); @@ -1071,13 +1215,13 @@ public class Component extends PaintOperation @Override public void serialize(MapSerializer serializer) { serializer.addTags(SerializeTags.COMPONENT); - serializer.add("type", getSerializedName()); + serializer.addType(getSerializedName()); serializer.add("id", mComponentId); serializer.add("x", mX); serializer.add("y", mY); serializer.add("width", mWidth); serializer.add("height", mHeight); - serializer.add("visibility", mVisibility); + serializer.add("visibility", Visibility.toString(mVisibility)); serializer.add("list", mList); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ImpulseOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ImpulseOperation.java index e277d49325be..0e629c5d2448 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ImpulseOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ImpulseOperation.java @@ -27,6 +27,7 @@ import com.android.internal.widget.remotecompose.core.WireBuffer; import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation; import com.android.internal.widget.remotecompose.core.operations.Utils; +import com.android.internal.widget.remotecompose.core.serialize.MapSerializer; import java.util.ArrayList; import java.util.List; @@ -228,4 +229,12 @@ public class ImpulseOperation extends PaintOperation implements VariableSupport, public void setProcess(ImpulseProcess impulseProcess) { mProcess = impulseProcess; } + + @Override + public void serialize(MapSerializer serializer) { + serializer + .addType(CLASS_NAME) + .add("duration", mDuration, mOutDuration) + .add("startAt", mStartAt, mOutStartAt); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ImpulseProcess.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ImpulseProcess.java index 8c9dd76c9ed5..83d4d38be66e 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ImpulseProcess.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ImpulseProcess.java @@ -157,6 +157,6 @@ public class ImpulseProcess extends PaintOperation @Override public void serialize(MapSerializer serializer) { - serializer.add("type", CLASS_NAME).add("list", mList); + serializer.addType(CLASS_NAME).add("list", mList); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopOperation.java index 2b63cf246555..dda328f57a3b 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopOperation.java @@ -206,12 +206,12 @@ public class LoopOperation extends PaintOperation @Override public void serialize(MapSerializer serializer) { serializer - .add("type", CLASS_NAME) + .addType(CLASS_NAME) .add("indexVariableId", mIndexVariableId) .add("until", mUntil, mUntilOut) .add("from", mFrom, mFromOut) .add("step", mStep, mStepOut) - .add("mUntilOut", mUntilOut) + .add("untilOut", mUntilOut) .add("list", mList); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/RootLayoutComponent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/RootLayoutComponent.java index f2503b26513e..77d3dae74558 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/RootLayoutComponent.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/RootLayoutComponent.java @@ -77,7 +77,7 @@ public class RootLayoutComponent extends Component { + " x " + mHeight + ") " - + mVisibility; + + Visibility.toString(mVisibility); } @Override @@ -97,7 +97,7 @@ public class RootLayoutComponent extends Component { + ", " + mHeight + "] " - + mVisibility); + + Visibility.toString(mVisibility)); } /** @@ -282,6 +282,6 @@ public class RootLayoutComponent extends Component { public void serialize(MapSerializer serializer) { super.serialize(serializer); serializer.addTags(SerializeTags.COMPONENT); - serializer.add("type", "RootLayoutComponent"); + serializer.addType("RootLayoutComponent"); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchCancelModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchCancelModifierOperation.java index 62b1b6cf9615..283bc7a45f85 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchCancelModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchCancelModifierOperation.java @@ -129,6 +129,6 @@ public class TouchCancelModifierOperation extends ListActionsOperation implement @Override public void serialize(MapSerializer serializer) { super.serialize(serializer); - serializer.add("type", "TouchCancelModifierOperation"); + serializer.addType("TouchCancelModifierOperation"); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchDownModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchDownModifierOperation.java index 5289fda2c74b..b010c148d122 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchDownModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchDownModifierOperation.java @@ -131,6 +131,6 @@ public class TouchDownModifierOperation extends ListActionsOperation implements @Override public void serialize(MapSerializer serializer) { super.serialize(serializer); - serializer.add("type", "TouchDownModifierOperation"); + serializer.addType("TouchDownModifierOperation"); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchUpModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchUpModifierOperation.java index 576c5e9281a4..bc5c10b86c96 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchUpModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchUpModifierOperation.java @@ -129,6 +129,6 @@ public class TouchUpModifierOperation extends ListActionsOperation implements To @Override public void serialize(MapSerializer serializer) { super.serialize(serializer); - serializer.add("type", "TouchUpModifierOperation"); + serializer.addType("TouchUpModifierOperation"); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimateMeasure.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimateMeasure.java index e5cd485967e8..1a60451ddd3b 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimateMeasure.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimateMeasure.java @@ -143,7 +143,7 @@ public class AnimateMeasure { */ public void paint(@NonNull PaintContext context) { if (mOriginal.getVisibility() != mTarget.getVisibility()) { - if (mTarget.getVisibility() == Component.Visibility.GONE) { + if (mTarget.isGone()) { switch (mExitAnimation) { case PARTICLE: // particleAnimation(context, component, original, target, vp) @@ -229,8 +229,7 @@ public class AnimateMeasure { mParticleAnimation.animate(context, mComponent, mOriginal, mTarget, mVp); break; } - } else if (mOriginal.getVisibility() == Component.Visibility.GONE - && mTarget.getVisibility() == Component.Visibility.VISIBLE) { + } else if (mOriginal.isGone() && mTarget.isVisible()) { switch (mEnterAnimation) { case ROTATE: float px = mTarget.getX() + mTarget.getW() / 2f; @@ -323,7 +322,7 @@ public class AnimateMeasure { } else { mComponent.paintingComponent(context); } - } else if (mTarget.getVisibility() == Component.Visibility.VISIBLE) { + } else if (mTarget.isVisible()) { mComponent.paintingComponent(context); } @@ -360,7 +359,7 @@ public class AnimateMeasure { public float getVisibility() { if (mOriginal.getVisibility() == mTarget.getVisibility()) { return 1f; - } else if (mTarget.getVisibility() == Component.Visibility.VISIBLE) { + } else if (mTarget.isVisible()) { return mVp; } else { return 1 - mVp; @@ -382,7 +381,7 @@ public class AnimateMeasure { float targetY = mTarget.getY(); float targetW = mTarget.getW(); float targetH = mTarget.getH(); - Component.Visibility targetVisibility = mTarget.getVisibility(); + int targetVisibility = mTarget.getVisibility(); if (targetX != measure.getX() || targetY != measure.getY() || targetW != measure.getW() @@ -393,7 +392,13 @@ public class AnimateMeasure { mTarget.setW(measure.getW()); mTarget.setH(measure.getH()); mTarget.setVisibility(measure.getVisibility()); - mStartTime = currentTime; + // We shouldn't reset the leftover animation time here + // 1/ if we are eg fading out a component, and an updateTarget comes on, we don't want + // to restart the full animation time + // 2/ if no visibility change but quick updates come in (eg live resize) it seems + // better as well to not restart the animation time and only allows the original + // time to wrap up + // mStartTime = currentTime; } } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java index 91348f5810a1..c87bbdc9809d 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java @@ -129,7 +129,7 @@ public class AnimationSpec extends Operation implements ModifierOperation { @Override public void serialize(MapSerializer serializer) { serializer - .add("type", "AnimationSpec") + .addType("AnimationSpec") .add("motionDuration", getMotionDuration()) .add("motionEasingType", Easing.getString(getMotionEasingType())) .add("visibilityDuration", getVisibilityDuration()) diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java index 35d639e65385..6ee18bbbd7e0 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java @@ -115,8 +115,10 @@ public class BoxLayout extends LayoutManager { for (Component c : mChildrenComponents) { c.measure(context, 0f, maxWidth, 0f, maxHeight, measure); ComponentMeasure m = measure.get(c); - size.setWidth(Math.max(size.getWidth(), m.getW())); - size.setHeight(Math.max(size.getHeight(), m.getH())); + if (!m.isGone()) { + size.setWidth(Math.max(size.getWidth(), m.getW())); + size.setHeight(Math.max(size.getHeight(), m.getH())); + } } // add padding size.setWidth(Math.max(size.getWidth(), computeModifierDefinedWidth(context.getContext()))); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CanvasLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CanvasLayout.java index 508b685b5407..f9111dffe2c4 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CanvasLayout.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CanvasLayout.java @@ -154,7 +154,7 @@ public class CanvasLayout extends BoxLayout { @Override public void serialize(MapSerializer serializer) { super.serialize(serializer); - serializer.add("type", getSerializedName()); + serializer.addType(getSerializedName()); serializer.add("horizontalPositioning", mHorizontalPositioning); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CollapsibleColumnLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CollapsibleColumnLayout.java index afc41b1873ef..b0089525af5a 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CollapsibleColumnLayout.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CollapsibleColumnLayout.java @@ -21,6 +21,7 @@ import android.annotation.Nullable; import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; +import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.WireBuffer; import com.android.internal.widget.remotecompose.core.operations.layout.Component; import com.android.internal.widget.remotecompose.core.operations.layout.measure.ComponentMeasure; @@ -134,6 +135,24 @@ public class CollapsibleColumnLayout extends ColumnLayout { } @Override + public float minIntrinsicHeight(@NonNull RemoteContext context) { + float height = computeModifierDefinedHeight(context); + if (!mChildrenComponents.isEmpty()) { + height += mChildrenComponents.get(0).minIntrinsicHeight(context); + } + return height; + } + + @Override + public float minIntrinsicWidth(@NonNull RemoteContext context) { + float width = computeModifierDefinedWidth(context); + if (!mChildrenComponents.isEmpty()) { + width += mChildrenComponents.get(0).minIntrinsicWidth(context); + } + return width; + } + + @Override protected boolean hasVerticalIntrinsicDimension() { return true; } @@ -147,29 +166,54 @@ public class CollapsibleColumnLayout extends ColumnLayout { boolean verticalWrap, @NonNull MeasurePass measure, @NonNull Size size) { - super.computeWrapSize( - context, maxWidth, Float.MAX_VALUE, horizontalWrap, verticalWrap, measure, size); - } + int visibleChildren = 0; + ComponentMeasure self = measure.get(this); + self.addVisibilityOverride(Visibility.OVERRIDE_VISIBLE); + float currentMaxHeight = maxHeight; + for (Component c : mChildrenComponents) { + if (c instanceof CollapsibleColumnLayout) { + c.measure(context, 0f, maxWidth, 0f, currentMaxHeight, measure); + } else { + c.measure(context, 0f, maxWidth, 0f, Float.MAX_VALUE, measure); + } + ComponentMeasure m = measure.get(c); + if (!m.isGone()) { + size.setWidth(Math.max(size.getWidth(), m.getW())); + size.setHeight(size.getHeight() + m.getH()); + visibleChildren++; + currentMaxHeight -= m.getH(); + } + } + if (!mChildrenComponents.isEmpty()) { + size.setHeight(size.getHeight() + (mSpacedBy * (visibleChildren - 1))); + } - @Override - public boolean applyVisibility( - float selfWidth, float selfHeight, @NonNull MeasurePass measure) { float childrenWidth = 0f; float childrenHeight = 0f; - boolean changedVisibility = false; + + boolean overflow = false; for (Component child : mChildrenComponents) { ComponentMeasure childMeasure = measure.get(child); - if (childMeasure.getVisibility() == Visibility.GONE) { + if (overflow || childMeasure.isGone()) { + childMeasure.addVisibilityOverride(Visibility.OVERRIDE_GONE); continue; } - if (childrenHeight + childMeasure.getH() > selfHeight) { - childMeasure.setVisibility(Visibility.GONE); - changedVisibility = true; + float childHeight = childMeasure.getH(); + boolean childDoesNotFits = childrenHeight + childHeight > maxHeight; + if (childDoesNotFits) { + childMeasure.addVisibilityOverride(Visibility.OVERRIDE_GONE); + overflow = true; } else { - childrenHeight += childMeasure.getH(); + childrenHeight += childHeight; childrenWidth = Math.max(childrenWidth, childMeasure.getW()); + visibleChildren++; } } - return changedVisibility; + if (verticalWrap) { + size.setHeight(Math.min(maxHeight, childrenHeight)); + } + if (visibleChildren == 0 || size.getHeight() <= 0f) { + self.addVisibilityOverride(Visibility.OVERRIDE_GONE); + } } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CollapsibleRowLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CollapsibleRowLayout.java index 0e7eb8676f46..05f332960c16 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CollapsibleRowLayout.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CollapsibleRowLayout.java @@ -21,6 +21,7 @@ import android.annotation.Nullable; import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; +import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.WireBuffer; import com.android.internal.widget.remotecompose.core.operations.layout.Component; import com.android.internal.widget.remotecompose.core.operations.layout.measure.ComponentMeasure; @@ -139,6 +140,24 @@ public class CollapsibleRowLayout extends RowLayout { } @Override + public float minIntrinsicWidth(@NonNull RemoteContext context) { + float width = computeModifierDefinedWidth(context); + if (!mChildrenComponents.isEmpty()) { + width += mChildrenComponents.get(0).minIntrinsicWidth(context); + } + return width; + } + + @Override + public float minIntrinsicHeight(@NonNull RemoteContext context) { + float height = computeModifierDefinedHeight(context); + if (!mChildrenComponents.isEmpty()) { + height += mChildrenComponents.get(0).minIntrinsicHeight(context); + } + return height; + } + + @Override public void computeWrapSize( @NonNull PaintContext context, float maxWidth, @@ -157,19 +176,35 @@ public class CollapsibleRowLayout extends RowLayout { float childrenWidth = 0f; float childrenHeight = 0f; boolean changedVisibility = false; + int visibleChildren = 0; + ComponentMeasure self = measure.get(this); + self.clearVisibilityOverride(); + if (selfWidth <= 0 || selfHeight <= 0) { + self.addVisibilityOverride(Visibility.OVERRIDE_GONE); + return true; + } for (Component child : mChildrenComponents) { ComponentMeasure childMeasure = measure.get(child); - if (childMeasure.getVisibility() == Visibility.GONE) { + int visibility = childMeasure.getVisibility(); + childMeasure.clearVisibilityOverride(); + if (!childMeasure.isVisible()) { continue; } - if (childrenWidth + childMeasure.getW() > selfWidth) { - childMeasure.setVisibility(Visibility.GONE); - changedVisibility = true; + if (childrenWidth + childMeasure.getW() > selfWidth + && childrenHeight + childMeasure.getH() > selfHeight) { + childMeasure.addVisibilityOverride(Visibility.OVERRIDE_GONE); + if (visibility != childMeasure.getVisibility()) { + changedVisibility = true; + } } else { childrenWidth += childMeasure.getW(); childrenHeight = Math.max(childrenHeight, childMeasure.getH()); + visibleChildren++; } } + if (visibleChildren == 0) { + self.addVisibilityOverride(Visibility.OVERRIDE_GONE); + } return changedVisibility; } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java index 47a55b6ed82a..cda90c2d3b0b 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java @@ -138,7 +138,7 @@ public class ColumnLayout extends LayoutManager { for (Component c : mChildrenComponents) { c.measure(context, 0f, maxWidth, 0f, currentMaxHeight, measure); ComponentMeasure m = measure.get(c); - if (m.getVisibility() != Visibility.GONE) { + if (!m.isGone()) { size.setWidth(Math.max(size.getWidth(), m.getW())); size.setHeight(size.getHeight() + m.getH()); visibleChildrens++; @@ -164,7 +164,7 @@ public class ColumnLayout extends LayoutManager { for (Component child : mChildrenComponents) { child.measure(context, minWidth, maxWidth, minHeight, mh, measure); ComponentMeasure m = measure.get(child); - if (m.getVisibility() != Visibility.GONE) { + if (!m.isGone()) { mh -= m.getH(); } } @@ -172,11 +172,11 @@ public class ColumnLayout extends LayoutManager { } @Override - public float intrinsicHeight(@NonNull RemoteContext context) { + public float minIntrinsicHeight(@NonNull RemoteContext context) { float height = computeModifierDefinedHeight(context); float componentHeights = 0f; for (Component c : mChildrenComponents) { - componentHeights += c.intrinsicHeight(context); + componentHeights += c.minIntrinsicHeight(context); } return Math.max(height, componentHeights); } @@ -225,7 +225,7 @@ public class ColumnLayout extends LayoutManager { float totalWeights = 0f; for (Component child : mChildrenComponents) { ComponentMeasure childMeasure = measure.get(child); - if (childMeasure.getVisibility() == Visibility.GONE) { + if (childMeasure.isGone()) { continue; } if (child instanceof LayoutComponent @@ -242,7 +242,7 @@ public class ColumnLayout extends LayoutManager { if (child instanceof LayoutComponent && ((LayoutComponent) child).getHeightModifier().hasWeight()) { ComponentMeasure childMeasure = measure.get(child); - if (childMeasure.getVisibility() == Visibility.GONE) { + if (childMeasure.isGone()) { continue; } float weight = ((LayoutComponent) child).getHeightModifier().getValue(); @@ -280,7 +280,7 @@ public class ColumnLayout extends LayoutManager { int visibleChildrens = 0; for (Component child : mChildrenComponents) { ComponentMeasure childMeasure = measure.get(child); - if (childMeasure.getVisibility() == Visibility.GONE) { + if (childMeasure.isGone()) { continue; } childrenWidth = Math.max(childrenWidth, childMeasure.getW()); @@ -307,17 +307,22 @@ public class ColumnLayout extends LayoutManager { case SPACE_BETWEEN: for (Component child : mChildrenComponents) { ComponentMeasure childMeasure = measure.get(child); - if (childMeasure.getVisibility() == Visibility.GONE) { + if (childMeasure.isGone()) { continue; } total += childMeasure.getH(); } - verticalGap = (selfHeight - total) / (visibleChildrens - 1); + if (visibleChildrens > 1) { + verticalGap = (selfHeight - total) / (visibleChildrens - 1); + } else { + // we center the element + ty = (selfHeight - childrenHeight) / 2f; + } break; case SPACE_EVENLY: for (Component child : mChildrenComponents) { ComponentMeasure childMeasure = measure.get(child); - if (childMeasure.getVisibility() == Visibility.GONE) { + if (childMeasure.isGone()) { continue; } total += childMeasure.getH(); @@ -328,7 +333,7 @@ public class ColumnLayout extends LayoutManager { case SPACE_AROUND: for (Component child : mChildrenComponents) { ComponentMeasure childMeasure = measure.get(child); - if (childMeasure.getVisibility() == Visibility.GONE) { + if (childMeasure.isGone()) { continue; } total += childMeasure.getH(); @@ -353,7 +358,7 @@ public class ColumnLayout extends LayoutManager { } childMeasure.setX(tx); childMeasure.setY(ty); - if (childMeasure.getVisibility() == Visibility.GONE) { + if (childMeasure.isGone()) { continue; } ty += childMeasure.getH(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/FitBoxLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/FitBoxLayout.java new file mode 100644 index 000000000000..ff7a3af11f20 --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/FitBoxLayout.java @@ -0,0 +1,371 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations.layout.managers; + +import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT; + +import android.annotation.NonNull; +import android.annotation.Nullable; + +import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.PaintContext; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.operations.layout.Component; +import com.android.internal.widget.remotecompose.core.operations.layout.LayoutComponent; +import com.android.internal.widget.remotecompose.core.operations.layout.measure.ComponentMeasure; +import com.android.internal.widget.remotecompose.core.operations.layout.measure.MeasurePass; +import com.android.internal.widget.remotecompose.core.operations.layout.measure.Size; +import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.HeightInModifierOperation; +import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.HeightModifierOperation; +import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.WidthInModifierOperation; +import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.WidthModifierOperation; +import com.android.internal.widget.remotecompose.core.serialize.MapSerializer; + +import java.util.List; + +/** FitBox layout implementation -- only display the child that fits in the available space */ +public class FitBoxLayout extends LayoutManager { + + public static final int START = 1; + public static final int CENTER = 2; + public static final int END = 3; + public static final int TOP = 4; + public static final int BOTTOM = 5; + + int mHorizontalPositioning; + int mVerticalPositioning; + + public FitBoxLayout( + @Nullable Component parent, + int componentId, + int animationId, + float x, + float y, + float width, + float height, + int horizontalPositioning, + int verticalPositioning) { + super(parent, componentId, animationId, x, y, width, height); + mHorizontalPositioning = horizontalPositioning; + mVerticalPositioning = verticalPositioning; + } + + public FitBoxLayout( + @Nullable Component parent, + int componentId, + int animationId, + int horizontalPositioning, + int verticalPositioning) { + this( + parent, + componentId, + animationId, + 0, + 0, + 0, + 0, + horizontalPositioning, + verticalPositioning); + } + + @NonNull + @Override + public String toString() { + return "BOX [" + + mComponentId + + ":" + + mAnimationId + + "] (" + + mX + + ", " + + mY + + " - " + + mWidth + + " x " + + mHeight + + ") " + + mVisibility; + } + + @NonNull + @Override + protected String getSerializedName() { + return "FITBOX"; + } + + @Override + public void computeWrapSize( + @NonNull PaintContext context, + float maxWidth, + float maxHeight, + boolean horizontalWrap, + boolean verticalWrap, + @NonNull MeasurePass measure, + @NonNull Size size) { + + boolean found = false; + ComponentMeasure self = measure.get(this); + for (Component c : mChildrenComponents) { + float cw = 0f; // c.intrinsicWidth(context.getContext()); + float ch = 0f; // c.intrinsicHeight(context.getContext()); + if (c instanceof LayoutComponent) { + LayoutComponent lc = (LayoutComponent) c; + WidthModifierOperation widthModifier = lc.getWidthModifier(); + if (widthModifier != null) { + WidthInModifierOperation widthIn = lc.getWidthModifier().getWidthIn(); + if (widthIn != null) { + cw = widthIn.getMin(); + } + } + HeightModifierOperation heightModifier = lc.getHeightModifier(); + if (heightModifier != null) { + HeightInModifierOperation heightIn = lc.getHeightModifier().getHeightIn(); + if (heightIn != null) { + ch = heightIn.getMin(); + } + } + } + c.measure(context, 0f, maxWidth, 0f, maxHeight, measure); + ComponentMeasure m = measure.get(c); + if (!found && cw <= maxWidth && ch <= maxHeight) { + found = true; + m.addVisibilityOverride(Visibility.OVERRIDE_VISIBLE); + size.setWidth(m.getW()); + size.setHeight(m.getH()); + } else { + m.addVisibilityOverride(Visibility.OVERRIDE_GONE); + } + } + if (!found) { + self.setVisibility(Visibility.GONE); + } else { + self.setVisibility(Visibility.VISIBLE); + } + + // add padding + size.setWidth(Math.max(size.getWidth(), computeModifierDefinedWidth(context.getContext()))); + size.setHeight( + Math.max(size.getHeight(), computeModifierDefinedHeight(context.getContext()))); + } + + @Override + public void computeSize( + @NonNull PaintContext context, + float minWidth, + float maxWidth, + float minHeight, + float maxHeight, + @NonNull MeasurePass measure) { + + ComponentMeasure self = measure.get(this); + boolean found = false; + for (Component c : mChildrenComponents) { + float cw = 0f; + float ch = 0f; + if (c instanceof LayoutComponent) { + LayoutComponent lc = (LayoutComponent) c; + WidthModifierOperation widthModifier = lc.getWidthModifier(); + if (widthModifier != null) { + WidthInModifierOperation widthIn = lc.getWidthModifier().getWidthIn(); + if (widthIn != null) { + cw = widthIn.getMin(); + } + } + HeightModifierOperation heightModifier = lc.getHeightModifier(); + if (heightModifier != null) { + HeightInModifierOperation heightIn = lc.getHeightModifier().getHeightIn(); + if (heightIn != null) { + ch = heightIn.getMin(); + } + } + } + c.measure(context, minWidth, maxWidth, minHeight, maxHeight, measure); + // child.measure(context, minWidth, Float.MAX_VALUE, minHeight, + // Float.MAX_VALUE, measure); + // m.getVisibility().clearOverride(); + ComponentMeasure m = measure.get(c); + // m.setVisibility(Visibility.GONE); + // m.getVisibility().add(Visibility.OVERRIDE_GONE); + // m.getVisibility().add(Visibility.OVERRIDE_GONE); + m.clearVisibilityOverride(); + if (!found && cw <= maxWidth && ch <= maxHeight) { + found = true; + m.addVisibilityOverride(Visibility.OVERRIDE_VISIBLE); + } else { + m.addVisibilityOverride(Visibility.OVERRIDE_GONE); + } + } + } + + @Override + public void internalLayoutMeasure(@NonNull PaintContext context, @NonNull MeasurePass measure) { + ComponentMeasure selfMeasure = measure.get(this); + float selfWidth = selfMeasure.getW() - mPaddingLeft - mPaddingRight; + float selfHeight = selfMeasure.getH() - mPaddingTop - mPaddingBottom; + applyVisibility(selfWidth, selfHeight, measure); + for (Component child : mChildrenComponents) { + ComponentMeasure m = measure.get(child); + float tx = 0f; + float ty = 0f; + switch (mVerticalPositioning) { + case TOP: + ty = 0f; + break; + case CENTER: + ty = (selfHeight - m.getH()) / 2f; + break; + case BOTTOM: + ty = selfHeight - m.getH(); + break; + } + switch (mHorizontalPositioning) { + case START: + tx = 0f; + break; + case CENTER: + tx = (selfWidth - m.getW()) / 2f; + break; + case END: + tx = selfWidth - m.getW(); + break; + } + m.setX(tx); + m.setY(ty); + } + } + + /** + * The name of the class + * + * @return the name + */ + @NonNull + public static String name() { + return "BoxLayout"; + } + + /** + * The OP_CODE for this command + * + * @return the opcode + */ + public static int id() { + return Operations.LAYOUT_FIT_BOX; + } + + /** + * Write the operation to the buffer + * + * @param buffer a WireBuffer + * @param componentId the component id + * @param animationId the component animation id + * @param horizontalPositioning the horizontal positioning rules + * @param verticalPositioning the vertical positioning rules + */ + public static void apply( + @NonNull WireBuffer buffer, + int componentId, + int animationId, + int horizontalPositioning, + int verticalPositioning) { + buffer.start(id()); + buffer.writeInt(componentId); + buffer.writeInt(animationId); + buffer.writeInt(horizontalPositioning); + buffer.writeInt(verticalPositioning); + } + + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ + public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) { + int componentId = buffer.readInt(); + int animationId = buffer.readInt(); + int horizontalPositioning = buffer.readInt(); + int verticalPositioning = buffer.readInt(); + operations.add( + new FitBoxLayout( + null, + componentId, + animationId, + horizontalPositioning, + verticalPositioning)); + } + + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ + public static void documentation(@NonNull DocumentationBuilder doc) { + doc.operation("Layout Operations", id(), name()) + .description( + "FitBox layout implementation.\n\n" + + "Only display the first child component that fits in the available" + + " space") + .examplesDimension(150, 100) + .exampleImage("Top", "layout-BoxLayout-start-top.png") + .exampleImage("Center", "layout-BoxLayout-center-center.png") + .exampleImage("Bottom", "layout-BoxLayout-end-bottom.png") + .field(INT, "COMPONENT_ID", "unique id for this component") + .field( + INT, + "ANIMATION_ID", + "id used to match components," + " for animation purposes") + .field(INT, "HORIZONTAL_POSITIONING", "horizontal positioning value") + .possibleValues("START", FitBoxLayout.START) + .possibleValues("CENTER", FitBoxLayout.CENTER) + .possibleValues("END", FitBoxLayout.END) + .field(INT, "VERTICAL_POSITIONING", "vertical positioning value") + .possibleValues("TOP", FitBoxLayout.TOP) + .possibleValues("CENTER", FitBoxLayout.CENTER) + .possibleValues("BOTTOM", FitBoxLayout.BOTTOM); + } + + @Override + public void write(@NonNull WireBuffer buffer) { + apply(buffer, mComponentId, mAnimationId, mHorizontalPositioning, mVerticalPositioning); + } + + @Override + public void serialize(MapSerializer serializer) { + super.serialize(serializer); + serializer.add("verticalPositioning", getPositioningString(mVerticalPositioning)); + serializer.add("horizontalPositioning", getPositioningString(mHorizontalPositioning)); + } + + private String getPositioningString(int pos) { + switch (pos) { + case START: + return "START"; + case CENTER: + return "CENTER"; + case END: + return "END"; + case TOP: + return "TOP"; + case BOTTOM: + return "BOTTOM"; + default: + return "NONE"; + } + } +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/LayoutManager.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/LayoutManager.java index 8b52bbe5cdf8..5b66b95cf1dd 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/LayoutManager.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/LayoutManager.java @@ -73,19 +73,19 @@ public abstract class LayoutManager extends LayoutComponent implements Measurabl } @Override - public float intrinsicHeight(@Nullable RemoteContext context) { + public float minIntrinsicHeight(@Nullable RemoteContext context) { float height = computeModifierDefinedHeight(context); for (Component c : mChildrenComponents) { - height = Math.max(c.intrinsicHeight(context), height); + height = Math.max(c.minIntrinsicHeight(context), height); } return height; } @Override - public float intrinsicWidth(@Nullable RemoteContext context) { + public float minIntrinsicWidth(@Nullable RemoteContext context) { float width = computeModifierDefinedWidth(context); for (Component c : mChildrenComponents) { - width = Math.max(c.intrinsicWidth(context), width); + width = Math.max(c.minIntrinsicWidth(context), width); } return width; } @@ -149,10 +149,10 @@ public abstract class LayoutManager extends LayoutComponent implements Measurabl Math.min(maxHeight, computeModifierDefinedHeight(context.getContext())); if (mWidthModifier.isIntrinsicMin()) { - maxWidth = intrinsicWidth(context.getContext()) + mPaddingLeft + mPaddingRight; + maxWidth = minIntrinsicWidth(context.getContext()) + mPaddingLeft + mPaddingRight; } if (mHeightModifier.isIntrinsicMin()) { - maxHeight = intrinsicHeight(context.getContext()) + mPaddingTop + mPaddingBottom; + maxHeight = minIntrinsicHeight(context.getContext()) + mPaddingTop + mPaddingBottom; } float insetMaxWidth = maxWidth - mPaddingLeft - mPaddingRight; @@ -171,6 +171,11 @@ public abstract class LayoutManager extends LayoutComponent implements Measurabl mHeightModifier.isWrap(), measure, mCachedWrapSize); + int selfVisibilityAfterMeasure = measure.get(this).getVisibility(); + if (Visibility.hasOverride(selfVisibilityAfterMeasure) + && mScheduledVisibility != selfVisibilityAfterMeasure) { + mScheduledVisibility = selfVisibilityAfterMeasure; + } measuredWidth = mCachedWrapSize.getWidth(); if (hasHorizontalWrap) { measuredWidth += mPaddingLeft + mPaddingRight; diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java index e93cbd74b0b5..d5d2e03c3f2a 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java @@ -136,7 +136,7 @@ public class RowLayout extends LayoutManager { for (Component c : mChildrenComponents) { c.measure(context, 0f, currentMaxWidth, 0f, maxHeight, measure); ComponentMeasure m = measure.get(c); - if (m.getVisibility() != Visibility.GONE) { + if (!m.isGone()) { size.setWidth(size.getWidth() + m.getW()); size.setHeight(Math.max(size.getHeight(), m.getH())); visibleChildrens++; @@ -162,7 +162,7 @@ public class RowLayout extends LayoutManager { for (Component child : mChildrenComponents) { child.measure(context, minWidth, mw, minHeight, maxHeight, measure); ComponentMeasure m = measure.get(child); - if (m.getVisibility() != Visibility.GONE) { + if (!m.isGone()) { mw -= m.getW(); } } @@ -170,16 +170,26 @@ public class RowLayout extends LayoutManager { } @Override - public float intrinsicWidth(@Nullable RemoteContext context) { + public float minIntrinsicWidth(@Nullable RemoteContext context) { float width = computeModifierDefinedWidth(context); float componentWidths = 0f; for (Component c : mChildrenComponents) { - componentWidths += c.intrinsicWidth(context); + componentWidths += c.minIntrinsicWidth(context); } return Math.max(width, componentWidths); } @Override + public float minIntrinsicHeight(@Nullable RemoteContext context) { + float height = computeModifierDefinedHeight(context); + float componentHeights = 0f; + for (Component c : mChildrenComponents) { + componentHeights = Math.max(componentHeights, c.minIntrinsicHeight(context)); + } + return Math.max(height, componentHeights); + } + + @Override public void internalLayoutMeasure(@NonNull PaintContext context, @NonNull MeasurePass measure) { ComponentMeasure selfMeasure = measure.get(this); DebugLog.s( @@ -225,7 +235,7 @@ public class RowLayout extends LayoutManager { float totalWeights = 0f; for (Component child : mChildrenComponents) { ComponentMeasure childMeasure = measure.get(child); - if (childMeasure.getVisibility() == Visibility.GONE) { + if (childMeasure.isGone()) { continue; } if (child instanceof LayoutComponent @@ -245,7 +255,7 @@ public class RowLayout extends LayoutManager { if (child instanceof LayoutComponent && ((LayoutComponent) child).getWidthModifier().hasWeight()) { ComponentMeasure childMeasure = measure.get(child); - if (childMeasure.getVisibility() == Visibility.GONE) { + if (childMeasure.isGone()) { continue; } float weight = ((LayoutComponent) child).getWidthModifier().getValue(); @@ -283,7 +293,7 @@ public class RowLayout extends LayoutManager { int visibleChildrens = 0; for (Component child : mChildrenComponents) { ComponentMeasure childMeasure = measure.get(child); - if (childMeasure.getVisibility() == Visibility.GONE) { + if (childMeasure.isGone()) { continue; } childrenWidth += childMeasure.getW(); @@ -311,17 +321,22 @@ public class RowLayout extends LayoutManager { case SPACE_BETWEEN: for (Component child : mChildrenComponents) { ComponentMeasure childMeasure = measure.get(child); - if (childMeasure.getVisibility() == Visibility.GONE) { + if (childMeasure.isGone()) { continue; } total += childMeasure.getW(); } - horizontalGap = (selfWidth - total) / (visibleChildrens - 1); + if (visibleChildrens > 1) { + horizontalGap = (selfWidth - total) / (visibleChildrens - 1); + } else { + // we center the element + tx = (selfWidth - childrenWidth) / 2f; + } break; case SPACE_EVENLY: for (Component child : mChildrenComponents) { ComponentMeasure childMeasure = measure.get(child); - if (childMeasure.getVisibility() == Visibility.GONE) { + if (childMeasure.isGone()) { continue; } total += childMeasure.getW(); @@ -332,7 +347,7 @@ public class RowLayout extends LayoutManager { case SPACE_AROUND: for (Component child : mChildrenComponents) { ComponentMeasure childMeasure = measure.get(child); - if (childMeasure.getVisibility() == Visibility.GONE) { + if (childMeasure.isGone()) { continue; } total += childMeasure.getW(); @@ -357,7 +372,7 @@ public class RowLayout extends LayoutManager { } childMeasure.setX(tx); childMeasure.setY(ty); - if (childMeasure.getVisibility() == Visibility.GONE) { + if (childMeasure.isGone()) { continue; } tx += childMeasure.getW(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/StateLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/StateLayout.java index ee16bc2f4459..0192d8438a75 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/StateLayout.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/StateLayout.java @@ -413,7 +413,7 @@ public class StateLayout extends LayoutManager { if (index != currentLayoutIndex && index != previousLayoutIndex) { pane.mVisibility = Visibility.GONE; } - if (index == currentLayoutIndex && pane.mVisibility != Visibility.VISIBLE) { + if (index == currentLayoutIndex && !pane.isVisible()) { pane.mVisibility = Visibility.VISIBLE; } index++; @@ -511,7 +511,7 @@ public class StateLayout extends LayoutManager { && previousLayout.mAnimateMeasure == null) { inTransition = false; LayoutManager previous = getLayout(previousLayoutIndex); - if (previous != currentLayout && previous.mVisibility != Visibility.GONE) { + if (previous != currentLayout && !previous.isGone()) { previous.mVisibility = Visibility.GONE; previous.needsRepaint(); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/TextLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/TextLayout.java index d5db74b5ca51..2595a71abaa5 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/TextLayout.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/TextLayout.java @@ -280,7 +280,7 @@ public class TextLayout extends LayoutManager implements VariableSupport, Access + " x " + mHeight + ") " - + mVisibility; + + Visibility.toString(mVisibility); } @NonNull @@ -308,7 +308,7 @@ public class TextLayout extends LayoutManager implements VariableSupport, Access + ", " + mHeight + "] " - + mVisibility + + Visibility.toString(mVisibility) + " (" + mTextId + ":\"" @@ -343,7 +343,7 @@ public class TextLayout extends LayoutManager implements VariableSupport, Access flags |= PaintContext.TEXT_COMPLEX; } context.getTextBounds(mTextId, 0, mCachedString.length(), flags, bounds); - if (bounds[2] - bounds[1] > maxWidth && mMaxLines > 1) { + if (bounds[2] - bounds[1] > maxWidth && mMaxLines > 1 && maxWidth > 0f) { mComputedTextLayout = context.layoutComplexText( mTextId, @@ -375,12 +375,12 @@ public class TextLayout extends LayoutManager implements VariableSupport, Access } @Override - public float intrinsicHeight(@Nullable RemoteContext context) { + public float minIntrinsicHeight(@Nullable RemoteContext context) { return mTextH; } @Override - public float intrinsicWidth(@Nullable RemoteContext context) { + public float minIntrinsicWidth(@Nullable RemoteContext context) { return mTextW; } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/ComponentMeasure.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/ComponentMeasure.java index 11ed9f435070..993441944c33 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/ComponentMeasure.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/ComponentMeasure.java @@ -26,7 +26,7 @@ public class ComponentMeasure { float mY; float mW; float mH; - @NonNull Component.Visibility mVisibility = Component.Visibility.VISIBLE; + int mVisibility = Component.Visibility.VISIBLE; public void setX(float value) { mX = value; @@ -60,16 +60,15 @@ public class ComponentMeasure { return mH; } - public @NonNull Component.Visibility getVisibility() { + public int getVisibility() { return mVisibility; } - public void setVisibility(@NonNull Component.Visibility visibility) { + public void setVisibility(int visibility) { mVisibility = visibility; } - public ComponentMeasure( - int id, float x, float y, float w, float h, @NonNull Component.Visibility visibility) { + public ComponentMeasure(int id, float x, float y, float w, float h, int visibility) { this.mId = id; this.mX = x; this.mY = y; @@ -114,4 +113,42 @@ public class ComponentMeasure { public boolean same(@NonNull ComponentMeasure m) { return mX == m.mX && mY == m.mY && mW == m.mW && mH == m.mH && mVisibility == m.mVisibility; } + + /** + * Returns true if the component will be gone + * + * @return true if gone + */ + public boolean isGone() { + return Component.Visibility.isGone(mVisibility); + } + + /** + * Returns true if the component will be visible + * + * @return true if visible + */ + public boolean isVisible() { + return Component.Visibility.isVisible(mVisibility); + } + + /** + * Returns true if the component will be invisible + * + * @return true if invisible + */ + public boolean isInvisible() { + return Component.Visibility.isInvisible(mVisibility); + } + + /** Clear any override on the visibility */ + public void clearVisibilityOverride() { + mVisibility = Component.Visibility.clearOverride(mVisibility); + } + + /** Add a visibility override */ + public void addVisibilityOverride(int value) { + mVisibility = Component.Visibility.clearOverride(mVisibility); + mVisibility = Component.Visibility.add(mVisibility, value); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java index fd5f8c9cdbe7..1ab0c3dc7fb8 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java @@ -228,7 +228,7 @@ public class BackgroundModifierOperation extends DecoratorModifierOperation { public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER) - .add("type", "BackgroundModifierOperation") + .addType("BackgroundModifierOperation") .add("x", mX) .add("y", mY) .add("width", mWidth) diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java index e5f318307a75..656a3c0fca68 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java @@ -290,7 +290,7 @@ public class BorderModifierOperation extends DecoratorModifierOperation { public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER) - .add("type", "BorderModifierOperation") + .addType("BorderModifierOperation") .add("x", mX) .add("y", mY) .add("width", mWidth) diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java index 00a53170fc48..e96dc838fc91 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java @@ -111,7 +111,7 @@ public class ClipRectModifierOperation extends DecoratorModifierOperation { public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER) - .add("type", "ClipRectModifierOperation") + .addType("ClipRectModifierOperation") .add("width", mWidth) .add("height", mHeight); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentModifiers.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentModifiers.java index a9e342144cc5..14b2fad5825d 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentModifiers.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentModifiers.java @@ -327,7 +327,7 @@ public class ComponentModifiers extends PaintOperation public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER) - .add("type", "ComponentModifiers") + .addType("ComponentModifiers") .add("modifiers", mList); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentVisibilityOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentVisibilityOperation.java index fbf8a95248b9..88b28c39eec6 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentVisibilityOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentVisibilityOperation.java @@ -41,7 +41,7 @@ public class ComponentVisibilityOperation extends Operation private static final int OP_CODE = Operations.MODIFIER_VISIBILITY; int mVisibilityId; - @NonNull Component.Visibility mVisibility = Component.Visibility.VISIBLE; + int mVisibility = Component.Visibility.VISIBLE; private LayoutComponent mParent; public ComponentVisibilityOperation(int id) { @@ -124,11 +124,11 @@ public class ComponentVisibilityOperation extends Operation @Override public void updateVariables(@NonNull RemoteContext context) { int visibility = context.getInteger(mVisibilityId); - if (visibility == Component.Visibility.VISIBLE.ordinal()) { + if (Component.Visibility.isVisible(visibility)) { mVisibility = Component.Visibility.VISIBLE; - } else if (visibility == Component.Visibility.GONE.ordinal()) { + } else if (Component.Visibility.isGone(visibility)) { mVisibility = Component.Visibility.GONE; - } else if (visibility == Component.Visibility.INVISIBLE.ordinal()) { + } else if (Component.Visibility.isInvisible(visibility)) { mVisibility = Component.Visibility.INVISIBLE; } else { mVisibility = Component.Visibility.GONE; @@ -150,8 +150,8 @@ public class ComponentVisibilityOperation extends Operation public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER) - .add("type", "ComponentVisibilityOperation") + .addType("ComponentVisibilityOperation") .add("visibilityId", mVisibilityId) - .add("visibility", mVisibility); + .add("visibility", Component.Visibility.toString(mVisibility)); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DrawContentOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DrawContentOperation.java index d7abdbae4962..6beb13586163 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DrawContentOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DrawContentOperation.java @@ -120,6 +120,6 @@ public class DrawContentOperation extends Operation @Override public void serialize(MapSerializer serializer) { - serializer.addTags(SerializeTags.MODIFIER).add("type", "DrawContentOperation"); + serializer.addTags(SerializeTags.MODIFIER).addType("DrawContentOperation"); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/GraphicsLayerModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/GraphicsLayerModifierOperation.java index c1c1f9568ea8..361438b51a47 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/GraphicsLayerModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/GraphicsLayerModifierOperation.java @@ -352,7 +352,7 @@ public class GraphicsLayerModifierOperation extends DecoratorModifierOperation { public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER) - .add("type", "GraphicsLayerModifierOperation") + .addType("GraphicsLayerModifierOperation") .add("scaleX", mScaleX) .add("scaleX", mScaleX) .add("rotationX", mRotationX) diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightInModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightInModifierOperation.java index 7f0dd8d8d8e5..9b63c034675a 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightInModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightInModifierOperation.java @@ -107,7 +107,7 @@ public class HeightInModifierOperation extends DimensionInModifierOperation { public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER) - .add("type", "HeightInModifierOperation") + .addType("HeightInModifierOperation") .add("min", mV1, mValue1) .add("max", mV2, mValue2); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java index 1df84257f344..5fbaafca5759 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java @@ -143,7 +143,7 @@ public class HeightModifierOperation extends DimensionModifierOperation { public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER) - .add("type", "HeightModifierOperation") + .addType("HeightModifierOperation") .add("height", mValue, mOutValue) .add("dimensionModifierType", mType); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostActionOperation.java index 67714ef5abac..4d8acb4f04e2 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostActionOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostActionOperation.java @@ -130,7 +130,7 @@ public class HostActionOperation extends Operation public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER) - .add("type", "HostActionOperation") + .addType("HostActionOperation") .add("id", mActionId); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostNamedActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostNamedActionOperation.java index 40c13f143468..807ff68fa965 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostNamedActionOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostNamedActionOperation.java @@ -157,7 +157,7 @@ public class HostNamedActionOperation extends Operation implements ActionOperati public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER) - .add("type", "HostNamedActionOperation") + .addType("HostNamedActionOperation") .add("textId", mTextId) .add("actionType", getActionType(mType)) .add("valueId", mValueId); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/MarqueeModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/MarqueeModifierOperation.java index d2a1684a262a..c493e253d243 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/MarqueeModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/MarqueeModifierOperation.java @@ -247,8 +247,8 @@ public class MarqueeModifierOperation extends DecoratorModifierOperation impleme mComponentHeight = height; if (component instanceof LayoutComponent) { LayoutComponent layoutComponent = (LayoutComponent) component; - setContentWidth(layoutComponent.intrinsicWidth(context)); - setContentHeight(layoutComponent.intrinsicHeight(context)); + setContentWidth(layoutComponent.minIntrinsicWidth(context)); + setContentHeight(layoutComponent.minIntrinsicHeight(context)); } } @@ -256,7 +256,7 @@ public class MarqueeModifierOperation extends DecoratorModifierOperation impleme public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER) - .add("type", "MarqueeModifierOperation") + .addType("MarqueeModifierOperation") .add("iterations", mIterations) .add("animationMode", mAnimationMode) .add("repeatDelayMillis", mRepeatDelayMillis) diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/OffsetModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/OffsetModifierOperation.java index b7fe97b0e936..37f56cbc02e1 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/OffsetModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/OffsetModifierOperation.java @@ -162,7 +162,7 @@ public class OffsetModifierOperation extends DecoratorModifierOperation { public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER) - .add("type", "OffsetModifierOperation") + .addType("OffsetModifierOperation") .add("x", mX) .add("y", mY); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java index d5b3a0b09261..0156992650ed 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java @@ -184,7 +184,7 @@ public class PaddingModifierOperation extends Operation implements ModifierOpera public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER) - .add("type", "PaddingModifierOperation") + .addType("PaddingModifierOperation") .add("left", mLeft) .add("top", mTop) .add("right", mRight) diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RippleModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RippleModifierOperation.java index 69ace8478e08..eb5bfcff7d40 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RippleModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RippleModifierOperation.java @@ -217,7 +217,7 @@ public class RippleModifierOperation extends DecoratorModifierOperation implemen public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER) - .add("type", "RippleModifierOperation") + .addType("RippleModifierOperation") .add("animateRippleStart", mAnimateRippleStart) .add("animateRippleX", mAnimateRippleX) .add("animateRippleY", mAnimateRippleY) diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RoundedClipRectModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RoundedClipRectModifierOperation.java index 8442e05e59df..f0ed905ac158 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RoundedClipRectModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RoundedClipRectModifierOperation.java @@ -167,7 +167,7 @@ public class RoundedClipRectModifierOperation extends DrawBase4 public void serialize(MapSerializer serializer) { serialize(serializer, "topStart", "topEnd", "bottomStart", "bottomEnd") .addTags(SerializeTags.MODIFIER) - .add("type", CLASS_NAME) + .addType(CLASS_NAME) .add("width", mWidth) .add("height", mHeight); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ScrollModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ScrollModifierOperation.java index a57365ec9132..466e435e20cf 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ScrollModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ScrollModifierOperation.java @@ -397,7 +397,7 @@ public class ScrollModifierOperation extends ListActionsOperation public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER) - .add("type", "ScrollModifierOperation") + .addType("ScrollModifierOperation") .add("direction", mDirection) .add("max", mMax) .add("notchMax", mNotchMax) diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatChangeActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatChangeActionOperation.java index bd91734602d9..171e2bed6b00 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatChangeActionOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatChangeActionOperation.java @@ -126,7 +126,7 @@ public class ValueFloatChangeActionOperation extends Operation implements Action public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER, SerializeTags.ACTION) - .add("type", "ValueFloatChangeActionOperation") + .addType("ValueFloatChangeActionOperation") .add("targetValueId", mTargetValueId) .add("value", mValue); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatExpressionChangeActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatExpressionChangeActionOperation.java index 4b18d0aaf0df..d8133f6715a8 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatExpressionChangeActionOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatExpressionChangeActionOperation.java @@ -133,7 +133,7 @@ public class ValueFloatExpressionChangeActionOperation extends Operation public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER, SerializeTags.ACTION) - .add("type", "ValueFloatExpressionChangeActionOperation") + .addType("ValueFloatExpressionChangeActionOperation") .add("targetValueId", mTargetValueId) .add("valueExpressionId", mValueExpressionId); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerChangeActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerChangeActionOperation.java index d86c4a6ad416..05a6fd0f10da 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerChangeActionOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerChangeActionOperation.java @@ -131,7 +131,7 @@ public class ValueIntegerChangeActionOperation extends Operation implements Acti public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER, SerializeTags.ACTION) - .add("type", "ValueIntegerChangeActionOperation") + .addType("ValueIntegerChangeActionOperation") .add("targetValueId", mTargetValueId) .add("value", mValue); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerExpressionChangeActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerExpressionChangeActionOperation.java index e253460d2afb..8994febe7f7c 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerExpressionChangeActionOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerExpressionChangeActionOperation.java @@ -133,7 +133,7 @@ public class ValueIntegerExpressionChangeActionOperation extends Operation public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER, SerializeTags.ACTION) - .add("type", "ValueIntegerExpressionChangeActionOperation") + .addType("ValueIntegerExpressionChangeActionOperation") .add("targetValueId", mTargetValueId) .add("valueExpressionId", mValueExpressionId); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueStringChangeActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueStringChangeActionOperation.java index e84b29922523..08960d3576f4 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueStringChangeActionOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueStringChangeActionOperation.java @@ -139,7 +139,7 @@ public class ValueStringChangeActionOperation extends Operation implements Actio public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER, SerializeTags.ACTION) - .add("type", "ValueIntegerExpressionChangeActionOperation") + .addType("ValueIntegerExpressionChangeActionOperation") .add("targetValueId", mTargetValueId) .add("valueId", mValueId); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthInModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthInModifierOperation.java index 3282a9cb5426..93074c79319f 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthInModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthInModifierOperation.java @@ -107,7 +107,7 @@ public class WidthInModifierOperation extends DimensionInModifierOperation { public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER) - .add("type", "WidthInModifierOperation") + .addType("WidthInModifierOperation") .add("min", mV1, mValue1) .add("max", mV2, mValue2); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java index 6fe5a70b7ad4..ebdafa2aaa89 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java @@ -143,7 +143,7 @@ public class WidthModifierOperation extends DimensionModifierOperation { public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER) - .add("type", "WidthModifierOperation") + .addType("WidthModifierOperation") .add("width", mValue, mOutValue) .add("dimensionModifierType", mType); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ZIndexModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ZIndexModifierOperation.java index f250951ab87e..ddb34b57e936 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ZIndexModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ZIndexModifierOperation.java @@ -147,7 +147,7 @@ public class ZIndexModifierOperation extends DecoratorModifierOperation { public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER) - .add("type", "ZIndexModifierOperation") + .addType("ZIndexModifierOperation") .add("value", mValue); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/paint/PaintBundle.java b/core/java/com/android/internal/widget/remotecompose/core/operations/paint/PaintBundle.java index 0f17b114133d..55b64364e4e5 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/paint/PaintBundle.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/paint/PaintBundle.java @@ -1248,7 +1248,7 @@ public class PaintBundle implements Serializable { @Override public void serialize(MapSerializer serializer) { - serializer.add("type", "PaintBundle"); + serializer.addType("PaintBundle"); List<Map<String, Object>> list = new ArrayList<>(); int i = 0; while (i < mPos) { @@ -1336,6 +1336,7 @@ public class PaintBundle implements Serializable { serializer.add("operations", list); } + @SuppressWarnings("JdkImmutableCollections") private static Map<String, Object> getVariable(int value) { float fValue = Float.intBitsToFloat(value); if (Float.isNaN(fValue)) { @@ -1344,6 +1345,7 @@ public class PaintBundle implements Serializable { return orderedOf("type", "Value", "value", fValue); } + @SuppressWarnings("JdkImmutableCollections") private static int serializeGradient( int cmd, int[] array, int i, List<Map<String, Object>> list) { int ret = i; diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/FloatAnimation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/FloatAnimation.java index cad76059f7a4..349ab6117b2b 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/FloatAnimation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/FloatAnimation.java @@ -34,8 +34,10 @@ public class FloatAnimation extends Easing implements Serializable { private float mWrap = Float.NaN; private float mInitialValue = Float.NaN; private float mTargetValue = Float.NaN; + private int mDirectionalSnap = 0; // private float mScale = 1; float mOffset = 0; + private boolean mPropagate = false; @NonNull @Override @@ -161,11 +163,15 @@ public class FloatAnimation extends Easing implements Serializable { int type = 0; float wrapValue = Float.NaN; float initialValue = Float.NaN; + int directionalSnap = 0; + boolean propagate = false; if (mSpec.length > 1) { int num_type = Float.floatToRawIntBits(mSpec[1]); type = num_type & 0xFF; boolean wrap = ((num_type >> 8) & 0x1) > 0; boolean init = ((num_type >> 8) & 0x2) > 0; + directionalSnap = (num_type >> 10) & 0x3; + propagate = ((num_type >> 12) & 0x1) > 0; len = (num_type >> 16) & 0xFFFF; int off = 2 + len; if (init) { @@ -229,6 +235,12 @@ public class FloatAnimation extends Easing implements Serializable { if (!Float.isNaN(wrapValue)) { str += " wrap =" + wrapValue; } + if (directionalSnap != 0) { + str += " directionalSnap=" + directionalSnap; + } + if (propagate) { + str += " propagate"; + } return str; } @@ -246,6 +258,8 @@ public class FloatAnimation extends Easing implements Serializable { mType = num_type & 0xFF; boolean wrap = ((num_type >> 8) & 0x1) > 0; boolean init = ((num_type >> 8) & 0x2) > 0; + int directional = (num_type >> 10) & 0x3; + boolean propagate = ((num_type >> 12) & 0x1) > 0; len = (num_type >> 16) & 0xFFFF; int off = 2 + len; if (init) { @@ -254,6 +268,8 @@ public class FloatAnimation extends Easing implements Serializable { if (wrap) { mWrap = mSpec[off]; } + mDirectionalSnap = directional; + mPropagate = propagate; } create(mType, description, 2, len); } @@ -347,7 +363,13 @@ public class FloatAnimation extends Easing implements Serializable { float dist = wrapDistance(mWrap, mInitialValue, mTargetValue); if ((dist > 0) && (mTargetValue < mInitialValue)) { mTargetValue += mWrap; - } else if ((dist < 0) && (mTargetValue > mInitialValue)) { + } else if ((dist < 0) && mDirectionalSnap != 0) { + if (mDirectionalSnap == 1 && mTargetValue > mInitialValue) { + mInitialValue = mTargetValue; + } + if (mDirectionalSnap == 2 && mTargetValue < mInitialValue) { + mInitialValue = mTargetValue; + } mTargetValue -= mWrap; } } @@ -377,6 +399,14 @@ public class FloatAnimation extends Easing implements Serializable { /** get the value at time t in seconds since start */ @Override public float get(float t) { + if (mDirectionalSnap == 1 && mTargetValue < mInitialValue) { + mInitialValue = mTargetValue; + return mTargetValue; + } + if (mDirectionalSnap == 2 && mTargetValue > mInitialValue) { + mInitialValue = mTargetValue; + return mTargetValue; + } return mEasingCurve.get(t / mDuration) * (mTargetValue - mInitialValue) + mInitialValue; } @@ -387,6 +417,13 @@ public class FloatAnimation extends Easing implements Serializable { } /** + * @return if you should propagate the animation + */ + public boolean isPropagate() { + return mPropagate; + } + + /** * Get the initial value * * @return the initial value @@ -398,7 +435,7 @@ public class FloatAnimation extends Easing implements Serializable { @Override public void serialize(MapSerializer serializer) { serializer - .add("type", "FloatAnimation") + .addType("FloatAnimation") .add("initialValue", mInitialValue) .add("targetValue", mInitialValue) .add("duration", mInitialValue) diff --git a/core/java/com/android/internal/widget/remotecompose/core/semantics/CoreSemantics.java b/core/java/com/android/internal/widget/remotecompose/core/semantics/CoreSemantics.java index 08559fc21acb..424894a3e665 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/semantics/CoreSemantics.java +++ b/core/java/com/android/internal/widget/remotecompose/core/semantics/CoreSemantics.java @@ -161,7 +161,7 @@ public class CoreSemantics extends Operation implements AccessibilityModifier { public void serialize(MapSerializer serializer) { serializer .addTags(SerializeTags.MODIFIER, SerializeTags.A11Y) - .add("type", "CoreSemantics") + .addType("CoreSemantics") .add("contentDescriptionId", mContentDescriptionId) .add("role", mRole) .add("textId", mTextId) diff --git a/core/java/com/android/internal/widget/remotecompose/core/serialize/MapSerializer.java b/core/java/com/android/internal/widget/remotecompose/core/serialize/MapSerializer.java index f9ecf0f4f672..20e94ab5d898 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/serialize/MapSerializer.java +++ b/core/java/com/android/internal/widget/remotecompose/core/serialize/MapSerializer.java @@ -25,11 +25,17 @@ import java.util.Map; public interface MapSerializer { /** + * Adds a "type" field with this value + * + * @param type The name of the type + */ + MapSerializer addType(String type); + + /** * Add a float expression * - * @param key - * @param value - * @return + * @param key The key + * @param value The float src */ MapSerializer addFloatExpressionSrc(String key, float[] value); diff --git a/core/java/com/android/internal/widget/remotecompose/core/types/BooleanConstant.java b/core/java/com/android/internal/widget/remotecompose/core/types/BooleanConstant.java index cb759a61249a..0da543f3336c 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/types/BooleanConstant.java +++ b/core/java/com/android/internal/widget/remotecompose/core/types/BooleanConstant.java @@ -131,6 +131,6 @@ public class BooleanConstant extends Operation implements Serializable { @Override public void serialize(MapSerializer serializer) { - serializer.add("type", CLASS_NAME).add("id", mId).add("value", mValue); + serializer.addType(CLASS_NAME).add("id", mId).add("value", mValue); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/types/IntegerConstant.java b/core/java/com/android/internal/widget/remotecompose/core/types/IntegerConstant.java index c734f813ede3..bdc765968387 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/types/IntegerConstant.java +++ b/core/java/com/android/internal/widget/remotecompose/core/types/IntegerConstant.java @@ -123,6 +123,6 @@ public class IntegerConstant extends Operation implements Serializable { @Override public void serialize(MapSerializer serializer) { - serializer.add("type", CLASS_NAME).add("id", mId).add("value", mValue); + serializer.addType(CLASS_NAME).add("id", mId).add("value", mValue); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/types/LongConstant.java b/core/java/com/android/internal/widget/remotecompose/core/types/LongConstant.java index 50509f3636b3..d071e0a21d22 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/types/LongConstant.java +++ b/core/java/com/android/internal/widget/remotecompose/core/types/LongConstant.java @@ -35,9 +35,13 @@ public class LongConstant extends Operation implements Serializable { private static final String CLASS_NAME = "LongConstant"; private static final int OP_CODE = Operations.DATA_LONG; - private final long mValue; + private long mValue; private final int mId; + /** + * @param id the id of the constant + * @param value the value of the constant + */ public LongConstant(int id, long value) { mId = id; mValue = value; @@ -52,6 +56,15 @@ public class LongConstant extends Operation implements Serializable { return mValue; } + /** + * Set the value of the long constant + * + * @param value the value to set it to + */ + public void setValue(long value) { + mValue = value; + } + @Override public void write(@NonNull WireBuffer buffer) { apply(buffer, mId, mValue); @@ -114,6 +127,6 @@ public class LongConstant extends Operation implements Serializable { @Override public void serialize(MapSerializer serializer) { - serializer.add("type", CLASS_NAME).add("id", mId).add("value", mValue); + serializer.addType(CLASS_NAME).add("id", mId).add("value", mValue); } } diff --git a/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java b/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java index 1d1e579ebc2f..1f9a27429067 100644 --- a/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java +++ b/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java @@ -388,6 +388,16 @@ public class RemoteComposePlayer extends FrameLayout implements RemoteContextAwa mInner.setColor(colorName, colorValue); } + /** + * This sets long based on its name. + * + * @param name Name of the color + * @param value The new long value + */ + public void setLong(String name, long value) { + mInner.setLong(name, value); + } + private void mapColors() { String[] name = getNamedColors(); diff --git a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java index ac4a294b5e5e..b5aedd8d0231 100644 --- a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java +++ b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java @@ -290,8 +290,8 @@ public class AndroidPaintContext extends PaintContext { } if ((flags & PaintContext.TEXT_MEASURE_FONT_HEIGHT) != 0) { - bounds[1] = Math.round(mCachedFontMetrics.top); - bounds[3] = Math.round(mCachedFontMetrics.bottom); + bounds[1] = Math.round(mCachedFontMetrics.ascent); + bounds[3] = Math.round(mCachedFontMetrics.descent); } else { bounds[1] = mTmpRect.top; bounds[3] = mTmpRect.bottom; @@ -344,6 +344,7 @@ public class AndroidPaintContext extends PaintContext { default: } staticLayoutBuilder.setMaxLines(maxLines); + staticLayoutBuilder.setIncludePad(false); StaticLayout staticLayout = staticLayoutBuilder.build(); return new AndroidComputedTextLayout( diff --git a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPlatformServices.java b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPlatformServices.java index ba8d83bff51f..51c42fe111bd 100644 --- a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPlatformServices.java +++ b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPlatformServices.java @@ -60,6 +60,14 @@ public class AndroidPlatformServices implements Platform { } @Override + public boolean isAlpha8Image(@NonNull Object image) { + if (image instanceof Bitmap) { + return ((Bitmap) image).getConfig().equals(Bitmap.Config.ALPHA_8); + } + return false; + } + + @Override @Nullable public float[] pathToFloatArray(@NonNull Object path) { // if (path is RemotePath) { diff --git a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java index 14349b028819..b31c76056e38 100644 --- a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java +++ b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java @@ -20,6 +20,7 @@ import android.annotation.Nullable; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; +import android.graphics.Paint; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.widget.remotecompose.core.RemoteContext; @@ -30,6 +31,7 @@ import com.android.internal.widget.remotecompose.core.operations.FloatExpression import com.android.internal.widget.remotecompose.core.operations.ShaderData; import com.android.internal.widget.remotecompose.core.operations.utilities.ArrayAccess; import com.android.internal.widget.remotecompose.core.operations.utilities.DataMap; +import com.android.internal.widget.remotecompose.core.types.LongConstant; import java.io.IOException; import java.net.MalformedURLException; @@ -141,6 +143,16 @@ public class AndroidRemoteContext extends RemoteContext { } @Override + public void setNamedLong(String name, long value) { + VarName entry = mVarNameHashMap.get(name); + if (entry != null) { + int id = entry.mId; + LongConstant longConstant = (LongConstant) mRemoteComposeState.getObject(id); + longConstant.setValue(value); + } + } + + @Override public void setNamedDataOverride(String dataName, Object value) { if (mVarNameHashMap.get(dataName) != null) { int id = mVarNameHashMap.get(dataName).mId; @@ -215,6 +227,27 @@ public class AndroidRemoteContext extends RemoteContext { case BitmapData.TYPE_PNG_8888: image = BitmapFactory.decodeByteArray(data, 0, data.length); break; + case BitmapData.TYPE_PNG_ALPHA_8: + image = decodePreferringAlpha8(data); + + // If needed convert to ALPHA_8. + if (!image.getConfig().equals(Bitmap.Config.ALPHA_8)) { + Bitmap alpha8Bitmap = + Bitmap.createBitmap( + image.getWidth(), + image.getHeight(), + Bitmap.Config.ALPHA_8); + Canvas canvas = new Canvas(alpha8Bitmap); + Paint paint = new Paint(); + paint.setXfermode( + new android.graphics.PorterDuffXfermode( + android.graphics.PorterDuff.Mode.SRC)); + canvas.drawBitmap(image, 0, 0, paint); + image.recycle(); // Release resources + + image = alpha8Bitmap; + } + break; case BitmapData.TYPE_RAW8888: image = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); int[] idata = new int[data.length / 4]; @@ -255,6 +288,12 @@ public class AndroidRemoteContext extends RemoteContext { } } + private Bitmap decodePreferringAlpha8(@NonNull byte[] data) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inPreferredConfig = Bitmap.Config.ALPHA_8; + return BitmapFactory.decodeByteArray(data, 0, data.length, options); + } + @Override public void loadText(int id, @NonNull String text) { if (!mRemoteComposeState.containsId(id)) { diff --git a/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java b/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java index 4d2dd05ca603..29cd40def562 100644 --- a/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java +++ b/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java @@ -200,6 +200,16 @@ public class RemoteComposeCanvas extends FrameLayout implements View.OnAttachSta mARContext.setNamedColorOverride(colorName, colorValue); } + /** + * set the value of a long associated with this name. + * + * @param name Name of color typically "android.xxx" + * @param value the long value + */ + public void setLong(String name, long value) { + mARContext.setNamedLong(name, value); + } + public RemoteComposeDocument getDocument() { return mDocument; } diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto index 34ec1481f697..8de77469d170 100644 --- a/core/proto/android/providers/settings/secure.proto +++ b/core/proto/android/providers/settings/secure.proto @@ -111,6 +111,7 @@ message SecureSettingsProto { optional SettingProto autoclick_cursor_area_size = 62 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto autoclick_ignore_minor_cursor_movement = 63 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto autoclick_panel_position = 64 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto autoclick_revert_to_left_click = 65 [ (android.privacy).dest = DEST_AUTOMATIC ]; } optional Accessibility accessibility = 2; diff --git a/core/tests/coretests/src/android/os/PerfettoTraceTest.java b/core/tests/coretests/src/android/os/PerfettoTraceTest.java index 69150150d6f9..790ac4a55dc6 100644 --- a/core/tests/coretests/src/android/os/PerfettoTraceTest.java +++ b/core/tests/coretests/src/android/os/PerfettoTraceTest.java @@ -33,6 +33,7 @@ import androidx.test.InstrumentationRegistry; import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Before; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -611,6 +612,7 @@ public class PerfettoTraceTest { @Test @RequiresFlagsEnabled(android.os.Flags.FLAG_PERFETTO_SDK_TRACING_V2) + @Ignore("b/303199244") public void testMessageQueue() throws Exception { TraceConfig traceConfig = getTraceConfig("mq"); diff --git a/libs/hwui/CanvasTransform.cpp b/libs/hwui/CanvasTransform.cpp index 30e7a628f1f6..6f60d01e4395 100644 --- a/libs/hwui/CanvasTransform.cpp +++ b/libs/hwui/CanvasTransform.cpp @@ -55,12 +55,20 @@ SkColor makeDark(SkColor color) { } } +SkColor invert(SkColor color) { + Lab lab = sRGBToLab(color); + lab.L = 100 - lab.L; + return LabToSRGB(lab, SkColorGetA(color)); +} + SkColor transformColor(ColorTransform transform, SkColor color) { switch (transform) { case ColorTransform::Light: return makeLight(color); case ColorTransform::Dark: return makeDark(color); + case ColorTransform::Invert: + return invert(color); default: return color; } @@ -80,19 +88,6 @@ SkColor transformColorInverse(ColorTransform transform, SkColor color) { static void applyColorTransform(ColorTransform transform, SkPaint& paint) { if (transform == ColorTransform::None) return; - if (transform == ColorTransform::Invert) { - auto filter = SkHighContrastFilter::Make( - {/* grayscale= */ false, SkHighContrastConfig::InvertStyle::kInvertLightness, - /* contrast= */ 0.0f}); - - if (paint.getColorFilter()) { - paint.setColorFilter(SkColorFilters::Compose(filter, paint.refColorFilter())); - } else { - paint.setColorFilter(filter); - } - return; - } - SkColor newColor = transformColor(transform, paint.getColor()); paint.setColor(newColor); @@ -112,6 +107,22 @@ static void applyColorTransform(ColorTransform transform, SkPaint& paint) { paint.setShader(SkGradientShader::MakeLinear( info.fPoints, info.fColors, info.fColorOffsets, info.fColorCount, info.fTileMode, info.fGradientFlags, nullptr)); + } else { + if (transform == ColorTransform::Invert) { + // Since we're trying to invert every thing around this draw call, we invert + // the color of the draw call if we don't know what it is. + auto filter = SkHighContrastFilter::Make( + {/* grayscale= */ false, + SkHighContrastConfig::InvertStyle::kInvertLightness, + /* contrast= */ 0.0f}); + + if (paint.getColorFilter()) { + paint.setColorFilter(SkColorFilters::Compose(filter, paint.refColorFilter())); + } else { + paint.setColorFilter(filter); + } + return; + } } } @@ -150,8 +161,13 @@ bool transformPaint(ColorTransform transform, SkPaint* paint) { } bool transformPaint(ColorTransform transform, SkPaint* paint, BitmapPalette palette) { - palette = filterPalette(paint, palette); bool shouldInvert = false; + if (transform == ColorTransform::Invert && palette != BitmapPalette::Colorful) { + // When the transform is Invert we invert any image that is not deemed "colorful", + // regardless of calculated image brightness. + shouldInvert = true; + } + palette = filterPalette(paint, palette); if (palette == BitmapPalette::Light && transform == ColorTransform::Dark) { shouldInvert = true; } diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 4801bd1038a3..8b4e59aa73e2 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -27,6 +27,7 @@ #include "DamageAccumulator.h" #include "Debug.h" +#include "FeatureFlags.h" #include "Properties.h" #include "TreeInfo.h" #include "VectorDrawable.h" @@ -398,26 +399,32 @@ void RenderNode::syncDisplayList(TreeObserver& observer, TreeInfo* info) { deleteDisplayList(observer, info); mDisplayList = std::move(mStagingDisplayList); if (mDisplayList) { - WebViewSyncData syncData{.applyForceDark = shouldEnableForceDark(info)}; + WebViewSyncData syncData{.applyForceDark = shouldEnableForceDark(info) || + (info && isForceInvertDark(*info))}; mDisplayList.syncContents(syncData); handleForceDark(info); } } +// Return true if the tree should use the force invert feature that inverts +// the entire tree to darken it. inline bool RenderNode::isForceInvertDark(TreeInfo& info) { - return CC_UNLIKELY( - info.forceDarkType == android::uirenderer::ForceDarkType::FORCE_INVERT_COLOR_DARK); + return CC_UNLIKELY(info.forceDarkType == + android::uirenderer::ForceDarkType::FORCE_INVERT_COLOR_DARK); } +// Return true if the tree should use the force dark feature that selectively +// darkens light nodes on the tree. inline bool RenderNode::shouldEnableForceDark(TreeInfo* info) { - return CC_UNLIKELY( - info && - (!info->disableForceDark || isForceInvertDark(*info))); + return CC_UNLIKELY(info && !info->disableForceDark); } - - -void RenderNode::handleForceDark(android::uirenderer::TreeInfo *info) { +void RenderNode::handleForceDark(TreeInfo *info) { + if (CC_UNLIKELY(view_accessibility_flags::force_invert_color() && info && + isForceInvertDark(*info))) { + mDisplayList.applyColorTransform(ColorTransform::Invert); + return; + } if (!shouldEnableForceDark(info)) { return; } @@ -427,13 +434,7 @@ void RenderNode::handleForceDark(android::uirenderer::TreeInfo *info) { children.push_back(node); }); if (mDisplayList.hasText()) { - if (isForceInvertDark(*info) && mDisplayList.hasFill()) { - // Handle a special case for custom views that draw both text and background in the - // same RenderNode, which would otherwise be altered to white-on-white text. - usage = UsageHint::Container; - } else { - usage = UsageHint::Foreground; - } + usage = UsageHint::Foreground; } if (usage == UsageHint::Unknown) { if (children.size() > 1) { diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp index 63a024b8e780..3ef970830dc4 100644 --- a/libs/hwui/hwui/Bitmap.cpp +++ b/libs/hwui/hwui/Bitmap.cpp @@ -16,6 +16,8 @@ #include "Bitmap.h" #include <android-base/file.h> + +#include "FeatureFlags.h" #include "HardwareBitmapUploader.h" #include "Properties.h" #ifdef __ANDROID__ // Layoutlib does not support render thread @@ -547,9 +549,16 @@ BitmapPalette Bitmap::computePalette(const SkImageInfo& info, const void* addr, } ALOGV("samples = %d, hue [min = %f, max = %f, avg = %f]; saturation [min = %f, max = %f, avg = " - "%f]", + "%f] %d x %d", sampledCount, hue.min(), hue.max(), hue.average(), saturation.min(), saturation.max(), - saturation.average()); + saturation.average(), info.width(), info.height()); + + if (CC_UNLIKELY(view_accessibility_flags::force_invert_color())) { + if (saturation.delta() > 0.1f || + (hue.delta() > 20 && saturation.average() > 0.2f && value.average() < 0.9f)) { + return BitmapPalette::Colorful; + } + } if (hue.delta() <= 20 && saturation.delta() <= .1f) { if (value.average() >= .5f) { diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h index 4e9bcf27c0ef..0fe5fe88f715 100644 --- a/libs/hwui/hwui/Bitmap.h +++ b/libs/hwui/hwui/Bitmap.h @@ -49,6 +49,7 @@ enum class BitmapPalette { Unknown, Light, Dark, + Colorful, }; namespace uirenderer { diff --git a/libs/hwui/jni/GIFMovie.cpp b/libs/hwui/jni/GIFMovie.cpp index 6c82aa1ca27d..476b6fda5007 100644 --- a/libs/hwui/jni/GIFMovie.cpp +++ b/libs/hwui/jni/GIFMovie.cpp @@ -63,7 +63,7 @@ GIFMovie::GIFMovie(SkStream* stream) } fCurrIndex = -1; fLastDrawIndex = -1; - fPaintingColor = SkPackARGB32(0, 0, 0, 0); + fPaintingColor = SK_AlphaTRANSPARENT; } GIFMovie::~GIFMovie() @@ -127,7 +127,7 @@ static void copyLine(uint32_t* dst, const unsigned char* src, const ColorMapObje for (; width > 0; width--, src++, dst++) { if (*src != transparent && *src < cmap->ColorCount) { const GifColorType& col = cmap->Colors[*src]; - *dst = SkPackARGB32(0xFF, col.Red, col.Green, col.Blue); + *dst = SkColorSetRGB(col.Red, col.Green, col.Blue); } } } @@ -395,10 +395,10 @@ bool GIFMovie::onGetBitmap(SkBitmap* bm) lastIndex = fGIF->ImageCount - 1; } - SkColor bgColor = SkPackARGB32(0, 0, 0, 0); + SkColor bgColor = SK_ColorTRANSPARENT; if (gif->SColorMap != nullptr && gif->SBackGroundColor < gif->SColorMap->ColorCount) { const GifColorType& col = gif->SColorMap->Colors[gif->SBackGroundColor]; - bgColor = SkColorSetARGB(0xFF, col.Red, col.Green, col.Blue); + bgColor = SkColorSetRGB(col.Red, col.Green, col.Blue); } // draw each frames - not intelligent way @@ -411,7 +411,7 @@ bool GIFMovie::onGetBitmap(SkBitmap* bm) if (!trans && gif->SColorMap != nullptr) { fPaintingColor = bgColor; } else { - fPaintingColor = SkColorSetARGB(0, 0, 0, 0); + fPaintingColor = SK_ColorTRANSPARENT; } bm->eraseColor(fPaintingColor); diff --git a/packages/EasterEgg/src/com/android/egg/landroid/Autopilot.kt b/packages/EasterEgg/src/com/android/egg/landroid/Autopilot.kt index 8214c540304e..a4803d248ea8 100644 --- a/packages/EasterEgg/src/com/android/egg/landroid/Autopilot.kt +++ b/packages/EasterEgg/src/com/android/egg/landroid/Autopilot.kt @@ -44,7 +44,7 @@ class Autopilot(val ship: Spacecraft, val universe: Universe) : Entity { if (enabled) listOf( "---- AUTOPILOT ENGAGED ----", - "TGT: " + (target?.name?.toUpperCase() ?: "SELECTING..."), + "TGT: " + (target?.name?.uppercase() ?: "SELECTING..."), "EXE: $strategy" + if (debug.isNotEmpty()) " ($debug)" else "", ) .joinToString("\n") diff --git a/packages/EasterEgg/src/com/android/egg/landroid/MainActivity.kt b/packages/EasterEgg/src/com/android/egg/landroid/MainActivity.kt index 95a60c7a5292..61ea08ecbf5d 100644 --- a/packages/EasterEgg/src/com/android/egg/landroid/MainActivity.kt +++ b/packages/EasterEgg/src/com/android/egg/landroid/MainActivity.kt @@ -236,8 +236,8 @@ fun Telemetry(universe: Universe, showControls: Boolean) { ((closest.pos - pos).mag() - closest.radius).toInt() listOfNotNull( landing?.let { - "LND: ${it.planet.name.toUpperCase()}\n" + - "JOB: ${it.text.toUpperCase()}" + "LND: ${it.planet.name.uppercase()}\n" + + "JOB: ${it.text.uppercase()}" } ?: if (distToClosest < 10_000) { "ALT: $distToClosest" diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java index f692601edcb7..3c70fc15485a 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java @@ -96,6 +96,7 @@ public class SecureSettings { Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY, Settings.Secure.ACCESSIBILITY_AUTOCLICK_PANEL_POSITION, + Settings.Secure.ACCESSIBILITY_AUTOCLICK_REVERT_TO_LEFT_CLICK, Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON, Settings.Secure.PREFERRED_TTY_MODE, Settings.Secure.ENHANCED_VOICE_PRIVACY_ENABLED, diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java index e42d3fb9da41..c09e45ed81a6 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -147,6 +147,7 @@ public class SecureSettingsValidators { VALIDATORS.put(Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.ACCESSIBILITY_AUTOCLICK_DELAY, NON_NEGATIVE_INTEGER_VALIDATOR); VALIDATORS.put(Secure.ACCESSIBILITY_AUTOCLICK_PANEL_POSITION, ANY_STRING_VALIDATOR); + VALIDATORS.put(Secure.ACCESSIBILITY_AUTOCLICK_REVERT_TO_LEFT_CLICK, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.ACCESSIBILITY_LARGE_POINTER_ICON, BOOLEAN_VALIDATOR); VALIDATORS.put( Secure.PREFERRED_TTY_MODE, diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index c29a5a20a96f..167674a451b3 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -1722,6 +1722,9 @@ class SettingsProtoDumpUtil { Settings.Secure.ACCESSIBILITY_AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT, SecureSettingsProto.Accessibility.AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT); dumpSetting(s, p, + Settings.Secure.ACCESSIBILITY_AUTOCLICK_REVERT_TO_LEFT_CLICK, + SecureSettingsProto.Accessibility.AUTOCLICK_REVERT_TO_LEFT_CLICK); + dumpSetting(s, p, Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, SecureSettingsProto.Accessibility.AUTOCLICK_ENABLED); dumpSetting(s, p, diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ComposedDigitalLayerController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ComposedDigitalLayerController.kt index b9200c15944c..e9e61a718f08 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ComposedDigitalLayerController.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ComposedDigitalLayerController.kt @@ -44,6 +44,7 @@ class ComposedDigitalLayerController(private val clockCtx: ClockContext) : val dozeState = DefaultClockController.AnimationState(1F) override val view = FlexClockView(clockCtx) + override var onViewBoundsChanged by view::onViewBoundsChanged init { fun createController(cfg: LayerConfig) { diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt index f24ad1c10c4a..9bb3bac824e9 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt @@ -17,6 +17,7 @@ import android.content.Context import android.content.res.Resources import android.graphics.Color import android.graphics.Rect +import android.graphics.RectF import android.icu.text.NumberFormat import android.util.TypedValue import android.view.LayoutInflater @@ -97,7 +98,12 @@ class DefaultClockController( events.onLocaleChanged(Locale.getDefault()) } - override fun initialize(isDarkTheme: Boolean, dozeFraction: Float, foldFraction: Float) { + override fun initialize( + isDarkTheme: Boolean, + dozeFraction: Float, + foldFraction: Float, + onBoundsChanged: (RectF) -> Unit, + ) { largeClock.recomputePadding(null) largeClock.animations = LargeClockAnimations(largeClock.view, dozeFraction, foldFraction) 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 1a1033ba42e0..6dfd2268005f 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 @@ -16,6 +16,7 @@ package com.android.systemui.shared.clocks +import android.graphics.RectF import com.android.systemui.animation.GSFAxes import com.android.systemui.customization.R import com.android.systemui.plugins.clocks.AlarmData @@ -102,9 +103,15 @@ class FlexClockController(private val clockCtx: ClockContext) : ClockController } } - override fun initialize(isDarkTheme: Boolean, dozeFraction: Float, foldFraction: Float) { + override fun initialize( + isDarkTheme: Boolean, + dozeFraction: Float, + foldFraction: Float, + onBoundsChanged: (RectF) -> Unit, + ) { events.onFontAxesChanged(clockCtx.settings.axes) smallClock.run { + layerController.onViewBoundsChanged = onBoundsChanged events.onThemeChanged(theme.copy(isDarkTheme = isDarkTheme)) animations.doze(dozeFraction) animations.fold(foldFraction) @@ -112,6 +119,7 @@ class FlexClockController(private val clockCtx: ClockContext) : ClockController } largeClock.run { + layerController.onViewBoundsChanged = onBoundsChanged events.onThemeChanged(theme.copy(isDarkTheme = isDarkTheme)) animations.doze(dozeFraction) animations.fold(foldFraction) diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleClockLayerController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleClockLayerController.kt index af00cc264208..336c66eed889 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleClockLayerController.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleClockLayerController.kt @@ -16,6 +16,7 @@ package com.android.systemui.shared.clocks +import android.graphics.RectF import android.view.View import androidx.annotation.VisibleForTesting import com.android.systemui.plugins.clocks.ClockAnimations @@ -31,4 +32,5 @@ interface SimpleClockLayerController { val config: ClockFaceConfig @VisibleForTesting var fakeTimeMills: Long? + var onViewBoundsChanged: ((RectF) -> Unit)? } diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleDigitalHandLayerController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleDigitalHandLayerController.kt index 0b7ea1a335ef..97004ef6f9a9 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleDigitalHandLayerController.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleDigitalHandLayerController.kt @@ -85,6 +85,7 @@ open class SimpleDigitalHandLayerController( override val view = SimpleDigitalClockTextView(clockCtx, isLargeClock) private val logger = Logger(clockCtx.messageBuffer, TAG) val timespec = DigitalTimespecHandler(layerCfg.timespec, layerCfg.dateTimeFormat) + override var onViewBoundsChanged by view::onViewBoundsChanged @VisibleForTesting override var fakeTimeMills: Long? diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/FlexClockView.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/FlexClockView.kt index 2d0ca5331299..c765ea9cc84c 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/FlexClockView.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/FlexClockView.kt @@ -100,6 +100,7 @@ class FlexClockView(clockCtx: ClockContext) : ViewGroup(clockCtx.context) { updateLocale(Locale.getDefault()) } + var onViewBoundsChanged: ((RectF) -> Unit)? = null private val digitOffsets = mutableMapOf<Int, Float>() protected fun calculateSize( @@ -189,13 +190,21 @@ class FlexClockView(clockCtx: ClockContext) : ViewGroup(clockCtx.context) { fun updateLocation() { val layoutBounds = this.layoutBounds ?: return + val bounds = + RectF( + layoutBounds.centerX() - measuredWidth / 2f, + layoutBounds.centerY() - measuredHeight / 2f, + layoutBounds.centerX() + measuredWidth / 2f, + layoutBounds.centerY() + measuredHeight / 2f, + ) setFrame( - (layoutBounds.centerX() - measuredWidth / 2f).roundToInt(), - (layoutBounds.centerY() - measuredHeight / 2f).roundToInt(), - (layoutBounds.centerX() + measuredWidth / 2f).roundToInt(), - (layoutBounds.centerY() + measuredHeight / 2f).roundToInt(), + bounds.left.roundToInt(), + bounds.top.roundToInt(), + bounds.right.roundToInt(), + bounds.bottom.roundToInt(), ) updateChildFrames(isLayout = false) + onViewBoundsChanged?.let { it(bounds) } } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { 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 015a82707ea2..5aea88de061c 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 @@ -117,6 +117,7 @@ open class SimpleDigitalClockTextView( fidgetFontVariation = buildFidgetVariation(lsFontAxes).toFVar() } + var onViewBoundsChanged: ((RectF) -> Unit)? = null private val parser = DimensionParser(clockCtx.context) var maxSingleDigitHeight = -1f var maxSingleDigitWidth = -1f @@ -497,6 +498,7 @@ open class SimpleDigitalClockTextView( targetRect.right.roundToInt(), targetRect.bottom.roundToInt(), ) + onViewBoundsChanged?.let { it(targetRect) } return targetRect } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt index 4d027088ca1a..5249bbe2a861 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt @@ -26,7 +26,10 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.airbnb.lottie.LottieAnimationView import com.android.systemui.SysuiTestCase +import com.android.systemui.biometrics.data.repository.biometricStatusRepository import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository +import com.android.systemui.biometrics.shared.model.AuthenticationReason +import com.android.systemui.biometrics.shared.model.AuthenticationReason.SettingsOperations import com.android.systemui.biometrics.shared.model.DisplayRotation import com.android.systemui.biometrics.shared.model.FingerprintSensorType import com.android.systemui.biometrics.shared.model.SensorStrength @@ -50,7 +53,6 @@ import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito.any import org.mockito.Mockito.inOrder -import org.mockito.Mockito.mock import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.Mockito.`when` @@ -67,6 +69,7 @@ class SideFpsOverlayViewBinderTest : SysuiTestCase() { @JvmField @Rule var mockitoRule: MockitoRule = MockitoJUnit.rule() @Mock private lateinit var layoutInflater: LayoutInflater @Mock private lateinit var sideFpsView: View + @Mock private lateinit var lottieAnimationView: LottieAnimationView @Captor private lateinit var viewCaptor: ArgumentCaptor<View> @Before @@ -76,7 +79,7 @@ class SideFpsOverlayViewBinderTest : SysuiTestCase() { context.addMockSystemService(WindowManager::class.java, kosmos.windowManager) `when`(layoutInflater.inflate(R.layout.sidefps_view, null, false)).thenReturn(sideFpsView) `when`(sideFpsView.requireViewById<LottieAnimationView>(eq(R.id.sidefps_animation))) - .thenReturn(mock(LottieAnimationView::class.java)) + .thenReturn(lottieAnimationView) } @Test @@ -184,6 +187,20 @@ class SideFpsOverlayViewBinderTest : SysuiTestCase() { } } + @Test + fun verifyToggleAnimation_onSideFpsIndicatorViewClickedWhileEnrolling() { + kosmos.testScope.runTest { + kosmos.biometricStatusRepository.setFingerprintAuthenticationReason( + AuthenticationReason.SettingsAuthentication(SettingsOperations.ENROLL_ENROLLING) + ) + setupTestConfiguration(isInRearDisplayMode = false) + val clickListenerCaptor = ArgumentCaptor.forClass(View.OnClickListener::class.java) + verify(sideFpsView).setOnClickListener(clickListenerCaptor.capture()) + clickListenerCaptor.value.onClick(sideFpsView) + verify(lottieAnimationView).toggleAnimation() + } + } + private suspend fun TestScope.setupTestConfiguration(isInRearDisplayMode: Boolean) { kosmos.fingerprintPropertyRepository.setProperties( sensorId = 1, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt index dd4af7bb780e..53ddcfaf9576 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt @@ -20,6 +20,7 @@ import android.content.testableContext import android.provider.Settings.Global.ONE_HANDED_KEYGUARD_SIDE import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest +import com.android.compose.animation.scene.ObservableTransitionState import com.android.internal.logging.uiEventLoggerFake import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository @@ -39,13 +40,22 @@ import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.flags.Flags.FULL_SCREEN_USER_SWITCHER import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository +import com.android.systemui.kosmos.collectLastValue +import com.android.systemui.kosmos.runCurrent +import com.android.systemui.kosmos.runTest import com.android.systemui.kosmos.testScope import com.android.systemui.power.data.repository.fakePowerRepository import com.android.systemui.res.R +import com.android.systemui.scene.data.repository.sceneContainerRepository +import com.android.systemui.scene.shared.model.Overlays +import com.android.systemui.scene.shared.model.Scenes +import com.android.systemui.scene.transitionState import com.android.systemui.testKosmos import com.android.systemui.util.settings.fakeGlobalSettings import com.google.common.truth.Truth.assertThat import kotlin.time.Duration.Companion.seconds +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest @@ -368,6 +378,76 @@ class BouncerInteractorTest : SysuiTestCase() { testableResources.removeOverride(R.bool.can_use_one_handed_bouncer) } + @Test + fun bouncerExpansion_lockscreenToBouncer() = + kosmos.runTest { + val bouncerExpansion by collectLastValue(underTest.bouncerExpansion) + + val progress = MutableStateFlow(0f) + kosmos.sceneContainerRepository.setTransitionState(transitionState) + transitionState.value = + ObservableTransitionState.Transition.showOverlay( + overlay = Overlays.Bouncer, + fromScene = Scenes.Lockscreen, + currentOverlays = flowOf(emptySet()), + progress = progress, + isInitiatedByUserInput = false, + isUserInputOngoing = flowOf(false), + ) + + assertThat(bouncerExpansion).isEqualTo(0f) + + progress.value = 1f + assertThat(bouncerExpansion).isEqualTo(1f) + } + + @Test + fun bouncerExpansion_BouncerToLockscreen() = + kosmos.runTest { + val bouncerExpansion by collectLastValue(underTest.bouncerExpansion) + + val progress = MutableStateFlow(0f) + kosmos.sceneContainerRepository.setTransitionState(transitionState) + transitionState.value = + ObservableTransitionState.Transition.hideOverlay( + overlay = Overlays.Bouncer, + toScene = Scenes.Lockscreen, + currentOverlays = flowOf(emptySet()), + progress = progress, + isInitiatedByUserInput = false, + isUserInputOngoing = flowOf(false), + ) + + assertThat(bouncerExpansion).isEqualTo(1f) + + progress.value = 1f + assertThat(bouncerExpansion).isEqualTo(0f) + } + + @Test + fun bouncerExpansion_shadeToLockscreenUnderBouncer() = + kosmos.runTest { + val bouncerExpansion by collectLastValue(underTest.bouncerExpansion) + + val progress = MutableStateFlow(0f) + kosmos.sceneContainerRepository.setTransitionState(transitionState) + transitionState.value = + ObservableTransitionState.Transition( + fromScene = Scenes.Shade, + toScene = Scenes.Lockscreen, + currentScene = flowOf(Scenes.Lockscreen), + progress = progress, + isInitiatedByUserInput = false, + isUserInputOngoing = flowOf(false), + currentOverlays = setOf(Overlays.Bouncer), + ) + + assertThat(bouncerExpansion).isEqualTo(1f) + + progress.value = 1f + assertThat(bouncerExpansion).isEqualTo(1f) + } + companion object { private const val MESSAGE_ENTER_YOUR_PIN = "Enter your PIN" private const val MESSAGE_ENTER_YOUR_PASSWORD = "Enter your password" diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt index 9eba410ffdb5..4f301031e77c 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt @@ -108,7 +108,7 @@ class DefaultClockProviderTest : SysuiTestCase() { verify(mockSmallClockView).setColors(DOZE_COLOR, Color.MAGENTA) verify(mockLargeClockView).setColors(DOZE_COLOR, Color.MAGENTA) - clock.initialize(true, 0f, 0f) + clock.initialize(true, 0f, 0f, {}) val expectedColor = 0 verify(mockSmallClockView).setColors(DOZE_COLOR, expectedColor) diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockController.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockController.kt index 32fec3277f18..4c1f6450dd78 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockController.kt +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockController.kt @@ -13,6 +13,7 @@ */ package com.android.systemui.plugins.clocks +import android.graphics.RectF import com.android.systemui.plugins.annotations.ProtectedInterface import com.android.systemui.plugins.annotations.SimpleProperty import java.io.PrintWriter @@ -37,7 +38,12 @@ interface ClockController { val events: ClockEvents /** Initializes various rendering parameters. If never called, provides reasonable defaults. */ - fun initialize(isDarkTheme: Boolean, dozeFraction: Float, foldFraction: Float) + fun initialize( + isDarkTheme: Boolean, + dozeFraction: Float, + foldFraction: Float, + onBoundsChanged: (RectF) -> Unit, + ) /** Optional method for dumping debug information */ fun dump(pw: PrintWriter) diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml index 6d446453d9f7..24fd86076d64 100644 --- a/packages/SystemUI/res-keyguard/values/dimens.xml +++ b/packages/SystemUI/res-keyguard/values/dimens.xml @@ -115,6 +115,7 @@ <dimen name="below_clock_padding_end">16dp</dimen> <dimen name="below_clock_padding_start_icons">28dp</dimen> <dimen name="smartspace_padding_horizontal">16dp</dimen> + <dimen name="smartspace_padding_vertical">12dp</dimen> <!-- Proportion of the screen height to use to set the maximum height of the bouncer to when the device is in the DEVICE_POSTURE_HALF_OPENED posture, for the PIN/pattern entry. 0 will diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt index 1b8282bf9b93..94342349e727 100644 --- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt +++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt @@ -21,6 +21,7 @@ import android.content.Context import android.content.Intent import android.content.IntentFilter import android.content.res.Resources +import android.graphics.RectF import android.os.Trace import android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS import android.provider.Settings.Global.ZEN_MODE_OFF @@ -78,7 +79,7 @@ import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.Job -import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.merge @@ -147,7 +148,7 @@ constructor( val clockStr = clock.toString() loggers.forEach { it.d({ "New Clock: $str1" }) { str1 = clockStr } } - clock.initialize(isDarkTheme(), dozeAmount, 0f) + clock.initialize(isDarkTheme(), dozeAmount.value, 0f, { onClockBoundsChanged.value = it }) if (!regionSamplingEnabled) { updateColors() @@ -240,17 +241,16 @@ constructor( private var smallClockFrame: ViewGroup? = null private var onGlobalLayoutListener: OnGlobalLayoutListener? = null - private var isDozing = false - private set - private var isCharging = false - private var dozeAmount = 0f private var isKeyguardVisible = false private var isRegistered = false private var disposableHandle: DisposableHandle? = null private val regionSamplingEnabled = featureFlags.isEnabled(REGION_SAMPLING) private var largeClockOnSecondaryDisplay = false + val dozeAmount = MutableStateFlow(0f) + val onClockBoundsChanged = MutableStateFlow<RectF?>(null) + private fun isDarkTheme(): Boolean { val isLightTheme = TypedValue() context.theme.resolveAttribute(android.R.attr.isLightTheme, isLightTheme, true) @@ -306,7 +306,7 @@ constructor( var smallTimeListener: TimeListener? = null var largeTimeListener: TimeListener? = null val shouldTimeListenerRun: Boolean - get() = isKeyguardVisible && dozeAmount < DOZE_TICKRATE_THRESHOLD + get() = isKeyguardVisible && dozeAmount.value < DOZE_TICKRATE_THRESHOLD private var weatherData: WeatherData? = null private var zenData: ZenData? = null @@ -466,7 +466,6 @@ constructor( disposableHandle = parent.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) { - listenForDozing(this) if (ModesUi.isEnabled) { listenForDnd(this) } @@ -576,17 +575,17 @@ constructor( } private fun handleDoze(doze: Float) { - dozeAmount = doze clock?.run { Trace.beginSection("$TAG#smallClock.animations.doze") - smallClock.animations.doze(dozeAmount) + smallClock.animations.doze(doze) Trace.endSection() Trace.beginSection("$TAG#largeClock.animations.doze") - largeClock.animations.doze(dozeAmount) + largeClock.animations.doze(doze) Trace.endSection() } smallTimeListener?.update(doze < DOZE_TICKRATE_THRESHOLD) largeTimeListener?.update(doze < DOZE_TICKRATE_THRESHOLD) + dozeAmount.value = doze } @VisibleForTesting @@ -642,18 +641,6 @@ constructor( } } - @VisibleForTesting - internal fun listenForDozing(scope: CoroutineScope): Job { - return scope.launch { - combine(keyguardInteractor.dozeAmount, keyguardInteractor.isDozing) { - localDozeAmount, - localIsDozing -> - localDozeAmount > dozeAmount || localIsDozing - } - .collect { localIsDozing -> isDozing = localIsDozing } - } - } - class TimeListener(val clockFace: ClockFaceController, val executor: DelayableExecutor) { val predrawListener = ViewTreeObserver.OnPreDrawListener { diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt index bbf9a19012a4..30b98a658821 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt @@ -137,6 +137,9 @@ constructor( ) bind(overlayView!!, overlayViewModel, windowManager.get()) overlayView!!.visibility = View.INVISIBLE + overlayView!!.setOnClickListener { v -> + v.requireViewById<LottieAnimationView>(R.id.sidefps_animation).toggleAnimation() + } Log.d(TAG, "show(): adding overlayView $overlayView") windowManager.get().addView(overlayView, overlayViewModel.defaultOverlayViewParams) } @@ -234,3 +237,11 @@ private fun LottieAnimationView.addOverlayDynamicColor(colorCallbacks: List<Lott resumeAnimation() } } + +fun LottieAnimationView.toggleAnimation() { + if (isAnimating) { + pauseAnimation() + } else { + resumeAnimation() + } +} diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt index 75503e8575f0..b26a2c08532e 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt @@ -17,7 +17,9 @@ package com.android.systemui.bouncer.domain.interactor import android.app.StatusBarManager.SESSION_KEYGUARD +import com.android.app.tracing.FlowTracing.traceAsCounter import com.android.app.tracing.coroutines.asyncTraced as async +import com.android.compose.animation.scene.ObservableTransitionState import com.android.compose.animation.scene.SceneKey import com.android.internal.logging.UiEventLogger import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor @@ -38,9 +40,12 @@ import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInt import com.android.systemui.log.SessionTracker import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.scene.domain.interactor.SceneBackInteractor +import com.android.systemui.scene.domain.interactor.SceneInteractor import com.android.systemui.scene.shared.flag.SceneContainerFlag +import com.android.systemui.scene.shared.model.Overlays import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shade.ShadeDisplayAware +import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow @@ -49,7 +54,9 @@ import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map /** Encapsulates business logic and application state accessing use-cases. */ @@ -65,6 +72,7 @@ constructor( private val powerInteractor: PowerInteractor, private val uiEventLogger: UiEventLogger, private val sessionTracker: SessionTracker, + sceneInteractor: SceneInteractor, sceneBackInteractor: SceneBackInteractor, @ShadeDisplayAware private val configurationInteractor: ConfigurationInteractor, ) { @@ -149,6 +157,31 @@ constructor( val dismissDestination: Flow<SceneKey> = sceneBackInteractor.backScene.map { it ?: Scenes.Lockscreen } + /** The amount [0-1] that the Bouncer Overlay has been transitioned to. */ + val bouncerExpansion: Flow<Float> = + if (SceneContainerFlag.isEnabled) { + sceneInteractor.transitionState.flatMapLatestConflated { state -> + when (state) { + is ObservableTransitionState.Idle -> + flowOf(if (Overlays.Bouncer in state.currentOverlays) 1f else 0f) + is ObservableTransitionState.Transition -> + if (state.toContent == Overlays.Bouncer) { + state.progress + } else if (state.fromContent == Overlays.Bouncer) { + state.progress.map { progress -> 1 - progress } + } else { + state.currentOverlays().map { + if (Overlays.Bouncer in it) 1f else 0f + } + } + } + } + } else { + flowOf() + } + .distinctUntilChanged() + .traceAsCounter("bouncer_expansion") { (it * 100f).toInt() } + /** Notifies that the user has places down a pointer, not necessarily dragging just yet. */ fun onDown() { falsingInteractor.avoidGesture() diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt index 63cf4f72e415..ab0efed2cb76 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt @@ -85,7 +85,7 @@ constructor( val previewClock: Flow<ClockController> = keyguardClockRepository.previewClock - val clockEventController: ClockEventController by keyguardClockRepository::clockEventController + val clockEventController: ClockEventController = keyguardClockRepository.clockEventController var clock: ClockController? by keyguardClockRepository.clockEventController::clock diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSmartspaceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSmartspaceViewBinder.kt index def1ac8742da..e81d5354ec6e 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSmartspaceViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSmartspaceViewBinder.kt @@ -81,22 +81,92 @@ object KeyguardSmartspaceViewBinder { } if (com.android.systemui.shared.Flags.clockReactiveSmartspaceLayout()) { + val xBuffer = + keyguardRootView.context.resources.getDimensionPixelSize( + R.dimen.smartspace_padding_horizontal + ) + val yBuffer = + keyguardRootView.context.resources.getDimensionPixelSize( + R.dimen.smartspace_padding_vertical + ) + + val smallViewIds = + listOf(sharedR.id.date_smartspace_view, sharedR.id.weather_smartspace_view) + + val largeViewIds = + listOf( + sharedR.id.date_smartspace_view_large, + sharedR.id.weather_smartspace_view_large, + ) + launch("$TAG#smartspaceViewModel.burnInLayerVisibility") { - keyguardRootViewModel.burnInLayerVisibility.collect { visibility -> - if (clockViewModel.isLargeClockVisible.value) { - // hide small clock date/weather - val dateView = - keyguardRootView.requireViewById<View>( - sharedR.id.date_smartspace_view - ) - dateView.visibility = View.GONE - val weatherView = - keyguardRootView.requireViewById<View>( - sharedR.id.weather_smartspace_view - ) - weatherView.visibility = View.GONE + combine( + keyguardRootViewModel.burnInLayerVisibility, + clockViewModel.isLargeClockVisible, + ::Pair, + ) + .collect { (visibility, isLargeClock) -> + if (isLargeClock) { + // hide small clock date/weather + for (viewId in smallViewIds) { + keyguardRootView.findViewById<View>(viewId)?.let { + it.visibility = View.GONE + } + } + } + } + } + + launch("$TAG#clockEventController.onClockBoundsChanged") { + // Whenever the doze amount changes, the clock may update it's view bounds. + // We need to update our layout position as a result. We could do this via + // `requestLayout`, but that's quite expensive when enclosed in since this + // recomputes the entire ConstraintLayout, so instead we do it manually. We + // would use translationX/Y for this, but that's used by burnin. + combine( + clockViewModel.isLargeClockVisible, + clockViewModel.clockEventController.onClockBoundsChanged, + ::Pair, + ) + .collect { (isLargeClock, clockBounds) -> + for (id in (if (isLargeClock) smallViewIds else largeViewIds)) { + keyguardRootView.findViewById<View>(id)?.let { + it.visibility = View.GONE + } + } + + if (clockBounds == null) return@collect + if (isLargeClock) { + val largeDateHeight = + keyguardRootView + .findViewById<View>( + sharedR.id.date_smartspace_view_large + ) + ?.height ?: 0 + for (id in largeViewIds) { + keyguardRootView.findViewById<View>(id)?.let { view -> + val viewHeight = view.height + val offset = (largeDateHeight - viewHeight) / 2 + view.top = + (clockBounds.bottom + yBuffer + offset).toInt() + view.bottom = view.top + viewHeight + } + } + } else { + for (id in smallViewIds) { + keyguardRootView.findViewById<View>(id)?.let { view -> + val viewWidth = view.width + if (view.isLayoutRtl()) { + view.right = (clockBounds.left - xBuffer).toInt() + view.left = view.right - viewWidth + } else { + view.left = (clockBounds.right + xBuffer).toInt() + view.right = view.left + viewWidth + } + } + } + } } - } } } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt index 37cc852ffe00..d0b5f743c277 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt @@ -226,7 +226,7 @@ constructor( ConstraintSet.TOP, customR.id.lockscreen_clock_view_large, ConstraintSet.BOTTOM, - dateWeatherPaddingStart, + context.resources.getDimensionPixelSize(R.dimen.smartspace_padding_vertical), ) connect( @@ -291,7 +291,9 @@ constructor( ConstraintSet.START, customR.id.lockscreen_clock_view, ConstraintSet.END, - 20, + context.resources.getDimensionPixelSize( + R.dimen.smartspace_padding_horizontal + ), ) connect( sharedR.id.date_smartspace_view, diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt index cf5cc264be8d..dcbf7b5a9335 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt @@ -19,6 +19,7 @@ package com.android.systemui.keyguard.ui.viewmodel import android.content.Context import android.content.res.Resources import androidx.constraintlayout.helper.widget.Layer +import com.android.keyguard.ClockEventController import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.customization.R as customR import com.android.systemui.dagger.SysUISingleton @@ -68,6 +69,7 @@ constructor( initialValue = true, ) + val clockEventController: ClockEventController = keyguardClockInteractor.clockEventController val currentClock = keyguardClockInteractor.currentClock val hasCustomWeatherDataDisplay = diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt index 246177e0c46d..81146852aefc 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt @@ -334,7 +334,7 @@ constructor( } else if (state.fromContent == overlay) { state.progress.map { progress -> 1 - progress } } else { - flowOf(0f) + state.currentOverlays().map { if (overlay in it) 1f else 0f } } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 4390f1b16ffd..1a17b8efb4ae 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -1226,6 +1226,14 @@ public class NotificationStackScrollLayout } @Override + public void setOccluded(boolean isOccluded) { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) { + return; + } + this.setVisibility(isOccluded ? View.INVISIBLE : View.VISIBLE); + } + + @Override public void setScrollState(@NonNull ShadeScrollState scrollState) { if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) { return; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt index a7305f7f27ab..9c855e9cd9b7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt @@ -49,6 +49,9 @@ interface NotificationScrollView { /** Max alpha for this view */ fun setMaxAlpha(alpha: Float) + /** Set whether this view is occluded by something else. */ + fun setOccluded(isOccluded: Boolean) + /** Sets a clipping shape, which defines the drawable area of this view. */ fun setClippingShape(shape: ShadeScrimShape?) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt index a4e39cbd8388..653344ae9203 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt @@ -86,6 +86,8 @@ constructor( .collectTraced { view.setClippingShape(it) } } + launch { viewModel.isOccluded.collectTraced { view.setOccluded(it) } } + launch { viewModel.maxAlpha.collectTraced { view.setMaxAlpha(it) } } launch { viewModel.shadeScrollState.collect { view.setScrollState(it) } } launch { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt index 1dbaf2f0f401..a277597e23df 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt @@ -24,7 +24,9 @@ import com.android.compose.animation.scene.ObservableTransitionState import com.android.compose.animation.scene.ObservableTransitionState.Idle import com.android.compose.animation.scene.ObservableTransitionState.Transition import com.android.compose.animation.scene.ObservableTransitionState.Transition.ChangeScene +import com.android.compose.animation.scene.OverlayKey import com.android.compose.animation.scene.SceneKey +import com.android.systemui.bouncer.domain.interactor.BouncerInteractor import com.android.systemui.dump.DumpManager import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.lifecycle.ExclusiveActivatable @@ -70,6 +72,7 @@ constructor( private val stackAppearanceInteractor: NotificationStackAppearanceInteractor, shadeInteractor: ShadeInteractor, shadeModeInteractor: ShadeModeInteractor, + bouncerInteractor: BouncerInteractor, private val remoteInputInteractor: RemoteInputInteractor, private val sceneInteractor: SceneInteractor, // TODO(b/336364825) Remove Lazy when SceneContainerFlag is released - @@ -131,12 +134,15 @@ constructor( private fun expandFractionDuringOverlayTransition( transition: Transition, currentScene: SceneKey, + currentOverlays: Set<OverlayKey>, shadeExpansion: Float, ): Float { return if (currentScene == Scenes.Lockscreen) { 1f } else if (transition.isTransitioningFromOrTo(Overlays.NotificationsShade)) { shadeExpansion + } else if (Overlays.NotificationsShade in currentOverlays) { + 1f } else { 0f } @@ -161,12 +167,13 @@ constructor( shadeInteractor.qsExpansion, shadeModeInteractor.shadeMode, sceneInteractor.transitionState, - ) { shadeExpansion, qsExpansion, _, transitionState -> + sceneInteractor.currentOverlays, + ) { shadeExpansion, qsExpansion, _, transitionState, currentOverlays -> when (transitionState) { is Idle -> if ( expandedInScene(transitionState.currentScene) || - Overlays.NotificationsShade in transitionState.currentOverlays + Overlays.NotificationsShade in currentOverlays ) { 1f } else { @@ -182,12 +189,14 @@ constructor( expandFractionDuringOverlayTransition( transition = transitionState, currentScene = transitionState.currentScene, + currentOverlays = currentOverlays, shadeExpansion = shadeExpansion, ) is Transition.ReplaceOverlay -> expandFractionDuringOverlayTransition( transition = transitionState, currentScene = transitionState.currentScene, + currentOverlays = currentOverlays, shadeExpansion = shadeExpansion, ) } @@ -198,6 +207,12 @@ constructor( val qsExpandFraction: Flow<Float> = shadeInteractor.qsExpansion.dumpWhileCollecting("qsExpandFraction") + val isOccluded: Flow<Boolean> = + bouncerInteractor.bouncerExpansion + .map { it == 1f } + .distinctUntilChanged() + .dumpWhileCollecting("isOccluded") + /** Blur radius to be applied to Notifications. */ fun blurRadius(maxBlurRadius: Flow<Int>) = combine(blurFraction, maxBlurRadius) { fraction, maxRadius -> fraction * maxRadius } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt index 33cc62c9a75a..9d55e1d9d592 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt @@ -21,6 +21,7 @@ import android.content.Context import androidx.annotation.VisibleForTesting import com.android.app.tracing.coroutines.flow.flowName import com.android.systemui.Flags.glanceableHubV2 +import com.android.systemui.bouncer.domain.interactor.BouncerInteractor import com.android.systemui.common.shared.model.NotificationContainerBounds import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor @@ -106,7 +107,6 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combineTransform import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.emptyFlow -import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flatMapLatest @@ -132,6 +132,7 @@ constructor( private val keyguardInteractor: KeyguardInteractor, private val keyguardTransitionInteractor: KeyguardTransitionInteractor, private val shadeInteractor: ShadeInteractor, + private val bouncerInteractor: BouncerInteractor, shadeModeInteractor: ShadeModeInteractor, notificationStackAppearanceInteractor: NotificationStackAppearanceInteractor, private val alternateBouncerToGoneTransitionViewModel: @@ -516,8 +517,13 @@ constructor( combineTransform( shadeInteractor.shadeExpansion, shadeInteractor.qsExpansion, - ) { shadeExpansion, qsExpansion -> - if (qsExpansion == 1f) { + bouncerInteractor.bouncerExpansion, + ) { shadeExpansion, qsExpansion, bouncerExpansion -> + if (bouncerExpansion == 1f) { + emit(0f) + } else if (bouncerExpansion > 0f) { + emit(1 - bouncerExpansion) + } else if (qsExpansion == 1f) { // Ensure HUNs will be visible in QS shade (at least while // unlocked) emit(1f) @@ -526,19 +532,36 @@ constructor( emit(1f - qsExpansion) } } - Split -> isAnyExpanded.filter { it }.map { 1f } + Split -> + combineTransform(isAnyExpanded, bouncerInteractor.bouncerExpansion) { + isAnyExpanded, + bouncerExpansion -> + if (bouncerExpansion == 1f) { + emit(0f) + } else if (bouncerExpansion > 0f) { + emit(1 - bouncerExpansion) + } else if (isAnyExpanded) { + emit(1f) + } + } Dual -> combineTransform( shadeModeInteractor.isShadeLayoutWide, headsUpNotificationInteractor.get().isHeadsUpOrAnimatingAway, shadeInteractor.shadeExpansion, shadeInteractor.qsExpansion, + bouncerInteractor.bouncerExpansion, ) { isShadeLayoutWide, isHeadsUpOrAnimatingAway, shadeExpansion, - qsExpansion -> - if (isShadeLayoutWide) { + qsExpansion, + bouncerExpansion -> + if (bouncerExpansion == 1f) { + emit(0f) + } else if (bouncerExpansion > 0f) { + emit(1 - bouncerExpansion) + } else if (isShadeLayoutWide) { if (shadeExpansion > 0f) { emit(1f) } diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/GradientColorWallpaper.kt b/packages/SystemUI/src/com/android/systemui/wallpapers/GradientColorWallpaper.kt index 33e1929ebf8b..952d40ed63eb 100644 --- a/packages/SystemUI/src/com/android/systemui/wallpapers/GradientColorWallpaper.kt +++ b/packages/SystemUI/src/com/android/systemui/wallpapers/GradientColorWallpaper.kt @@ -17,8 +17,13 @@ package com.android.systemui.wallpapers import android.app.Flags +import android.content.res.Configuration.UI_MODE_NIGHT_MASK +import android.content.res.Configuration.UI_MODE_NIGHT_YES import android.graphics.Canvas +import android.graphics.Color import android.graphics.Paint +import android.graphics.PorterDuff +import android.graphics.PorterDuffXfermode import android.graphics.RadialGradient import android.graphics.Shader import android.service.wallpaper.WallpaperService @@ -74,9 +79,9 @@ class GradientColorWallpaper : WallpaperService() { .toFloat() val totalHeight = destRectF.height() + (offsetPx * 2) val leftCenterX = -offsetPx - val leftCenterY = -offsetPx + val leftCenterY = totalHeight - offsetPx val rightCenterX = offsetPx + destRectF.width() - val rightCenterY = totalHeight - offsetPx + val rightCenterY = -offsetPx val radius = (destRectF.width() / 2) + offsetPx canvas.drawCircle( @@ -112,6 +117,28 @@ class GradientColorWallpaper : WallpaperService() { ) }, ) + + val isDarkMode = + context.resources.configuration.uiMode and UI_MODE_NIGHT_MASK == + UI_MODE_NIGHT_YES + val maskColor = + ColorUtils.setAlphaComponent( + if (isDarkMode) Color.BLACK else Color.WHITE, + /* alpha= */ 87, // 0.34f * 255 + ) + val maskPaint = + Paint().apply { + xfermode = + PorterDuffXfermode( + if (isDarkMode) { + PorterDuff.Mode.DARKEN + } else { + PorterDuff.Mode.LIGHTEN + } + ) + color = maskColor + } + canvas.drawRect(destRectF, maskPaint) } catch (exception: IllegalStateException) { Log.d(TAG, "Fail to draw in the canvas", exception) } finally { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt index f822ee97807e..f18d73d57f83 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt @@ -194,7 +194,7 @@ class ClockEventControllerTest : SysuiTestCase() { @Test fun clockSet_validateInitialization() { - verify(clock).initialize(any(), anyFloat(), anyFloat()) + verify(clock).initialize(any(), anyFloat(), anyFloat(), any()) } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/GradientColorWallpaperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/GradientColorWallpaperTest.kt index b4fbaad6ab37..5f3442048fcd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/GradientColorWallpaperTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/GradientColorWallpaperTest.kt @@ -18,7 +18,6 @@ package com.android.systemui.wallpapers import android.app.Flags import android.content.Context -import android.content.res.Resources import android.graphics.Canvas import android.graphics.Paint import android.graphics.Rect @@ -43,6 +42,7 @@ import org.mockito.Mock import org.mockito.Mockito.spy import org.mockito.MockitoAnnotations import org.mockito.kotlin.any +import org.mockito.kotlin.doReturn import org.mockito.kotlin.times import org.mockito.kotlin.verify import org.mockito.kotlin.verifyZeroInteractions @@ -61,23 +61,20 @@ class GradientColorWallpaperTest : SysuiTestCase() { @Mock private lateinit var mockContext: Context - @Mock private lateinit var mockResources: Resources - @Before fun setUp() { MockitoAnnotations.initMocks(this) + val spyResources = spy(context.resources) + whenever(surfaceHolder.surface).thenReturn(surface) whenever(surfaceHolder.surfaceFrame).thenReturn(surfaceFrame) whenever(surface.lockHardwareCanvas()).thenReturn(canvas) whenever(mockContext.getColor(anyInt())).thenReturn(1) - whenever(mockContext.resources).thenReturn(mockResources) - whenever( - mockResources.getDimensionPixelOffset( - eq(R.dimen.gradient_color_wallpaper_center_offset) - ) - ) - .thenReturn(OFFSET_PX) + whenever(mockContext.resources).thenReturn(spyResources) + doReturn(OFFSET_PX) + .`when`(spyResources) + .getDimensionPixelOffset(eq(R.dimen.gradient_color_wallpaper_center_offset)) } private fun createGradientColorWallpaperEngine(): Engine { @@ -106,7 +103,8 @@ class GradientColorWallpaperTest : SysuiTestCase() { engine.onSurfaceRedrawNeeded(surfaceHolder) - verify(canvas).drawRect(any<RectF>(), any<Paint>()) + // One rect for the background, one rect for the foreground mask. + verify(canvas, times(2)).drawRect(any<RectF>(), any<Paint>()) verify(canvas, times(2)).drawCircle(anyFloat(), anyFloat(), anyFloat(), any<Paint>()) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorKosmos.kt index d27ecce89937..94d27f73aee7 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorKosmos.kt @@ -28,6 +28,7 @@ import com.android.systemui.kosmos.testScope import com.android.systemui.log.sessionTracker import com.android.systemui.power.domain.interactor.powerInteractor import com.android.systemui.scene.domain.interactor.sceneBackInteractor +import com.android.systemui.scene.domain.interactor.sceneInteractor val Kosmos.bouncerInteractor by Fixture { BouncerInteractor( @@ -39,6 +40,7 @@ val Kosmos.bouncerInteractor by Fixture { powerInteractor = powerInteractor, uiEventLogger = uiEventLogger, sessionTracker = sessionTracker, + sceneInteractor = sceneInteractor, sceneBackInteractor = sceneBackInteractor, configurationInteractor = configurationInteractor, ) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModelKosmos.kt index 167b11da9dba..87ce501b0402 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModelKosmos.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.stack.ui.viewmodel +import com.android.systemui.bouncer.domain.interactor.bouncerInteractor import com.android.systemui.dump.dumpManager import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.kosmos.Kosmos @@ -32,6 +33,7 @@ val Kosmos.notificationScrollViewModel by Fixture { stackAppearanceInteractor = notificationStackAppearanceInteractor, shadeInteractor = shadeInteractor, shadeModeInteractor = shadeModeInteractor, + bouncerInteractor = bouncerInteractor, remoteInputInteractor = remoteInputInteractor, sceneInteractor = sceneInteractor, keyguardInteractor = { keyguardInteractor }, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt index 17ef208fe12e..85fe3d9a44ce 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.stack.ui.viewmodel import android.content.applicationContext +import com.android.systemui.bouncer.domain.interactor.bouncerInteractor import com.android.systemui.common.ui.domain.interactor.configurationInteractor import com.android.systemui.communal.domain.interactor.communalSceneInteractor import com.android.systemui.dump.dumpManager @@ -74,6 +75,7 @@ val Kosmos.sharedNotificationContainerViewModel by Fixture { keyguardInteractor = keyguardInteractor, keyguardTransitionInteractor = keyguardTransitionInteractor, shadeInteractor = shadeInteractor, + bouncerInteractor = bouncerInteractor, shadeModeInteractor = shadeModeInteractor, notificationStackAppearanceInteractor = notificationStackAppearanceInteractor, alternateBouncerToGoneTransitionViewModel = alternateBouncerToGoneTransitionViewModel, diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index 9d4fe9e9765b..39a849a22622 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -32,6 +32,7 @@ import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS; import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT; import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED; import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER; +import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_SIMULATE_REQUESTED_ORIENTATION; import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT; import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE; import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE; @@ -133,6 +134,7 @@ import android.os.Bundle; import android.os.PersistableBundle; import android.os.Process; import android.os.RemoteException; +import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; import android.provider.DeviceConfig; @@ -736,6 +738,8 @@ public class ActivityRecordTests extends WindowTestsBase { } @Test + @EnableFlags(Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) + @DisableFlags(Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING_OPT_OUT) public void testOrientation_dontAllowFixedOrientationForCameraCompatFreeformIfNotEnabled() { final ActivityRecord activity = setupDisplayAndActivityForCameraCompat( /* isCameraRunning= */ true, WINDOWING_MODE_FREEFORM); @@ -749,6 +753,22 @@ public class ActivityRecordTests extends WindowTestsBase { } @Test + @EnableFlags({Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING, + Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING_OPT_OUT}) + @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_DISABLE_SIMULATE_REQUESTED_ORIENTATION}) + public void testOrientation_dontAllowFixedOrientationForCameraCompatFreeformIfOptedOut() { + final ActivityRecord activity = setupDisplayAndActivityForCameraCompat( + /* isCameraRunning= */ true, WINDOWING_MODE_FREEFORM); + + // Task in landscape. + assertEquals(ORIENTATION_LANDSCAPE, activity.getTask().getConfiguration().orientation); + // Activity is not letterboxed. + assertEquals(ORIENTATION_LANDSCAPE, activity.getConfiguration().orientation); + assertFalse(activity.mAppCompatController.getAspectRatioPolicy() + .isLetterboxedForFixedOrientationAndAspectRatio()); + } + + @Test @EnableFlags(Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT}) public void testOrientation_noFixedOrientationForCameraCompatFreeformIfCameraNotRunning() { diff --git a/services/tests/wmtests/src/com/android/server/wm/CameraCompatFreeformPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/CameraCompatFreeformPolicyTests.java index 50876c7a6758..f5bec04a98d5 100644 --- a/services/tests/wmtests/src/com/android/server/wm/CameraCompatFreeformPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/CameraCompatFreeformPolicyTests.java @@ -192,7 +192,8 @@ public class CameraCompatFreeformPolicyTests extends WindowTestsBase { @Test @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) - public void testIsFreeformLetterboxingForCameraAllowed_overrideDisabled_returnsFalse() { + @DisableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING_OPT_OUT) + public void testIsFreeformLetterboxingForCameraAllowed_optInMechanism_notOptedIn_retFalse() { configureActivity(SCREEN_ORIENTATION_PORTRAIT); onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); @@ -201,6 +202,17 @@ public class CameraCompatFreeformPolicyTests extends WindowTestsBase { } @Test + @EnableFlags({FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING, + FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING_OPT_OUT}) + public void testIsFreeformLetterboxingForCameraAllowed_notOptedOut_returnsTrue() { + configureActivity(SCREEN_ORIENTATION_PORTRAIT); + + onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); + + assertTrue(mCameraCompatFreeformPolicy.isFreeformLetterboxingForCameraAllowed(mActivity)); + } + + @Test @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT}) public void testIsFreeformLetterboxingForCameraAllowed_cameraNotRunning_returnsFalse() { @@ -222,6 +234,7 @@ public class CameraCompatFreeformPolicyTests extends WindowTestsBase { @Test @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) + @DisableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING_OPT_OUT) @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT}) public void testIsFreeformLetterboxingForCameraAllowed_optInFreeformCameraRunning_true() { configureActivity(SCREEN_ORIENTATION_PORTRAIT); @@ -346,6 +359,7 @@ public class CameraCompatFreeformPolicyTests extends WindowTestsBase { @Test @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) + @DisableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING_OPT_OUT) public void testShouldApplyCameraCompatFreeformTreatment_overrideNotEnabled_returnsFalse() { configureActivity(SCREEN_ORIENTATION_PORTRAIT); @@ -356,6 +370,18 @@ public class CameraCompatFreeformPolicyTests extends WindowTestsBase { } @Test + @EnableFlags({FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING, + FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING_OPT_OUT}) + public void testShouldApplyCameraCompatFreeformTreatment_notOptedOut_returnsTrue() { + configureActivity(SCREEN_ORIENTATION_PORTRAIT); + + onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); + + assertTrue(mCameraCompatFreeformPolicy.isTreatmentEnabledForActivity(mActivity, + /* checkOrientation */ true)); + } + + @Test @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) @EnableCompatChanges(OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT) public void testShouldApplyCameraCompatFreeformTreatment_enabledByOverride_returnsTrue() { diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java index a97f9a837bab..3cccbc419425 100644 --- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java +++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java @@ -41,6 +41,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.junit.Assume.assumeTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; @@ -1088,6 +1089,10 @@ public class VcnManagementServiceTest { @Test public void testGetRestrictedTransportsFromCarrierConfig() { + assumeTrue( + "Configuring restricted transport types is only allowed on a debuggable build", + Build.isDebuggable()); + final Set<Integer> restrictedTransports = new ArraySet<>(); restrictedTransports.add(TRANSPORT_CELLULAR); restrictedTransports.add(TRANSPORT_WIFI); @@ -1109,6 +1114,10 @@ public class VcnManagementServiceTest { @Test public void testGetRestrictedTransportsFromCarrierConfig_noRestrictPolicyConfigured() { + assumeTrue( + "Configuring restricted transport types is only allowed on a debuggable build", + Build.isDebuggable()); + final Set<Integer> restrictedTransports = Collections.singleton(TRANSPORT_WIFI); final PersistableBundleWrapper carrierConfig = @@ -1123,6 +1132,10 @@ public class VcnManagementServiceTest { @Test public void testGetRestrictedTransportsFromCarrierConfig_noCarrierConfig() { + assumeTrue( + "Configuring restricted transport types is only allowed on a debuggable build", + Build.isDebuggable()); + final Set<Integer> restrictedTransports = Collections.singleton(TRANSPORT_WIFI); final TelephonySubscriptionSnapshot lastSnapshot = @@ -1134,6 +1147,10 @@ public class VcnManagementServiceTest { @Test public void testGetRestrictedTransportsFromCarrierConfigAndVcnConfig() { + assumeTrue( + "Configuring restricted transport types is only allowed on a debuggable build", + Build.isDebuggable()); + // Configure restricted transport in CarrierConfig final Set<Integer> restrictedTransportInCarrierConfig = Collections.singleton(TRANSPORT_WIFI); |