[go: nahoru, domu]

Copy tiles-material library to protolayout-material

This CL purely copies tiles-material without new API
changes
(https://android.git.corp.google.com/platform/frameworks/support/+/refs/heads/androidx-main/wear/tiles/tiles-material/api/current.txt)

New APIs will be added in a follow up CLs to avoid introducing
many new changes at once.

Note that remaining Tiles references from Javadocs will be update in a
follow up, to minimize changes here.

Bug: 268312818
Test: Copied from tiles-material in child CL
Relnote: "ProtoLayout Material has been added with the same functionalities as Tiles Material."
Change-Id: Ib5e1c673a692aee8c27bd78c74bfcb651ba0393d
diff --git a/wear/protolayout/protolayout-material/api/current.txt b/wear/protolayout/protolayout-material/api/current.txt
index e6f50d0..862495c3 100644
--- a/wear/protolayout/protolayout-material/api/current.txt
+++ b/wear/protolayout/protolayout-material/api/current.txt
@@ -1 +1,298 @@
 // Signature format: 4.0
+package androidx.wear.protolayout.material {
+
+  public class Button implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.Button? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ButtonColors getButtonColors();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable getClickable();
+    method public CharSequence? getContentDescription();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getCustomContent();
+    method public String? getIconContent();
+    method public String? getImageContent();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension getSize();
+    method public String? getTextContent();
+  }
+
+  public static final class Button.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public Button.Builder(android.content.Context, androidx.wear.protolayout.ModifiersBuilders.Clickable);
+    method public androidx.wear.protolayout.material.Button build();
+    method public androidx.wear.protolayout.material.Button.Builder setButtonColors(androidx.wear.protolayout.material.ButtonColors);
+    method public androidx.wear.protolayout.material.Button.Builder setContentDescription(CharSequence);
+    method public androidx.wear.protolayout.material.Button.Builder setCustomContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.Button.Builder setIconContent(String, androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public androidx.wear.protolayout.material.Button.Builder setIconContent(String);
+    method public androidx.wear.protolayout.material.Button.Builder setImageContent(String);
+    method public androidx.wear.protolayout.material.Button.Builder setSize(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public androidx.wear.protolayout.material.Button.Builder setSize(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.material.Button.Builder setTextContent(String);
+    method public androidx.wear.protolayout.material.Button.Builder setTextContent(String, int);
+  }
+
+  public class ButtonColors {
+    ctor public ButtonColors(@ColorInt int, @ColorInt int);
+    ctor public ButtonColors(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getBackgroundColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getContentColor();
+    method public static androidx.wear.protolayout.material.ButtonColors primaryButtonColors(androidx.wear.protolayout.material.Colors);
+    method public static androidx.wear.protolayout.material.ButtonColors secondaryButtonColors(androidx.wear.protolayout.material.Colors);
+  }
+
+  public class ButtonDefaults {
+    method public static androidx.wear.protolayout.DimensionBuilders.DpProp recommendedIconSize(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public static androidx.wear.protolayout.DimensionBuilders.DpProp recommendedIconSize(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp DEFAULT_SIZE;
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp EXTRA_LARGE_SIZE;
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp LARGE_SIZE;
+    field public static final androidx.wear.protolayout.material.ButtonColors PRIMARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ButtonColors SECONDARY_COLORS;
+  }
+
+  public class Chip implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.Chip? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ChipColors getChipColors();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable getClickable();
+    method public CharSequence? getContentDescription();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getCustomContent();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension getHeight();
+    method public int getHorizontalAlignment();
+    method public String? getIconContent();
+    method public String? getPrimaryLabelContent();
+    method public String? getSecondaryLabelContent();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension getWidth();
+  }
+
+  public static final class Chip.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public Chip.Builder(android.content.Context, androidx.wear.protolayout.ModifiersBuilders.Clickable, androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.Chip build();
+    method public androidx.wear.protolayout.material.Chip.Builder setChipColors(androidx.wear.protolayout.material.ChipColors);
+    method public androidx.wear.protolayout.material.Chip.Builder setContentDescription(CharSequence);
+    method public androidx.wear.protolayout.material.Chip.Builder setCustomContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.Chip.Builder setHorizontalAlignment(int);
+    method public androidx.wear.protolayout.material.Chip.Builder setIconContent(String);
+    method public androidx.wear.protolayout.material.Chip.Builder setPrimaryLabelContent(String);
+    method public androidx.wear.protolayout.material.Chip.Builder setSecondaryLabelContent(String);
+    method public androidx.wear.protolayout.material.Chip.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.ContainerDimension);
+    method public androidx.wear.protolayout.material.Chip.Builder setWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  public class ChipColors {
+    ctor public ChipColors(@ColorInt int, @ColorInt int, @ColorInt int, @ColorInt int);
+    ctor public ChipColors(@ColorInt int, @ColorInt int);
+    ctor public ChipColors(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    ctor public ChipColors(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getBackgroundColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getContentColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getIconColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getSecondaryContentColor();
+    method public static androidx.wear.protolayout.material.ChipColors primaryChipColors(androidx.wear.protolayout.material.Colors);
+    method public static androidx.wear.protolayout.material.ChipColors secondaryChipColors(androidx.wear.protolayout.material.Colors);
+  }
+
+  public class ChipDefaults {
+    field public static final androidx.wear.protolayout.material.ChipColors COMPACT_PRIMARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors COMPACT_SECONDARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors PRIMARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors SECONDARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors TITLE_PRIMARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors TITLE_SECONDARY_COLORS;
+  }
+
+  public class CircularProgressIndicator implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.CircularProgressIndicator? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ProgressIndicatorColors getCircularProgressIndicatorColors();
+    method public CharSequence? getContentDescription();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp getEndAngle();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp getProgress();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp getStartAngle();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp getStrokeWidth();
+  }
+
+  public static final class CircularProgressIndicator.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public CircularProgressIndicator.Builder();
+    method public androidx.wear.protolayout.material.CircularProgressIndicator build();
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setCircularProgressIndicatorColors(androidx.wear.protolayout.material.ProgressIndicatorColors);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setContentDescription(CharSequence);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setEndAngle(float);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setProgress(@FloatRange(from=0, to=1) float);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setStartAngle(float);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setStrokeWidth(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setStrokeWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  public class Colors {
+    ctor public Colors(@ColorInt int, @ColorInt int, @ColorInt int, @ColorInt int);
+    method @ColorInt public int getOnPrimary();
+    method @ColorInt public int getOnSurface();
+    method @ColorInt public int getPrimary();
+    method @ColorInt public int getSurface();
+    field public static final androidx.wear.protolayout.material.Colors DEFAULT;
+  }
+
+  public class CompactChip implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.CompactChip? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ChipColors getChipColors();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable getClickable();
+    method public String getText();
+  }
+
+  public static final class CompactChip.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public CompactChip.Builder(android.content.Context, String, androidx.wear.protolayout.ModifiersBuilders.Clickable, androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.CompactChip build();
+    method public androidx.wear.protolayout.material.CompactChip.Builder setChipColors(androidx.wear.protolayout.material.ChipColors);
+  }
+
+  public class ProgressIndicatorColors {
+    ctor public ProgressIndicatorColors(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    ctor public ProgressIndicatorColors(@ColorInt int, @ColorInt int);
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getIndicatorColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getTrackColor();
+    method public static androidx.wear.protolayout.material.ProgressIndicatorColors progressIndicatorColors(androidx.wear.protolayout.material.Colors);
+  }
+
+  public class ProgressIndicatorDefaults {
+    field public static final androidx.wear.protolayout.material.ProgressIndicatorColors DEFAULT_COLORS;
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp DEFAULT_STROKE_WIDTH;
+    field public static final float GAP_END_ANGLE = 156.1f;
+    field public static final float GAP_START_ANGLE = -156.1f;
+  }
+
+  public class Text implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.Text? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getColor();
+    method public androidx.wear.protolayout.LayoutElementBuilders.FontStyle getFontStyle();
+    method public float getLineHeight();
+    method public int getMaxLines();
+    method public androidx.wear.protolayout.ModifiersBuilders.Modifiers getModifiers();
+    method public int getMultilineAlignment();
+    method public int getOverflow();
+    method public String getText();
+    method public int getWeight();
+    method public boolean isItalic();
+    method public boolean isUnderline();
+  }
+
+  public static final class Text.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public Text.Builder(android.content.Context, String);
+    method public androidx.wear.protolayout.material.Text build();
+    method public androidx.wear.protolayout.material.Text.Builder setColor(androidx.wear.protolayout.ColorBuilders.ColorProp);
+    method public androidx.wear.protolayout.material.Text.Builder setItalic(boolean);
+    method public androidx.wear.protolayout.material.Text.Builder setMaxLines(@IntRange(from=1) int);
+    method public androidx.wear.protolayout.material.Text.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.Modifiers);
+    method public androidx.wear.protolayout.material.Text.Builder setMultilineAlignment(int);
+    method public androidx.wear.protolayout.material.Text.Builder setOverflow(int);
+    method public androidx.wear.protolayout.material.Text.Builder setTypography(int);
+    method public androidx.wear.protolayout.material.Text.Builder setUnderline(boolean);
+    method public androidx.wear.protolayout.material.Text.Builder setWeight(int);
+  }
+
+  public class TitleChip implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.TitleChip? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ChipColors getChipColors();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable getClickable();
+    method public int getHorizontalAlignment();
+    method public String getText();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension getWidth();
+  }
+
+  public static final class TitleChip.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public TitleChip.Builder(android.content.Context, String, androidx.wear.protolayout.ModifiersBuilders.Clickable, androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.TitleChip build();
+    method public androidx.wear.protolayout.material.TitleChip.Builder setChipColors(androidx.wear.protolayout.material.ChipColors);
+    method public androidx.wear.protolayout.material.TitleChip.Builder setHorizontalAlignment(int);
+    method public androidx.wear.protolayout.material.TitleChip.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.ContainerDimension);
+    method public androidx.wear.protolayout.material.TitleChip.Builder setWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  public class Typography {
+    field public static final int TYPOGRAPHY_BODY1 = 7; // 0x7
+    field public static final int TYPOGRAPHY_BODY2 = 8; // 0x8
+    field public static final int TYPOGRAPHY_BUTTON = 9; // 0x9
+    field public static final int TYPOGRAPHY_CAPTION1 = 10; // 0xa
+    field public static final int TYPOGRAPHY_CAPTION2 = 11; // 0xb
+    field public static final int TYPOGRAPHY_CAPTION3 = 12; // 0xc
+    field public static final int TYPOGRAPHY_DISPLAY1 = 1; // 0x1
+    field public static final int TYPOGRAPHY_DISPLAY2 = 2; // 0x2
+    field public static final int TYPOGRAPHY_DISPLAY3 = 3; // 0x3
+    field public static final int TYPOGRAPHY_TITLE1 = 4; // 0x4
+    field public static final int TYPOGRAPHY_TITLE2 = 5; // 0x5
+    field public static final int TYPOGRAPHY_TITLE3 = 6; // 0x6
+  }
+
+}
+
+package androidx.wear.protolayout.material.layouts {
+
+  public class EdgeContentLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.layouts.EdgeContentLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getEdgeContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
+  }
+
+  public static final class EdgeContentLayout.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public EdgeContentLayout.Builder(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout build();
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setEdgeContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setPrimaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setSecondaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+  }
+
+  public class LayoutDefaults {
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp DEFAULT_VERTICAL_SPACER_HEIGHT;
+    field public static final float EDGE_CONTENT_LAYOUT_PADDING_ABOVE_MAIN_CONTENT_DP = 6.0f;
+    field public static final float EDGE_CONTENT_LAYOUT_PADDING_BELOW_MAIN_CONTENT_DP = 8.0f;
+    field public static final int MULTI_BUTTON_MAX_NUMBER = 7; // 0x7
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp MULTI_SLOT_LAYOUT_HORIZONTAL_SPACER_WIDTH;
+  }
+
+  public class MultiButtonLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.layouts.MultiButtonLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public java.util.List<androidx.wear.protolayout.LayoutElementBuilders.LayoutElement!> getButtonContents();
+    method public int getFiveButtonDistribution();
+    field public static final int FIVE_BUTTON_DISTRIBUTION_BOTTOM_HEAVY = 2; // 0x2
+    field public static final int FIVE_BUTTON_DISTRIBUTION_TOP_HEAVY = 1; // 0x1
+  }
+
+  public static final class MultiButtonLayout.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public MultiButtonLayout.Builder();
+    method public androidx.wear.protolayout.material.layouts.MultiButtonLayout.Builder addButtonContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.MultiButtonLayout build();
+    method public androidx.wear.protolayout.material.layouts.MultiButtonLayout.Builder setFiveButtonDistribution(int);
+  }
+
+  public class MultiSlotLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.layouts.MultiSlotLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getHorizontalSpacerWidth();
+    method public java.util.List<androidx.wear.protolayout.LayoutElementBuilders.LayoutElement!> getSlotContents();
+  }
+
+  public static final class MultiSlotLayout.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public MultiSlotLayout.Builder();
+    method public androidx.wear.protolayout.material.layouts.MultiSlotLayout.Builder addSlotContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.MultiSlotLayout build();
+    method public androidx.wear.protolayout.material.layouts.MultiSlotLayout.Builder setHorizontalSpacerWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  public class PrimaryLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.layouts.PrimaryLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryChipContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getVerticalSpacerHeight();
+  }
+
+  public static final class PrimaryLayout.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public PrimaryLayout.Builder(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout build();
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setPrimaryChipContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setPrimaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setSecondaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setVerticalSpacerHeight(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+}
+
diff --git a/wear/protolayout/protolayout-material/api/public_plus_experimental_current.txt b/wear/protolayout/protolayout-material/api/public_plus_experimental_current.txt
index e6f50d0..862495c3 100644
--- a/wear/protolayout/protolayout-material/api/public_plus_experimental_current.txt
+++ b/wear/protolayout/protolayout-material/api/public_plus_experimental_current.txt
@@ -1 +1,298 @@
 // Signature format: 4.0
+package androidx.wear.protolayout.material {
+
+  public class Button implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.Button? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ButtonColors getButtonColors();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable getClickable();
+    method public CharSequence? getContentDescription();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getCustomContent();
+    method public String? getIconContent();
+    method public String? getImageContent();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension getSize();
+    method public String? getTextContent();
+  }
+
+  public static final class Button.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public Button.Builder(android.content.Context, androidx.wear.protolayout.ModifiersBuilders.Clickable);
+    method public androidx.wear.protolayout.material.Button build();
+    method public androidx.wear.protolayout.material.Button.Builder setButtonColors(androidx.wear.protolayout.material.ButtonColors);
+    method public androidx.wear.protolayout.material.Button.Builder setContentDescription(CharSequence);
+    method public androidx.wear.protolayout.material.Button.Builder setCustomContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.Button.Builder setIconContent(String, androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public androidx.wear.protolayout.material.Button.Builder setIconContent(String);
+    method public androidx.wear.protolayout.material.Button.Builder setImageContent(String);
+    method public androidx.wear.protolayout.material.Button.Builder setSize(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public androidx.wear.protolayout.material.Button.Builder setSize(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.material.Button.Builder setTextContent(String);
+    method public androidx.wear.protolayout.material.Button.Builder setTextContent(String, int);
+  }
+
+  public class ButtonColors {
+    ctor public ButtonColors(@ColorInt int, @ColorInt int);
+    ctor public ButtonColors(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getBackgroundColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getContentColor();
+    method public static androidx.wear.protolayout.material.ButtonColors primaryButtonColors(androidx.wear.protolayout.material.Colors);
+    method public static androidx.wear.protolayout.material.ButtonColors secondaryButtonColors(androidx.wear.protolayout.material.Colors);
+  }
+
+  public class ButtonDefaults {
+    method public static androidx.wear.protolayout.DimensionBuilders.DpProp recommendedIconSize(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public static androidx.wear.protolayout.DimensionBuilders.DpProp recommendedIconSize(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp DEFAULT_SIZE;
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp EXTRA_LARGE_SIZE;
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp LARGE_SIZE;
+    field public static final androidx.wear.protolayout.material.ButtonColors PRIMARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ButtonColors SECONDARY_COLORS;
+  }
+
+  public class Chip implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.Chip? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ChipColors getChipColors();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable getClickable();
+    method public CharSequence? getContentDescription();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getCustomContent();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension getHeight();
+    method public int getHorizontalAlignment();
+    method public String? getIconContent();
+    method public String? getPrimaryLabelContent();
+    method public String? getSecondaryLabelContent();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension getWidth();
+  }
+
+  public static final class Chip.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public Chip.Builder(android.content.Context, androidx.wear.protolayout.ModifiersBuilders.Clickable, androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.Chip build();
+    method public androidx.wear.protolayout.material.Chip.Builder setChipColors(androidx.wear.protolayout.material.ChipColors);
+    method public androidx.wear.protolayout.material.Chip.Builder setContentDescription(CharSequence);
+    method public androidx.wear.protolayout.material.Chip.Builder setCustomContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.Chip.Builder setHorizontalAlignment(int);
+    method public androidx.wear.protolayout.material.Chip.Builder setIconContent(String);
+    method public androidx.wear.protolayout.material.Chip.Builder setPrimaryLabelContent(String);
+    method public androidx.wear.protolayout.material.Chip.Builder setSecondaryLabelContent(String);
+    method public androidx.wear.protolayout.material.Chip.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.ContainerDimension);
+    method public androidx.wear.protolayout.material.Chip.Builder setWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  public class ChipColors {
+    ctor public ChipColors(@ColorInt int, @ColorInt int, @ColorInt int, @ColorInt int);
+    ctor public ChipColors(@ColorInt int, @ColorInt int);
+    ctor public ChipColors(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    ctor public ChipColors(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getBackgroundColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getContentColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getIconColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getSecondaryContentColor();
+    method public static androidx.wear.protolayout.material.ChipColors primaryChipColors(androidx.wear.protolayout.material.Colors);
+    method public static androidx.wear.protolayout.material.ChipColors secondaryChipColors(androidx.wear.protolayout.material.Colors);
+  }
+
+  public class ChipDefaults {
+    field public static final androidx.wear.protolayout.material.ChipColors COMPACT_PRIMARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors COMPACT_SECONDARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors PRIMARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors SECONDARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors TITLE_PRIMARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors TITLE_SECONDARY_COLORS;
+  }
+
+  public class CircularProgressIndicator implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.CircularProgressIndicator? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ProgressIndicatorColors getCircularProgressIndicatorColors();
+    method public CharSequence? getContentDescription();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp getEndAngle();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp getProgress();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp getStartAngle();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp getStrokeWidth();
+  }
+
+  public static final class CircularProgressIndicator.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public CircularProgressIndicator.Builder();
+    method public androidx.wear.protolayout.material.CircularProgressIndicator build();
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setCircularProgressIndicatorColors(androidx.wear.protolayout.material.ProgressIndicatorColors);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setContentDescription(CharSequence);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setEndAngle(float);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setProgress(@FloatRange(from=0, to=1) float);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setStartAngle(float);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setStrokeWidth(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setStrokeWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  public class Colors {
+    ctor public Colors(@ColorInt int, @ColorInt int, @ColorInt int, @ColorInt int);
+    method @ColorInt public int getOnPrimary();
+    method @ColorInt public int getOnSurface();
+    method @ColorInt public int getPrimary();
+    method @ColorInt public int getSurface();
+    field public static final androidx.wear.protolayout.material.Colors DEFAULT;
+  }
+
+  public class CompactChip implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.CompactChip? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ChipColors getChipColors();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable getClickable();
+    method public String getText();
+  }
+
+  public static final class CompactChip.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public CompactChip.Builder(android.content.Context, String, androidx.wear.protolayout.ModifiersBuilders.Clickable, androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.CompactChip build();
+    method public androidx.wear.protolayout.material.CompactChip.Builder setChipColors(androidx.wear.protolayout.material.ChipColors);
+  }
+
+  public class ProgressIndicatorColors {
+    ctor public ProgressIndicatorColors(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    ctor public ProgressIndicatorColors(@ColorInt int, @ColorInt int);
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getIndicatorColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getTrackColor();
+    method public static androidx.wear.protolayout.material.ProgressIndicatorColors progressIndicatorColors(androidx.wear.protolayout.material.Colors);
+  }
+
+  public class ProgressIndicatorDefaults {
+    field public static final androidx.wear.protolayout.material.ProgressIndicatorColors DEFAULT_COLORS;
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp DEFAULT_STROKE_WIDTH;
+    field public static final float GAP_END_ANGLE = 156.1f;
+    field public static final float GAP_START_ANGLE = -156.1f;
+  }
+
+  public class Text implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.Text? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getColor();
+    method public androidx.wear.protolayout.LayoutElementBuilders.FontStyle getFontStyle();
+    method public float getLineHeight();
+    method public int getMaxLines();
+    method public androidx.wear.protolayout.ModifiersBuilders.Modifiers getModifiers();
+    method public int getMultilineAlignment();
+    method public int getOverflow();
+    method public String getText();
+    method public int getWeight();
+    method public boolean isItalic();
+    method public boolean isUnderline();
+  }
+
+  public static final class Text.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public Text.Builder(android.content.Context, String);
+    method public androidx.wear.protolayout.material.Text build();
+    method public androidx.wear.protolayout.material.Text.Builder setColor(androidx.wear.protolayout.ColorBuilders.ColorProp);
+    method public androidx.wear.protolayout.material.Text.Builder setItalic(boolean);
+    method public androidx.wear.protolayout.material.Text.Builder setMaxLines(@IntRange(from=1) int);
+    method public androidx.wear.protolayout.material.Text.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.Modifiers);
+    method public androidx.wear.protolayout.material.Text.Builder setMultilineAlignment(int);
+    method public androidx.wear.protolayout.material.Text.Builder setOverflow(int);
+    method public androidx.wear.protolayout.material.Text.Builder setTypography(int);
+    method public androidx.wear.protolayout.material.Text.Builder setUnderline(boolean);
+    method public androidx.wear.protolayout.material.Text.Builder setWeight(int);
+  }
+
+  public class TitleChip implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.TitleChip? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ChipColors getChipColors();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable getClickable();
+    method public int getHorizontalAlignment();
+    method public String getText();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension getWidth();
+  }
+
+  public static final class TitleChip.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public TitleChip.Builder(android.content.Context, String, androidx.wear.protolayout.ModifiersBuilders.Clickable, androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.TitleChip build();
+    method public androidx.wear.protolayout.material.TitleChip.Builder setChipColors(androidx.wear.protolayout.material.ChipColors);
+    method public androidx.wear.protolayout.material.TitleChip.Builder setHorizontalAlignment(int);
+    method public androidx.wear.protolayout.material.TitleChip.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.ContainerDimension);
+    method public androidx.wear.protolayout.material.TitleChip.Builder setWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  public class Typography {
+    field public static final int TYPOGRAPHY_BODY1 = 7; // 0x7
+    field public static final int TYPOGRAPHY_BODY2 = 8; // 0x8
+    field public static final int TYPOGRAPHY_BUTTON = 9; // 0x9
+    field public static final int TYPOGRAPHY_CAPTION1 = 10; // 0xa
+    field public static final int TYPOGRAPHY_CAPTION2 = 11; // 0xb
+    field public static final int TYPOGRAPHY_CAPTION3 = 12; // 0xc
+    field public static final int TYPOGRAPHY_DISPLAY1 = 1; // 0x1
+    field public static final int TYPOGRAPHY_DISPLAY2 = 2; // 0x2
+    field public static final int TYPOGRAPHY_DISPLAY3 = 3; // 0x3
+    field public static final int TYPOGRAPHY_TITLE1 = 4; // 0x4
+    field public static final int TYPOGRAPHY_TITLE2 = 5; // 0x5
+    field public static final int TYPOGRAPHY_TITLE3 = 6; // 0x6
+  }
+
+}
+
+package androidx.wear.protolayout.material.layouts {
+
+  public class EdgeContentLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.layouts.EdgeContentLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getEdgeContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
+  }
+
+  public static final class EdgeContentLayout.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public EdgeContentLayout.Builder(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout build();
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setEdgeContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setPrimaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setSecondaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+  }
+
+  public class LayoutDefaults {
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp DEFAULT_VERTICAL_SPACER_HEIGHT;
+    field public static final float EDGE_CONTENT_LAYOUT_PADDING_ABOVE_MAIN_CONTENT_DP = 6.0f;
+    field public static final float EDGE_CONTENT_LAYOUT_PADDING_BELOW_MAIN_CONTENT_DP = 8.0f;
+    field public static final int MULTI_BUTTON_MAX_NUMBER = 7; // 0x7
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp MULTI_SLOT_LAYOUT_HORIZONTAL_SPACER_WIDTH;
+  }
+
+  public class MultiButtonLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.layouts.MultiButtonLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public java.util.List<androidx.wear.protolayout.LayoutElementBuilders.LayoutElement!> getButtonContents();
+    method public int getFiveButtonDistribution();
+    field public static final int FIVE_BUTTON_DISTRIBUTION_BOTTOM_HEAVY = 2; // 0x2
+    field public static final int FIVE_BUTTON_DISTRIBUTION_TOP_HEAVY = 1; // 0x1
+  }
+
+  public static final class MultiButtonLayout.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public MultiButtonLayout.Builder();
+    method public androidx.wear.protolayout.material.layouts.MultiButtonLayout.Builder addButtonContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.MultiButtonLayout build();
+    method public androidx.wear.protolayout.material.layouts.MultiButtonLayout.Builder setFiveButtonDistribution(int);
+  }
+
+  public class MultiSlotLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.layouts.MultiSlotLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getHorizontalSpacerWidth();
+    method public java.util.List<androidx.wear.protolayout.LayoutElementBuilders.LayoutElement!> getSlotContents();
+  }
+
+  public static final class MultiSlotLayout.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public MultiSlotLayout.Builder();
+    method public androidx.wear.protolayout.material.layouts.MultiSlotLayout.Builder addSlotContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.MultiSlotLayout build();
+    method public androidx.wear.protolayout.material.layouts.MultiSlotLayout.Builder setHorizontalSpacerWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  public class PrimaryLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.layouts.PrimaryLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryChipContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getVerticalSpacerHeight();
+  }
+
+  public static final class PrimaryLayout.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public PrimaryLayout.Builder(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout build();
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setPrimaryChipContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setPrimaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setSecondaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setVerticalSpacerHeight(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+}
+
diff --git a/wear/protolayout/protolayout-material/api/restricted_current.txt b/wear/protolayout/protolayout-material/api/restricted_current.txt
index e6f50d0..862495c3 100644
--- a/wear/protolayout/protolayout-material/api/restricted_current.txt
+++ b/wear/protolayout/protolayout-material/api/restricted_current.txt
@@ -1 +1,298 @@
 // Signature format: 4.0
+package androidx.wear.protolayout.material {
+
+  public class Button implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.Button? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ButtonColors getButtonColors();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable getClickable();
+    method public CharSequence? getContentDescription();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getCustomContent();
+    method public String? getIconContent();
+    method public String? getImageContent();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension getSize();
+    method public String? getTextContent();
+  }
+
+  public static final class Button.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public Button.Builder(android.content.Context, androidx.wear.protolayout.ModifiersBuilders.Clickable);
+    method public androidx.wear.protolayout.material.Button build();
+    method public androidx.wear.protolayout.material.Button.Builder setButtonColors(androidx.wear.protolayout.material.ButtonColors);
+    method public androidx.wear.protolayout.material.Button.Builder setContentDescription(CharSequence);
+    method public androidx.wear.protolayout.material.Button.Builder setCustomContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.Button.Builder setIconContent(String, androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public androidx.wear.protolayout.material.Button.Builder setIconContent(String);
+    method public androidx.wear.protolayout.material.Button.Builder setImageContent(String);
+    method public androidx.wear.protolayout.material.Button.Builder setSize(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public androidx.wear.protolayout.material.Button.Builder setSize(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.material.Button.Builder setTextContent(String);
+    method public androidx.wear.protolayout.material.Button.Builder setTextContent(String, int);
+  }
+
+  public class ButtonColors {
+    ctor public ButtonColors(@ColorInt int, @ColorInt int);
+    ctor public ButtonColors(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getBackgroundColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getContentColor();
+    method public static androidx.wear.protolayout.material.ButtonColors primaryButtonColors(androidx.wear.protolayout.material.Colors);
+    method public static androidx.wear.protolayout.material.ButtonColors secondaryButtonColors(androidx.wear.protolayout.material.Colors);
+  }
+
+  public class ButtonDefaults {
+    method public static androidx.wear.protolayout.DimensionBuilders.DpProp recommendedIconSize(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public static androidx.wear.protolayout.DimensionBuilders.DpProp recommendedIconSize(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp DEFAULT_SIZE;
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp EXTRA_LARGE_SIZE;
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp LARGE_SIZE;
+    field public static final androidx.wear.protolayout.material.ButtonColors PRIMARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ButtonColors SECONDARY_COLORS;
+  }
+
+  public class Chip implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.Chip? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ChipColors getChipColors();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable getClickable();
+    method public CharSequence? getContentDescription();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getCustomContent();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension getHeight();
+    method public int getHorizontalAlignment();
+    method public String? getIconContent();
+    method public String? getPrimaryLabelContent();
+    method public String? getSecondaryLabelContent();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension getWidth();
+  }
+
+  public static final class Chip.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public Chip.Builder(android.content.Context, androidx.wear.protolayout.ModifiersBuilders.Clickable, androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.Chip build();
+    method public androidx.wear.protolayout.material.Chip.Builder setChipColors(androidx.wear.protolayout.material.ChipColors);
+    method public androidx.wear.protolayout.material.Chip.Builder setContentDescription(CharSequence);
+    method public androidx.wear.protolayout.material.Chip.Builder setCustomContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.Chip.Builder setHorizontalAlignment(int);
+    method public androidx.wear.protolayout.material.Chip.Builder setIconContent(String);
+    method public androidx.wear.protolayout.material.Chip.Builder setPrimaryLabelContent(String);
+    method public androidx.wear.protolayout.material.Chip.Builder setSecondaryLabelContent(String);
+    method public androidx.wear.protolayout.material.Chip.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.ContainerDimension);
+    method public androidx.wear.protolayout.material.Chip.Builder setWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  public class ChipColors {
+    ctor public ChipColors(@ColorInt int, @ColorInt int, @ColorInt int, @ColorInt int);
+    ctor public ChipColors(@ColorInt int, @ColorInt int);
+    ctor public ChipColors(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    ctor public ChipColors(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getBackgroundColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getContentColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getIconColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getSecondaryContentColor();
+    method public static androidx.wear.protolayout.material.ChipColors primaryChipColors(androidx.wear.protolayout.material.Colors);
+    method public static androidx.wear.protolayout.material.ChipColors secondaryChipColors(androidx.wear.protolayout.material.Colors);
+  }
+
+  public class ChipDefaults {
+    field public static final androidx.wear.protolayout.material.ChipColors COMPACT_PRIMARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors COMPACT_SECONDARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors PRIMARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors SECONDARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors TITLE_PRIMARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors TITLE_SECONDARY_COLORS;
+  }
+
+  public class CircularProgressIndicator implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.CircularProgressIndicator? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ProgressIndicatorColors getCircularProgressIndicatorColors();
+    method public CharSequence? getContentDescription();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp getEndAngle();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp getProgress();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp getStartAngle();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp getStrokeWidth();
+  }
+
+  public static final class CircularProgressIndicator.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public CircularProgressIndicator.Builder();
+    method public androidx.wear.protolayout.material.CircularProgressIndicator build();
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setCircularProgressIndicatorColors(androidx.wear.protolayout.material.ProgressIndicatorColors);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setContentDescription(CharSequence);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setEndAngle(float);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setProgress(@FloatRange(from=0, to=1) float);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setStartAngle(float);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setStrokeWidth(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setStrokeWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  public class Colors {
+    ctor public Colors(@ColorInt int, @ColorInt int, @ColorInt int, @ColorInt int);
+    method @ColorInt public int getOnPrimary();
+    method @ColorInt public int getOnSurface();
+    method @ColorInt public int getPrimary();
+    method @ColorInt public int getSurface();
+    field public static final androidx.wear.protolayout.material.Colors DEFAULT;
+  }
+
+  public class CompactChip implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.CompactChip? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ChipColors getChipColors();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable getClickable();
+    method public String getText();
+  }
+
+  public static final class CompactChip.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public CompactChip.Builder(android.content.Context, String, androidx.wear.protolayout.ModifiersBuilders.Clickable, androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.CompactChip build();
+    method public androidx.wear.protolayout.material.CompactChip.Builder setChipColors(androidx.wear.protolayout.material.ChipColors);
+  }
+
+  public class ProgressIndicatorColors {
+    ctor public ProgressIndicatorColors(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    ctor public ProgressIndicatorColors(@ColorInt int, @ColorInt int);
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getIndicatorColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getTrackColor();
+    method public static androidx.wear.protolayout.material.ProgressIndicatorColors progressIndicatorColors(androidx.wear.protolayout.material.Colors);
+  }
+
+  public class ProgressIndicatorDefaults {
+    field public static final androidx.wear.protolayout.material.ProgressIndicatorColors DEFAULT_COLORS;
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp DEFAULT_STROKE_WIDTH;
+    field public static final float GAP_END_ANGLE = 156.1f;
+    field public static final float GAP_START_ANGLE = -156.1f;
+  }
+
+  public class Text implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.Text? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getColor();
+    method public androidx.wear.protolayout.LayoutElementBuilders.FontStyle getFontStyle();
+    method public float getLineHeight();
+    method public int getMaxLines();
+    method public androidx.wear.protolayout.ModifiersBuilders.Modifiers getModifiers();
+    method public int getMultilineAlignment();
+    method public int getOverflow();
+    method public String getText();
+    method public int getWeight();
+    method public boolean isItalic();
+    method public boolean isUnderline();
+  }
+
+  public static final class Text.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public Text.Builder(android.content.Context, String);
+    method public androidx.wear.protolayout.material.Text build();
+    method public androidx.wear.protolayout.material.Text.Builder setColor(androidx.wear.protolayout.ColorBuilders.ColorProp);
+    method public androidx.wear.protolayout.material.Text.Builder setItalic(boolean);
+    method public androidx.wear.protolayout.material.Text.Builder setMaxLines(@IntRange(from=1) int);
+    method public androidx.wear.protolayout.material.Text.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.Modifiers);
+    method public androidx.wear.protolayout.material.Text.Builder setMultilineAlignment(int);
+    method public androidx.wear.protolayout.material.Text.Builder setOverflow(int);
+    method public androidx.wear.protolayout.material.Text.Builder setTypography(int);
+    method public androidx.wear.protolayout.material.Text.Builder setUnderline(boolean);
+    method public androidx.wear.protolayout.material.Text.Builder setWeight(int);
+  }
+
+  public class TitleChip implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.TitleChip? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ChipColors getChipColors();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable getClickable();
+    method public int getHorizontalAlignment();
+    method public String getText();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension getWidth();
+  }
+
+  public static final class TitleChip.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public TitleChip.Builder(android.content.Context, String, androidx.wear.protolayout.ModifiersBuilders.Clickable, androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.TitleChip build();
+    method public androidx.wear.protolayout.material.TitleChip.Builder setChipColors(androidx.wear.protolayout.material.ChipColors);
+    method public androidx.wear.protolayout.material.TitleChip.Builder setHorizontalAlignment(int);
+    method public androidx.wear.protolayout.material.TitleChip.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.ContainerDimension);
+    method public androidx.wear.protolayout.material.TitleChip.Builder setWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  public class Typography {
+    field public static final int TYPOGRAPHY_BODY1 = 7; // 0x7
+    field public static final int TYPOGRAPHY_BODY2 = 8; // 0x8
+    field public static final int TYPOGRAPHY_BUTTON = 9; // 0x9
+    field public static final int TYPOGRAPHY_CAPTION1 = 10; // 0xa
+    field public static final int TYPOGRAPHY_CAPTION2 = 11; // 0xb
+    field public static final int TYPOGRAPHY_CAPTION3 = 12; // 0xc
+    field public static final int TYPOGRAPHY_DISPLAY1 = 1; // 0x1
+    field public static final int TYPOGRAPHY_DISPLAY2 = 2; // 0x2
+    field public static final int TYPOGRAPHY_DISPLAY3 = 3; // 0x3
+    field public static final int TYPOGRAPHY_TITLE1 = 4; // 0x4
+    field public static final int TYPOGRAPHY_TITLE2 = 5; // 0x5
+    field public static final int TYPOGRAPHY_TITLE3 = 6; // 0x6
+  }
+
+}
+
+package androidx.wear.protolayout.material.layouts {
+
+  public class EdgeContentLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.layouts.EdgeContentLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getEdgeContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
+  }
+
+  public static final class EdgeContentLayout.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public EdgeContentLayout.Builder(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout build();
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setEdgeContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setPrimaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setSecondaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+  }
+
+  public class LayoutDefaults {
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp DEFAULT_VERTICAL_SPACER_HEIGHT;
+    field public static final float EDGE_CONTENT_LAYOUT_PADDING_ABOVE_MAIN_CONTENT_DP = 6.0f;
+    field public static final float EDGE_CONTENT_LAYOUT_PADDING_BELOW_MAIN_CONTENT_DP = 8.0f;
+    field public static final int MULTI_BUTTON_MAX_NUMBER = 7; // 0x7
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp MULTI_SLOT_LAYOUT_HORIZONTAL_SPACER_WIDTH;
+  }
+
+  public class MultiButtonLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.layouts.MultiButtonLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public java.util.List<androidx.wear.protolayout.LayoutElementBuilders.LayoutElement!> getButtonContents();
+    method public int getFiveButtonDistribution();
+    field public static final int FIVE_BUTTON_DISTRIBUTION_BOTTOM_HEAVY = 2; // 0x2
+    field public static final int FIVE_BUTTON_DISTRIBUTION_TOP_HEAVY = 1; // 0x1
+  }
+
+  public static final class MultiButtonLayout.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public MultiButtonLayout.Builder();
+    method public androidx.wear.protolayout.material.layouts.MultiButtonLayout.Builder addButtonContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.MultiButtonLayout build();
+    method public androidx.wear.protolayout.material.layouts.MultiButtonLayout.Builder setFiveButtonDistribution(int);
+  }
+
+  public class MultiSlotLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.layouts.MultiSlotLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getHorizontalSpacerWidth();
+    method public java.util.List<androidx.wear.protolayout.LayoutElementBuilders.LayoutElement!> getSlotContents();
+  }
+
+  public static final class MultiSlotLayout.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public MultiSlotLayout.Builder();
+    method public androidx.wear.protolayout.material.layouts.MultiSlotLayout.Builder addSlotContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.MultiSlotLayout build();
+    method public androidx.wear.protolayout.material.layouts.MultiSlotLayout.Builder setHorizontalSpacerWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  public class PrimaryLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.layouts.PrimaryLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryChipContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getVerticalSpacerHeight();
+  }
+
+  public static final class PrimaryLayout.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    ctor public PrimaryLayout.Builder(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout build();
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setPrimaryChipContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setPrimaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setSecondaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setVerticalSpacerHeight(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+}
+
diff --git a/wear/protolayout/protolayout-material/build.gradle b/wear/protolayout/protolayout-material/build.gradle
index 7241009..fdd52a9 100644
--- a/wear/protolayout/protolayout-material/build.gradle
+++ b/wear/protolayout/protolayout-material/build.gradle
@@ -23,10 +23,46 @@
 
 dependencies {
     annotationProcessor(libs.nullaway)
-    // Add dependencies here
+    api("androidx.annotation:annotation:1.2.0")
+    implementation(project(":wear:protolayout:protolayout"))
+    implementation(project(":wear:protolayout:protolayout-proto"))
+    implementation(project(":wear:protolayout:protolayout-expression"))
+    androidTestImplementation(libs.junit)
+    androidTestImplementation(libs.testCore)
+    androidTestImplementation(libs.testExtJunit)
+    androidTestImplementation(libs.testRules)
+    androidTestImplementation(libs.testRunner)
+    androidTestImplementation("androidx.core:core:1.7.0")
+    androidTestImplementation(project(":test:screenshot:screenshot"))
+    androidTestImplementation(project(":wear:tiles:tiles-renderer"))
+    androidTestRuntimeOnly(project(path: ":wear:protolayout:protolayout-proto", configuration: "shadow"))
+    androidTestImplementation(libs.protobuf)
+
+    testImplementation(libs.junit)
+    testImplementation(libs.mockitoCore4)
+    testImplementation(libs.robolectric)
+    testImplementation(libs.testExtJunit)
+    testImplementation(libs.testExtTruth)
+    testImplementation(libs.testCore)
+    testImplementation(libs.testRunner)
+    testImplementation(libs.testRules)
+    testImplementation(libs.truth)
 }
 
 android {
+    defaultConfig {
+        minSdkVersion 26
+    }
+
+    sourceSets {
+        // TODO(b/268312818): Update to protolayout location and copy images.
+        androidTest.assets.srcDirs += project.rootDir.absolutePath + "/../../golden/wear/wear-tiles-material"
+    }
+
+    defaultConfig {
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    }
+
     namespace "androidx.wear.protolayout.material"
 }
 
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Button.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Button.java
new file mode 100644
index 0000000..996cae8
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Button.java
@@ -0,0 +1,565 @@
+/*
+ * Copyright 2021 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 androidx.wear.protolayout.material;
+
+import static androidx.annotation.Dimension.DP;
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+import static androidx.wear.protolayout.LayoutElementBuilders.CONTENT_SCALE_MODE_FILL_BOUNDS;
+import static androidx.wear.protolayout.material.ButtonDefaults.DEFAULT_SIZE;
+import static androidx.wear.protolayout.material.ButtonDefaults.EXTRA_LARGE_SIZE;
+import static androidx.wear.protolayout.material.ButtonDefaults.LARGE_SIZE;
+import static androidx.wear.protolayout.material.ButtonDefaults.PRIMARY_COLORS;
+import static androidx.wear.protolayout.material.Helper.checkNotNull;
+import static androidx.wear.protolayout.material.Helper.checkTag;
+import static androidx.wear.protolayout.material.Helper.getMetadataTagName;
+import static androidx.wear.protolayout.material.Helper.getTagBytes;
+import static androidx.wear.protolayout.material.Helper.radiusOf;
+
+import android.content.Context;
+
+import androidx.annotation.Dimension;
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.ColorBuilders.ColorProp;
+import androidx.wear.protolayout.DimensionBuilders.ContainerDimension;
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+import androidx.wear.protolayout.LayoutElementBuilders.Box;
+import androidx.wear.protolayout.LayoutElementBuilders.ColorFilter;
+import androidx.wear.protolayout.LayoutElementBuilders.Image;
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement;
+import androidx.wear.protolayout.ModifiersBuilders;
+import androidx.wear.protolayout.ModifiersBuilders.Background;
+import androidx.wear.protolayout.ModifiersBuilders.Clickable;
+import androidx.wear.protolayout.ModifiersBuilders.Corner;
+import androidx.wear.protolayout.ModifiersBuilders.ElementMetadata;
+import androidx.wear.protolayout.ModifiersBuilders.Modifiers;
+import androidx.wear.protolayout.ModifiersBuilders.Semantics;
+import androidx.wear.protolayout.expression.Fingerprint;
+import androidx.wear.protolayout.material.Typography.TypographyName;
+import androidx.wear.protolayout.proto.LayoutElementProto;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Tiles component {@link Button} that represents clickable button with the given content.
+ *
+ * <p>The Button is circular in shape. The recommended sizes are defined in {@link ButtonDefaults}.
+ *
+ * <p>The recommended set of {@link ButtonColors} styles can be obtained from {@link
+ * ButtonDefaults}., e.g. {@link ButtonDefaults#PRIMARY_COLORS} to get a color scheme for a primary
+ * {@link Button}.
+ *
+ * <p>When accessing the contents of a container for testing, note that this element can't be simply
+ * casted back to the original type, i.e.:
+ *
+ * <pre>{@code
+ * Button button = new Button...
+ * Box box = new Box.Builder().addContent(button).build();
+ *
+ * Button myButton = (Button) box.getContents().get(0);
+ * }</pre>
+ *
+ * will fail.
+ *
+ * <p>To be able to get {@link Button} object from any layout element, {@link #fromLayoutElement}
+ * method should be used, i.e.:
+ *
+ * <pre>{@code
+ * Button myButton = Button.fromLayoutElement(box.getContents().get(0));
+ * }</pre>
+ */
+public class Button implements LayoutElement {
+    /** Tool tag for Metadata in Modifiers, so we know that Box is actually a Button with text. */
+    static final String METADATA_TAG_TEXT = "TXTBTN";
+    /** Tool tag for Metadata in Modifiers, so we know that Box is actually a Button with icon. */
+    static final String METADATA_TAG_ICON = "ICNBTN";
+    /** Tool tag for Metadata in Modifiers, so we know that Box is actually a Button with image. */
+    static final String METADATA_TAG_IMAGE = "IMGBTN";
+    /**
+     * Tool tag for Metadata in Modifiers, so we know that Box is actually a Button with custom
+     * content.
+     */
+    static final String METADATA_TAG_CUSTOM_CONTENT = "CSTBTN";
+
+    @NonNull private final Box mElement;
+
+    Button(@NonNull Box element) {
+        mElement = element;
+    }
+
+    /** Builder class for {@link Button}. */
+    public static final class Builder implements LayoutElement.Builder {
+        private static final int NOT_SET = -1;
+        private static final int ICON = 0;
+        private static final int TEXT = 1;
+        private static final int IMAGE = 2;
+        private static final int CUSTOM_CONTENT = 3;
+
+        @NonNull static final Map<Integer, String> TYPE_TO_TAG = new HashMap<>();
+
+        @RestrictTo(Scope.LIBRARY)
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef({NOT_SET, ICON, TEXT, IMAGE, CUSTOM_CONTENT})
+        @interface ButtonType {}
+
+        @NonNull private final Context mContext;
+        @Nullable private LayoutElement mCustomContent;
+        @NonNull private final Clickable mClickable;
+        @NonNull private CharSequence mContentDescription = "";
+        @NonNull private DpProp mSize = DEFAULT_SIZE;
+        @Nullable private String mText = null;
+        @Nullable private Integer mTypographyName = null;
+        @Nullable private String mIcon = null;
+        @Nullable private DpProp mIconSize = null;
+        @Nullable private String mImage = null;
+        @NonNull private ButtonColors mButtonColors = PRIMARY_COLORS;
+        @ButtonType private int mType = NOT_SET;
+
+        static {
+            TYPE_TO_TAG.put(ICON, METADATA_TAG_ICON);
+            TYPE_TO_TAG.put(TEXT, METADATA_TAG_TEXT);
+            TYPE_TO_TAG.put(IMAGE, METADATA_TAG_IMAGE);
+            TYPE_TO_TAG.put(CUSTOM_CONTENT, METADATA_TAG_CUSTOM_CONTENT);
+        }
+
+        /**
+         * Creates a builder for the {@link Button} from the given content. Custom content should be
+         * later set with one of the following ({@link #setIconContent}, {@link #setTextContent},
+         * {@link #setImageContent}.
+         *
+         * @param context The application's context.
+         * @param clickable Associated {@link Clickable} for click events. When the Button is
+         *     clicked it will fire the associated action.
+         */
+        public Builder(@NonNull Context context, @NonNull Clickable clickable) {
+            mClickable = clickable;
+            mContext = context;
+        }
+
+        /**
+         * Sets the content description for the {@link Button}. It is highly recommended to provide
+         * this for button containing icon or image.
+         */
+        @NonNull
+        public Builder setContentDescription(@NonNull CharSequence contentDescription) {
+            this.mContentDescription = contentDescription;
+            return this;
+        }
+
+        /**
+         * Sets the size for the {@link Button}. Strongly recommended values are {@link
+         * ButtonDefaults#DEFAULT_SIZE}, {@link ButtonDefaults#LARGE_SIZE} and {@link
+         * ButtonDefaults#EXTRA_LARGE_SIZE}. If not set, {@link ButtonDefaults#DEFAULT_SIZE} will be
+         * used.
+         */
+        @NonNull
+        public Builder setSize(@NonNull DpProp size) {
+            mSize = size;
+            return this;
+        }
+
+        /**
+         * Sets the size for the {@link Button}. Strongly recommended values are {@link
+         * ButtonDefaults#DEFAULT_SIZE}, {@link ButtonDefaults#LARGE_SIZE} and {@link
+         * ButtonDefaults#EXTRA_LARGE_SIZE}. If not set, {@link ButtonDefaults#DEFAULT_SIZE} will be
+         * used.
+         */
+        @NonNull
+        public Builder setSize(@Dimension(unit = DP) float size) {
+            mSize = dp(size);
+            return this;
+        }
+
+        /**
+         * Sets the colors for the {@link Button}. If not set, {@link ButtonDefaults#PRIMARY_COLORS}
+         * will be used.
+         */
+        @NonNull
+        public Builder setButtonColors(@NonNull ButtonColors buttonColors) {
+            mButtonColors = buttonColors;
+            return this;
+        }
+
+        /**
+         * Sets the custom content for this Button. Any previously added content will be overridden.
+         */
+        @NonNull
+        public Builder setCustomContent(@NonNull LayoutElement content) {
+            resetContent();
+            this.mCustomContent = content;
+            this.mType = CUSTOM_CONTENT;
+            return this;
+        }
+
+        /**
+         * Sets the content of this Button to be the given icon with the given size. Any previously
+         * added content will be overridden. Provided icon will be tinted to the given content color
+         * from {@link ButtonColors} and with the given size. This icon should be image with chosen
+         * alpha channel and not an actual image.
+         */
+        @NonNull
+        public Builder setIconContent(@NonNull String imageResourceId, @NonNull DpProp size) {
+            resetContent();
+            this.mIcon = imageResourceId;
+            this.mType = ICON;
+            this.mIconSize = size;
+            return this;
+        }
+
+        /**
+         * Sets the content of this Button to be the given icon with the default size that is half
+         * of the set size of the button. Any previously added content will be overridden. Provided
+         * icon will be tinted to the given content color from {@link ButtonColors}. This icon
+         * should be image with chosen alpha channel and not an actual image.
+         */
+        @NonNull
+        public Builder setIconContent(@NonNull String imageResourceId) {
+            resetContent();
+            this.mIcon = imageResourceId;
+            this.mType = ICON;
+            return this;
+        }
+
+        /**
+         * Sets the content of this Button to be the given text with the default font for the set
+         * size (for the {@link ButtonDefaults#DEFAULT_SIZE}, {@link ButtonDefaults#LARGE_SIZE} and
+         * {@link ButtonDefaults#EXTRA_LARGE_SIZE} is {@link Typography#TYPOGRAPHY_TITLE2}, {@link
+         * Typography#TYPOGRAPHY_TITLE1} and {@link Typography#TYPOGRAPHY_DISPLAY3} respectively).
+         * Any previously added content will be overridden. Text should contain no more than 3
+         * characters, otherwise it will overflow from the edges.
+         */
+        @NonNull
+        public Builder setTextContent(@NonNull String text) {
+            resetContent();
+            this.mText = text;
+            this.mType = TEXT;
+            return this;
+        }
+
+        /**
+         * Sets the content of this Button to be the given text with the given font. If you need
+         * more font related customization, consider using {@link #setCustomContent} with {@link
+         * Text} component. Any previously added content will be overridden. Text should contain no
+         * more than 3 characters, otherwise it will overflow from the edges.
+         */
+        @NonNull
+        public Builder setTextContent(@NonNull String text, @TypographyName int typographyName) {
+            resetContent();
+            this.mText = text;
+            this.mTypographyName = typographyName;
+            this.mType = TEXT;
+            return this;
+        }
+
+        /**
+         * Sets the content of this Button to be the given image, i.e. contacts photo. Any
+         * previously added content will be overridden.
+         */
+        @NonNull
+        public Builder setImageContent(@NonNull String imageResourceId) {
+            resetContent();
+            this.mImage = imageResourceId;
+            this.mType = IMAGE;
+            return this;
+        }
+
+        private void resetContent() {
+            this.mText = null;
+            this.mTypographyName = null;
+            this.mIcon = null;
+            this.mImage = null;
+            this.mCustomContent = null;
+            this.mIconSize = null;
+        }
+
+        /** Constructs and returns {@link Button} with the provided field and look. */
+        @NonNull
+        @Override
+        public Button build() {
+            Modifiers.Builder modifiers =
+                    new Modifiers.Builder()
+                            .setClickable(mClickable)
+                            .setBackground(
+                                    new Background.Builder()
+                                            .setColor(mButtonColors.getBackgroundColor())
+                                            .setCorner(
+                                                    new Corner.Builder()
+                                                            .setRadius(radiusOf(mSize))
+                                                            .build())
+                                            .build())
+                            .setMetadata(
+                                    new ElementMetadata.Builder()
+                                            .setTagData(
+                                                    getTagBytes(
+                                                            checkNotNull(TYPE_TO_TAG.get(mType))))
+                                            .build());
+            if (mContentDescription.length() > 0) {
+                modifiers.setSemantics(
+                        new ModifiersBuilders.Semantics.Builder()
+                                .setContentDescription(mContentDescription.toString())
+                                .build());
+            }
+
+            Box.Builder element =
+                    new Box.Builder()
+                            .setHeight(mSize)
+                            .setWidth(mSize)
+                            .setModifiers(modifiers.build());
+
+            element.addContent(getCorrectContent());
+
+            return new Button(element.build());
+        }
+
+        @NonNull
+        private LayoutElement getCorrectContent() {
+            LayoutElement.Builder content;
+            switch (mType) {
+                case ICON:
+                {
+                    DpProp iconSize =
+                            mIconSize != null
+                                    ? mIconSize
+                                    : ButtonDefaults.recommendedIconSize(mSize);
+                    content =
+                            new Image.Builder()
+                                    .setResourceId(checkNotNull(mIcon))
+                                    .setHeight(checkNotNull(iconSize))
+                                    .setWidth(iconSize)
+                                    .setContentScaleMode(CONTENT_SCALE_MODE_FILL_BOUNDS)
+                                    .setColorFilter(
+                                            new ColorFilter.Builder()
+                                                    .setTint(mButtonColors.getContentColor())
+                                                    .build());
+
+                    return content.build();
+                }
+                case TEXT:
+                {
+                    @TypographyName
+                    int typographyName =
+                            mTypographyName != null
+                                    ? mTypographyName
+                                    : getDefaultTypographyForSize(mSize);
+                    content =
+                            new Text.Builder(mContext, checkNotNull(mText))
+                                    .setMaxLines(1)
+                                    .setTypography(typographyName)
+                                    .setColor(mButtonColors.getContentColor());
+
+                    return content.build();
+                }
+                case IMAGE:
+                {
+                    content =
+                            new Image.Builder()
+                                    .setResourceId(checkNotNull(mImage))
+                                    .setHeight(mSize)
+                                    .setWidth(mSize)
+                                    .setContentScaleMode(CONTENT_SCALE_MODE_FILL_BOUNDS);
+                    return content.build();
+                }
+                case CUSTOM_CONTENT:
+                    return checkNotNull(mCustomContent);
+                case NOT_SET:
+                    // Shouldn't happen.
+                default:
+                    // Shouldn't happen.
+                    throw new IllegalArgumentException("Wrong Button type");
+            }
+        }
+
+        private static @TypographyName int getDefaultTypographyForSize(@NonNull DpProp size) {
+            if (size.getValue() == LARGE_SIZE.getValue()) {
+                return Typography.TYPOGRAPHY_TITLE1;
+            } else if (size.getValue() == EXTRA_LARGE_SIZE.getValue()) {
+                return Typography.TYPOGRAPHY_DISPLAY3;
+            } else {
+                return Typography.TYPOGRAPHY_TITLE2;
+            }
+        }
+    }
+
+    /**
+     * Returns the custom content of this Button if it has been added. Otherwise, it returns null.
+     */
+    @Nullable
+    public LayoutElement getCustomContent() {
+        if (!getMetadataTag().equals(METADATA_TAG_CUSTOM_CONTENT)) {
+            return null;
+        }
+        return getAnyContent();
+    }
+
+    /** Returns the icon content of this Button if it has been added. Otherwise, it returns null. */
+    @Nullable
+    public String getIconContent() {
+        Image icon = getIconContentObject();
+        return icon != null ? checkNotNull(icon.getResourceId()).getValue() : null;
+    }
+
+    /**
+     * Returns the image content of this Button if it has been added. Otherwise, it returns null.
+     */
+    @Nullable
+    public String getImageContent() {
+        Image image = getImageContentObject();
+        return image != null ? checkNotNull(image.getResourceId()).getValue() : null;
+    }
+
+    /** Returns the text content of this Button if it has been added. Otherwise, it returns null. */
+    @Nullable
+    public String getTextContent() {
+        Text text = getTextContentObject();
+        return text != null ? text.getText() : null;
+    }
+
+    @NonNull
+    private LayoutElement getAnyContent() {
+        return checkNotNull(mElement.getContents().get(0));
+    }
+
+    @Nullable
+    private Image getIconContentObject() {
+        if (!getMetadataTag().equals(METADATA_TAG_ICON)) {
+            return null;
+        }
+        return (Image) getAnyContent();
+    }
+
+    @Nullable
+    private Text getTextContentObject() {
+        if (!getMetadataTag().equals(METADATA_TAG_TEXT)) {
+            return null;
+        }
+        return Text.fromLayoutElement(getAnyContent());
+    }
+
+    @Nullable
+    private Image getImageContentObject() {
+        if (!getMetadataTag().equals(METADATA_TAG_IMAGE)) {
+            return null;
+        }
+        return (Image) getAnyContent();
+    }
+
+    /** Returns click event action associated with this Button. */
+    @NonNull
+    public Clickable getClickable() {
+        return checkNotNull(checkNotNull(mElement.getModifiers()).getClickable());
+    }
+
+    /** Returns content description for this Button. */
+    @Nullable
+    public CharSequence getContentDescription() {
+        Semantics semantics = checkNotNull(mElement.getModifiers()).getSemantics();
+        if (semantics == null) {
+            return null;
+        }
+        return semantics.getContentDescription();
+    }
+
+    /** Returns size for this Button. */
+    @NonNull
+    public ContainerDimension getSize() {
+        return checkNotNull(mElement.getWidth());
+    }
+
+    private ColorProp getBackgroundColor() {
+        return checkNotNull(
+                checkNotNull(checkNotNull(mElement.getModifiers()).getBackground()).getColor());
+    }
+
+    /** Returns button color of this Button. */
+    @NonNull
+    public ButtonColors getButtonColors() {
+        ColorProp backgroundColor = getBackgroundColor();
+        ColorProp contentColor = null;
+
+        switch (getMetadataTag()) {
+            case METADATA_TAG_TEXT:
+                contentColor = checkNotNull(getTextContentObject()).getColor();
+                break;
+            case METADATA_TAG_ICON:
+                contentColor =
+                        checkNotNull(checkNotNull(getIconContentObject()).getColorFilter())
+                                .getTint();
+                break;
+            case METADATA_TAG_IMAGE:
+                contentColor =
+                        checkNotNull(checkNotNull(getImageContentObject()).getColorFilter())
+                                .getTint();
+                break;
+            case METADATA_TAG_CUSTOM_CONTENT:
+                break;
+        }
+
+        if (contentColor == null) {
+            contentColor = new ColorProp.Builder(0).build();
+        }
+
+        return new ButtonColors(backgroundColor, contentColor);
+    }
+
+    /** Returns metadata tag set to this Button. */
+    @NonNull
+    String getMetadataTag() {
+        return getMetadataTagName(
+                checkNotNull(checkNotNull(mElement.getModifiers()).getMetadata()));
+    }
+
+    /**
+     * Returns Button object from the given LayoutElement (e.g. one retrieved from a container's
+     * content with {@code container.getContents().get(index)}) if that element can be converted to
+     * Button. Otherwise, it will return null.
+     */
+    @Nullable
+    public static Button fromLayoutElement(@NonNull LayoutElement element) {
+        if (element instanceof Button) {
+            return (Button) element;
+        }
+        if (!(element instanceof Box)) {
+            return null;
+        }
+        Box boxElement = (Box) element;
+        if (!checkTag(boxElement.getModifiers(), Builder.TYPE_TO_TAG.values())) {
+            return null;
+        }
+        // Now we are sure that this element is a Button.
+        return new Button(boxElement);
+    }
+
+    @NonNull
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public LayoutElementProto.LayoutElement toLayoutElementProto() {
+        return checkNotNull(mElement.toLayoutElementProto());
+    }
+
+    @Nullable
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public Fingerprint getFingerprint() {
+        return mElement.getFingerprint();
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ButtonColors.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ButtonColors.java
new file mode 100644
index 0000000..3ebfc62
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ButtonColors.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2021 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 androidx.wear.protolayout.material;
+
+import static androidx.wear.protolayout.ColorBuilders.argb;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.wear.protolayout.ColorBuilders.ColorProp;
+
+/**
+ * Represents the background and content colors used in a button Tiles component.
+ *
+ * <p>See {@link ButtonDefaults#PRIMARY_COLORS} for the default colors used in a primary styled
+ * {@link Button}. See {@link ButtonDefaults#SECONDARY_COLORS} for the default colors used in a
+ * secondary styled {@link Button}.
+ */
+public class ButtonColors {
+    @NonNull private final ColorProp mBackgroundColor;
+    @NonNull private final ColorProp mContentColor;
+
+    /**
+     * Constructor for {@link ButtonColors} object.
+     *
+     * @param backgroundColor The background color to be used for a button Tiles component. Should
+     *     be in ARGB format.
+     * @param contentColor The content color or tint color to be used for a button Tiles component.
+     *     Should be in ARGB format.
+     */
+    public ButtonColors(@ColorInt int backgroundColor, @ColorInt int contentColor) {
+        mBackgroundColor = argb(backgroundColor);
+        mContentColor = argb(contentColor);
+    }
+
+    /**
+     * Constructor for {@link ButtonColors} object.
+     *
+     * @param backgroundColor The background color to be used for a button.
+     * @param contentColor The content color or tint color to be used for a button.
+     */
+    public ButtonColors(@NonNull ColorProp backgroundColor, @NonNull ColorProp contentColor) {
+        mBackgroundColor = backgroundColor;
+        mContentColor = contentColor;
+    }
+
+    /**
+     * Returns a {@link ButtonColors} object, using the current Primary colors from the given {@link
+     * Colors}.
+     */
+    @NonNull
+    public static ButtonColors primaryButtonColors(@NonNull Colors colors) {
+        return new ButtonColors(colors.getPrimary(), colors.getOnPrimary());
+    }
+
+    /**
+     * Returns a {@link ButtonColors} object, using the current Surface colors from the given {@link
+     * Colors}.
+     */
+    @NonNull
+    public static ButtonColors secondaryButtonColors(@NonNull Colors colors) {
+        return new ButtonColors(colors.getSurface(), colors.getOnSurface());
+    }
+
+    /** The background color to be used on a button Tiles components. */
+    @NonNull
+    public ColorProp getBackgroundColor() {
+        return mBackgroundColor;
+    }
+
+    /** The content or tint color to be used on a button Tiles components. */
+    @NonNull
+    public ColorProp getContentColor() {
+        return mContentColor;
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ButtonDefaults.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ButtonDefaults.java
new file mode 100644
index 0000000..e98e212
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ButtonDefaults.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2021 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 androidx.wear.protolayout.material;
+
+import static androidx.annotation.Dimension.DP;
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+
+import androidx.annotation.Dimension;
+import androidx.annotation.NonNull;
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+
+/** Contains the default values used by button Tiles components. */
+public class ButtonDefaults {
+    private ButtonDefaults() {}
+
+    /** The default size for standard {@link Button}. */
+    @NonNull public static final DpProp DEFAULT_SIZE = dp(52);
+
+    /** The recommended size for large {@link Button}. */
+    @NonNull public static final DpProp LARGE_SIZE = dp(60);
+
+    /** The recommended size for extra large {@link Button}. */
+    @NonNull public static final DpProp EXTRA_LARGE_SIZE = dp(88);
+
+    /** Returns the recommended icon size for the given size of a {@link Button}. */
+    @NonNull
+    public static DpProp recommendedIconSize(@NonNull DpProp buttonSize) {
+        return recommendedIconSize(buttonSize.getValue());
+    }
+
+    /** Returns the recommended icon size for the given size of a {@link Button}. */
+    @NonNull
+    public static DpProp recommendedIconSize(@Dimension(unit = DP) float buttonSize) {
+        return dp(buttonSize / 2);
+    }
+
+    /** The recommended colors for a primary {@link Button}. */
+    @NonNull
+    public static final ButtonColors PRIMARY_COLORS =
+            ButtonColors.primaryButtonColors(Colors.DEFAULT);
+
+    /** The recommended colors for a secondary {@link Button}. */
+    @NonNull
+    public static final ButtonColors SECONDARY_COLORS =
+            ButtonColors.secondaryButtonColors(Colors.DEFAULT);
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Chip.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Chip.java
new file mode 100644
index 0000000..74732d5
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Chip.java
@@ -0,0 +1,682 @@
+/*
+ * Copyright 2021 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 androidx.wear.protolayout.material;
+
+import static androidx.annotation.Dimension.DP;
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+import static androidx.wear.protolayout.LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER;
+import static androidx.wear.protolayout.LayoutElementBuilders.HORIZONTAL_ALIGN_START;
+import static androidx.wear.protolayout.LayoutElementBuilders.HORIZONTAL_ALIGN_UNDEFINED;
+import static androidx.wear.protolayout.material.ChipDefaults.DEFAULT_HEIGHT;
+import static androidx.wear.protolayout.material.ChipDefaults.DEFAULT_MARGIN_PERCENT;
+import static androidx.wear.protolayout.material.ChipDefaults.HORIZONTAL_PADDING;
+import static androidx.wear.protolayout.material.ChipDefaults.ICON_SIZE;
+import static androidx.wear.protolayout.material.ChipDefaults.ICON_SPACER_WIDTH;
+import static androidx.wear.protolayout.material.ChipDefaults.PRIMARY_COLORS;
+import static androidx.wear.protolayout.material.Helper.checkNotNull;
+import static androidx.wear.protolayout.material.Helper.checkTag;
+import static androidx.wear.protolayout.material.Helper.getMetadataTagName;
+import static androidx.wear.protolayout.material.Helper.getTagBytes;
+import static androidx.wear.protolayout.material.Helper.radiusOf;
+
+import android.content.Context;
+
+import androidx.annotation.Dimension;
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.ColorBuilders.ColorProp;
+import androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters;
+import androidx.wear.protolayout.DimensionBuilders.ContainerDimension;
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+import androidx.wear.protolayout.LayoutElementBuilders;
+import androidx.wear.protolayout.LayoutElementBuilders.Box;
+import androidx.wear.protolayout.LayoutElementBuilders.ColorFilter;
+import androidx.wear.protolayout.LayoutElementBuilders.Column;
+import androidx.wear.protolayout.LayoutElementBuilders.HorizontalAlignment;
+import androidx.wear.protolayout.LayoutElementBuilders.Image;
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement;
+import androidx.wear.protolayout.LayoutElementBuilders.Row;
+import androidx.wear.protolayout.LayoutElementBuilders.Spacer;
+import androidx.wear.protolayout.ModifiersBuilders.Background;
+import androidx.wear.protolayout.ModifiersBuilders.Clickable;
+import androidx.wear.protolayout.ModifiersBuilders.Corner;
+import androidx.wear.protolayout.ModifiersBuilders.ElementMetadata;
+import androidx.wear.protolayout.ModifiersBuilders.Modifiers;
+import androidx.wear.protolayout.ModifiersBuilders.Padding;
+import androidx.wear.protolayout.ModifiersBuilders.Semantics;
+import androidx.wear.protolayout.expression.Fingerprint;
+import androidx.wear.protolayout.material.Typography.TypographyName;
+import androidx.wear.protolayout.proto.LayoutElementProto;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Tiles component {@link Chip} that represents clickable object with the text, optional label and
+ * optional icon or with custom content.
+ *
+ * <p>The Chip is Stadium shape and has a max height designed to take no more than two lines of text
+ * of {@link Typography#TYPOGRAPHY_BUTTON} style. The {@link Chip} can have an icon horizontally
+ * parallel to the two lines of text. Width of chip can very, and the recommended size is screen
+ * dependent with the recommended margin being applied.
+ *
+ * <p>The recommended set of {@link ChipColors} styles can be obtained from {@link ChipDefaults}.,
+ * e.g. {@link ChipDefaults#PRIMARY_COLORS} to get a color scheme for a primary {@link Chip}.
+ *
+ * <p>When accessing the contents of a container for testing, note that this element can't be simply
+ * casted back to the original type, i.e.:
+ *
+ * <pre>{@code
+ * Chip chip = new Chip...
+ * Box box = new Box.Builder().addContent(chip).build();
+ *
+ * Chip myChip = (Chip) box.getContents().get(0);
+ * }</pre>
+ *
+ * will fail.
+ *
+ * <p>To be able to get {@link Chip} object from any layout element, {@link #fromLayoutElement}
+ * method should be used, i.e.:
+ *
+ * <pre>{@code
+ * Chip myChip = Chip.fromLayoutElement(box.getContents().get(0));
+ * }</pre>
+ *
+ * @see  androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder#setContent if this Chip is
+ * used inside of {@link androidx.wear.protolayout.material.layouts.PrimaryLayout}.
+ */
+public class Chip implements LayoutElement {
+    /**
+     * Tool tag for Metadata in Modifiers, so we know that Box is actually a Chip with only text.
+     */
+    static final String METADATA_TAG_TEXT = "TXTCHP";
+    /** Tool tag for Metadata in Modifiers, so we know that Box is actually a Chip with icon. */
+    static final String METADATA_TAG_ICON = "ICNCHP";
+    /**
+     * Tool tag for Metadata in Modifiers, so we know that Box is actually a Chip with custom
+     * content.
+     */
+    static final String METADATA_TAG_CUSTOM_CONTENT = "CSTCHP";
+
+    @NonNull private final Box mElement;
+
+    Chip(@NonNull Box element) {
+        mElement = element;
+    }
+    /** Builder class for {@link androidx.wear.protolayout.material.Chip}. */
+    public static final class Builder implements LayoutElement.Builder {
+        private static final int NOT_SET = 0;
+        private static final int TEXT = 1;
+        private static final int ICON = 2;
+        private static final int CUSTOM_CONTENT = 3;
+
+        @RestrictTo(Scope.LIBRARY)
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef({NOT_SET, TEXT, ICON, CUSTOM_CONTENT})
+        @interface ChipType {}
+
+        @NonNull private final Context mContext;
+        @Nullable private LayoutElement mCustomContent;
+        @Nullable private String mImageResourceId = null;
+        @Nullable private String mPrimaryLabel = null;
+        @Nullable private String mSecondaryLabel = null;
+        @NonNull private final Clickable mClickable;
+        @NonNull private CharSequence mContentDescription = "";
+        @NonNull private ContainerDimension mWidth;
+        @NonNull private DpProp mHeight = DEFAULT_HEIGHT;
+        @NonNull private ChipColors mChipColors = PRIMARY_COLORS;
+        @HorizontalAlignment private int mHorizontalAlign = HORIZONTAL_ALIGN_UNDEFINED;
+        @TypographyName private int mPrimaryLabelTypography;
+        @NonNull private DpProp mHorizontalPadding = HORIZONTAL_PADDING;
+        private boolean mIsScalable = true;
+        private int mMaxLines = 0; // 0 indicates that is not set.
+        @NonNull private String mMetadataTag = "";
+
+        @NonNull static final Map<Integer, String> TYPE_TO_TAG = new HashMap<>();
+
+        static {
+            TYPE_TO_TAG.put(ICON, METADATA_TAG_ICON);
+            TYPE_TO_TAG.put(TEXT, METADATA_TAG_TEXT);
+            TYPE_TO_TAG.put(CUSTOM_CONTENT, METADATA_TAG_CUSTOM_CONTENT);
+        }
+
+        /**
+         * Creates a builder for the {@link Chip} with associated action. It is required to add
+         * content later with setters.
+         *
+         * @param context The application's context.
+         * @param clickable Associated {@link Clickable} for click events. When the Chip is clicked
+         *     it will fire the associated action.
+         * @param deviceParameters The device parameters used to derive defaults for this Chip.
+         */
+        public Builder(
+                @NonNull Context context,
+                @NonNull Clickable clickable,
+                @NonNull DeviceParameters deviceParameters) {
+            mContext = context;
+            mClickable = clickable;
+            mWidth =
+                    dp(
+                            (100 - 2 * DEFAULT_MARGIN_PERCENT)
+                                    * deviceParameters.getScreenWidthDp()
+                                    / 100);
+            mPrimaryLabelTypography = Typography.TYPOGRAPHY_BUTTON;
+        }
+
+        /**
+         * Sets the width of {@link Chip}. If not set, default value will be set to fill the screen.
+         */
+        @NonNull
+        public Builder setWidth(@NonNull ContainerDimension width) {
+            mWidth = width;
+            return this;
+        }
+
+        /**
+         * Sets the width of {@link TitleChip}. If not set, default value will be set to fill the
+         * screen.
+         */
+        @NonNull
+        public Builder setWidth(@Dimension(unit = DP) float width) {
+            mWidth = dp(width);
+            return this;
+        }
+
+        /**
+         * Sets the custom content for the {@link Chip}. Any previously added content will be
+         * overridden.
+         */
+        @NonNull
+        public Builder setCustomContent(@NonNull LayoutElement content) {
+            this.mCustomContent = content;
+            this.mPrimaryLabel = "";
+            this.mSecondaryLabel = "";
+            this.mImageResourceId = "";
+            return this;
+        }
+
+        /**
+         * Sets the content description for the {@link Chip}. It is highly recommended to provide
+         * this for chip containing icon.
+         */
+        @NonNull
+        public Builder setContentDescription(@NonNull CharSequence contentDescription) {
+            this.mContentDescription = contentDescription;
+            return this;
+        }
+
+        /**
+         * Sets the primary label for the {@link Chip}. Any previously added custom content will be
+         * overridden. Primary label can be on 1 or 2 lines, depending on the length and existence
+         * of secondary label.
+         */
+        @NonNull
+        public Builder setPrimaryLabelContent(@NonNull String primaryLabel) {
+            this.mPrimaryLabel = primaryLabel;
+            this.mCustomContent = null;
+            return this;
+        }
+
+        /**
+         * Used for creating CompactChip and TitleChip.
+         *
+         * <p>Sets the font for the primary label and should only be used internally.
+         */
+        @NonNull
+        Builder setPrimaryLabelTypography(@TypographyName int typography) {
+            this.mPrimaryLabelTypography = typography;
+            return this;
+        }
+
+        /**
+         * Used for creating CompactChip and TitleChip.
+         *
+         * <p>Sets whether the font for the primary label is scalable.
+         */
+        @NonNull
+        Builder setIsPrimaryLabelScalable(boolean isScalable) {
+            this.mIsScalable = isScalable;
+            return this;
+        }
+
+        /**
+         * Sets the secondary label for the {@link Chip}. Any previously added custom content will
+         * be overridden. If secondary label is set, primary label must be set too with {@link
+         * #setPrimaryLabelContent}.
+         */
+        @NonNull
+        public Builder setSecondaryLabelContent(@NonNull String secondaryLabel) {
+            this.mSecondaryLabel = secondaryLabel;
+            this.mCustomContent = null;
+            return this;
+        }
+
+        /**
+         * Sets the icon for the {@link Chip}. Any previously added custom content will be
+         * overridden. Provided icon will be tinted to the given content color from {@link
+         * ChipColors}. This icon should be image with chosen alpha channel and not an actual image.
+         * If icon is set, primary label must be set too with {@link #setPrimaryLabelContent}.
+         */
+        @NonNull
+        public Builder setIconContent(@NonNull String imageResourceId) {
+            this.mImageResourceId = imageResourceId;
+            this.mCustomContent = null;
+            return this;
+        }
+
+        /**
+         * Sets the colors for the {@link Chip}. If set, {@link ChipColors#getBackgroundColor()}
+         * will be used for the background of the button, {@link ChipColors#getContentColor()} for
+         * main text, {@link ChipColors#getSecondaryContentColor()} for label text and {@link
+         * ChipColors#getIconColor()} will be used as color for the icon itself. If not set, {@link
+         * ChipDefaults#PRIMARY_COLORS} will be used.
+         */
+        @NonNull
+        public Builder setChipColors(@NonNull ChipColors chipColors) {
+            mChipColors = chipColors;
+            return this;
+        }
+
+        /**
+         * Sets the horizontal alignment in the chip. It is strongly recommended that the content of
+         * the chip is start-aligned if there is more than primary text in it. By default, {@link
+         * HorizontalAlignment#HORIZONTAL_ALIGN_CENTER} will be used when only a primary label is
+         * present. Otherwise {@link HorizontalAlignment#HORIZONTAL_ALIGN_START} will be used.
+         */
+        @NonNull
+        public Builder setHorizontalAlignment(@HorizontalAlignment int horizontalAlignment) {
+            mHorizontalAlign = horizontalAlignment;
+            return this;
+        }
+
+        /** Used for creating CompactChip and TitleChip. */
+        @NonNull
+        Builder setHorizontalPadding(@NonNull DpProp horizontalPadding) {
+            this.mHorizontalPadding = horizontalPadding;
+            return this;
+        }
+
+        /** Used for creating CompactChip and TitleChip. */
+        @NonNull
+        Builder setHeight(@NonNull DpProp height) {
+            this.mHeight = height;
+            return this;
+        }
+
+        /** Used for creating CompactChip and TitleChip. */
+        @NonNull
+        Builder setMaxLines(int maxLines) {
+            this.mMaxLines = maxLines;
+            return this;
+        }
+
+        /** Used for setting the correct tag in CompactChip and TitleChip. */
+        @NonNull
+        Builder setMetadataTag(@NonNull String metadataTag) {
+            this.mMetadataTag = metadataTag;
+            return this;
+        }
+
+        /** Constructs and returns {@link Chip} with the provided content and look. */
+        @NonNull
+        @Override
+        public Chip build() {
+            Modifiers.Builder modifiers =
+                    new Modifiers.Builder()
+                            .setClickable(mClickable)
+                            .setPadding(
+                                    new Padding.Builder()
+                                            .setStart(mHorizontalPadding)
+                                            .setEnd(mHorizontalPadding)
+                                            .build())
+                            .setBackground(
+                                    new Background.Builder()
+                                            .setColor(mChipColors.getBackgroundColor())
+                                            .setCorner(
+                                                    new Corner.Builder()
+                                                            .setRadius(radiusOf(mHeight))
+                                                            .build())
+                                            .build())
+                            .setMetadata(
+                                    new ElementMetadata.Builder()
+                                            .setTagData(getTagBytes(getCorrectMetadataTag()))
+                                            .build())
+                            .setSemantics(
+                                    new Semantics.Builder()
+                                            .setContentDescription(getCorrectContentDescription())
+                                            .build());
+
+            Box.Builder element =
+                    new Box.Builder()
+                            .setWidth(mWidth)
+                            .setHeight(mHeight)
+                            .setHorizontalAlignment(getCorrectHorizontalAlignment())
+                            .addContent(getCorrectContent())
+                            .setModifiers(modifiers.build());
+
+            return new Chip(element.build());
+        }
+
+        @NonNull
+        private String getCorrectContentDescription() {
+            if (mContentDescription.length() == 0) {
+                mContentDescription = "";
+                if (mPrimaryLabel != null) {
+                    mContentDescription += mPrimaryLabel;
+                }
+                if (mSecondaryLabel != null) {
+                    mContentDescription += "\n" + mSecondaryLabel;
+                }
+            }
+            return mContentDescription.toString();
+        }
+
+        @HorizontalAlignment
+        private int getCorrectHorizontalAlignment() {
+            if (mHorizontalAlign != HORIZONTAL_ALIGN_UNDEFINED) {
+                return mHorizontalAlign;
+            }
+            if (mPrimaryLabel != null && mSecondaryLabel == null && mImageResourceId == null) {
+                return HORIZONTAL_ALIGN_CENTER;
+            } else {
+                return HORIZONTAL_ALIGN_START;
+            }
+        }
+
+        private String getCorrectMetadataTag() {
+            if (!mMetadataTag.isEmpty()) {
+                return mMetadataTag;
+            }
+            if (mCustomContent != null) {
+                return METADATA_TAG_CUSTOM_CONTENT;
+            }
+            if (mImageResourceId != null) {
+                return METADATA_TAG_ICON;
+            }
+            return METADATA_TAG_TEXT;
+        }
+
+        @NonNull
+        private LayoutElement getCorrectContent() {
+            if (mCustomContent != null) {
+                return mCustomContent;
+            }
+
+            Text mainTextElement =
+                    new Text.Builder(mContext, checkNotNull(mPrimaryLabel))
+                            .setTypography(mPrimaryLabelTypography)
+                            .setColor(mChipColors.getContentColor())
+                            .setMaxLines(getCorrectMaxLines())
+                            .setOverflow(LayoutElementBuilders.TEXT_OVERFLOW_ELLIPSIZE_END)
+                            .setMultilineAlignment(LayoutElementBuilders.TEXT_ALIGN_START)
+                            .setIsScalable(mIsScalable)
+                            .build();
+
+            // Placeholder for text.
+            Column.Builder column =
+                    new Column.Builder()
+                            .setHorizontalAlignment(HORIZONTAL_ALIGN_START)
+                            .addContent(putLayoutInBox(mainTextElement).build());
+
+            if (mSecondaryLabel != null) {
+                Text labelTextElement =
+                        new Text.Builder(mContext, mSecondaryLabel)
+                                .setTypography(Typography.TYPOGRAPHY_CAPTION2)
+                                .setColor(mChipColors.getSecondaryContentColor())
+                                .setMaxLines(1)
+                                .setOverflow(LayoutElementBuilders.TEXT_OVERFLOW_ELLIPSIZE_END)
+                                .setMultilineAlignment(LayoutElementBuilders.TEXT_ALIGN_START)
+                                .build();
+                column.addContent(putLayoutInBox(labelTextElement).build());
+            }
+
+            Box texts = putLayoutInBox(column.build()).build();
+            if (mImageResourceId == null) {
+                return texts;
+            } else {
+                return new Row.Builder()
+                        .addContent(
+                                new Image.Builder()
+                                        .setResourceId(mImageResourceId)
+                                        .setWidth(ICON_SIZE)
+                                        .setHeight(ICON_SIZE)
+                                        .setColorFilter(
+                                                new ColorFilter.Builder()
+                                                        .setTint(mChipColors.getIconColor())
+                                                        .build())
+                                        .build())
+                        .addContent(
+                                new Spacer.Builder()
+                                        .setHeight(mHeight)
+                                        .setWidth(ICON_SPACER_WIDTH)
+                                        .build())
+                        .addContent(texts)
+                        .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER)
+                        .build();
+            }
+        }
+
+        private int getCorrectMaxLines() {
+            if (mMaxLines > 0) {
+                return mMaxLines;
+            }
+            return mSecondaryLabel != null ? 1 : 2;
+        }
+
+        private Box.Builder putLayoutInBox(@NonNull LayoutElement element) {
+            // Wrapped and centered content are default.
+            return new Box.Builder().addContent(element);
+        }
+    }
+
+    /** Returns height of this Chip. */
+    @NonNull
+    public ContainerDimension getHeight() {
+        return checkNotNull(mElement.getHeight());
+    }
+
+    /** Returns width of this Chip. */
+    @NonNull
+    public ContainerDimension getWidth() {
+        return checkNotNull(mElement.getWidth());
+    }
+
+    /** Returns click event action associated with this Chip. */
+    @NonNull
+    public Clickable getClickable() {
+        return checkNotNull(checkNotNull(mElement.getModifiers()).getClickable());
+    }
+
+    /** Returns background color of this Chip. */
+    @NonNull
+    private ColorProp getBackgroundColor() {
+        return checkNotNull(
+                checkNotNull(checkNotNull(mElement.getModifiers()).getBackground()).getColor());
+    }
+
+    /** Returns chip colors of this Chip. */
+    @NonNull
+    public ChipColors getChipColors() {
+        ColorProp backgroundColor = getBackgroundColor();
+        ColorProp contentColor = null;
+        ColorProp secondaryContentColor = null;
+        ColorProp iconTintColor = null;
+
+        if (!getMetadataTag().equals(METADATA_TAG_CUSTOM_CONTENT)) {
+            if (getMetadataTag().equals(METADATA_TAG_ICON)) {
+                Image icon = checkNotNull(getIconContentObject());
+                iconTintColor = checkNotNull(checkNotNull(icon.getColorFilter()).getTint());
+            }
+
+            contentColor = checkNotNull(getPrimaryLabelContentObject()).getColor();
+            Text label = getSecondaryLabelContentObject();
+            if (label != null) {
+                secondaryContentColor = label.getColor();
+            }
+        }
+
+        // Populate other colors if they are not found.
+        if (contentColor == null) {
+            contentColor = new ColorProp.Builder(0).build();
+        }
+        if (secondaryContentColor == null) {
+            secondaryContentColor = contentColor;
+        }
+        if (iconTintColor == null) {
+            iconTintColor = contentColor;
+        }
+
+        return new ChipColors(backgroundColor, iconTintColor, contentColor, secondaryContentColor);
+    }
+
+    /** Returns content description of this Chip. */
+    @Nullable
+    public CharSequence getContentDescription() {
+        Semantics semantics = checkNotNull(mElement.getModifiers()).getSemantics();
+        if (semantics == null) {
+            return null;
+        }
+        return semantics.getContentDescription();
+    }
+
+    /** Returns custom content from this Chip if it has been added. Otherwise, it returns null. */
+    @Nullable
+    public LayoutElement getCustomContent() {
+        if (getMetadataTag().equals(METADATA_TAG_CUSTOM_CONTENT)) {
+            return checkNotNull(checkNotNull(mElement.getContents()).get(0));
+        }
+        return null;
+    }
+
+    /** Returns primary label from this Chip if it has been added. Otherwise, it returns null. */
+    @Nullable
+    public String getPrimaryLabelContent() {
+        Text primaryLabel = getPrimaryLabelContentObject();
+        return primaryLabel != null ? primaryLabel.getText() : null;
+    }
+
+    /** Returns secondary label from this Chip if it has been added. Otherwise, it returns null. */
+    @Nullable
+    public String getSecondaryLabelContent() {
+        Text label = getSecondaryLabelContentObject();
+        return label != null ? label.getText() : null;
+    }
+
+    /** Returns icon id from this Chip if it has been added. Otherwise, it returns null. */
+    @Nullable
+    public String getIconContent() {
+        Image icon = getIconContentObject();
+        return icon != null ? checkNotNull(icon.getResourceId()).getValue() : null;
+    }
+
+    @Nullable
+    private Text getPrimaryLabelContentObject() {
+        return getPrimaryOrSecondaryLabelContent(0);
+    }
+
+    @Nullable
+    private Text getSecondaryLabelContentObject() {
+        return getPrimaryOrSecondaryLabelContent(1);
+    }
+
+    @Nullable
+    private Image getIconContentObject() {
+        if (!getMetadataTag().equals(METADATA_TAG_ICON)) {
+            return null;
+        }
+        return ((Image) ((Row) mElement.getContents().get(0)).getContents().get(0));
+    }
+
+    @Nullable
+    private Text getPrimaryOrSecondaryLabelContent(int index) {
+        String metadataTag = getMetadataTag();
+        if (metadataTag.equals(METADATA_TAG_CUSTOM_CONTENT)) {
+            return null;
+        }
+        // In any other case, text (either primary or primary + label) must be present.
+        Column content;
+        if (metadataTag.equals(METADATA_TAG_ICON)) {
+            content =
+                    (Column)
+                            ((Box) ((Row) mElement.getContents().get(0)).getContents().get(2))
+                                    .getContents()
+                                    .get(0);
+        } else {
+            content = (Column) ((Box) mElement.getContents().get(0)).getContents().get(0);
+        }
+
+        // We need to check this as this can be the case when we called for label, which doesn't
+        // exist.
+        return index < content.getContents().size()
+                ? Text.fromLayoutElement(
+                        ((Box) content.getContents().get(index)).getContents().get(0))
+                : null;
+    }
+
+    /** Returns the horizontal alignment of the content in this Chip. */
+    @HorizontalAlignment
+    public int getHorizontalAlignment() {
+        return checkNotNull(mElement.getHorizontalAlignment()).getValue();
+    }
+
+    /** Returns metadata tag set to this Chip. */
+    @NonNull
+    String getMetadataTag() {
+        return getMetadataTagName(
+                checkNotNull(checkNotNull(mElement.getModifiers()).getMetadata()));
+    }
+
+    /**
+     * Returns Chip object from the given LayoutElement (e.g. one retrieved from a container's
+     * content with {@code container.getContents().get(index)}) if that element can be converted to
+     * Chip. Otherwise, it will return null.
+     */
+    @Nullable
+    public static Chip fromLayoutElement(@NonNull LayoutElement element) {
+        if (element instanceof Chip) {
+            return (Chip) element;
+        }
+        if (!(element instanceof Box)) {
+            return null;
+        }
+        Box boxElement = (Box) element;
+        if (!checkTag(boxElement.getModifiers(), Builder.TYPE_TO_TAG.values())) {
+            return null;
+        }
+        // Now we are sure that this element is a Chip.
+        return new Chip(boxElement);
+    }
+
+    @NonNull
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public LayoutElementProto.LayoutElement toLayoutElementProto() {
+        return mElement.toLayoutElementProto();
+    }
+
+    @Nullable
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public Fingerprint getFingerprint() {
+        return mElement.getFingerprint();
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ChipColors.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ChipColors.java
new file mode 100644
index 0000000..a24e6c4
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ChipColors.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2021 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 androidx.wear.protolayout.material;
+
+import static androidx.wear.protolayout.ColorBuilders.argb;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.wear.protolayout.ColorBuilders.ColorProp;
+
+/**
+ * Represents the background and content colors used in a chip Tiles component.
+ *
+ * <p>See {@link ChipDefaults#PRIMARY_COLORS} for the default colors used in a primary styled {@link
+ * Chip}. See {@link ChipDefaults#SECONDARY_COLORS} for the default colors used in a secondary
+ * styled {@link Chip}.
+ */
+public class ChipColors {
+    @NonNull private final ColorProp mBackgroundColor;
+    @NonNull private final ColorProp mIconColor;
+    @NonNull private final ColorProp mContentColor;
+    @NonNull private final ColorProp mSecondaryContentColor;
+
+    /**
+     * Constructor for the {@link ChipColors} object.
+     *
+     * @param backgroundColor The background color to be used for a chip Tiles component. Should be
+     *     in ARGB format.
+     * @param iconColor The color to be used for an icon in a chip Tiles component. Should be in
+     *     ARGB format.
+     * @param contentColor The text color to be used for a main text in a chip Tiles component.
+     *     Should be in ARGB format.
+     * @param secondaryContentColor The text color to be used for a label text in a chip Tiles
+     *     component. Should be in ARGB format.
+     */
+    public ChipColors(
+            @ColorInt int backgroundColor,
+            @ColorInt int iconColor,
+            @ColorInt int contentColor,
+            @ColorInt int secondaryContentColor) {
+        mBackgroundColor = argb(backgroundColor);
+        mIconColor = argb(iconColor);
+        mContentColor = argb(contentColor);
+        mSecondaryContentColor = argb(secondaryContentColor);
+    }
+
+    /**
+     * Constructor for the {@link ChipColors} object.
+     *
+     * @param backgroundColor The background color to be used for a chip Tiles component. Should be
+     *     in ARGB format.
+     * @param contentColor The content color to be used for all items inside a chip Tiles component.
+     *     Should be in ARGB format.
+     */
+    public ChipColors(@ColorInt int backgroundColor, @ColorInt int contentColor) {
+        mBackgroundColor = argb(backgroundColor);
+        mIconColor = argb(contentColor);
+        mContentColor = argb(contentColor);
+        mSecondaryContentColor = argb(contentColor);
+    }
+
+    /**
+     * Constructor for the {@link ChipColors} object.
+     *
+     * @param backgroundColor The background color to be used for a chip Tiles component.
+     * @param iconColor The color to be used for an icon in a chip Tiles component.
+     * @param contentColor The text color to be used for a main text in a chip Tiles component.
+     * @param secondaryContentColor The text color to be used for a label text in a chip Tiles
+     *     component.
+     */
+    public ChipColors(
+            @NonNull ColorProp backgroundColor,
+            @NonNull ColorProp iconColor,
+            @NonNull ColorProp contentColor,
+            @NonNull ColorProp secondaryContentColor) {
+        mBackgroundColor = backgroundColor;
+        mIconColor = iconColor;
+        mContentColor = contentColor;
+        mSecondaryContentColor = secondaryContentColor;
+    }
+
+    /**
+     * Constructor for the {@link ChipColors} object.
+     *
+     * @param backgroundColor The background color to be used for a chip Tiles component.
+     * @param contentColor The content color to be used for all items inside a chip Tiles component.
+     */
+    public ChipColors(@NonNull ColorProp backgroundColor, @NonNull ColorProp contentColor) {
+        mBackgroundColor = backgroundColor;
+        mIconColor = contentColor;
+        mContentColor = contentColor;
+        mSecondaryContentColor = contentColor;
+    }
+
+    /**
+     * Returns a {@link ChipColors} object, using the current Primary colors from the given {@link
+     * Colors}.
+     */
+    @NonNull
+    public static ChipColors primaryChipColors(@NonNull Colors colors) {
+        return new ChipColors(colors.getPrimary(), colors.getOnPrimary());
+    }
+
+    /**
+     * Returns a {@link ChipColors} object, using the current Surface colors from the given {@link
+     * Colors}.
+     */
+    @NonNull
+    public static ChipColors secondaryChipColors(@NonNull Colors colors) {
+        return new ChipColors(colors.getSurface(), colors.getOnSurface());
+    }
+
+    /** The background color to be used on a chip Tiles components. */
+    @NonNull
+    public ColorProp getBackgroundColor() {
+        return mBackgroundColor;
+    }
+
+    /** The icon color to be used on a chip Tiles components. */
+    @NonNull
+    public ColorProp getIconColor() {
+        return mIconColor;
+    }
+
+    /** The main text color to be used on a chip Tiles components. */
+    @NonNull
+    public ColorProp getContentColor() {
+        return mContentColor;
+    }
+
+    /** The label text color to be used on a chip Tiles components. */
+    @NonNull
+    public ColorProp getSecondaryContentColor() {
+        return mSecondaryContentColor;
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ChipDefaults.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ChipDefaults.java
new file mode 100644
index 0000000..8059369
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ChipDefaults.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2021 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 androidx.wear.protolayout.material;
+
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+
+/** Contains the default values used by chip Tiles components. */
+public class ChipDefaults {
+    private ChipDefaults() {}
+
+    /**
+     * The default height for standard {@link Chip}
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static final DpProp DEFAULT_HEIGHT = dp(52);
+
+    /**
+     * The default height for standard {@link CompactChip}
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static final DpProp COMPACT_HEIGHT = dp(32);
+
+    /**
+     * The default height of tappable area for standard {@link CompactChip}
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static final DpProp COMPACT_HEIGHT_TAPPABLE = dp(48);
+
+    /**
+     * The default height for standard {@link TitleChip}
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static final DpProp TITLE_HEIGHT = dp(60);
+
+    /**
+     * The recommended horizontal margin used for width for standard {@link Chip}
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public static final float DEFAULT_MARGIN_PERCENT = 5.2f;
+
+    /**
+     * The recommended horizontal padding for standard {@link Chip}
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static final DpProp HORIZONTAL_PADDING = dp(14);
+
+    /**
+     * The recommended horizontal padding for standard {@link CompactChip}
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static final DpProp COMPACT_HORIZONTAL_PADDING = dp(12);
+
+    /**
+     * The recommended horizontal padding for standard {@link TitleChip}
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static final DpProp TITLE_HORIZONTAL_PADDING = dp(16);
+
+    /**
+     * The recommended vertical space between icon and text in standard {@link Chip}
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static final DpProp ICON_SPACER_WIDTH = dp(6);
+
+    /**
+     * The icon size used in standard {@link Chip}
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static final DpProp ICON_SIZE = dp(24);
+
+    /** The recommended colors for a primary {@link Chip}. */
+    @NonNull
+    public static final ChipColors PRIMARY_COLORS = ChipColors.primaryChipColors(Colors.DEFAULT);
+
+    /** The recommended colors for a secondary {@link Chip}. */
+    @NonNull
+    public static final ChipColors SECONDARY_COLORS =
+            ChipColors.secondaryChipColors(Colors.DEFAULT);
+
+    /** The recommended colors for a primary {@link CompactChip}. */
+    @NonNull
+    public static final ChipColors COMPACT_PRIMARY_COLORS =
+            ChipColors.primaryChipColors(Colors.DEFAULT);
+
+    /** The recommended colors for a secondary {@link CompactChip}. */
+    @NonNull
+    public static final ChipColors COMPACT_SECONDARY_COLORS =
+            ChipColors.secondaryChipColors(Colors.DEFAULT);
+
+    /** The recommended colors for a primary {@link TitleChip}. */
+    @NonNull
+    public static final ChipColors TITLE_PRIMARY_COLORS =
+            ChipColors.primaryChipColors(Colors.DEFAULT);
+
+    /** The recommended colors for a secondary {@link TitleChip}. */
+    @NonNull
+    public static final ChipColors TITLE_SECONDARY_COLORS =
+            ChipColors.secondaryChipColors(Colors.DEFAULT);
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/CircularProgressIndicator.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/CircularProgressIndicator.java
new file mode 100644
index 0000000..820be12
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/CircularProgressIndicator.java
@@ -0,0 +1,354 @@
+/*
+ * Copyright 2022 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 androidx.wear.protolayout.material;
+
+import static androidx.annotation.Dimension.DP;
+import static androidx.wear.protolayout.DimensionBuilders.degrees;
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+import static androidx.wear.protolayout.material.Helper.checkNotNull;
+import static androidx.wear.protolayout.material.Helper.checkTag;
+import static androidx.wear.protolayout.material.Helper.getMetadataTagName;
+import static androidx.wear.protolayout.material.Helper.getTagBytes;
+import static androidx.wear.protolayout.material.ProgressIndicatorDefaults.DEFAULT_COLORS;
+import static androidx.wear.protolayout.material.ProgressIndicatorDefaults.DEFAULT_END_ANGLE;
+import static androidx.wear.protolayout.material.ProgressIndicatorDefaults.DEFAULT_PADDING;
+import static androidx.wear.protolayout.material.ProgressIndicatorDefaults.DEFAULT_START_ANGLE;
+import static androidx.wear.protolayout.material.ProgressIndicatorDefaults.DEFAULT_STROKE_WIDTH;
+
+import androidx.annotation.Dimension;
+import androidx.annotation.FloatRange;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.DimensionBuilders.DegreesProp;
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+import androidx.wear.protolayout.LayoutElementBuilders;
+import androidx.wear.protolayout.LayoutElementBuilders.Arc;
+import androidx.wear.protolayout.LayoutElementBuilders.ArcLine;
+import androidx.wear.protolayout.LayoutElementBuilders.ArcSpacer;
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement;
+import androidx.wear.protolayout.ModifiersBuilders;
+import androidx.wear.protolayout.ModifiersBuilders.ElementMetadata;
+import androidx.wear.protolayout.ModifiersBuilders.Modifiers;
+import androidx.wear.protolayout.ModifiersBuilders.Padding;
+import androidx.wear.protolayout.ModifiersBuilders.Semantics;
+import androidx.wear.protolayout.expression.Fingerprint;
+import androidx.wear.protolayout.proto.LayoutElementProto;
+
+/**
+ * Tiles component {@link CircularProgressIndicator} that represents circular progress indicator
+ * which supports a gap in the circular track between startAngle and endAngle. [Progress Indicator
+ * doc] (https://developer.android.com/training/wearables/components/progress-indicator)
+ *
+ * <p>The CircularProgressIndicator is a colored arc around the edge of the screen with the given
+ * start and end angles, which can describe a full or partial circle. Behind it is an arc with
+ * optional gap representing full progress. The recommended sizes are defined in {@link
+ * ProgressIndicatorDefaults}. Unless specified, the CircularProgressIndicator will have the full
+ * length.
+ *
+ * <p>The recommended set of {@link ProgressIndicatorColors} can be obtained from {@link
+ * ProgressIndicatorDefaults}, e.g. {@link ProgressIndicatorDefaults#DEFAULT_COLORS} to get a
+ * default color scheme for a {@link CircularProgressIndicator}.
+ *
+ * <p>When accessing the contents of a container for testing, note that this element can't be simply
+ * casted back to the original type, i.e.:
+ *
+ * <pre>{@code
+ * CircularProgressIndicator cpi = new CircularProgressIndicator...
+ * Box box = new Box.Builder().addContent(cpi).build();
+ *
+ * CircularProgressIndicator myCpi = (CircularProgressIndicator) box.getContents().get(0);
+ * }</pre>
+ *
+ * will fail.
+ *
+ * <p>To be able to get {@link CircularProgressIndicator} object from any layout element, {@link
+ * #fromLayoutElement} method should be used, i.e.:
+ *
+ * <pre>{@code
+ * CircularProgressIndicator myCpi =
+ *   CircularProgressIndicator.fromLayoutElement(box.getContents().get(0));
+ * }</pre>
+ */
+public class CircularProgressIndicator implements LayoutElement {
+    /**
+     * Tool tag for Metadata in Modifiers, so we know that Arc is actually a
+     * CircularProgressIndicator.
+     */
+    static final String METADATA_TAG = "CPI";
+
+    @NonNull private final Arc mElement;
+    @NonNull private final ArcLine mProgress;
+    @NonNull private final ArcLine mBackground;
+
+    CircularProgressIndicator(@NonNull Arc element) {
+        this.mElement = element;
+        this.mBackground = (ArcLine) element.getContents().get(0);
+        this.mProgress = (ArcLine) element.getContents().get(2);
+    }
+
+    /** Builder class for {@link CircularProgressIndicator} */
+    public static final class Builder implements LayoutElement.Builder {
+        @NonNull private ProgressIndicatorColors mCircularProgressIndicatorColors = DEFAULT_COLORS;
+        @NonNull private DpProp mStrokeWidth = DEFAULT_STROKE_WIDTH;
+        @NonNull private CharSequence mContentDescription = "";
+        @NonNull private DegreesProp mStartAngle = degrees(DEFAULT_START_ANGLE);
+        @NonNull private DegreesProp mEndAngle = degrees(DEFAULT_END_ANGLE);
+
+        @FloatRange(from = 0, to = 1)
+        private float mProgress = 0;
+
+        /** Creates a builder for the {@link CircularProgressIndicator}. */
+        public Builder() {}
+
+        /**
+         * Sets the progress of the {@link CircularProgressIndicator}. Progress should be percentage
+         * from 0 to 1. Progress will be colored in {@link ProgressIndicatorColors#getTrackColor}.
+         * If not set, 0 will be used.
+         */
+        @NonNull
+        public Builder setProgress(@FloatRange(from = 0, to = 1) float progressPercentage) {
+            this.mProgress = progressPercentage;
+            return this;
+        }
+
+        /**
+         * Sets the start angle of the {@link CircularProgressIndicator}'s background arc, where
+         * angle 0 is 12 o'clock. Start angle doesn't need to be within 0-360 range. I.e. -90 is to
+         * start arc from the 9 o'clock. If not set 0 will be used and the indicator will have full
+         * length.
+         */
+        @NonNull
+        public Builder setStartAngle(float startAngle) {
+            this.mStartAngle = degrees(startAngle);
+            return this;
+        }
+
+        /**
+         * Sets the end angle of the {@link CircularProgressIndicator}'s background arc, where angle
+         * 0 is 12 o'clock. End angle doesn't need to be within 0-360 range, but it must be larger
+         * than start angle. If not set 360 will be used and the indicator will have full length.
+         */
+        @NonNull
+        public Builder setEndAngle(float endAngle) {
+            this.mEndAngle = degrees(endAngle);
+            return this;
+        }
+
+        /**
+         * Sets the content description of the {@link CircularProgressIndicator} to be used for
+         * accessibility support.
+         */
+        @NonNull
+        public Builder setContentDescription(@NonNull CharSequence contentDescription) {
+            this.mContentDescription = contentDescription;
+            return this;
+        }
+
+        /**
+         * Sets the colors for the {@link CircularProgressIndicator}. If set, {@link
+         * ProgressIndicatorColors#getIndicatorColor()} will be used for a progress that has been
+         * made, while {@link ProgressIndicatorColors#getTrackColor()} will be used for a background
+         * full size arc. If not set, {@link ProgressIndicatorDefaults#DEFAULT_COLORS} will be used.
+         */
+        @NonNull
+        public Builder setCircularProgressIndicatorColors(
+                @NonNull ProgressIndicatorColors circularProgressIndicatorColors) {
+            this.mCircularProgressIndicatorColors = circularProgressIndicatorColors;
+            return this;
+        }
+
+        /**
+         * Sets the stroke width of the {@link CircularProgressIndicator}. Strongly recommended
+         * value is {@link ProgressIndicatorDefaults#DEFAULT_STROKE_WIDTH}.
+         */
+        @NonNull
+        public Builder setStrokeWidth(@NonNull DpProp strokeWidth) {
+            this.mStrokeWidth = strokeWidth;
+            return this;
+        }
+
+        /**
+         * Sets the stroke width of the {@link CircularProgressIndicator}. Strongly recommended
+         * value is {@link ProgressIndicatorDefaults#DEFAULT_STROKE_WIDTH}.
+         */
+        @NonNull
+        public Builder setStrokeWidth(@Dimension(unit = DP) float strokeWidth) {
+            this.mStrokeWidth = dp(strokeWidth);
+            return this;
+        }
+
+        /**
+         * Constructs and returns {@link CircularProgressIndicator} with the provided field and
+         * look.
+         */
+        @NonNull
+        @Override
+        public CircularProgressIndicator build() {
+            checkAngles();
+
+            DegreesProp length = getLength();
+            Modifiers.Builder modifiers =
+                    new Modifiers.Builder()
+                            .setPadding(new Padding.Builder().setAll(DEFAULT_PADDING).build())
+                            .setMetadata(
+                                    new ElementMetadata.Builder()
+                                            .setTagData(getTagBytes(METADATA_TAG))
+                                            .build());
+
+            if (mContentDescription.length() > 0) {
+                modifiers.setSemantics(
+                        new ModifiersBuilders.Semantics.Builder()
+                                .setContentDescription(mContentDescription.toString())
+                                .build());
+            }
+
+            Arc.Builder element =
+                    new Arc.Builder()
+                            .setAnchorType(LayoutElementBuilders.ARC_ANCHOR_START)
+                            .setAnchorAngle(mStartAngle)
+                            .setModifiers(modifiers.build())
+                            .addContent(
+                                    new ArcLine.Builder()
+                                            .setColor(
+                                                    mCircularProgressIndicatorColors
+                                                            .getTrackColor())
+                                            .setThickness(mStrokeWidth)
+                                            .setLength(length)
+                                            .build())
+                            .addContent(
+                                    // Fill in the space to make a full circle, so that progress is
+                                    // correctly aligned.
+                                    new ArcSpacer.Builder()
+                                            .setLength(degrees(360 - length.getValue()))
+                                            .build())
+                            .addContent(
+                                    new ArcLine.Builder()
+                                            .setColor(
+                                                    mCircularProgressIndicatorColors
+                                                            .getIndicatorColor())
+                                            .setThickness(mStrokeWidth)
+                                            .setLength(degrees(mProgress * length.getValue()))
+                                            .build());
+            return new CircularProgressIndicator(element.build());
+        }
+
+        private void checkAngles() {
+            if (mEndAngle.getValue() < mStartAngle.getValue()) {
+                throw new IllegalArgumentException("End angle must be bigger than start angle.");
+            }
+        }
+
+        @NonNull
+        private DegreesProp getLength() {
+            float startAngle = mStartAngle.getValue();
+            float endAngle = mEndAngle.getValue();
+            if (endAngle <= startAngle) {
+                endAngle += 360;
+            }
+            return degrees(endAngle - startAngle);
+        }
+    }
+
+    /** Returns angle representing progressed part of this CircularProgressIndicator. */
+    @NonNull
+    public DegreesProp getProgress() {
+        return checkNotNull(mProgress.getLength());
+    }
+
+    /** Returns stroke width of this CircularProgressIndicator. */
+    @NonNull
+    public DpProp getStrokeWidth() {
+        return checkNotNull(mProgress.getThickness());
+    }
+
+    /** Returns start angle of this CircularProgressIndicator. */
+    @NonNull
+    public DegreesProp getStartAngle() {
+        return checkNotNull(mElement.getAnchorAngle());
+    }
+
+    /** Returns start angle of this CircularProgressIndicator. */
+    @NonNull
+    public DegreesProp getEndAngle() {
+        float backArcLength = checkNotNull(mBackground.getLength()).getValue();
+        return degrees(getStartAngle().getValue() + backArcLength);
+    }
+
+    /** Returns main arc color of this CircularProgressIndicator. */
+    @NonNull
+    public ProgressIndicatorColors getCircularProgressIndicatorColors() {
+        return new ProgressIndicatorColors(
+                checkNotNull(mProgress.getColor()), checkNotNull(mBackground.getColor()));
+    }
+
+    /** Returns content description of this CircularProgressIndicator. */
+    @Nullable
+    public CharSequence getContentDescription() {
+        Semantics semantics = checkNotNull(mElement.getModifiers()).getSemantics();
+        if (semantics == null) {
+            return null;
+        }
+        return semantics.getContentDescription();
+    }
+
+    /**
+     * Returns metadata tag set to this CircularProgressIndicator, which should be {@link
+     * #METADATA_TAG}.
+     */
+    @NonNull
+    String getMetadataTag() {
+        return getMetadataTagName(
+                checkNotNull(checkNotNull(mElement.getModifiers()).getMetadata()));
+    }
+
+    /**
+     * Returns CircularProgressIndicator object from the given LayoutElement (e.g. one retrieved
+     * from a container's content with {@code container.getContents().get(index)}) if that element
+     * can be converted to CircularProgressIndicator. Otherwise, it will return null.
+     */
+    @Nullable
+    public static CircularProgressIndicator fromLayoutElement(@NonNull LayoutElement element) {
+        if (element instanceof CircularProgressIndicator) {
+            return (CircularProgressIndicator) element;
+        }
+        if (!(element instanceof Arc)) {
+            return null;
+        }
+        Arc arcElement = (Arc) element;
+        if (!checkTag(arcElement.getModifiers(), METADATA_TAG)) {
+            return null;
+        }
+        // Now we are sure that this element is a CircularProgressIndicator.
+        return new CircularProgressIndicator(arcElement);
+    }
+
+    @NonNull
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public LayoutElementProto.LayoutElement toLayoutElementProto() {
+        return mElement.toLayoutElementProto();
+    }
+
+    @Nullable
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public Fingerprint getFingerprint() {
+        return mElement.getFingerprint();
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Colors.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Colors.java
new file mode 100644
index 0000000..84026bd
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Colors.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2021 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 androidx.wear.protolayout.material;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+
+/**
+ * Represent the container for default color scheme in your Tile, that can be used to create color
+ * objects for all Material components.
+ *
+ * <p>See {@link #DEFAULT} for default color scheme.
+ */
+public class Colors {
+
+    /**
+     * The default color used for primary elements (i.e. background color).
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @ColorInt
+    public static final int PRIMARY = 0xFFAECBFA;
+
+    /**
+     * The default color used on primary elements (i.e. content color).
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @ColorInt
+    public static final int ON_PRIMARY = 0xFF303133;
+
+    /**
+     * The default color used for secondary elements (i.e. background color).
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @ColorInt
+    public static final int SURFACE = 0xFF303133;
+
+    /**
+     * The default color used on secondary elements (i.e. content color).
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @ColorInt
+    public static final int ON_SURFACE = 0xFFFFFFFF;
+
+    /** The default color scheme to be used in Tiles Material components. */
+    @NonNull
+    public static final Colors DEFAULT = new Colors(PRIMARY, ON_PRIMARY, SURFACE, ON_SURFACE);
+
+    private @ColorInt final int mPrimary;
+    private @ColorInt final int mOnPrimary;
+    private @ColorInt final int mSurface;
+    private @ColorInt final int mOnSurface;
+
+    /**
+     * Constructor for {@link Colors} object.
+     *
+     * @param primary The background color to be used for primary components. Should be in ARGB
+     *     format.
+     * @param onPrimary The content color or tint color to be used for primary components. Should be
+     *     in ARGB format.
+     * @param surface The background color to be used for secondary components. Should be in ARGB
+     *     format.
+     * @param onSurface The content color or tint color to be used for secondary components. Should
+     *     be in ARGB format.
+     */
+    public Colors(
+            @ColorInt int primary,
+            @ColorInt int onPrimary,
+            @ColorInt int surface,
+            @ColorInt int onSurface) {
+        this.mPrimary = primary;
+        this.mOnPrimary = onPrimary;
+        this.mSurface = surface;
+        this.mOnSurface = onSurface;
+    }
+
+    /** The primary color to be used on components. */
+    @ColorInt
+    public int getPrimary() {
+        return mPrimary;
+    }
+
+    /** The onPrimary color to be used on components. */
+    @ColorInt
+    public int getOnPrimary() {
+        return mOnPrimary;
+    }
+
+    /** The surface color to be used on components. */
+    @ColorInt
+    public int getSurface() {
+        return mSurface;
+    }
+
+    /** The onSurface color to be used on components. */
+    @ColorInt
+    public int getOnSurface() {
+        return mOnSurface;
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/CompactChip.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/CompactChip.java
new file mode 100644
index 0000000..58bf3b8
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/CompactChip.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2021 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 androidx.wear.protolayout.material;
+
+import static androidx.wear.protolayout.DimensionBuilders.wrap;
+import static androidx.wear.protolayout.LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER;
+import static androidx.wear.protolayout.material.ChipDefaults.COMPACT_HEIGHT;
+import static androidx.wear.protolayout.material.ChipDefaults.COMPACT_HEIGHT_TAPPABLE;
+import static androidx.wear.protolayout.material.ChipDefaults.COMPACT_HORIZONTAL_PADDING;
+import static androidx.wear.protolayout.material.ChipDefaults.COMPACT_PRIMARY_COLORS;
+import static androidx.wear.protolayout.material.Helper.checkNotNull;
+import static androidx.wear.protolayout.material.Helper.checkTag;
+import static androidx.wear.protolayout.material.Helper.getTagBytes;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters;
+import androidx.wear.protolayout.LayoutElementBuilders;
+import androidx.wear.protolayout.LayoutElementBuilders.Box;
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement;
+import androidx.wear.protolayout.ModifiersBuilders.Clickable;
+import androidx.wear.protolayout.ModifiersBuilders.ElementMetadata;
+import androidx.wear.protolayout.ModifiersBuilders.Modifiers;
+import androidx.wear.protolayout.expression.Fingerprint;
+import androidx.wear.protolayout.proto.LayoutElementProto;
+
+/**
+ * Tiles component {@link CompactChip} that represents clickable object with the text.
+ *
+ * <p>The Chip is Stadium shape and has a max height designed to take no more than one line of text
+ * of {@link Typography#TYPOGRAPHY_CAPTION1} style. Width of the chip is adjustable to the text
+ * size.
+ *
+ * <p>The recommended set of {@link ChipColors} styles can be obtained from {@link ChipDefaults}.,
+ * e.g. {@link ChipDefaults#COMPACT_PRIMARY_COLORS} to get a color scheme for a primary {@link
+ * CompactChip}.
+ *
+ * <p>When accessing the contents of a container for testing, note that this element can't be simply
+ * casted back to the original type, i.e.:
+ *
+ * <pre>{@code
+ * CompactChip chip = new CompactChip...
+ * Box box = new Box.Builder().addContent(chip).build();
+ *
+ * CompactChip myChip = (CompactChip) box.getContents().get(0);
+ * }</pre>
+ *
+ * will fail.
+ *
+ * <p>To be able to get {@link CompactChip} object from any layout element, {@link
+ * #fromLayoutElement} method should be used, i.e.:
+ *
+ * <pre>{@code
+ * CompactChip myChip = CompactChip.fromLayoutElement(box.getContents().get(0));
+ * }</pre>
+ */
+public class CompactChip implements LayoutElement {
+    /** Tool tag for Metadata in Modifiers, so we know that Box is actually a CompactChip. */
+    static final String METADATA_TAG = "CMPCHP";
+
+    @NonNull private final Box mImpl;
+    @NonNull private final Chip mElement;
+
+    CompactChip(@NonNull Box element) {
+        this.mImpl = element;
+        // We know for sure that content of the Box is Chip.
+        this.mElement = new Chip((Box) element.getContents().get(0));
+    }
+
+    /** Builder class for {@link androidx.wear.protolayout.material.CompactChip}. */
+    public static final class Builder implements LayoutElement.Builder {
+        @NonNull private final Context mContext;
+        @NonNull private final String mText;
+        @NonNull private final Clickable mClickable;
+        @NonNull private final DeviceParameters mDeviceParameters;
+        @NonNull private ChipColors mChipColors = COMPACT_PRIMARY_COLORS;
+
+        /**
+         * Creates a builder for the {@link CompactChip} with associated action and the given text
+         *
+         * @param context The application's context.
+         * @param text The text to be displayed in this compact chip.
+         * @param clickable Associated {@link Clickable} for click events. When the CompactChip is
+         *     clicked it will fire the associated action.
+         * @param deviceParameters The device parameters used for styling text.
+         */
+        public Builder(
+                @NonNull Context context,
+                @NonNull String text,
+                @NonNull Clickable clickable,
+                @NonNull DeviceParameters deviceParameters) {
+            this.mContext = context;
+            this.mText = text;
+            this.mClickable = clickable;
+            this.mDeviceParameters = deviceParameters;
+        }
+
+        /**
+         * Sets the colors for the {@link CompactChip}. If set, {@link
+         * ChipColors#getBackgroundColor()} will be used for the background of the button and {@link
+         * ChipColors#getContentColor()} for the text. If not set, {@link
+         * ChipDefaults#COMPACT_PRIMARY_COLORS} will be used.
+         */
+        @NonNull
+        public Builder setChipColors(@NonNull ChipColors chipColors) {
+            mChipColors = chipColors;
+            return this;
+        }
+
+        /** Constructs and returns {@link CompactChip} with the provided content and look. */
+        @NonNull
+        @Override
+        public CompactChip build() {
+            Chip.Builder chipBuilder =
+                    new Chip.Builder(mContext, mClickable, mDeviceParameters)
+                            .setMetadataTag(METADATA_TAG)
+                            .setChipColors(mChipColors)
+                            .setContentDescription(mText)
+                            .setHorizontalAlignment(HORIZONTAL_ALIGN_CENTER)
+                            .setWidth(wrap())
+                            .setHeight(COMPACT_HEIGHT)
+                            .setMaxLines(1)
+                            .setHorizontalPadding(COMPACT_HORIZONTAL_PADDING)
+                            .setPrimaryLabelContent(mText)
+                            .setPrimaryLabelTypography(Typography.TYPOGRAPHY_CAPTION1)
+                            .setIsPrimaryLabelScalable(false);
+
+            Box tappableChip =
+                    new Box.Builder()
+                            .setModifiers(
+                                    new Modifiers.Builder()
+                                            .setClickable(mClickable)
+                                            .setMetadata(
+                                                    new ElementMetadata.Builder()
+                                                            .setTagData(getTagBytes(METADATA_TAG))
+                                                            .build())
+                                            .build())
+                            .setWidth(wrap())
+                            .setHeight(COMPACT_HEIGHT_TAPPABLE)
+                            .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER)
+                            .addContent(chipBuilder.build())
+                            .build();
+
+            return new CompactChip(tappableChip);
+        }
+    }
+
+    /** Returns click event action associated with this Chip. */
+    @NonNull
+    public Clickable getClickable() {
+        return mElement.getClickable();
+    }
+
+    /** Returns chip color of this Chip. */
+    @NonNull
+    public ChipColors getChipColors() {
+        return mElement.getChipColors();
+    }
+
+    /** Returns text content of this Chip. */
+    @NonNull
+    public String getText() {
+        return checkNotNull(mElement.getPrimaryLabelContent());
+    }
+
+    /** Returns metadata tag set to this CompactChip, which should be {@link #METADATA_TAG}. */
+    @NonNull
+    String getMetadataTag() {
+        return mElement.getMetadataTag();
+    }
+
+    /**
+     * Returns CompactChip object from the given LayoutElement (e.g. one retrieved from a
+     * container's content with {@code container.getContents().get(index)}) if that element can be
+     * converted to CompactChip. Otherwise, it will return null.
+     */
+    @Nullable
+    public static CompactChip fromLayoutElement(@NonNull LayoutElement element) {
+        if (element instanceof CompactChip) {
+            return (CompactChip) element;
+        }
+        if (!(element instanceof Box)) {
+            return null;
+        }
+        Box boxElement = (Box) element;
+        if (!checkTag(boxElement.getModifiers(), METADATA_TAG)) {
+            return null;
+        }
+        // Now to check that inner content of the Box is CompactChip's Chip.
+        LayoutElement innerElement = boxElement.getContents().get(0);
+        if (!(innerElement instanceof Box)) {
+            return null;
+        }
+        Box innerBoxElement = (Box) innerElement;
+        if (!checkTag(innerBoxElement.getModifiers(), METADATA_TAG)) {
+            return null;
+        }
+
+        // Now we are sure that this element is a CompactChip.
+        return new CompactChip(boxElement);
+    }
+
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    @Override
+    public LayoutElementProto.LayoutElement toLayoutElementProto() {
+        return mImpl.toLayoutElementProto();
+    }
+
+    @Nullable
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public Fingerprint getFingerprint() {
+        return mImpl.getFingerprint();
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/DeleteMe.kt b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/DeleteMe.kt
new file mode 100644
index 0000000..8f2cad2
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/DeleteMe.kt
@@ -0,0 +1,17 @@
+package androidx.wear.protolayout.material/*
+ * Copyright 2022 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.
+ */
+
+// This file exists to trick AGP/lint to work around b/234865137
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Helper.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Helper.java
new file mode 100644
index 0000000..630bf29
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Helper.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2021 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 androidx.wear.protolayout.material;
+
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.DeviceParametersBuilders;
+import androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters;
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+import androidx.wear.protolayout.ModifiersBuilders.ElementMetadata;
+import androidx.wear.protolayout.ModifiersBuilders.Modifiers;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Collection;
+
+/**
+ * Helper class used for Tiles Material.
+ *
+ */
+@RestrictTo(Scope.LIBRARY_GROUP)
+public class Helper {
+    private Helper() {}
+
+    /**
+     * Returns given value if not null or throws {@code NullPointerException} otherwise.
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static <T> T checkNotNull(@Nullable T value) {
+        if (value == null) {
+            throw new NullPointerException();
+        }
+        return value;
+    }
+
+    /** Returns radius in {@link DpProp} of the given diameter. */
+    @NonNull
+    static DpProp radiusOf(DpProp diameter) {
+        return dp(diameter.getValue() / 2);
+    }
+
+    /**
+     * Returns true if the given DeviceParameters belong to the round screen device.
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public static boolean isRoundDevice(@NonNull DeviceParameters deviceParameters) {
+        return deviceParameters.getScreenShape() == DeviceParametersBuilders.SCREEN_SHAPE_ROUND;
+    }
+
+    /**
+     * Returns String representation of tag from byte array.
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static String getTagName(@NonNull byte[] tagData) {
+        return new String(tagData, StandardCharsets.UTF_8);
+    }
+
+    /**
+     * Returns byte array representation of tag from String.
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static byte[] getTagBytes(@NonNull String tagName) {
+        return tagName.getBytes(StandardCharsets.UTF_8);
+    }
+
+    /** Returns the String representation of metadata tag from the given ElementMetadata. */
+    @NonNull
+    public static String getMetadataTagName(@NonNull ElementMetadata metadata) {
+        return getTagName(getMetadataTagBytes(metadata));
+    }
+
+    /** Returns the metadata tag from the given ElementMetadata. */
+    @NonNull
+    public static byte[] getMetadataTagBytes(@NonNull ElementMetadata metadata) {
+        return checkNotNull(metadata).getTagData();
+    }
+
+    /** Returns true if the given Modifiers have Metadata tag set to the given String value. */
+    public static boolean checkTag(@Nullable Modifiers modifiers, @NonNull String validTag) {
+        return modifiers != null
+                && modifiers.getMetadata() != null
+                && validTag.equals(getMetadataTagName(modifiers.getMetadata()));
+    }
+
+    /**
+     * Returns true if the given Modifiers have Metadata tag set to any of the value in the given
+     * String collection.
+     */
+    public static boolean checkTag(
+            @Nullable Modifiers modifiers, @NonNull Collection<String> validTags) {
+        return modifiers != null
+                && modifiers.getMetadata() != null
+                && validTags.contains(getMetadataTagName(modifiers.getMetadata()));
+    }
+
+    /**
+     * Returns true if the given Modifiers have Metadata tag set with prefix that is equal to the
+     * given String and its length is of the given base array.
+     */
+    public static boolean checkTag(
+            @Nullable Modifiers modifiers, @NonNull String validPrefix, @NonNull byte[] validBase) {
+        if (modifiers == null || modifiers.getMetadata() == null) {
+            return false;
+        }
+        byte[] metadataTag = getMetadataTagBytes(modifiers.getMetadata());
+        byte[] tag = Arrays.copyOf(metadataTag, validPrefix.length());
+        return metadataTag.length == validBase.length && validPrefix.equals(getTagName(tag));
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ProgressIndicatorColors.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ProgressIndicatorColors.java
new file mode 100644
index 0000000..668fe3e
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ProgressIndicatorColors.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2021 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 androidx.wear.protolayout.material;
+
+import static androidx.wear.protolayout.ColorBuilders.argb;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.wear.protolayout.ColorBuilders.ColorProp;
+
+/**
+ * Represents the indicator and track colors used in a progress indicator Tiles component.
+ *
+ * <p>See {@link ProgressIndicatorDefaults#DEFAULT_COLORS} for the default colors used in a {@link
+ * CircularProgressIndicator}.
+ */
+public class ProgressIndicatorColors {
+    @NonNull private final ColorProp mIndicatorColor;
+    @NonNull private final ColorProp mTrackColor;
+
+    /**
+     * Constructor for {@link ProgressIndicatorColors} object.
+     *
+     * @param indicatorColor The indicator color to be used for a progress indicator Tiles
+     *     component.
+     * @param trackColor The background track color to be used for a progress indicator Tiles
+     *     component.
+     */
+    public ProgressIndicatorColors(
+            @NonNull ColorProp indicatorColor, @NonNull ColorProp trackColor) {
+        this.mIndicatorColor = indicatorColor;
+        this.mTrackColor = trackColor;
+    }
+
+    /**
+     * Constructor for {@link ProgressIndicatorColors} object.
+     *
+     * @param indicatorColor The indicator color to be used for a progress indicator Tiles
+     *     component. Should be in ARGB format.
+     * @param trackColor The background track color to be used for a progress indicator Tiles
+     *     component. Should be in ARGB format.
+     */
+    public ProgressIndicatorColors(@ColorInt int indicatorColor, @ColorInt int trackColor) {
+        this.mIndicatorColor = argb(indicatorColor);
+        this.mTrackColor = argb(trackColor);
+    }
+
+    /**
+     * Returns a {@link ProgressIndicatorColors} object, using the current Primary color for
+     * indicator color and the current Surface color for the track color from the given {@link
+     * Colors}.
+     */
+    @NonNull
+    public static ProgressIndicatorColors progressIndicatorColors(@NonNull Colors colors) {
+        return new ProgressIndicatorColors(colors.getPrimary(), colors.getSurface());
+    }
+
+    /** The indicator color to be used for a progress indicator Tiles component. */
+    @NonNull
+    public ColorProp getIndicatorColor() {
+        return mIndicatorColor;
+    }
+
+    /** The background track color to be used for a progress indicator Tiles component. */
+    @NonNull
+    public ColorProp getTrackColor() {
+        return mTrackColor;
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ProgressIndicatorDefaults.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ProgressIndicatorDefaults.java
new file mode 100644
index 0000000..dd2f9cf
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ProgressIndicatorDefaults.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2021 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 androidx.wear.protolayout.material;
+
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+
+/** Contains the default values used by {@link CircularProgressIndicator} Tiles components. */
+public class ProgressIndicatorDefaults {
+    private ProgressIndicatorDefaults() {}
+
+    /** The default stroke width for {@link CircularProgressIndicator} */
+    @NonNull public static final DpProp DEFAULT_STROKE_WIDTH = dp(8);
+
+    /**
+     * The default padding for {@link CircularProgressIndicator}
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static final DpProp DEFAULT_PADDING = dp(6);
+
+    /** The recommended colors for {@link CircularProgressIndicator}. */
+    @NonNull
+    public static final ProgressIndicatorColors DEFAULT_COLORS =
+            ProgressIndicatorColors.progressIndicatorColors(Colors.DEFAULT);
+
+    static final float DEFAULT_GAP_LENGTH = 47.8f;
+
+    /** The recommended start angle for {@link CircularProgressIndicator} if there's a gap. */
+    public static final float GAP_START_ANGLE = 180 + DEFAULT_GAP_LENGTH / 2 - 360;
+
+    /** The recommended end angle for {@link CircularProgressIndicator} if there's a gap. */
+    public static final float GAP_END_ANGLE = 180 - DEFAULT_GAP_LENGTH / 2;
+
+    /** Start angle for full length {@link CircularProgressIndicator}. */
+    static final float DEFAULT_START_ANGLE = 0;
+
+    /** End angle for full length {@link CircularProgressIndicator}. */
+    static final float DEFAULT_END_ANGLE = 360;
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Text.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Text.java
new file mode 100644
index 0000000..ed5e309
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Text.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright 2022 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 androidx.wear.protolayout.material;
+
+import static androidx.wear.protolayout.ColorBuilders.argb;
+import static androidx.wear.protolayout.LayoutElementBuilders.TEXT_ALIGN_CENTER;
+import static androidx.wear.protolayout.LayoutElementBuilders.TEXT_OVERFLOW_ELLIPSIZE_END;
+import static androidx.wear.protolayout.material.Helper.checkNotNull;
+import static androidx.wear.protolayout.material.Typography.TYPOGRAPHY_DISPLAY1;
+import static androidx.wear.protolayout.material.Typography.getFontStyleBuilder;
+import static androidx.wear.protolayout.material.Typography.getLineHeightForTypography;
+
+import android.content.Context;
+
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.ColorBuilders.ColorProp;
+import androidx.wear.protolayout.LayoutElementBuilders;
+import androidx.wear.protolayout.LayoutElementBuilders.FontStyle;
+import androidx.wear.protolayout.LayoutElementBuilders.FontWeight;
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement;
+import androidx.wear.protolayout.LayoutElementBuilders.TextAlignment;
+import androidx.wear.protolayout.LayoutElementBuilders.TextOverflow;
+import androidx.wear.protolayout.ModifiersBuilders.Modifiers;
+import androidx.wear.protolayout.expression.Fingerprint;
+import androidx.wear.protolayout.material.Typography.TypographyName;
+import androidx.wear.protolayout.proto.LayoutElementProto;
+
+/**
+ * Tiles component {@link Text} that represents text object holding any information.
+ *
+ * <p>There are pre-built typography styles that can be obtained from constants in {@link
+ * FontStyle}.
+ *
+ * <p>When accessing the contents of a container for testing, note that this element can't be simply
+ * casted back to the original type, i.e.:
+ *
+ * <pre>{@code
+ * Text text = new Text...
+ * Box box = new Box.Builder().addContent(text).build();
+ *
+ * Text myText = (Text) box.getContents().get(0);
+ * }</pre>
+ *
+ * will fail.
+ *
+ * <p>To be able to get {@link Text} object from any layout element, {@link #fromLayoutElement}
+ * method should be used, i.e.:
+ *
+ * <pre>{@code
+ * Text myText = Text.fromLayoutElement(box.getContents().get(0));
+ * }</pre>
+ */
+public class Text implements LayoutElement {
+
+    @NonNull private final LayoutElementBuilders.Text mText;
+
+    Text(@NonNull LayoutElementBuilders.Text mText) {
+        this.mText = mText;
+    }
+
+    /** Builder class for {@link Text}. */
+    public static final class Builder implements LayoutElement.Builder {
+        @NonNull private final Context mContext;
+        @NonNull private String mTextContent = "";
+        @NonNull private ColorProp mColor = argb(Colors.DEFAULT.getOnPrimary());
+        private @TypographyName int mTypographyName = TYPOGRAPHY_DISPLAY1;
+        private boolean mItalic = false;
+        private int mMaxLines = 1;
+        private boolean mUnderline = false;
+        @TextAlignment private int mMultilineAlignment = TEXT_ALIGN_CENTER;
+        @NonNull private Modifiers mModifiers = new Modifiers.Builder().build();
+        private @TextOverflow int mOverflow = TEXT_OVERFLOW_ELLIPSIZE_END;
+        private boolean mIsScalable = true;
+        @Nullable private Integer mCustomWeight = null;
+
+        /**
+         * Creates a builder for {@link Text}.
+         *
+         * @param context The application's context.
+         * @param text The text content for this component.
+         */
+        public Builder(@NonNull Context context, @NonNull String text) {
+            mContext = context;
+            mTextContent = text;
+        }
+
+        /**
+         * Sets the typography for the {@link Text}. If not set, {@link
+         * Typography#TYPOGRAPHY_DISPLAY1} will be used.
+         */
+        @NonNull
+        @SuppressWarnings("MissingGetterMatchingBuilder")
+        // There is getFontStyle matching getter for this setter as the serialized format of the
+        // Tiles do not allow for a direct reconstruction of the all arguments, but it has FontStyle
+        // object of that text.
+        public Builder setTypography(@TypographyName int typography) {
+            this.mTypographyName = typography;
+            return this;
+        }
+
+        /**
+         * Sets whether the text size will change if user has changed the default font size. If not
+         * set, true will be used.
+         */
+        Builder setIsScalable(boolean isScalable) {
+            this.mIsScalable = isScalable;
+            return this;
+        }
+
+        /**
+         * Sets the color for the {@link Text}. If not set, onPrimary color from the {@link
+         * Colors#DEFAULT} will be used.
+         */
+        @NonNull
+        public Builder setColor(@NonNull ColorProp color) {
+            this.mColor = color;
+            return this;
+        }
+
+        /** Sets the text to be italic. If not set, false will be used. */
+        @NonNull
+        public Builder setItalic(boolean italic) {
+            this.mItalic = italic;
+            return this;
+        }
+
+        /** Sets the text to be underlined. If not set, false will be used. */
+        @NonNull
+        public Builder setUnderline(boolean underline) {
+            this.mUnderline = underline;
+            return this;
+        }
+
+        /** Sets the maximum lines of text. If not set, 1 will be used. */
+        @NonNull
+        public Builder setMaxLines(@IntRange(from = 1) int maxLines) {
+            this.mMaxLines = maxLines;
+            return this;
+        }
+
+        /**
+         * Sets the multiline alignment for text within bounds of the Text element. Note that this
+         * option has no effect for single line of text, and for that, alignment on the outer
+         * container should be used. If not set, {@link TextAlignment#TEXT_ALIGN_CENTER} will be
+         * used.
+         */
+        @NonNull
+        public Builder setMultilineAlignment(@TextAlignment int multilineAlignment) {
+            this.mMultilineAlignment = multilineAlignment;
+            return this;
+        }
+
+        /** Sets the modifiers of text. */
+        @NonNull
+        public Builder setModifiers(@NonNull Modifiers modifiers) {
+            this.mModifiers = modifiers;
+            return this;
+        }
+
+        /**
+         * Sets the overflow for text. If not set, {@link TextAlignment#TEXT_OVERFLOW_ELLIPSIZE_END}
+         * will be used.
+         */
+        @NonNull
+        public Builder setOverflow(@TextOverflow int overflow) {
+            this.mOverflow = overflow;
+            return this;
+        }
+
+        /**
+         * Sets the weight of the font. If not set, default weight for the chosen Typography will be
+         * used.
+         */
+        @NonNull
+        public Builder setWeight(@FontWeight int weight) {
+            this.mCustomWeight = weight;
+            return this;
+        }
+
+        /** Constructs and returns {@link Text} with the provided content and look. */
+        @NonNull
+        @Override
+        public Text build() {
+            FontStyle.Builder fontStyleBuilder =
+                    getFontStyleBuilder(mTypographyName, mContext, mIsScalable)
+                            .setColor(mColor)
+                            .setItalic(mItalic)
+                            .setUnderline(mUnderline);
+            if (mCustomWeight != null) {
+                fontStyleBuilder.setWeight(mCustomWeight);
+            }
+
+            LayoutElementBuilders.Text.Builder text =
+                    new LayoutElementBuilders.Text.Builder()
+                            .setText(mTextContent)
+                            .setFontStyle(fontStyleBuilder.build())
+                            .setLineHeight(getLineHeightForTypography(mTypographyName))
+                            .setMaxLines(mMaxLines)
+                            .setMultilineAlignment(mMultilineAlignment)
+                            .setModifiers(mModifiers)
+                            .setOverflow(mOverflow);
+            return new Text(text.build());
+        }
+    }
+
+    /** Returns the text of this Text element. */
+    @NonNull
+    public String getText() {
+        return checkNotNull(checkNotNull(mText.getText()).getValue());
+    }
+
+    /** Returns the color of this Text element. */
+    @NonNull
+    public ColorProp getColor() {
+        return checkNotNull(checkNotNull(mText.getFontStyle()).getColor());
+    }
+
+    /** Returns the font style of this Text element. */
+    @NonNull
+    public FontStyle getFontStyle() {
+        return checkNotNull(mText.getFontStyle());
+    }
+
+    /** Returns the line height of this Text element. */
+    public float getLineHeight() {
+        return checkNotNull(mText.getLineHeight()).getValue();
+    }
+
+    /** Returns the max lines of text of this Text element. */
+    public int getMaxLines() {
+        return checkNotNull(mText.getMaxLines()).getValue();
+    }
+
+    /** Returns the multiline alignment of this Text element. */
+    @TextAlignment
+    public int getMultilineAlignment() {
+        return checkNotNull(mText.getMultilineAlignment()).getValue();
+    }
+
+    /** Returns the modifiers of this Text element. */
+    @NonNull
+    public Modifiers getModifiers() {
+        return checkNotNull(mText.getModifiers());
+    }
+
+    /** Returns the overflow of this Text element. */
+    @TextOverflow
+    public int getOverflow() {
+        return checkNotNull(mText.getOverflow()).getValue();
+    }
+
+    /** Returns the overflow of this Text element. */
+    @FontWeight
+    public int getWeight() {
+        return checkNotNull(checkNotNull(mText.getFontStyle()).getWeight()).getValue();
+    }
+
+    /** Returns whether the Text is in italic. */
+    public boolean isItalic() {
+        return checkNotNull(checkNotNull(mText.getFontStyle()).getItalic()).getValue();
+    }
+
+    /** Returns whether the Text is underlined. */
+    public boolean isUnderline() {
+        return checkNotNull(checkNotNull(mText.getFontStyle()).getUnderline()).getValue();
+    }
+
+    /**
+     * Returns Material Text object from the given LayoutElement (e.g. one retrieved from a
+     * container's content with {@code container.getContents().get(index)}) if that element can be
+     * converted to Material Text. Otherwise, it will return null.
+     */
+    @Nullable
+    public static Text fromLayoutElement(@NonNull LayoutElement element) {
+        if (element instanceof Text) {
+            return (Text) element;
+        }
+        if (!(element instanceof LayoutElementBuilders.Text)) {
+            return null;
+        }
+        LayoutElementBuilders.Text textElement = (LayoutElementBuilders.Text) element;
+        // We don't need to check the tag as LayoutElement.Text will have the same fields as our
+        // getters even if it's not Material.
+        return new Text(textElement);
+    }
+
+    @NonNull
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public LayoutElementProto.LayoutElement toLayoutElementProto() {
+        return mText.toLayoutElementProto();
+    }
+
+    @Nullable
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public Fingerprint getFingerprint() {
+        return mText.getFingerprint();
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/TitleChip.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/TitleChip.java
new file mode 100644
index 0000000..009dd8c
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/TitleChip.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2021 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 androidx.wear.protolayout.material;
+
+import static androidx.annotation.Dimension.DP;
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+import static androidx.wear.protolayout.LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER;
+import static androidx.wear.protolayout.material.ChipDefaults.TITLE_HEIGHT;
+import static androidx.wear.protolayout.material.ChipDefaults.TITLE_HORIZONTAL_PADDING;
+import static androidx.wear.protolayout.material.ChipDefaults.TITLE_PRIMARY_COLORS;
+import static androidx.wear.protolayout.material.Helper.checkNotNull;
+import static androidx.wear.protolayout.material.Helper.checkTag;
+
+import android.content.Context;
+
+import androidx.annotation.Dimension;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters;
+import androidx.wear.protolayout.DimensionBuilders.ContainerDimension;
+import androidx.wear.protolayout.LayoutElementBuilders.Box;
+import androidx.wear.protolayout.LayoutElementBuilders.HorizontalAlignment;
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement;
+import androidx.wear.protolayout.ModifiersBuilders.Clickable;
+import androidx.wear.protolayout.expression.Fingerprint;
+import androidx.wear.protolayout.proto.LayoutElementProto;
+
+/**
+ * Tiles component {@link TitleChip} that represents clickable object with the text.
+ *
+ * <p>The Title Chip is Stadium shaped object with a larger height then standard Chip and it will
+ * take one line of text of {@link Typography#TYPOGRAPHY_TITLE2} style.
+ *
+ * <p>The recommended set of {@link ChipColors} styles can be obtained from {@link ChipDefaults},
+ * e.g. {@link ChipDefaults#TITLE_PRIMARY_COLORS} to get a color scheme for a primary {@link
+ * TitleChip}.
+ *
+ * <p>When accessing the contents of a container for testing, note that this element can't be simply
+ * casted back to the original type, i.e.:
+ *
+ * <pre>{@code
+ * TitleChip chip = new TitleChip...
+ * Box box = new Box.Builder().addContent(chip).build();
+ *
+ * TitleChip myChip = (TitleChip) box.getContents().get(0);
+ * }</pre>
+ *
+ * will fail.
+ *
+ * <p>To be able to get {@link TitleChip} object from any layout element, {@link #fromLayoutElement}
+ * method should be used, i.e.:
+ *
+ * <pre>{@code
+ * TitleChip myChip = TitleChip.fromLayoutElement(box.getContents().get(0));
+ * }</pre>
+ *
+ * @see  androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder#setContent if this
+ * TitleChip is used inside of {@link androidx.wear.protolayout.material.layouts.PrimaryLayout}.
+ */
+public class TitleChip implements LayoutElement {
+    /** Tool tag for Metadata in Modifiers, so we know that Box is actually a TitleChip. */
+    static final String METADATA_TAG = "TTLCHP";
+
+    @NonNull private final Chip mElement;
+
+    TitleChip(@NonNull Chip element) {
+        this.mElement = element;
+    }
+
+    /** Builder class for {@link TitleChip}. */
+    public static final class Builder implements LayoutElement.Builder {
+        @NonNull private final Context mContext;
+        @NonNull private final String mText;
+        @NonNull private final Clickable mClickable;
+        @NonNull private final DeviceParameters mDeviceParameters;
+        @NonNull private ChipColors mChipColors = TITLE_PRIMARY_COLORS;
+        @HorizontalAlignment private int mHorizontalAlign = HORIZONTAL_ALIGN_CENTER;
+
+        // Indicates that the width isn't set, so it will be automatically set by Chip.Builder
+        // constructor.
+        @Nullable private ContainerDimension mWidth = null;
+
+        /**
+         * Creates a builder for the {@link TitleChip} with associated action and the given text
+         *
+         * @param context The application's context.
+         * @param text The text to be displayed in this title chip. Text will be displayed in 1 line
+         *     and truncated if it doesn't fit.
+         * @param clickable Associated {@link Clickable} for click events. When the TitleChip is
+         *     clicked it will fire the associated action.
+         * @param deviceParameters The device parameters used for styling text.
+         */
+        public Builder(
+                @NonNull Context context,
+                @NonNull String text,
+                @NonNull Clickable clickable,
+                @NonNull DeviceParameters deviceParameters) {
+            this.mContext = context;
+            this.mText = text;
+            this.mClickable = clickable;
+            this.mDeviceParameters = deviceParameters;
+        }
+
+        /**
+         * Sets the colors for the {@link TitleChip}. If set, {@link
+         * ChipColors#getBackgroundColor()} will be used for the background of the button and {@link
+         * ChipColors#getContentColor()} for the text. If not set, {@link
+         * ChipDefaults#TITLE_PRIMARY_COLORS} will be used.
+         */
+        @NonNull
+        public Builder setChipColors(@NonNull ChipColors chipColors) {
+            mChipColors = chipColors;
+            return this;
+        }
+
+        /** Sets the horizontal alignment in the chip. If not set, content will be centered. */
+        @NonNull
+        public Builder setHorizontalAlignment(@HorizontalAlignment int horizontalAlignment) {
+            mHorizontalAlign = horizontalAlignment;
+            return this;
+        }
+
+        /**
+         * Sets the width of {@link TitleChip}. If not set, default value will be set to fill the
+         * screen.
+         */
+        @NonNull
+        public Builder setWidth(@NonNull ContainerDimension width) {
+            mWidth = width;
+            return this;
+        }
+
+        /**
+         * Sets the width of {@link TitleChip}. If not set, default value will be set to fill the
+         * screen.
+         */
+        @NonNull
+        public Builder setWidth(@Dimension(unit = DP) float width) {
+            mWidth = dp(width);
+            return this;
+        }
+
+        /** Constructs and returns {@link TitleChip} with the provided content and look. */
+        @NonNull
+        @Override
+        public TitleChip build() {
+            Chip.Builder chipBuilder =
+                    new Chip.Builder(mContext, mClickable, mDeviceParameters)
+                            .setMetadataTag(METADATA_TAG)
+                            .setChipColors(mChipColors)
+                            .setContentDescription(mText)
+                            .setHorizontalAlignment(mHorizontalAlign)
+                            .setHeight(TITLE_HEIGHT)
+                            .setMaxLines(1)
+                            .setHorizontalPadding(TITLE_HORIZONTAL_PADDING)
+                            .setPrimaryLabelContent(mText)
+                            .setPrimaryLabelTypography(Typography.TYPOGRAPHY_TITLE2)
+                            .setIsPrimaryLabelScalable(false);
+
+            if (mWidth != null) {
+                chipBuilder.setWidth(mWidth);
+            }
+
+            return new TitleChip(chipBuilder.build());
+        }
+    }
+
+    /** Returns width of this Chip. */
+    @NonNull
+    public ContainerDimension getWidth() {
+        return mElement.getWidth();
+    }
+
+    /** Returns click event action associated with this Chip. */
+    @NonNull
+    public Clickable getClickable() {
+        return mElement.getClickable();
+    }
+
+    /** Returns chip color of this Chip. */
+    @NonNull
+    public ChipColors getChipColors() {
+        return mElement.getChipColors();
+    }
+
+    /** Returns text content of this Chip. */
+    @NonNull
+    public String getText() {
+        return checkNotNull(mElement.getPrimaryLabelContent());
+    }
+
+    /** Returns the horizontal alignment of the content in this Chip. */
+    @HorizontalAlignment
+    public int getHorizontalAlignment() {
+        return mElement.getHorizontalAlignment();
+    }
+
+    /** Returns metadata tag set to this TitleChip, which should be {@link #METADATA_TAG}. */
+    @NonNull
+    String getMetadataTag() {
+        return mElement.getMetadataTag();
+    }
+
+    /**
+     * Returns TitleChip object from the given LayoutElement (e.g. one retrieved from a container's
+     * content with {@code container.getContents().get(index)}) if that element can be converted to
+     * TitleChip. Otherwise, it will return null.
+     */
+    @Nullable
+    public static TitleChip fromLayoutElement(@NonNull LayoutElement element) {
+        if (element instanceof TitleChip) {
+            return (TitleChip) element;
+        }
+        if (!(element instanceof Box)) {
+            return null;
+        }
+        Box boxElement = (Box) element;
+        if (!checkTag(boxElement.getModifiers(), METADATA_TAG)) {
+            return null;
+        }
+        // Now we are sure that this element is a TitleChip.
+        return new TitleChip(new Chip(boxElement));
+    }
+
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    @Override
+    public LayoutElementProto.LayoutElement toLayoutElementProto() {
+        return mElement.toLayoutElementProto();
+    }
+
+    @Nullable
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public Fingerprint getFingerprint() {
+        return mElement.getFingerprint();
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Typography.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Typography.java
new file mode 100644
index 0000000..d5b5b9f
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Typography.java
@@ -0,0 +1,298 @@
+/*
+ * Copyright 2022 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 androidx.wear.protolayout.material;
+
+import static androidx.annotation.Dimension.DP;
+import static androidx.annotation.Dimension.SP;
+import static androidx.wear.protolayout.DimensionBuilders.sp;
+import static androidx.wear.protolayout.LayoutElementBuilders.FONT_VARIANT_BODY;
+import static androidx.wear.protolayout.LayoutElementBuilders.FONT_VARIANT_TITLE;
+import static androidx.wear.protolayout.LayoutElementBuilders.FONT_WEIGHT_BOLD;
+import static androidx.wear.protolayout.LayoutElementBuilders.FONT_WEIGHT_MEDIUM;
+import static androidx.wear.protolayout.LayoutElementBuilders.FONT_WEIGHT_NORMAL;
+import static androidx.wear.protolayout.material.Helper.checkNotNull;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.util.DisplayMetrics;
+
+import androidx.annotation.Dimension;
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.wear.protolayout.DimensionBuilders;
+import androidx.wear.protolayout.DimensionBuilders.SpProp;
+import androidx.wear.protolayout.LayoutElementBuilders.FontStyle;
+import androidx.wear.protolayout.LayoutElementBuilders.FontVariant;
+import androidx.wear.protolayout.LayoutElementBuilders.FontWeight;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
+import java.util.Map;
+
+/** Typography styles, currently set up to match Wear's styling. */
+public class Typography {
+    /** Typography for large display text. */
+    public static final int TYPOGRAPHY_DISPLAY1 = 1;
+
+    /** Typography for medium display text. */
+    public static final int TYPOGRAPHY_DISPLAY2 = 2;
+
+    /** Typography for small display text. */
+    public static final int TYPOGRAPHY_DISPLAY3 = 3;
+
+    /** Typography for large title text. */
+    public static final int TYPOGRAPHY_TITLE1 = 4;
+
+    /** Typography for medium title text. */
+    public static final int TYPOGRAPHY_TITLE2 = 5;
+
+    /** Typography for small title text. */
+    public static final int TYPOGRAPHY_TITLE3 = 6;
+
+    /** Typography for large body text. */
+    public static final int TYPOGRAPHY_BODY1 = 7;
+
+    /** Typography for medium body text. */
+    public static final int TYPOGRAPHY_BODY2 = 8;
+
+    /** Typography for bold button text. */
+    public static final int TYPOGRAPHY_BUTTON = 9;
+
+    /** Typography for large caption text. */
+    public static final int TYPOGRAPHY_CAPTION1 = 10;
+
+    /** Typography for medium caption text. */
+    public static final int TYPOGRAPHY_CAPTION2 = 11;
+
+    /** Typography for small caption text. */
+    public static final int TYPOGRAPHY_CAPTION3 = 12;
+
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+        TYPOGRAPHY_DISPLAY1,
+        TYPOGRAPHY_DISPLAY2,
+        TYPOGRAPHY_DISPLAY3,
+        TYPOGRAPHY_TITLE1,
+        TYPOGRAPHY_TITLE2,
+        TYPOGRAPHY_TITLE3,
+        TYPOGRAPHY_BODY1,
+        TYPOGRAPHY_BODY2,
+        TYPOGRAPHY_BUTTON,
+        TYPOGRAPHY_CAPTION1,
+        TYPOGRAPHY_CAPTION2,
+        TYPOGRAPHY_CAPTION3
+    })
+    @interface TypographyName {}
+
+    /** Mapping for line height for different typography. */
+    @NonNull
+    private static final Map<Integer, Float> TYPOGRAPHY_TO_LINE_HEIGHT_SP = new HashMap<>();
+
+    static {
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_DISPLAY1, 46f);
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_DISPLAY2, 40f);
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_DISPLAY3, 36f);
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_TITLE1, 28f);
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_TITLE2, 24f);
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_TITLE3, 20f);
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_BODY1, 20f);
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_BODY2, 18f);
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_BUTTON, 19f);
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_CAPTION1, 18f);
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_CAPTION2, 16f);
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_CAPTION3, 14f);
+    }
+    /**
+     * Returns the {@link FontStyle.Builder} for the given FontStyle code with the recommended size,
+     * weight and letter spacing. Font will be scalable.
+     */
+    @NonNull
+    static FontStyle.Builder getFontStyleBuilder(
+            @TypographyName int fontStyleCode, @NonNull Context context) {
+        return getFontStyleBuilder(fontStyleCode, context, true);
+    }
+
+    private Typography() {}
+
+    /**
+     * Returns the {@link FontStyle.Builder} for the given Typography code with the recommended
+     * size, weight and letter spacing, with the option to make this font not scalable.
+     */
+    @NonNull
+    static FontStyle.Builder getFontStyleBuilder(
+            @TypographyName int typographyCode, @NonNull Context context, boolean isScalable) {
+        switch (typographyCode) {
+            case TYPOGRAPHY_BODY1:
+                return body1(isScalable, context);
+            case TYPOGRAPHY_BODY2:
+                return body2(isScalable, context);
+            case TYPOGRAPHY_BUTTON:
+                return button(isScalable, context);
+            case TYPOGRAPHY_CAPTION1:
+                return caption1(isScalable, context);
+            case TYPOGRAPHY_CAPTION2:
+                return caption2(isScalable, context);
+            case TYPOGRAPHY_CAPTION3:
+                return caption3(isScalable, context);
+            case TYPOGRAPHY_DISPLAY1:
+                return display1(isScalable, context);
+            case TYPOGRAPHY_DISPLAY2:
+                return display2(isScalable, context);
+            case TYPOGRAPHY_DISPLAY3:
+                return display3(isScalable, context);
+            case TYPOGRAPHY_TITLE1:
+                return title1(isScalable, context);
+            case TYPOGRAPHY_TITLE2:
+                return title2(isScalable, context);
+            case TYPOGRAPHY_TITLE3:
+                return title3(isScalable, context);
+            default:
+                // Shouldn't happen.
+                throw new IllegalArgumentException(
+                        "Typography " + typographyCode + " doesn't exist.");
+        }
+    }
+
+    /**
+     * Returns the recommended line height for the given Typography to be added to the Text
+     * component.
+     */
+    @NonNull
+    static SpProp getLineHeightForTypography(@TypographyName int typography) {
+        if (!TYPOGRAPHY_TO_LINE_HEIGHT_SP.containsKey(typography)) {
+            throw new IllegalArgumentException("Typography " + typography + " doesn't exist.");
+        }
+        return sp(checkNotNull(TYPOGRAPHY_TO_LINE_HEIGHT_SP.get(typography)).intValue());
+    }
+
+    @NonNull
+    @SuppressLint("ResourceType")
+    @SuppressWarnings("deprecation")
+    // This is a helper function to make the font not scalable. It should interpret in value as DP
+    // and convert it to SP which is needed to be passed in as a font size. However, we will pass an
+    // SP object to it, because the default style is defined in it, but for the case when the font
+    // size on device in 1, so the DP is equal to SP.
+    private static SpProp dpToSp(@NonNull Context context, @Dimension(unit = DP) float valueDp) {
+        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
+        float scaledSp = (valueDp / metrics.scaledDensity) * metrics.density;
+        return sp(scaledSp);
+    }
+
+    // The @Dimension(unit = SP) on sp() is seemingly being ignored, so lint complains that we're
+    // passing SP to something expecting PX. Just suppress the warning for now.
+    @SuppressLint("ResourceType")
+    private static FontStyle.Builder createFontStyleBuilder(
+            @Dimension(unit = SP) int size,
+            @FontWeight int weight,
+            @FontVariant int variant,
+            float letterSpacing,
+            boolean isScalable,
+            @NonNull Context context) {
+        return new FontStyle.Builder()
+                .setSize(isScalable ? DimensionBuilders.sp(size) : dpToSp(context, size))
+                .setLetterSpacing(DimensionBuilders.em(letterSpacing))
+                .setVariant(variant)
+                .setWeight(weight);
+    }
+
+    /** Font style for large display text. */
+    @NonNull
+    private static FontStyle.Builder display1(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                40, FONT_WEIGHT_MEDIUM, FONT_VARIANT_TITLE, 0.01f, isScalable, context);
+    }
+
+    /** Font style for medium display text. */
+    @NonNull
+    private static FontStyle.Builder display2(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                34, FONT_WEIGHT_MEDIUM, FONT_VARIANT_TITLE, 0.03f, isScalable, context);
+    }
+
+    /** Font style for small display text. */
+    @NonNull
+    private static FontStyle.Builder display3(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                30, FONT_WEIGHT_MEDIUM, FONT_VARIANT_TITLE, 0.03f, isScalable, context);
+    }
+
+    /** Font style for large title text. */
+    @NonNull
+    private static FontStyle.Builder title1(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                24, FONT_WEIGHT_MEDIUM, FONT_VARIANT_TITLE, 0.008f, isScalable, context);
+    }
+
+    /** Font style for medium title text. */
+    @NonNull
+    private static FontStyle.Builder title2(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                20, FONT_WEIGHT_MEDIUM, FONT_VARIANT_TITLE, 0.01f, isScalable, context);
+    }
+
+    /** Font style for small title text. */
+    @NonNull
+    private static FontStyle.Builder title3(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                16, FONT_WEIGHT_MEDIUM, FONT_VARIANT_TITLE, 0.01f, isScalable, context);
+    }
+
+    /** Font style for normal body text. */
+    @NonNull
+    private static FontStyle.Builder body1(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                16, FONT_WEIGHT_NORMAL, FONT_VARIANT_BODY, 0.01f, isScalable, context);
+    }
+
+    /** Font style for small body text. */
+    @NonNull
+    private static FontStyle.Builder body2(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                14, FONT_WEIGHT_NORMAL, FONT_VARIANT_BODY, 0.014f, isScalable, context);
+    }
+
+    /** Font style for bold button text. */
+    @NonNull
+    private static FontStyle.Builder button(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                15, FONT_WEIGHT_BOLD, FONT_VARIANT_BODY, 0.03f, isScalable, context);
+    }
+
+    /** Font style for large caption text. */
+    @NonNull
+    private static FontStyle.Builder caption1(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                14, FONT_WEIGHT_MEDIUM, FONT_VARIANT_BODY, 0.01f, isScalable, context);
+    }
+
+    /** Font style for medium caption text. */
+    @NonNull
+    private static FontStyle.Builder caption2(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                12, FONT_WEIGHT_MEDIUM, FONT_VARIANT_BODY, 0.01f, isScalable, context);
+    }
+
+    /** Font style for small caption text. */
+    @NonNull
+    private static FontStyle.Builder caption3(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                10, FONT_WEIGHT_MEDIUM, FONT_VARIANT_BODY, 0.01f, isScalable, context);
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/androidx-wear-protolayout-protolayout-material-documentation.md b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/androidx-wear-protolayout-protolayout-material-documentation.md
new file mode 100644
index 0000000..0b7dc77
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/androidx-wear-protolayout-protolayout-material-documentation.md
@@ -0,0 +1,8 @@
+# Module root
+
+Wear ProtoLayout Material
+
+# Package androidx.wear.protolayout.material
+
+This package provides helpers for Wear ProtoLayout, to enable you to use Wear Material components
+such as Buttons and Chips within your ProtoLayout.
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/EdgeContentLayout.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/EdgeContentLayout.java
new file mode 100644
index 0000000..e3e78d2
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/EdgeContentLayout.java
@@ -0,0 +1,381 @@
+/*
+ * Copyright 2022 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 androidx.wear.protolayout.material.layouts;
+
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+import static androidx.wear.protolayout.DimensionBuilders.expand;
+import static androidx.wear.protolayout.material.Helper.checkNotNull;
+import static androidx.wear.protolayout.material.Helper.checkTag;
+import static androidx.wear.protolayout.material.Helper.getMetadataTagBytes;
+import static androidx.wear.protolayout.material.Helper.getTagBytes;
+import static androidx.wear.protolayout.material.Helper.isRoundDevice;
+import static androidx.wear.protolayout.material.ProgressIndicatorDefaults.DEFAULT_PADDING;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.EDGE_CONTENT_LAYOUT_MARGIN_HORIZONTAL_ROUND_DP;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.EDGE_CONTENT_LAYOUT_MARGIN_HORIZONTAL_SQUARE_DP;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.EDGE_CONTENT_LAYOUT_PADDING_ABOVE_MAIN_CONTENT_DP;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.EDGE_CONTENT_LAYOUT_PADDING_BELOW_MAIN_CONTENT_DP;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters;
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+import androidx.wear.protolayout.LayoutElementBuilders;
+import androidx.wear.protolayout.LayoutElementBuilders.Box;
+import androidx.wear.protolayout.LayoutElementBuilders.Column;
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement;
+import androidx.wear.protolayout.LayoutElementBuilders.Spacer;
+import androidx.wear.protolayout.ModifiersBuilders.ElementMetadata;
+import androidx.wear.protolayout.ModifiersBuilders.Modifiers;
+import androidx.wear.protolayout.ModifiersBuilders.Padding;
+import androidx.wear.protolayout.expression.Fingerprint;
+import androidx.wear.protolayout.material.CircularProgressIndicator;
+import androidx.wear.protolayout.proto.LayoutElementProto;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Tiles layout that represents the suggested layout style for Material Tiles, which has content
+ * around the edge of the screen (e.g. a ProgressIndicator) and the given content inside of it with
+ * the recommended margin and padding applied. Optional primary or secondary label can be added
+ * above and below the main content, respectively.
+ *
+ * <p>For additional examples and suggested layouts see <a
+ * href="/training/wearables/design/tiles-design-system">Tiles Design System</a>.
+ *
+ * <p>When accessing the contents of a container for testing, note that this element can't be simply
+ * casted back to the original type, i.e.:
+ *
+ * <pre>{@code
+ * EdgeContentLayout ecl = new EdgeContentLayout...
+ * Box box = new Box.Builder().addContent(ecl).build();
+ *
+ * EdgeContentLayout myEcl = (EdgeContentLayout) box.getContents().get(0);
+ * }</pre>
+ *
+ * will fail.
+ *
+ * <p>To be able to get {@link EdgeContentLayout} object from any layout element, {@link
+ * #fromLayoutElement} method should be used, i.e.:
+ *
+ * <pre>{@code
+ * EdgeContentLayout myEcl =
+ *   EdgeContentLayout.fromLayoutElement(box.getContents().get(0));
+ * }</pre>
+ */
+public class EdgeContentLayout implements LayoutElement {
+    /**
+     * Prefix tool tag for Metadata in Modifiers, so we know that Box is actually a
+     * EdgeContentLayout.
+     */
+    static final String METADATA_TAG_PREFIX = "ECL_";
+
+    /**
+     * Index for byte array that contains bits to check whether the content and indicator are
+     * present or not.
+     */
+    static final int FLAG_INDEX = METADATA_TAG_PREFIX.length();
+
+    /**
+     * Base tool tag for Metadata in Modifiers, so we know that Box is actually a EdgeContentLayout
+     * and what optional content is added.
+     */
+    static final byte[] METADATA_TAG_BASE =
+            Arrays.copyOf(getTagBytes(METADATA_TAG_PREFIX), FLAG_INDEX + 1);
+
+    /**
+     * Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
+     * the edge content is present or not.
+     */
+    static final int EDGE_CONTENT_PRESENT = 0x1;
+    /**
+     * Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
+     * the primary label is present or not.
+     */
+    static final int PRIMARY_LABEL_PRESENT = 0x2;
+    /**
+     * Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
+     * the secondary label is present or not.
+     */
+    static final int SECONDARY_LABEL_PRESENT = 0x4;
+    /**
+     * Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
+     * the main content is present or not.
+     */
+    static final int CONTENT_PRESENT = 0x8;
+
+    @RestrictTo(Scope.LIBRARY)
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(
+            flag = true,
+            value = {
+                EDGE_CONTENT_PRESENT,
+                PRIMARY_LABEL_PRESENT,
+                CONTENT_PRESENT,
+                SECONDARY_LABEL_PRESENT
+            })
+    @interface ContentBits {}
+
+    @NonNull private final Box mImpl;
+
+    // This contains inner columns and edge content.
+    @NonNull private final List<LayoutElement> mContents;
+
+    // This contains optional labels, spacers and main content.
+    @NonNull private final List<LayoutElement> mInnerColumn;
+
+    EdgeContentLayout(@NonNull Box layoutElement) {
+        this.mImpl = layoutElement;
+        this.mContents = mImpl.getContents();
+        this.mInnerColumn = ((Column) ((Box) mContents.get(0)).getContents().get(0)).getContents();
+    }
+
+    /** Builder class for {@link EdgeContentLayout}. */
+    public static final class Builder implements LayoutElement.Builder {
+        @NonNull private final DeviceParameters mDeviceParameters;
+        @Nullable private LayoutElement mEdgeContent = null;
+        @Nullable private LayoutElement mPrimaryLabelText = null;
+        @Nullable private LayoutElement mSecondaryLabelText = null;
+        @Nullable private LayoutElement mContent = null;
+        private byte mMetadataContentByte = 0;
+
+        /**
+         * Creates a builder for the {@link EdgeContentLayout}t. Custom content inside of it can
+         * later be set with ({@link #setContent}.
+         */
+        public Builder(@NonNull DeviceParameters deviceParameters) {
+            this.mDeviceParameters = deviceParameters;
+        }
+
+        /**
+         * Sets the content to be around the edges. This can be {@link CircularProgressIndicator}.
+         */
+        @NonNull
+        public Builder setEdgeContent(@NonNull LayoutElement edgeContent) {
+            this.mEdgeContent = edgeContent;
+            mMetadataContentByte = (byte) (mMetadataContentByte | EDGE_CONTENT_PRESENT);
+            return this;
+        }
+
+        /** Sets the content in the primary label slot which will be above the main content. */
+        @NonNull
+        public Builder setPrimaryLabelTextContent(@NonNull LayoutElement primaryLabelText) {
+            this.mPrimaryLabelText = primaryLabelText;
+            mMetadataContentByte = (byte) (mMetadataContentByte | PRIMARY_LABEL_PRESENT);
+            return this;
+        }
+
+        /**
+         * Sets the content in the secondary label slot which will be below the main content. It is
+         * highly recommended to have primary label set when having secondary label.
+         */
+        @NonNull
+        public Builder setSecondaryLabelTextContent(@NonNull LayoutElement secondaryLabelText) {
+            this.mSecondaryLabelText = secondaryLabelText;
+            mMetadataContentByte = (byte) (mMetadataContentByte | SECONDARY_LABEL_PRESENT);
+            return this;
+        }
+
+        /** Sets the additional content to this layout, inside of the screen. */
+        @NonNull
+        public Builder setContent(@NonNull LayoutElement content) {
+            this.mContent = content;
+            mMetadataContentByte = (byte) (mMetadataContentByte | CONTENT_PRESENT);
+            return this;
+        }
+
+        /** Constructs and returns {@link EdgeContentLayout} with the provided content and look. */
+        @NonNull
+        @Override
+        public EdgeContentLayout build() {
+            float thicknessDp =
+                    mEdgeContent instanceof CircularProgressIndicator
+                            ? ((CircularProgressIndicator) mEdgeContent).getStrokeWidth().getValue()
+                            : 0;
+            float horizontalPaddingDp =
+                    isRoundDevice(mDeviceParameters)
+                            ? EDGE_CONTENT_LAYOUT_MARGIN_HORIZONTAL_ROUND_DP
+                            : EDGE_CONTENT_LAYOUT_MARGIN_HORIZONTAL_SQUARE_DP;
+            float indicatorWidth = 2 * (thicknessDp + DEFAULT_PADDING.getValue());
+            float mainContentHeightDp = mDeviceParameters.getScreenHeightDp() - indicatorWidth;
+            float mainContentWidthDp = mDeviceParameters.getScreenWidthDp() - indicatorWidth;
+
+            DpProp mainContentHeight = dp(Math.min(mainContentHeightDp, mainContentWidthDp));
+            DpProp mainContentWidth = dp(Math.min(mainContentHeightDp, mainContentWidthDp));
+
+            Modifiers modifiers =
+                    new Modifiers.Builder()
+                            .setPadding(
+                                    new Padding.Builder()
+                                            .setStart(dp(horizontalPaddingDp))
+                                            .setEnd(dp(horizontalPaddingDp))
+                                            .build())
+                            .build();
+
+            byte[] metadata = METADATA_TAG_BASE.clone();
+            metadata[FLAG_INDEX] = mMetadataContentByte;
+            Box.Builder mainBoxBuilder =
+                    new Box.Builder()
+                            .setWidth(expand())
+                            .setHeight(expand())
+                            .setModifiers(
+                                    new Modifiers.Builder()
+                                            .setMetadata(
+                                                    new ElementMetadata.Builder()
+                                                            .setTagData(metadata)
+                                                            .build())
+                                            .build())
+                            .setHorizontalAlignment(LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER)
+                            .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER);
+
+            Column.Builder innerContentBuilder =
+                    new Column.Builder()
+                            .setHorizontalAlignment(LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER);
+
+            if (mPrimaryLabelText != null) {
+                innerContentBuilder.addContent(mPrimaryLabelText);
+                innerContentBuilder.addContent(
+                        new Spacer.Builder()
+                                .setHeight(dp(EDGE_CONTENT_LAYOUT_PADDING_ABOVE_MAIN_CONTENT_DP))
+                                .build());
+            }
+
+            if (mContent != null) {
+                innerContentBuilder.addContent(
+                        new Box.Builder()
+                                .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER)
+                                .addContent(mContent)
+                                .build());
+            }
+
+            if (mSecondaryLabelText != null) {
+                innerContentBuilder.addContent(
+                        new Spacer.Builder()
+                                .setHeight(dp(EDGE_CONTENT_LAYOUT_PADDING_BELOW_MAIN_CONTENT_DP))
+                                .build());
+                innerContentBuilder.addContent(mSecondaryLabelText);
+            }
+
+            mainBoxBuilder.addContent(
+                    new Box.Builder()
+                            .setModifiers(modifiers)
+                            .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER)
+                            .setHorizontalAlignment(LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER)
+                            .setHeight(mainContentHeight)
+                            .setWidth(mainContentWidth)
+                            .addContent(innerContentBuilder.build())
+                            .build());
+
+            if (mEdgeContent != null) {
+                mainBoxBuilder.addContent(mEdgeContent);
+            }
+
+            return new EdgeContentLayout(mainBoxBuilder.build());
+        }
+    }
+
+    private boolean areElementsPresent(@ContentBits int elementFlag) {
+        return (getMetadataTag()[FLAG_INDEX] & elementFlag) == elementFlag;
+    }
+
+    /** Returns metadata tag set to this EdgeContentLayout. */
+    @NonNull
+    byte[] getMetadataTag() {
+        return getMetadataTagBytes(checkNotNull(checkNotNull(mImpl.getModifiers()).getMetadata()));
+    }
+
+    /** Returns the inner content from this layout. */
+    @Nullable
+    public LayoutElement getContent() {
+        if (!areElementsPresent(CONTENT_PRESENT)) {
+            return null;
+        }
+        // By tag we know that content exists. It will be at position 0 if there is no primary
+        // label, or at position 2 (primary label, spacer - content) otherwise.
+        int contentPosition = areElementsPresent(PRIMARY_LABEL_PRESENT) ? 2 : 0;
+        return ((Box) mInnerColumn.get(contentPosition)).getContents().get(0);
+    }
+
+    /** Get the primary label content from this layout. */
+    @Nullable
+    public LayoutElement getPrimaryLabelTextContent() {
+        if (!areElementsPresent(PRIMARY_LABEL_PRESENT)) {
+            return null;
+        }
+        // By tag we know that primary label exists. It will always be at position 0.
+        return mInnerColumn.get(0);
+    }
+
+    /** Get the secondary label content from this layout. */
+    @Nullable
+    public LayoutElement getSecondaryLabelTextContent() {
+        if (!areElementsPresent(SECONDARY_LABEL_PRESENT)) {
+            return null;
+        }
+        // By tag we know that secondary label exists. It will always be at last position.
+        return mInnerColumn.get(mInnerColumn.size() - 1);
+    }
+
+    /** Returns the edge content from this layout. */
+    @Nullable
+    public LayoutElement getEdgeContent() {
+        if (areElementsPresent(EDGE_CONTENT_PRESENT)) {
+            return mContents.get(1);
+        }
+        return null;
+    }
+
+    /**
+     * Returns EdgeContentLayout object from the given LayoutElement (e.g. one retrieved from a
+     * container's content with {@code container.getContents().get(index)}) if that element can be
+     * converted to EdgeContentLayout. Otherwise, it will return null.
+     */
+    @Nullable
+    public static EdgeContentLayout fromLayoutElement(@NonNull LayoutElement element) {
+        if (element instanceof EdgeContentLayout) {
+            return (EdgeContentLayout) element;
+        }
+        if (!(element instanceof Box)) {
+            return null;
+        }
+        Box boxElement = (Box) element;
+        if (!checkTag(boxElement.getModifiers(), METADATA_TAG_PREFIX, METADATA_TAG_BASE)) {
+            return null;
+        }
+        // Now we are sure that this element is a EdgeContentLayout.
+        return new EdgeContentLayout(boxElement);
+    }
+
+    @NonNull
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public LayoutElementProto.LayoutElement toLayoutElementProto() {
+        return mImpl.toLayoutElementProto();
+    }
+
+    @Nullable
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public Fingerprint getFingerprint() {
+        return mImpl.getFingerprint();
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/LayoutDefaults.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/LayoutDefaults.java
new file mode 100644
index 0000000..42a3381
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/LayoutDefaults.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2022 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 androidx.wear.protolayout.material.layouts;
+
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+import androidx.wear.protolayout.material.ButtonDefaults;
+
+/** Contains the default values used by layout templates for Tiles. */
+public class LayoutDefaults {
+    private LayoutDefaults() {}
+
+    /**
+     * The default percentage for the bottom margin for primary chip in the {@link PrimaryLayout}.
+     */
+    static final float PRIMARY_LAYOUT_MARGIN_BOTTOM_ROUND_PERCENT = 2.1f / 100;
+
+    /**
+     * The default percentage for the bottom margin for primary chip in the {@link PrimaryLayout}.
+     */
+    static final float PRIMARY_LAYOUT_MARGIN_BOTTOM_SQUARE_PERCENT = 0;
+
+    /**
+     * The default percentage for the top margin for primary chip in the {@link PrimaryLayout} on
+     * round devices.
+     */
+    static final float PRIMARY_LAYOUT_MARGIN_TOP_ROUND_PERCENT = 16.7f / 100;
+
+    /**
+     * The default percentage for the top margin for primary chip in the {@link PrimaryLayout} on
+     * square devices.
+     */
+    static final float PRIMARY_LAYOUT_MARGIN_TOP_SQUARE_PERCENT = 13.3f / 100;
+
+    /**
+     * The default spacer above primary label in {@link PrimaryLayout} to make space for Tile icon
+     * on round devices.
+     */
+    static final DpProp PRIMARY_LAYOUT_PRIMARY_LABEL_SPACER_HEIGHT_ROUND_DP = dp(0);
+
+    /**
+     * The default spacer above primary label in {@link PrimaryLayout} to make space for Tile icon
+     * on square devices.
+     */
+    static final DpProp PRIMARY_LAYOUT_PRIMARY_LABEL_SPACER_HEIGHT_SQUARE_DP = dp(4);
+
+    /**
+     * The default percentage for the horizontal margin for primary chip in the {@link
+     * PrimaryLayout}.
+     */
+    static final float PRIMARY_LAYOUT_MARGIN_HORIZONTAL_ROUND_PERCENT = 6.3f / 100;
+
+    /**
+     * The default percentage for the horizontal margin for primary chip in the {@link
+     * PrimaryLayout}.
+     */
+    static final float PRIMARY_LAYOUT_MARGIN_HORIZONTAL_SQUARE_PERCENT = 2.8f / 100;
+
+    /**
+     * The padding for the primary chip in {@link PrimaryLayout} so it doesn't bleed off screen if
+     * text is too big.
+     */
+    static final float PRIMARY_LAYOUT_CHIP_HORIZONTAL_PADDING_ROUND_DP = 30;
+
+    /**
+     * The padding for the primary chip in {@link PrimaryLayout} so it doesn't bleed off screen if
+     * text is too big.
+     */
+    static final float PRIMARY_LAYOUT_CHIP_HORIZONTAL_PADDING_SQUARE_DP = 0;
+
+    /** The default horizontal margin in the {@link EdgeContentLayout}. */
+    static final float EDGE_CONTENT_LAYOUT_MARGIN_HORIZONTAL_ROUND_DP = 14;
+
+    /** The default horizontal margin in the {@link EdgeContentLayout}. */
+    static final float EDGE_CONTENT_LAYOUT_MARGIN_HORIZONTAL_SQUARE_DP = 16;
+
+    /**
+     * The recommended padding that should be above the main content (text) in the {@link
+     * EdgeContentLayout}.
+     */
+    public static final float EDGE_CONTENT_LAYOUT_PADDING_ABOVE_MAIN_CONTENT_DP = 6;
+
+    /**
+     * The recommended padding that should be below the main content (text) in the {@link
+     * EdgeContentLayout}.
+     */
+    public static final float EDGE_CONTENT_LAYOUT_PADDING_BELOW_MAIN_CONTENT_DP = 8;
+
+    /** The default spacer width for slots in a {@link MultiSlotLayout}. */
+    public static final DpProp MULTI_SLOT_LAYOUT_HORIZONTAL_SPACER_WIDTH = dp(8);
+
+    /** The recommended space between the main content and additional labels in layouts. */
+    public static final DpProp DEFAULT_VERTICAL_SPACER_HEIGHT = dp(8);
+
+    /** The maximum number of button that can be added to the {@link MultiButtonLayout}. */
+    public static final int MULTI_BUTTON_MAX_NUMBER = 7;
+
+    /**
+     * The default size of button in case when there are 3 or more buttons in the {@link
+     * MultiButtonLayout}.
+     */
+    static final DpProp MULTI_BUTTON_3_PLUS_SIZE = ButtonDefaults.DEFAULT_SIZE;
+
+    /** The default size of button in case when there 2 buttons in the {@link MultiButtonLayout}. */
+    static final DpProp MULTI_BUTTON_2_SIZE = ButtonDefaults.LARGE_SIZE;
+
+    /**
+     * The default size of button in case when there is 1 button in the {@link MultiButtonLayout}.
+     */
+    static final DpProp MULTI_BUTTON_1_SIZE = ButtonDefaults.EXTRA_LARGE_SIZE;
+
+    /** The default width for vertical spacer between buttons in the {@link MultiButtonLayout}. */
+    static final DpProp MULTI_BUTTON_SPACER_WIDTH = dp(6);
+
+    /**
+     * The default height for horizontal spacer between buttons in the {@link MultiButtonLayout}.
+     */
+    static final DpProp MULTI_BUTTON_SPACER_HEIGHT = dp(4);
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/MultiButtonLayout.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/MultiButtonLayout.java
new file mode 100644
index 0000000..e4186c5
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/MultiButtonLayout.java
@@ -0,0 +1,399 @@
+/*
+ * Copyright 2022 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 androidx.wear.protolayout.material.layouts;
+
+import static androidx.wear.protolayout.DimensionBuilders.wrap;
+import static androidx.wear.protolayout.material.Helper.checkNotNull;
+import static androidx.wear.protolayout.material.Helper.checkTag;
+import static androidx.wear.protolayout.material.Helper.getMetadataTagName;
+import static androidx.wear.protolayout.material.Helper.getTagBytes;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.MULTI_BUTTON_1_SIZE;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.MULTI_BUTTON_2_SIZE;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.MULTI_BUTTON_3_PLUS_SIZE;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.MULTI_BUTTON_MAX_NUMBER;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.MULTI_BUTTON_SPACER_HEIGHT;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.MULTI_BUTTON_SPACER_WIDTH;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+import androidx.wear.protolayout.LayoutElementBuilders.Box;
+import androidx.wear.protolayout.LayoutElementBuilders.Column;
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement;
+import androidx.wear.protolayout.LayoutElementBuilders.Row;
+import androidx.wear.protolayout.LayoutElementBuilders.Spacer;
+import androidx.wear.protolayout.ModifiersBuilders.ElementMetadata;
+import androidx.wear.protolayout.ModifiersBuilders.Modifiers;
+import androidx.wear.protolayout.expression.Fingerprint;
+import androidx.wear.protolayout.material.Button;
+import androidx.wear.protolayout.proto.LayoutElementProto;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Opinionated Tiles layout, that can contain between 1 and {@link
+ * LayoutDefaults#MULTI_BUTTON_MAX_NUMBER} number of buttons arranged inline with the Material
+ * guidelines. Can be used as a content passed in to the {@link PrimaryLayout}, but if there is
+ * {@link LayoutDefaults#MULTI_BUTTON_MAX_NUMBER} buttons it should be used on its own.
+ *
+ * <p>For additional examples and suggested layouts see <a
+ * href="/training/wearables/design/tiles-design-system">Tiles Design System</a>.
+ *
+ * <p>When accessing the contents of a container for testing, note that this element can't be simply
+ * casted back to the original type, i.e.:
+ *
+ * <pre>{@code
+ * MultiButtonLayout mbl = new MultiButtonLayout...
+ * Box box = new Box.Builder().addContent(mbl).build();
+ *
+ * MultiButtonLayout myMbl = (MultiButtonLayout) box.getContents().get(0);
+ * }</pre>
+ *
+ * will fail.
+ *
+ * <p>To be able to get {@link MultiButtonLayout} object from any layout element, {@link
+ * #fromLayoutElement} method should be used, i.e.:
+ *
+ * <pre>{@code
+ * MultiButtonLayout myMbl = MultiButtonLayout.fromLayoutElement(box.getContents().get(0));
+ * }</pre>
+ */
+public class MultiButtonLayout implements LayoutElement {
+    /** Tool tag for Metadata in Modifiers, so we know that Box is actually a MultiButtonLayout. */
+    static final String METADATA_TAG = "MBL";
+
+    /** Button distribution where the first row has more buttons than other rows. */
+    public static final int FIVE_BUTTON_DISTRIBUTION_TOP_HEAVY = 1;
+
+    /** Button distribution where the last row has more buttons than other rows. */
+    public static final int FIVE_BUTTON_DISTRIBUTION_BOTTOM_HEAVY = 2;
+
+    @RestrictTo(Scope.LIBRARY)
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FIVE_BUTTON_DISTRIBUTION_TOP_HEAVY, FIVE_BUTTON_DISTRIBUTION_BOTTOM_HEAVY})
+    public @interface ButtonDistribution {}
+
+    @NonNull private final Box mElement;
+
+    MultiButtonLayout(@NonNull Box mElement) {
+        this.mElement = mElement;
+    }
+
+    /** Builder class for {@link MultiButtonLayout}. */
+    public static final class Builder implements LayoutElement.Builder {
+        @NonNull private final List<LayoutElement> mButtonsContent = new ArrayList<>();
+        private @ButtonDistribution int mFiveButtonDistribution =
+                FIVE_BUTTON_DISTRIBUTION_BOTTOM_HEAVY;
+
+        /**
+         * Creates a builder for the {@link MultiButtonLayout}. Content inside of it can later be
+         * added with {@link #addButtonContent}.
+         */
+        public Builder() {}
+
+        /**
+         * Add one new button to the layout. Note that it is accepted to pass in any {@link
+         * LayoutElement}, but it is strongly recommended to add a {@link Button} as the layout is
+         * optimized for it. Any button added after {@link LayoutDefaults#MULTI_BUTTON_MAX_NUMBER}
+         * is reached will be discarded.
+         */
+        @NonNull
+        @SuppressWarnings("MissingGetterMatchingBuilder")
+        // There is no direct matching getter for this setter, but there is a getter that gets all
+        // added buttons.
+        public Builder addButtonContent(@NonNull LayoutElement buttonContent) {
+            mButtonsContent.add(buttonContent);
+            return this;
+        }
+
+        /**
+         * Sets the button distribution for this layout. Button distribution is used in case when
+         * there is 5 buttons in the layout to determine whether the 3 buttons row is at the top or
+         * bottom.
+         */
+        @NonNull
+        public Builder setFiveButtonDistribution(@ButtonDistribution int fiveButtonDistribution) {
+            this.mFiveButtonDistribution = fiveButtonDistribution;
+            return this;
+        }
+
+        /** Constructs and returns {@link MultiButtonLayout} with the provided content and look. */
+        @NonNull
+        @Override
+        public MultiButtonLayout build() {
+            int buttonNum = mButtonsContent.size();
+            if (buttonNum > MULTI_BUTTON_MAX_NUMBER) {
+                throw new IllegalArgumentException(
+                        "Too many buttons are added. Maximum number is "
+                                + MULTI_BUTTON_MAX_NUMBER
+                                + ".");
+            }
+
+            LayoutElement buttons = buildButtons(buttonNum);
+            Box.Builder elementBuilder =
+                    new Box.Builder()
+                        .setModifiers(
+                            new Modifiers.Builder()
+                                .setMetadata(
+                                    new ElementMetadata.Builder()
+                                        .setTagData(getTagBytes(METADATA_TAG))
+                                        .build())
+                                .build())
+                        .addContent(buttons);
+
+            return new MultiButtonLayout(elementBuilder.build());
+        }
+
+        @NonNull
+        private LayoutElement buildButtons(int buttonNum) {
+            switch (buttonNum) {
+                case 1:
+                    return wrapButton(mButtonsContent.get(0), MULTI_BUTTON_1_SIZE);
+                case 2:
+                    return build2ButtonRow(
+                            mButtonsContent.get(0), mButtonsContent.get(1), MULTI_BUTTON_2_SIZE);
+                case 3:
+                    return build3ButtonRow(
+                            mButtonsContent.get(0), mButtonsContent.get(1), mButtonsContent.get(2));
+                case 4:
+                    return new Column.Builder()
+                            .addContent(
+                                    build2ButtonRow(
+                                            mButtonsContent.get(0),
+                                            mButtonsContent.get(1),
+                                            MULTI_BUTTON_3_PLUS_SIZE))
+                            .addContent(buildVerticalSpacer())
+                            .addContent(
+                                    build2ButtonRow(
+                                            mButtonsContent.get(2),
+                                            mButtonsContent.get(3),
+                                            MULTI_BUTTON_3_PLUS_SIZE))
+                            .build();
+                case 5:
+                    return new Column.Builder()
+                            .addContent(
+                                    mFiveButtonDistribution == FIVE_BUTTON_DISTRIBUTION_TOP_HEAVY
+                                            ? build3ButtonRow(
+                                                    mButtonsContent.get(0),
+                                                    mButtonsContent.get(1),
+                                                    mButtonsContent.get(2))
+                                            : build2ButtonRow(
+                                                    mButtonsContent.get(0),
+                                                    mButtonsContent.get(1),
+                                                    MULTI_BUTTON_3_PLUS_SIZE))
+                            .addContent(buildVerticalSpacer())
+                            .addContent(
+                                    mFiveButtonDistribution == FIVE_BUTTON_DISTRIBUTION_TOP_HEAVY
+                                            ? build2ButtonRow(
+                                                    mButtonsContent.get(3),
+                                                    mButtonsContent.get(4),
+                                                    MULTI_BUTTON_3_PLUS_SIZE)
+                                            : build3ButtonRow(
+                                                    mButtonsContent.get(2),
+                                                    mButtonsContent.get(3),
+                                                    mButtonsContent.get(4)))
+                            .build();
+                case 6:
+                    return new Column.Builder()
+                            .addContent(
+                                    build3ButtonRow(
+                                            mButtonsContent.get(0),
+                                            mButtonsContent.get(1),
+                                            mButtonsContent.get(2)))
+                            .addContent(buildVerticalSpacer())
+                            .addContent(
+                                    build3ButtonRow(
+                                            mButtonsContent.get(3),
+                                            mButtonsContent.get(4),
+                                            mButtonsContent.get(5)))
+                            .build();
+                case 7:
+                    return new Column.Builder()
+                            .addContent(
+                                    build2ButtonRow(
+                                            mButtonsContent.get(0),
+                                            mButtonsContent.get(1),
+                                            MULTI_BUTTON_3_PLUS_SIZE))
+                            .addContent(buildVerticalSpacer())
+                            .addContent(
+                                    build3ButtonRow(
+                                            mButtonsContent.get(2),
+                                            mButtonsContent.get(3),
+                                            mButtonsContent.get(4)))
+                            .addContent(buildVerticalSpacer())
+                            .addContent(
+                                    build2ButtonRow(
+                                            mButtonsContent.get(5),
+                                            mButtonsContent.get(6),
+                                            MULTI_BUTTON_3_PLUS_SIZE))
+                            .build();
+            }
+            // This shouldn't happen, but return an empty Box instead of having this method nullable
+            // and checks above.
+            return new Box.Builder().build();
+        }
+
+        @NonNull
+        private Row build3ButtonRow(
+                @NonNull LayoutElement button1,
+                @NonNull LayoutElement button2,
+                @NonNull LayoutElement button3) {
+            return new Row.Builder()
+                    .setWidth(wrap())
+                    .setHeight(wrap())
+                    .addContent(wrapButton(button1, MULTI_BUTTON_3_PLUS_SIZE))
+                    .addContent(buildHorizontalSpacer())
+                    .addContent(wrapButton(button2, MULTI_BUTTON_3_PLUS_SIZE))
+                    .addContent(buildHorizontalSpacer())
+                    .addContent(wrapButton(button3, MULTI_BUTTON_3_PLUS_SIZE))
+                    .build();
+        }
+
+        @NonNull
+        private Row build2ButtonRow(
+                @NonNull LayoutElement button1,
+                @NonNull LayoutElement button2,
+                @NonNull DpProp size) {
+            return new Row.Builder()
+                    .setWidth(wrap())
+                    .setHeight(wrap())
+                    .addContent(wrapButton(button1, size))
+                    .addContent(buildHorizontalSpacer())
+                    .addContent(wrapButton(button2, size))
+                    .build();
+        }
+
+        @NonNull
+        private Spacer buildHorizontalSpacer() {
+            return new Spacer.Builder().setWidth(MULTI_BUTTON_SPACER_WIDTH).build();
+        }
+
+        @NonNull
+        private Spacer buildVerticalSpacer() {
+            return new Spacer.Builder().setHeight(MULTI_BUTTON_SPACER_HEIGHT).build();
+        }
+
+        @NonNull
+        private Box wrapButton(@NonNull LayoutElement button, @NonNull DpProp size) {
+            return new Box.Builder().setWidth(size).setHeight(size).addContent(button).build();
+        }
+    }
+
+    /** Gets the content from this layout, containing all buttons that were added. */
+    @NonNull
+    public List<LayoutElement> getButtonContents() {
+        List<LayoutElement> buttons = new ArrayList<>();
+        List<LayoutElement> contents = mElement.getContents();
+        if (contents.isEmpty()) {
+            return buttons;
+        }
+        LayoutElement innerContent = contents.get(0);
+        if (innerContent instanceof Column) {
+            for (LayoutElement row : ((Column) innerContent).getContents()) {
+                if (row instanceof Row) {
+                    buttons.addAll(getButtonsFromRow((Row) row));
+                }
+            }
+        } else if (innerContent instanceof Row) {
+            return getButtonsFromRow((Row) innerContent);
+        } else if (innerContent instanceof Box) {
+            buttons.add(((Box) innerContent).getContents().get(0));
+        }
+
+        return buttons;
+    }
+
+    /** Returns metadata tag set to this MultiButtonLayouts. */
+    @NonNull
+    String getMetadataTag() {
+        return getMetadataTagName(
+                checkNotNull(checkNotNull(mElement.getModifiers()).getMetadata()));
+    }
+
+    /**
+     * Gets the button distribution from this layout for the case when there is 5 buttons in the
+     * layout. If there is more or less buttons than 5, default {@link
+     * #FIVE_BUTTON_DISTRIBUTION_BOTTOM_HEAVY} will be returned.
+     */
+    public int getFiveButtonDistribution() {
+        List<LayoutElement> contents = mElement.getContents();
+        if (getButtonContents().size() != 5) {
+            return FIVE_BUTTON_DISTRIBUTION_BOTTOM_HEAVY;
+        }
+        LayoutElement innerContent = contents.get(0);
+        if (innerContent instanceof Column && ((Column) innerContent).getContents().size() == 3) {
+            // 1st and 3rd row are buttons. Check whether the first row has 5 (3 buttons + 2 spacer)
+            // - top heavy or 3 (2 buttons + spacer) - bottom heavy elements.
+            LayoutElement firstElement = ((Column) innerContent).getContents().get(0);
+            if (firstElement instanceof Row && ((Row) firstElement).getContents().size() == 5) {
+                return FIVE_BUTTON_DISTRIBUTION_TOP_HEAVY;
+            }
+        }
+        return FIVE_BUTTON_DISTRIBUTION_BOTTOM_HEAVY;
+    }
+
+    private List<LayoutElement> getButtonsFromRow(Row row) {
+        List<LayoutElement> buttons = new ArrayList<>();
+        for (LayoutElement element : row.getContents()) {
+            if (element instanceof Box) {
+                buttons.add(((Box) element).getContents().get(0));
+            }
+        }
+        return buttons;
+    }
+
+    /**
+     * Returns MultiButtonLayout object from the given LayoutElement (e.g. one retrieved from a
+     * container's content with {@code container.getContents().get(index)}) if that element can be
+     * converted to MultiButtonLayout. Otherwise, it will return null.
+     */
+    @Nullable
+    public static MultiButtonLayout fromLayoutElement(@NonNull LayoutElement element) {
+        if (element instanceof MultiButtonLayout) {
+            return (MultiButtonLayout) element;
+        }
+        if (!(element instanceof Box)) {
+            return null;
+        }
+        Box boxElement = (Box) element;
+        if (!checkTag(boxElement.getModifiers(), METADATA_TAG)) {
+            return null;
+        }
+        // Now we are sure that this element is a MultiButtonLayout.
+        return new MultiButtonLayout(boxElement);
+    }
+
+    @NonNull
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public LayoutElementProto.LayoutElement toLayoutElementProto() {
+        return mElement.toLayoutElementProto();
+    }
+
+    @Nullable
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public Fingerprint getFingerprint() {
+        return mElement.getFingerprint();
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/MultiSlotLayout.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/MultiSlotLayout.java
new file mode 100644
index 0000000..8f9e903
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/MultiSlotLayout.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2022 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 androidx.wear.protolayout.material.layouts;
+
+import static androidx.annotation.Dimension.DP;
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+import static androidx.wear.protolayout.DimensionBuilders.wrap;
+import static androidx.wear.protolayout.material.Helper.checkNotNull;
+import static androidx.wear.protolayout.material.Helper.checkTag;
+import static androidx.wear.protolayout.material.Helper.getMetadataTagName;
+import static androidx.wear.protolayout.material.Helper.getTagBytes;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.MULTI_SLOT_LAYOUT_HORIZONTAL_SPACER_WIDTH;
+
+import android.annotation.SuppressLint;
+
+import androidx.annotation.Dimension;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+import androidx.wear.protolayout.DimensionBuilders.SpacerDimension;
+import androidx.wear.protolayout.LayoutElementBuilders;
+import androidx.wear.protolayout.LayoutElementBuilders.Box;
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement;
+import androidx.wear.protolayout.LayoutElementBuilders.Row;
+import androidx.wear.protolayout.LayoutElementBuilders.Spacer;
+import androidx.wear.protolayout.ModifiersBuilders.ElementMetadata;
+import androidx.wear.protolayout.ModifiersBuilders.Modifiers;
+import androidx.wear.protolayout.expression.Fingerprint;
+import androidx.wear.protolayout.proto.LayoutElementProto;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Opinionated Tiles layout, row like style with horizontally aligned and spaced slots (for icons or
+ * other small content). Should be used as a content passed in to the {@link PrimaryLayout}.
+ *
+ * <p>Recommended number of added slots is 1 to 3. Their width will be the width of an element
+ * passed in, with the {@link LayoutDefaults#MULTI_SLOT_LAYOUT_HORIZONTAL_SPACER_WIDTH} space
+ * between.
+ *
+ * <p>For additional examples and suggested layouts see <a
+ * href="/training/wearables/design/tiles-design-system">Tiles Design System</a>.
+ *
+ * <p>When accessing the contents of a container for testing, note that this element can't be simply
+ * casted back to the original type, i.e.:
+ *
+ * <pre>{@code
+ * MultiSlotLayout msl = new MultiSlotLayout...
+ * Box box = new Box.Builder().addContent(msl).build();
+ *
+ * MultiSlotLayout myMsl = (MultiSlotLayout) box.getContents().get(0);
+ * }</pre>
+ *
+ * will fail.
+ *
+ * <p>To be able to get {@link MultiSlotLayout} object from any layout element, {@link
+ * #fromLayoutElement} method should be used, i.e.:
+ *
+ * <pre>{@code
+ * MultiSlotLayout myMsl = MultiSlotLayout.fromLayoutElement(box.getContents().get(0));
+ * }</pre>
+ */
+public class MultiSlotLayout implements LayoutElement {
+    /** Tool tag for Metadata in Modifiers, so we know that Row is actually a MultiSlotLayout. */
+    static final String METADATA_TAG = "MSL";
+
+    @NonNull private final Row mElement;
+
+    MultiSlotLayout(@NonNull Row mElement) {
+        this.mElement = mElement;
+    }
+
+    /** Builder class for {@link MultiSlotLayout}. */
+    public static final class Builder implements LayoutElement.Builder {
+
+        @NonNull private final List<LayoutElement> mSlotsContent = new ArrayList<>();
+        @NonNull private DpProp mHorizontalSpacerWidth = MULTI_SLOT_LAYOUT_HORIZONTAL_SPACER_WIDTH;
+
+        /**
+         * Creates a builder for the {@link MultiSlotLayout}. Content inside of it can later be
+         * added with {@link #addSlotContent}.
+         */
+        public Builder() {}
+
+        /** Add one new slot to the layout with the given content inside. */
+        @NonNull
+        @SuppressWarnings("MissingGetterMatchingBuilder")
+        // There is no direct matching getter for this setter, but there is a getter that gets all
+        // added slots.
+        public Builder addSlotContent(@NonNull LayoutElement slotContent) {
+            mSlotsContent.add(slotContent);
+            return this;
+        }
+
+        /**
+         * Sets the horizontal spacer width which is used as a space between slots if there is more
+         * than one slot. If not set, {@link
+         * LayoutDefaults#MULTI_SLOT_LAYOUT_HORIZONTAL_SPACER_WIDTH} will be used.
+         */
+        @NonNull
+        public Builder setHorizontalSpacerWidth(@Dimension(unit = DP) float width) {
+            this.mHorizontalSpacerWidth = dp(width);
+            return this;
+        }
+
+        /** Constructs and returns {@link MultiSlotLayout} with the provided content and look. */
+        @NonNull
+        @Override
+        // The @Dimension(unit = DP) on mVerticalSpacerHeight.getValue() is seemingly being ignored,
+        // so lint complains that we're passing PX to something expecting DP. Just suppress the
+        // warning for now.
+        @SuppressLint("ResourceType")
+        public MultiSlotLayout build() {
+            Row.Builder rowBuilder =
+                    new Row.Builder()
+                            .setHeight(wrap())
+                            .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER)
+                            .setWidth(wrap())
+                            .setModifiers(
+                                    new Modifiers.Builder()
+                                            .setMetadata(
+                                                    new ElementMetadata.Builder()
+                                                            .setTagData(getTagBytes(METADATA_TAG))
+                                                            .build())
+                                            .build());
+            if (!mSlotsContent.isEmpty()) {
+
+                boolean isFirst = true;
+                for (LayoutElement slot : mSlotsContent) {
+                    if (!isFirst) {
+                        rowBuilder.addContent(
+                                new Spacer.Builder().setWidth(mHorizontalSpacerWidth).build());
+                    } else {
+                        isFirst = false;
+                    }
+                    rowBuilder.addContent(
+                            new Box.Builder()
+                                    .setWidth(wrap())
+                                    .setHeight(wrap())
+                                    .addContent(slot)
+                                    .build());
+                }
+            }
+
+            return new MultiSlotLayout(rowBuilder.build());
+        }
+    }
+
+    /** Gets the content from this layout, containing all slots that were added. */
+    @NonNull
+    public List<LayoutElement> getSlotContents() {
+        List<LayoutElement> slots = new ArrayList<>();
+        for (LayoutElement slot : mElement.getContents()) {
+            if (slot instanceof Box) {
+                slots.add(((Box) slot).getContents().get(0));
+            }
+        }
+        return slots;
+    }
+
+    /** Gets the width of horizontal spacer that is between slots. */
+    // The @Dimension(unit = DP) on getLinearDimension.getValue() is seemingly being ignored, so
+    // lint complains that we're passing PX to something expecting DP. Just suppress the warning for
+    // now.
+    @SuppressLint("ResourceType")
+    @Dimension(unit = DP)
+    public float getHorizontalSpacerWidth() {
+        for (LayoutElement slot : mElement.getContents()) {
+            if (slot instanceof Spacer) {
+                SpacerDimension width = ((Spacer) slot).getWidth();
+                if (width instanceof DpProp) {
+                    return ((DpProp) width).getValue();
+                }
+            }
+        }
+        return LayoutDefaults.MULTI_SLOT_LAYOUT_HORIZONTAL_SPACER_WIDTH.getValue();
+    }
+
+    /** Returns metadata tag set to this MultiSlotLayout. */
+    @NonNull
+    String getMetadataTag() {
+        return getMetadataTagName(
+                checkNotNull(checkNotNull(mElement.getModifiers()).getMetadata()));
+    }
+
+    /**
+     * Returns MultiSlotLayout object from the given LayoutElement (e.g. one retrieved from a
+     * container's content with {@code container.getContents().get(index)}) if that element can be
+     * converted to MultiSlotLayout. Otherwise, it will return null.
+     */
+    @Nullable
+    public static MultiSlotLayout fromLayoutElement(@NonNull LayoutElement element) {
+        if (element instanceof MultiSlotLayout) {
+            return (MultiSlotLayout) element;
+        }
+        if (!(element instanceof Row)) {
+            return null;
+        }
+        Row rowElement = (Row) element;
+        if (!checkTag(rowElement.getModifiers(), METADATA_TAG)) {
+            return null;
+        }
+        // Now we are sure that this element is a MultiSlotLayout.
+        return new MultiSlotLayout(rowElement);
+    }
+
+    @NonNull
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public LayoutElementProto.LayoutElement toLayoutElementProto() {
+        return mElement.toLayoutElementProto();
+    }
+
+    @Nullable
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public Fingerprint getFingerprint() {
+        return mElement.getFingerprint();
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/PrimaryLayout.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/PrimaryLayout.java
new file mode 100644
index 0000000..2bbbac5
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/PrimaryLayout.java
@@ -0,0 +1,540 @@
+/*
+ * Copyright 2022 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 androidx.wear.protolayout.material.layouts;
+
+import static androidx.annotation.Dimension.DP;
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+import static androidx.wear.protolayout.DimensionBuilders.expand;
+import static androidx.wear.protolayout.DimensionBuilders.wrap;
+import static androidx.wear.protolayout.material.ChipDefaults.COMPACT_HEIGHT_TAPPABLE;
+import static androidx.wear.protolayout.material.Helper.checkNotNull;
+import static androidx.wear.protolayout.material.Helper.checkTag;
+import static androidx.wear.protolayout.material.Helper.getMetadataTagBytes;
+import static androidx.wear.protolayout.material.Helper.getTagBytes;
+import static androidx.wear.protolayout.material.Helper.isRoundDevice;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.DEFAULT_VERTICAL_SPACER_HEIGHT;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.PRIMARY_LAYOUT_CHIP_HORIZONTAL_PADDING_ROUND_DP;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.PRIMARY_LAYOUT_CHIP_HORIZONTAL_PADDING_SQUARE_DP;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.PRIMARY_LAYOUT_MARGIN_BOTTOM_ROUND_PERCENT;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.PRIMARY_LAYOUT_MARGIN_BOTTOM_SQUARE_PERCENT;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.PRIMARY_LAYOUT_MARGIN_HORIZONTAL_ROUND_PERCENT;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.PRIMARY_LAYOUT_MARGIN_HORIZONTAL_SQUARE_PERCENT;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.PRIMARY_LAYOUT_MARGIN_TOP_ROUND_PERCENT;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.PRIMARY_LAYOUT_MARGIN_TOP_SQUARE_PERCENT;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.PRIMARY_LAYOUT_PRIMARY_LABEL_SPACER_HEIGHT_ROUND_DP;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.PRIMARY_LAYOUT_PRIMARY_LABEL_SPACER_HEIGHT_SQUARE_DP;
+
+import android.annotation.SuppressLint;
+
+import androidx.annotation.Dimension;
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters;
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+import androidx.wear.protolayout.DimensionBuilders.SpacerDimension;
+import androidx.wear.protolayout.LayoutElementBuilders;
+import androidx.wear.protolayout.LayoutElementBuilders.Box;
+import androidx.wear.protolayout.LayoutElementBuilders.Column;
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement;
+import androidx.wear.protolayout.LayoutElementBuilders.Spacer;
+import androidx.wear.protolayout.ModifiersBuilders.ElementMetadata;
+import androidx.wear.protolayout.ModifiersBuilders.Modifiers;
+import androidx.wear.protolayout.ModifiersBuilders.Padding;
+import androidx.wear.protolayout.expression.Fingerprint;
+import androidx.wear.protolayout.material.CompactChip;
+import androidx.wear.protolayout.proto.LayoutElementProto;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Tiles layout that represents a suggested layout style for Material Tiles with the primary
+ * (compact) chip at the bottom with the given content in the center and the recommended margin and
+ * padding applied. There is a fixed slot for an optional primary label above or optional secondary
+ * label below the main content area.
+ *
+ * <p>It is highly recommended that main content has max lines between 2 and 4 (dependant on labels
+ * present), i.e.: * No labels are present: content with max 4 lines, * 1 label is present: content
+ * with max 3 lines, * 2 labels are present: content with max 2 lines.
+ *
+ * <p>For additional examples and suggested layouts see <a
+ * href="/training/wearables/design/tiles-design-system">Tiles Design System</a>.
+ *
+ * <p>When accessing the contents of a container for testing, note that this element can't be simply
+ * casted back to the original type, i.e.:
+ *
+ * <pre>{@code
+ * PrimaryLayout pl = new PrimaryLayout...
+ * Box box = new Box.Builder().addContent(pl).build();
+ *
+ * PrimaryLayout myPl = (PrimaryLayout) box.getContents().get(0);
+ * }</pre>
+ *
+ * will fail.
+ *
+ * <p>To be able to get {@link PrimaryLayout} object from any layout element, {@link
+ * #fromLayoutElement} method should be used, i.e.:
+ *
+ * <pre>{@code
+ * PrimaryLayout myPl = PrimaryLayout.fromLayoutElement(box.getContents().get(0));
+ * }</pre>
+ */
+public class PrimaryLayout implements LayoutElement {
+    /**
+     * Prefix tool tag for Metadata in Modifiers, so we know that Box is actually a PrimaryLayout.
+     */
+    static final String METADATA_TAG_PREFIX = "PL_";
+
+    /** Index for byte array that contains bits to check whether the contents are present or not. */
+    static final int FLAG_INDEX = METADATA_TAG_PREFIX.length();
+
+    /**
+     * Base tool tag for Metadata in Modifiers, so we know that Box is actually a PrimaryLayout and
+     * what optional content is added.
+     */
+    static final byte[] METADATA_TAG_BASE =
+            Arrays.copyOf(getTagBytes(METADATA_TAG_PREFIX), FLAG_INDEX + 1);
+
+    /**
+     * Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
+     * the primary chip is present or not.
+     */
+    static final int CHIP_PRESENT = 0x1;
+    /**
+     * Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
+     * the primary label is present or not.
+     */
+    static final int PRIMARY_LABEL_PRESENT = 0x2;
+    /**
+     * Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
+     * the secondary label is present or not.
+     */
+    static final int SECONDARY_LABEL_PRESENT = 0x4;
+    /**
+     * Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
+     * the content is present or not.
+     */
+    static final int CONTENT_PRESENT = 0x8;
+
+    /** Position of the primary label in its own inner column if exists. */
+    static final int PRIMARY_LABEL_POSITION = 1;
+    /** Position of the content in its own inner column. */
+    static final int CONTENT_ONLY_POSITION = 0;
+    /** Position of the primary chip in main layout column. */
+    static final int PRIMARY_CHIP_POSITION = 1;
+
+    @RestrictTo(Scope.LIBRARY)
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(
+            flag = true,
+            value = {CHIP_PRESENT, PRIMARY_LABEL_PRESENT, SECONDARY_LABEL_PRESENT, CONTENT_PRESENT})
+    @interface ContentBits {}
+
+    @NonNull private final Box mImpl;
+
+    // This contains inner columns and primary chip.
+    @NonNull private final List<LayoutElement> mAllContent;
+    // This contains optional labels, spacers and main content.
+    @NonNull private final List<LayoutElement> mPrimaryLabel;
+    // This contains optional labels, spacers and main content.
+    @NonNull private final List<LayoutElement> mContentAndSecondaryLabel;
+
+    PrimaryLayout(@NonNull Box layoutElement) {
+        this.mImpl = layoutElement;
+        this.mAllContent = ((Column) layoutElement.getContents().get(0)).getContents();
+        List<LayoutElement> innerContent = ((Column) mAllContent.get(0)).getContents();
+        this.mPrimaryLabel = ((Column) innerContent.get(0)).getContents();
+        this.mContentAndSecondaryLabel =
+                ((Column) ((Box) innerContent.get(1)).getContents().get(0)).getContents();
+    }
+
+    /** Builder class for {@link PrimaryLayout}. */
+    public static final class Builder implements LayoutElement.Builder {
+        @NonNull private final DeviceParameters mDeviceParameters;
+        @Nullable private LayoutElement mPrimaryChip = null;
+        @Nullable private LayoutElement mPrimaryLabelText = null;
+        @Nullable private LayoutElement mSecondaryLabelText = null;
+        @NonNull private LayoutElement mContent = new Box.Builder().build();
+        @NonNull private DpProp mVerticalSpacerHeight = DEFAULT_VERTICAL_SPACER_HEIGHT;
+        private byte mMetadataContentByte = 0;
+
+        /**
+         * Creates a builder for the {@link PrimaryLayout} from the given content. Content inside of
+         * it can later be set with {@link #setContent}, {@link #setPrimaryChipContent}, {@link
+         * #setPrimaryLabelTextContent} and {@link #setSecondaryLabelTextContent}.
+         */
+        public Builder(@NonNull DeviceParameters deviceParameters) {
+            this.mDeviceParameters = deviceParameters;
+        }
+
+        /**
+         * Sets the element which is in the slot at the bottom of the layout. Note that it is
+         * accepted to pass in any {@link LayoutElement}, but it is strongly recommended to add a
+         * {@link CompactChip} as the layout is optimized for it.
+         */
+        @NonNull
+        public Builder setPrimaryChipContent(@NonNull LayoutElement compactChip) {
+            this.mPrimaryChip = compactChip;
+            mMetadataContentByte = (byte) (mMetadataContentByte | CHIP_PRESENT);
+            return this;
+        }
+
+        /** Sets the content in the primary label slot which will be above the main content. */
+        @NonNull
+        public Builder setPrimaryLabelTextContent(@NonNull LayoutElement primaryLabelText) {
+            this.mPrimaryLabelText = primaryLabelText;
+            mMetadataContentByte = (byte) (mMetadataContentByte | PRIMARY_LABEL_PRESENT);
+            return this;
+        }
+
+        /**
+         * Sets the content in the primary label slot which will be below the main content. It is
+         * highly recommended to have primary label set when having secondary label.
+         */
+        @NonNull
+        public Builder setSecondaryLabelTextContent(@NonNull LayoutElement secondaryLabelText) {
+            this.mSecondaryLabelText = secondaryLabelText;
+            mMetadataContentByte = (byte) (mMetadataContentByte | SECONDARY_LABEL_PRESENT);
+            return this;
+        }
+
+        /**
+         * Sets the additional content to this layout, above the primary chip.
+         *
+         * The content slot will wrap the elements' height, so the height of the given content must
+         * be fixed or set to wrap ({@code expand} can't be used).
+         *
+         * This layout has built-in horizontal margins, so the given content should have width set
+         * to {@code expand} to use all the available space, rather than an explicit width which may
+         * lead to clipping.
+         */
+        @NonNull
+        public Builder setContent(@NonNull LayoutElement content) {
+            this.mContent = content;
+            mMetadataContentByte = (byte) (mMetadataContentByte | CONTENT_PRESENT);
+            return this;
+        }
+
+        /**
+         * Sets the vertical spacer height which is used as a space between main content and
+         * secondary label if there is any. If not set, {@link
+         * LayoutDefaults#DEFAULT_VERTICAL_SPACER_HEIGHT} will be used.
+         */
+        @NonNull
+        // The @Dimension(unit = DP) on dp() is seemingly being ignored, so lint complains that
+        // we're passing PX to something expecting DP. Just suppress the warning for now.
+        @SuppressLint("ResourceType")
+        public Builder setVerticalSpacerHeight(@Dimension(unit = DP) float height) {
+            this.mVerticalSpacerHeight = dp(height);
+            return this;
+        }
+
+        /** Constructs and returns {@link PrimaryLayout} with the provided content and look. */
+        // The @Dimension(unit = DP) on dp() is seemingly being ignored, so lint complains that
+        // we're passing DP to something expecting PX. Just suppress the warning for now.
+        @SuppressLint("ResourceType")
+        @NonNull
+        @Override
+        public PrimaryLayout build() {
+            float topPadding = getTopPadding();
+            float bottomPadding = getBottomPadding();
+            float horizontalPadding = getHorizontalPadding();
+            float horizontalChipPadding = getChipHorizontalPadding();
+
+            float primaryChipHeight = mPrimaryChip != null ? COMPACT_HEIGHT_TAPPABLE.getValue() : 0;
+
+            DpProp mainContentHeight =
+                    dp(
+                            mDeviceParameters.getScreenHeightDp()
+                                    - primaryChipHeight
+                                    - bottomPadding
+                                    - topPadding);
+
+            // Layout organization: column(column(primary label + spacer + (box(column(content +
+            // secondary label))) + chip)
+
+            // First column that has all other content and chip.
+            Column.Builder layoutBuilder = new Column.Builder();
+
+            // Contains primary label, main content and secondary label. Primary label will be
+            // wrapped, while other content will be expanded so it can be centered in the remaining
+            // space.
+            Column.Builder contentAreaBuilder =
+                    new Column.Builder()
+                            .setWidth(expand())
+                            .setHeight(mainContentHeight)
+                            .setHorizontalAlignment(LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER);
+
+            // Contains main content and secondary label with wrapped height so it can be put inside
+            // of the Box to be centered.
+            Column.Builder contentSecondaryLabelBuilder =
+                    new Column.Builder()
+                            .setWidth(expand())
+                            .setHeight(wrap())
+                            .setHorizontalAlignment(LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER);
+
+            // Needs to be in column because of the spacers.
+            Column.Builder primaryLabelBuilder =
+                    new Column.Builder().setWidth(expand()).setHeight(wrap());
+
+            if (mPrimaryLabelText != null) {
+                primaryLabelBuilder.addContent(
+                        new Spacer.Builder().setHeight(getPrimaryLabelTopSpacerHeight()).build());
+                primaryLabelBuilder.addContent(mPrimaryLabelText);
+            }
+
+            contentAreaBuilder.addContent(primaryLabelBuilder.build());
+
+            contentSecondaryLabelBuilder.addContent(
+                    new Box.Builder()
+                            .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER)
+                            .setWidth(expand())
+                            .setHeight(wrap())
+                            .addContent(mContent)
+                            .build());
+
+            if (mSecondaryLabelText != null) {
+                contentSecondaryLabelBuilder.addContent(
+                        new Spacer.Builder().setHeight(mVerticalSpacerHeight).build());
+                contentSecondaryLabelBuilder.addContent(mSecondaryLabelText);
+            }
+
+            contentAreaBuilder.addContent(
+                    new Box.Builder()
+                            .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER)
+                            .setWidth(expand())
+                            .setHeight(expand())
+                            .addContent(contentSecondaryLabelBuilder.build())
+                            .build());
+
+            layoutBuilder
+                    .setModifiers(
+                            new Modifiers.Builder()
+                                    .setPadding(
+                                            new Padding.Builder()
+                                                    .setStart(dp(horizontalPadding))
+                                                    .setEnd(dp(horizontalPadding))
+                                                    .setTop(dp(topPadding))
+                                                    .setBottom(dp(bottomPadding))
+                                                    .build())
+                                    .build())
+                    .setWidth(expand())
+                    .setHeight(expand())
+                    .setHorizontalAlignment(LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER);
+
+            layoutBuilder.addContent(contentAreaBuilder.build());
+
+            if (mPrimaryChip != null) {
+                layoutBuilder.addContent(
+                        new Box.Builder()
+                                .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_BOTTOM)
+                                .setWidth(expand())
+                                .setHeight(wrap())
+                                .setModifiers(
+                                        new Modifiers.Builder()
+                                                .setPadding(
+                                                        new Padding.Builder()
+                                                                .setStart(dp(horizontalChipPadding))
+                                                                .setEnd(dp(horizontalChipPadding))
+                                                                .build())
+                                                .build())
+                                .addContent(mPrimaryChip)
+                                .build());
+            }
+
+            byte[] metadata = METADATA_TAG_BASE.clone();
+            metadata[FLAG_INDEX] = mMetadataContentByte;
+
+            Box.Builder element =
+                    new Box.Builder()
+                            .setWidth(expand())
+                            .setHeight(expand())
+                            .setModifiers(
+                                    new Modifiers.Builder()
+                                            .setMetadata(
+                                                    new ElementMetadata.Builder()
+                                                            .setTagData(metadata)
+                                                            .build())
+                                            .build())
+                            .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_BOTTOM)
+                            .addContent(layoutBuilder.build());
+
+            return new PrimaryLayout(element.build());
+        }
+
+        /**
+         * Returns the recommended bottom padding, based on percentage values in {@link
+         * LayoutDefaults}.
+         */
+        private float getBottomPadding() {
+            return mPrimaryChip != null
+                    ? (mDeviceParameters.getScreenHeightDp()
+                            * (isRoundDevice(mDeviceParameters)
+                                    ? PRIMARY_LAYOUT_MARGIN_BOTTOM_ROUND_PERCENT
+                                    : PRIMARY_LAYOUT_MARGIN_BOTTOM_SQUARE_PERCENT))
+                    : getTopPadding();
+        }
+
+        /**
+         * Returns the recommended top padding, based on percentage values in {@link
+         * LayoutDefaults}.
+         */
+        @Dimension(unit = DP)
+        private float getTopPadding() {
+            return mDeviceParameters.getScreenHeightDp()
+                    * (isRoundDevice(mDeviceParameters)
+                            ? PRIMARY_LAYOUT_MARGIN_TOP_ROUND_PERCENT
+                            : PRIMARY_LAYOUT_MARGIN_TOP_SQUARE_PERCENT);
+        }
+
+        /**
+         * Returns the recommended horizontal padding, based on percentage values in {@link
+         * LayoutDefaults}.
+         */
+        @Dimension(unit = DP)
+        private float getHorizontalPadding() {
+            return mDeviceParameters.getScreenWidthDp()
+                    * (isRoundDevice(mDeviceParameters)
+                            ? PRIMARY_LAYOUT_MARGIN_HORIZONTAL_ROUND_PERCENT
+                            : PRIMARY_LAYOUT_MARGIN_HORIZONTAL_SQUARE_PERCENT);
+        }
+
+        /**
+         * Returns the recommended horizontal padding for primary chip, based on percentage values
+         * and DP values in {@link LayoutDefaults}.
+         */
+        @Dimension(unit = DP)
+        private float getChipHorizontalPadding() {
+            return isRoundDevice(mDeviceParameters)
+                    ? PRIMARY_LAYOUT_CHIP_HORIZONTAL_PADDING_ROUND_DP
+                    : PRIMARY_LAYOUT_CHIP_HORIZONTAL_PADDING_SQUARE_DP;
+        }
+
+        /** Returns the spacer height to be placed above primary label to accommodate Tile icon. */
+        @NonNull
+        private DpProp getPrimaryLabelTopSpacerHeight() {
+            return isRoundDevice(mDeviceParameters)
+                    ? PRIMARY_LAYOUT_PRIMARY_LABEL_SPACER_HEIGHT_ROUND_DP
+                    : PRIMARY_LAYOUT_PRIMARY_LABEL_SPACER_HEIGHT_SQUARE_DP;
+        }
+    }
+
+    /** Get the primary label content from this layout. */
+    @Nullable
+    public LayoutElement getPrimaryLabelTextContent() {
+        if (!areElementsPresent(PRIMARY_LABEL_PRESENT)) {
+            return null;
+        }
+        return mPrimaryLabel.get(PRIMARY_LABEL_POSITION);
+    }
+
+    /** Get the secondary label content from this layout. */
+    @Nullable
+    public LayoutElement getSecondaryLabelTextContent() {
+        if (!areElementsPresent(SECONDARY_LABEL_PRESENT)) {
+            return null;
+        }
+        // By tag we know that secondary label exists. It will always be at last position.
+        return mContentAndSecondaryLabel.get(mContentAndSecondaryLabel.size() - 1);
+    }
+
+    /** Get the inner content from this layout. */
+    @Nullable
+    public LayoutElement getContent() {
+        if (!areElementsPresent(CONTENT_PRESENT)) {
+            return null;
+        }
+        return ((Box) mContentAndSecondaryLabel.get(CONTENT_ONLY_POSITION)).getContents().get(0);
+    }
+
+    /** Get the primary chip content from this layout. */
+    @Nullable
+    public LayoutElement getPrimaryChipContent() {
+        if (areElementsPresent(CHIP_PRESENT)) {
+            return ((Box) mAllContent.get(PRIMARY_CHIP_POSITION)).getContents().get(0);
+        }
+        return null;
+    }
+
+    /** Get the vertical spacer height from this layout. */
+    // The @Dimension(unit = DP) on getValue() is seemingly being ignored, so lint complains that
+    // we're passing PX to something expecting DP. Just suppress the warning for now.
+    @SuppressLint("ResourceType")
+    @Dimension(unit = DP)
+    public float getVerticalSpacerHeight() {
+        if (areElementsPresent(SECONDARY_LABEL_PRESENT)) {
+            LayoutElement element = mContentAndSecondaryLabel.get(CONTENT_ONLY_POSITION + 1);
+            if (element instanceof Spacer) {
+                SpacerDimension height = ((Spacer) element).getHeight();
+                if (height instanceof DpProp) {
+                    return ((DpProp) height).getValue();
+                }
+            }
+        }
+        return DEFAULT_VERTICAL_SPACER_HEIGHT.getValue();
+    }
+
+    private boolean areElementsPresent(@ContentBits int elementFlag) {
+        return (getMetadataTag()[FLAG_INDEX] & elementFlag) == elementFlag;
+    }
+
+    /** Returns metadata tag set to this PrimaryLayout. */
+    @NonNull
+    byte[] getMetadataTag() {
+        return getMetadataTagBytes(checkNotNull(checkNotNull(mImpl.getModifiers()).getMetadata()));
+    }
+
+    /**
+     * Returns PrimaryLayout object from the given LayoutElement (e.g. one retrieved from a
+     * container's content with {@code container.getContents().get(index)}) if that element can be
+     * converted to PrimaryLayout. Otherwise, it will return null.
+     */
+    @Nullable
+    public static PrimaryLayout fromLayoutElement(@NonNull LayoutElement element) {
+        if (element instanceof PrimaryLayout) {
+            return (PrimaryLayout) element;
+        }
+        if (!(element instanceof Box)) {
+            return null;
+        }
+        Box boxElement = (Box) element;
+        if (!checkTag(boxElement.getModifiers(), METADATA_TAG_PREFIX, METADATA_TAG_BASE)) {
+            return null;
+        }
+        // Now we are sure that this element is a PrimaryLayout.
+        return new PrimaryLayout(boxElement);
+    }
+
+    @NonNull
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public LayoutElementProto.LayoutElement toLayoutElementProto() {
+        return mImpl.toLayoutElementProto();
+    }
+
+    @Nullable
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public Fingerprint getFingerprint() {
+        return mImpl.getFingerprint();
+    }
+}