Merge changes from topic "androidx-no-internet-2" into androidx-master-dev

* changes:
  Disabling network in most builds
  Support to depend on artifacts having no groupId
diff --git a/appcompat/appcompat/api/1.2.0-alpha01.txt b/appcompat/appcompat/api/1.2.0-alpha01.txt
index a19c8b1..330bca1 100644
--- a/appcompat/appcompat/api/1.2.0-alpha01.txt
+++ b/appcompat/appcompat/api/1.2.0-alpha01.txt
@@ -253,7 +253,8 @@
   public abstract class AppCompatDelegate {
     method public abstract void addContentView(android.view.View!, android.view.ViewGroup.LayoutParams!);
     method public abstract boolean applyDayNight();
-    method public void attachBaseContext(android.content.Context!);
+    method @Deprecated public void attachBaseContext(android.content.Context!);
+    method @CallSuper public android.content.Context attachBaseContext2(android.content.Context);
     method public static androidx.appcompat.app.AppCompatDelegate create(android.app.Activity, androidx.appcompat.app.AppCompatCallback?);
     method public static androidx.appcompat.app.AppCompatDelegate create(android.app.Dialog, androidx.appcompat.app.AppCompatCallback?);
     method public static androidx.appcompat.app.AppCompatDelegate create(android.content.Context, android.view.Window, androidx.appcompat.app.AppCompatCallback?);
diff --git a/appcompat/appcompat/api/current.txt b/appcompat/appcompat/api/current.txt
index a19c8b1..330bca1 100644
--- a/appcompat/appcompat/api/current.txt
+++ b/appcompat/appcompat/api/current.txt
@@ -253,7 +253,8 @@
   public abstract class AppCompatDelegate {
     method public abstract void addContentView(android.view.View!, android.view.ViewGroup.LayoutParams!);
     method public abstract boolean applyDayNight();
-    method public void attachBaseContext(android.content.Context!);
+    method @Deprecated public void attachBaseContext(android.content.Context!);
+    method @CallSuper public android.content.Context attachBaseContext2(android.content.Context);
     method public static androidx.appcompat.app.AppCompatDelegate create(android.app.Activity, androidx.appcompat.app.AppCompatCallback?);
     method public static androidx.appcompat.app.AppCompatDelegate create(android.app.Dialog, androidx.appcompat.app.AppCompatCallback?);
     method public static androidx.appcompat.app.AppCompatDelegate create(android.content.Context, android.view.Window, androidx.appcompat.app.AppCompatCallback?);
diff --git a/appcompat/appcompat/api/public_plus_experimental_1.2.0-alpha01.txt b/appcompat/appcompat/api/public_plus_experimental_1.2.0-alpha01.txt
index a19c8b1..330bca1 100644
--- a/appcompat/appcompat/api/public_plus_experimental_1.2.0-alpha01.txt
+++ b/appcompat/appcompat/api/public_plus_experimental_1.2.0-alpha01.txt
@@ -253,7 +253,8 @@
   public abstract class AppCompatDelegate {
     method public abstract void addContentView(android.view.View!, android.view.ViewGroup.LayoutParams!);
     method public abstract boolean applyDayNight();
-    method public void attachBaseContext(android.content.Context!);
+    method @Deprecated public void attachBaseContext(android.content.Context!);
+    method @CallSuper public android.content.Context attachBaseContext2(android.content.Context);
     method public static androidx.appcompat.app.AppCompatDelegate create(android.app.Activity, androidx.appcompat.app.AppCompatCallback?);
     method public static androidx.appcompat.app.AppCompatDelegate create(android.app.Dialog, androidx.appcompat.app.AppCompatCallback?);
     method public static androidx.appcompat.app.AppCompatDelegate create(android.content.Context, android.view.Window, androidx.appcompat.app.AppCompatCallback?);
diff --git a/appcompat/appcompat/api/public_plus_experimental_current.txt b/appcompat/appcompat/api/public_plus_experimental_current.txt
index a19c8b1..330bca1 100644
--- a/appcompat/appcompat/api/public_plus_experimental_current.txt
+++ b/appcompat/appcompat/api/public_plus_experimental_current.txt
@@ -253,7 +253,8 @@
   public abstract class AppCompatDelegate {
     method public abstract void addContentView(android.view.View!, android.view.ViewGroup.LayoutParams!);
     method public abstract boolean applyDayNight();
-    method public void attachBaseContext(android.content.Context!);
+    method @Deprecated public void attachBaseContext(android.content.Context!);
+    method @CallSuper public android.content.Context attachBaseContext2(android.content.Context);
     method public static androidx.appcompat.app.AppCompatDelegate create(android.app.Activity, androidx.appcompat.app.AppCompatCallback?);
     method public static androidx.appcompat.app.AppCompatDelegate create(android.app.Dialog, androidx.appcompat.app.AppCompatCallback?);
     method public static androidx.appcompat.app.AppCompatDelegate create(android.content.Context, android.view.Window, androidx.appcompat.app.AppCompatCallback?);
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeRotateDoesNotRecreateActivityTestCase.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeRotateDoesNotRecreateActivityTestCase.kt
index 5af7154..bd54923 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeRotateDoesNotRecreateActivityTestCase.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeRotateDoesNotRecreateActivityTestCase.kt
@@ -69,8 +69,12 @@
 
     @Test
     fun testRotateDoesNotRecreateActivity() {
-        // Don't run this test on SDK 26 because it has issues with setRequestedOrientation.
-        if (Build.VERSION.SDK_INT == 26) {
+        // Don't run this test on SDK 26 because it has issues with setRequestedOrientation. Also
+        // don't run it on SDK 24 (Nexus Player) or SDK 23 (Pixel C) because those devices only
+        // support a single orientation and there doesn't seem to be a way to query supported
+        // screen orientations.
+        val sdkInt = Build.VERSION.SDK_INT
+        if (sdkInt == 26 || sdkInt == 24 || sdkInt == 23) {
             return
         }
 
diff --git a/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatActivity.java b/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatActivity.java
index 2340c83..a85ba01 100644
--- a/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatActivity.java
+++ b/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatActivity.java
@@ -94,8 +94,7 @@
 
     @Override
     protected void attachBaseContext(Context newBase) {
-        super.attachBaseContext(newBase);
-        getDelegate().attachBaseContext(newBase);
+        super.attachBaseContext(getDelegate().attachBaseContext2(newBase));
     }
 
     @Override
diff --git a/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegate.java b/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegate.java
index 61a1936..116dcbf 100644
--- a/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegate.java
+++ b/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegate.java
@@ -30,6 +30,7 @@
 import android.view.ViewGroup;
 import android.view.Window;
 
+import androidx.annotation.CallSuper;
 import androidx.annotation.IdRes;
 import androidx.annotation.IntDef;
 import androidx.annotation.LayoutRes;
@@ -373,12 +374,23 @@
     public abstract void addContentView(View v, ViewGroup.LayoutParams lp);
 
     /**
-     * Should be called from {@link Activity#attachBaseContext(Context)}
+     * @deprecated use {@link #attachBaseContext2(Context)} instead.
      */
+    @Deprecated
     public void attachBaseContext(Context context) {
     }
 
     /**
+     * Should be called from {@link Activity#attachBaseContext(Context)}.
+     */
+    @NonNull
+    @CallSuper
+    public Context attachBaseContext2(@NonNull Context context) {
+        attachBaseContext(context);
+        return context;
+    }
+
+    /**
      * Should be called from {@link Activity#onTitleChanged(CharSequence, int)}}
      */
     public abstract void setTitle(@Nullable CharSequence title);
diff --git a/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java b/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java
index bfa0f2b..6d462f1 100644
--- a/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java
+++ b/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java
@@ -72,6 +72,7 @@
 import android.widget.PopupWindow;
 import android.widget.TextView;
 
+import androidx.annotation.CallSuper;
 import androidx.annotation.IdRes;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -136,18 +137,18 @@
 
     private static final int[] sWindowBackgroundStyleable = {android.R.attr.windowBackground};
 
-    private static boolean sInstalledExceptionHandler;
-
     /**
-     * AppCompat selectively uses applyOverrideConfiguration() for DayNight functionality.
-     * Unfortunately the framework has a few bugs around Resources instances on SDKs 21-25,
+     * AppCompat selectively uses an override configuration for DayNight functionality.
+     * Unfortunately the framework has a few issues around Resources instances on SDKs 21-25,
      * resulting in the root Resources instance (i.e. Application) being modified when it
-     * shouldn't be. We can work around it by always calling applyOverrideConfiguration()
-     * where available.
+     * shouldn't be. We can work around it by always calling using an override configuration
+     * where available, to force a local resources instance being used.
      */
     private static final boolean sAlwaysOverrideConfiguration = Build.VERSION.SDK_INT >= 21
             && Build.VERSION.SDK_INT <= 25;
 
+    private static boolean sInstalledExceptionHandler;
+
     static final String EXCEPTION_HANDLER_MESSAGE_SUFFIX= ". If the resource you are"
             + " trying to use is a vector resource, you may be referencing it in an unsupported"
             + " way. See AppCompatDelegate.setCompatVectorFromResourcesEnabled() for more info.";
@@ -330,11 +331,13 @@
         AppCompatDrawableManager.preload();
     }
 
+    @NonNull
     @Override
-    public void attachBaseContext(Context context) {
+    @CallSuper
+    public Context attachBaseContext2(@NonNull final Context baseContext) {
         final Configuration appConfig =
-                context.getApplicationContext().getResources().getConfiguration();
-        final Configuration baseConfig = context.getResources().getConfiguration();
+                baseContext.getApplicationContext().getResources().getConfiguration();
+        final Configuration baseConfig = baseContext.getResources().getConfiguration();
         final Configuration configOverlay;
         if (!appConfig.equals(baseConfig)) {
             configOverlay = generateConfigDelta(appConfig, baseConfig);
@@ -350,9 +353,27 @@
             }
         }
 
-        // Activity.recreate() cannot be called before attach is complete.
-        applyDayNight(false, configOverlay);
         mBaseContextAttached = true;
+
+        if (Build.VERSION.SDK_INT >= 17) {
+            @ApplyableNightMode final int modeToApply = mapNightMode(baseContext,
+                    calculateNightMode());
+            final Configuration config = createOverrideConfigurationForDayNight(
+                    baseContext, modeToApply, configOverlay);
+
+            final int currentNightMode = baseContext.getResources().getConfiguration().uiMode
+                    & Configuration.UI_MODE_NIGHT_MASK;
+            final int newNightMode = config.uiMode & Configuration.UI_MODE_NIGHT_MASK;
+
+            if (sAlwaysOverrideConfiguration || currentNightMode != newNightMode) {
+                // If the target night mode is different to the new night mode, return a
+                // configuration context with the new config.
+                return super.attachBaseContext2(baseContext.createConfigurationContext(config));
+            }
+        }
+
+        // Otherwise just return the original base context
+        return super.attachBaseContext2(baseContext);
     }
 
     @Override
@@ -363,7 +384,7 @@
 
         // Our implicit call to applyDayNight() should not recreate until after the Activity is
         // created
-        applyDayNight(false, null);
+        applyDayNight(false);
 
         // We lazily fetch the Window for Activities, to allow DayNight to apply in
         // attachBaseContext
@@ -518,7 +539,7 @@
 
         // Re-apply Day/Night with the new configuration but disable recreations. Since this
         // configuration change has only just happened we can safely just update the resources now
-        applyDayNight(false, null);
+        applyDayNight(false);
     }
 
     @Override
@@ -2179,29 +2200,28 @@
 
     @Override
     public boolean applyDayNight() {
-        return applyDayNight(true, null);
+        return applyDayNight(true);
     }
 
     @SuppressWarnings("deprecation")
-    private boolean applyDayNight(final boolean allowRecreation,
-            @Nullable Configuration configOverlay) {
+    private boolean applyDayNight(final boolean allowRecreation) {
         if (mIsDestroyed) {
             // If we're destroyed, ignore the call
             return false;
         }
 
         @NightMode final int nightMode = calculateNightMode();
-        @ApplyableNightMode final int modeToApply = mapNightMode(nightMode);
-        final boolean applied = updateForNightMode(modeToApply, allowRecreation, configOverlay);
+        @ApplyableNightMode final int modeToApply = mapNightMode(mContext, nightMode);
+        final boolean applied = updateForNightMode(modeToApply, allowRecreation);
 
         if (nightMode == MODE_NIGHT_AUTO_TIME) {
-            getAutoTimeNightModeManager().setup();
+            getAutoTimeNightModeManager(mContext).setup();
         } else if (mAutoTimeNightModeManager != null) {
             // Make sure we clean up the existing manager
             mAutoTimeNightModeManager.cleanup();
         }
         if (nightMode == MODE_NIGHT_AUTO_BATTERY) {
-            getAutoBatteryNightModeManager().setup();
+            getAutoBatteryNightModeManager(mContext).setup();
         } else if (mAutoBatteryNightModeManager != null) {
             // Make sure we clean up the existing manager
             mAutoBatteryNightModeManager.cleanup();
@@ -2225,7 +2245,7 @@
 
     @SuppressWarnings("deprecation")
     @ApplyableNightMode
-    int mapNightMode(@NightMode final int mode) {
+    int mapNightMode(@NonNull Context context, @NightMode final int mode) {
         switch (mode) {
             case MODE_NIGHT_NO:
             case MODE_NIGHT_YES:
@@ -2234,16 +2254,16 @@
                 return mode;
             case MODE_NIGHT_AUTO_TIME:
                 if (Build.VERSION.SDK_INT >= 23) {
-                    UiModeManager uiModeManager = mContext.getSystemService(UiModeManager.class);
+                    UiModeManager uiModeManager = context.getSystemService(UiModeManager.class);
                     if (uiModeManager.getNightMode() == UiModeManager.MODE_NIGHT_AUTO) {
                         // If we're set to AUTO and the system's auto night mode is already enabled,
                         // we'll just let the system handle it by returning FOLLOW_SYSTEM
                         return MODE_NIGHT_FOLLOW_SYSTEM;
                     }
                 }
-                return getAutoTimeNightModeManager().getApplyableNightMode();
+                return getAutoTimeNightModeManager(context).getApplyableNightMode();
             case MODE_NIGHT_AUTO_BATTERY:
-                return getAutoBatteryNightModeManager().getApplyableNightMode();
+                return getAutoBatteryNightModeManager(context).getApplyableNightMode();
             case MODE_NIGHT_UNSPECIFIED:
                 // If we don't have a mode specified, let the system handle it
                 return MODE_NIGHT_FOLLOW_SYSTEM;
@@ -2258,23 +2278,10 @@
         return mLocalNightMode != MODE_NIGHT_UNSPECIFIED ? mLocalNightMode : getDefaultNightMode();
     }
 
-    /**
-     * Updates the {@link Resources} configuration {@code uiMode} with the
-     * chosen {@code UI_MODE_NIGHT} value.
-     *
-     * @param mode The new night mode to apply
-     * @param allowRecreation whether to attempt activity recreate
-     * @param configOverlay the developer-provided configuration overlay to use, if any
-     * @return true if an action has been taken (recreation, resources updating, etc)
-     */
-    private boolean updateForNightMode(@ApplyableNightMode final int mode,
-            final boolean allowRecreation, @Nullable Configuration configOverlay) {
-        boolean handled = false;
-
-        final Configuration appConfig = mContext.getApplicationContext()
-                .getResources().getConfiguration();
-        final int applicationNightMode = appConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK;
-
+    @NonNull
+    private Configuration createOverrideConfigurationForDayNight(
+            @NonNull Context context, @ApplyableNightMode final int mode,
+            @Nullable Configuration configOverlay) {
         int newNightMode;
         switch (mode) {
             case MODE_NIGHT_YES:
@@ -2287,64 +2294,56 @@
             case MODE_NIGHT_FOLLOW_SYSTEM:
                 // If we're following the system, we just use the system default from the
                 // application context
-                newNightMode = applicationNightMode;
+                final Configuration appConfig =
+                        context.getApplicationContext().getResources().getConfiguration();
+                newNightMode = appConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK;
                 break;
         }
 
-        final boolean activityHandlingUiMode = isActivityManifestHandlingUiMode();
-
-        if ((sAlwaysOverrideConfiguration || newNightMode != applicationNightMode)
-                && !activityHandlingUiMode
-                && Build.VERSION.SDK_INT >= 17
-                && !mBaseContextAttached
-                && mHost instanceof android.view.ContextThemeWrapper) {
-            final android.view.ContextThemeWrapper host = (android.view.ContextThemeWrapper) mHost;
-
-            // If we're here then we can try and apply an override configuration on the Context.
-            final Configuration overrideConfig;
-            if (configOverlay != null) {
-                overrideConfig = new Configuration(configOverlay);
-            } else {
-                overrideConfig = new Configuration();
-                overrideConfig.fontScale = 0;
-            }
-            overrideConfig.uiMode =
-                    newNightMode | (overrideConfig.uiMode & ~Configuration.UI_MODE_NIGHT_MASK);
-
-            try {
-                if (DEBUG) {
-                    Log.d(TAG, "updateForNightMode. Applying override config: " + overrideConfig);
-                }
-                host.applyOverrideConfiguration(overrideConfig);
-                handled = true;
-            } catch (IllegalStateException e) {
-                // applyOverrideConfiguration throws an IllegalStateException if its resources
-                // have already been created. Since there's no way to check this beforehand we
-                // just have to try it and catch the exception. We only log if we're actually
-                // trying to apply a uiMode configuration though.
-                if (newNightMode != applicationNightMode) {
-                    Log.w(TAG, "updateForNightMode. Calling applyOverrideConfiguration() failed"
-                            + " with an exception. Will fall back to using"
-                            + " Resources.updateConfiguration()", e);
-                }
-                handled = false;
-            }
+        // If we're here then we can try and apply an override configuration on the Context.
+        final Configuration overrideConf = new Configuration();
+        overrideConf.fontScale = 0;
+        if (configOverlay != null) {
+            overrideConf.setTo(configOverlay);
         }
+        overrideConf.uiMode = newNightMode
+                | (overrideConf.uiMode & ~Configuration.UI_MODE_NIGHT_MASK);
+
+        return overrideConf;
+    }
+
+    /**
+     * Updates the {@link Resources} configuration {@code uiMode} with the
+     * chosen {@code UI_MODE_NIGHT} value.
+     *
+     * @param mode The new night mode to apply
+     * @param allowRecreation whether to attempt activity recreate
+     * @return true if an action has been taken (recreation, resources updating, etc)
+     */
+    private boolean updateForNightMode(@ApplyableNightMode final int mode,
+            final boolean allowRecreation) {
+        boolean handled = false;
+
+        final Configuration overrideConfig =
+                createOverrideConfigurationForDayNight(mContext, mode, null);
+
+        final boolean activityHandlingUiMode = isActivityManifestHandlingUiMode();
 
         final int currentNightMode = mContext.getResources().getConfiguration().uiMode
                 & Configuration.UI_MODE_NIGHT_MASK;
+        final int newNightMode = overrideConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK;
 
-        if (!handled
-                && currentNightMode != newNightMode
+        if (currentNightMode != newNightMode
                 && allowRecreation
                 && !activityHandlingUiMode
                 && mBaseContextAttached
                 && (Build.VERSION.SDK_INT >= 17 || mCreated)
                 && mHost instanceof Activity) {
             // If we're an attached Activity, we can recreate to apply
-            // The SDK_INT check above is because applyOverrideConfiguration only exists on
-            // API 17+, so we don't want to get into an loop of infinite recreations.
-            // On < API 17 we need to use updateConfiguration before we're 'created'
+            // The SDK_INT check above is because createConfigurationContext(), called from
+            // attachBaseContext(), only exists on API 17+, so we don't want to get into an loop
+            // of infinite recreations.
+            // On < API 17 we need to use updateConfiguration() before we're 'created' (below)
             if (DEBUG) {
                 Log.d(TAG, "updateForNightMode. Recreating Activity");
             }
@@ -2357,8 +2356,7 @@
             if (DEBUG) {
                 Log.d(TAG, "updateForNightMode. Updating resources config");
             }
-            updateResourcesConfigurationForNightMode(newNightMode, activityHandlingUiMode,
-                    configOverlay);
+            updateResourcesConfigurationForNightMode(newNightMode, activityHandlingUiMode, null);
             handled = true;
         }
 
@@ -2431,17 +2429,22 @@
      */
     @NonNull
     @RestrictTo(LIBRARY)
+    @VisibleForTesting
     final AutoNightModeManager getAutoTimeNightModeManager() {
+        return getAutoTimeNightModeManager(mContext);
+    }
+
+    private AutoNightModeManager getAutoTimeNightModeManager(@NonNull Context context) {
         if (mAutoTimeNightModeManager == null) {
             mAutoTimeNightModeManager = new AutoTimeNightModeManager(
-                    TwilightManager.getInstance(mContext));
+                    TwilightManager.getInstance(context));
         }
         return mAutoTimeNightModeManager;
     }
 
-    private AutoNightModeManager getAutoBatteryNightModeManager() {
+    private AutoNightModeManager getAutoBatteryNightModeManager(@NonNull Context context) {
         if (mAutoBatteryNightModeManager == null) {
-            mAutoBatteryNightModeManager = new AutoBatteryNightModeManager(mContext);
+            mAutoBatteryNightModeManager = new AutoBatteryNightModeManager(context);
         }
         return mAutoBatteryNightModeManager;
     }
diff --git a/arch/core-common/build.gradle b/arch/core-common/build.gradle
index 3c5f2fd..77324ae 100644
--- a/arch/core-common/build.gradle
+++ b/arch/core-common/build.gradle
@@ -26,10 +26,10 @@
 }
 
 dependencies {
-    compile("androidx.annotation:annotation:1.1.0")
+    api("androidx.annotation:annotation:1.1.0")
 
-    testCompile(JUNIT)
-    testCompile(MOCKITO_CORE)
+    testImplementation(JUNIT)
+    testImplementation(MOCKITO_CORE)
 }
 
 sourceCompatibility = JavaVersion.VERSION_1_7
diff --git a/buildSrc/build_dependencies.gradle b/buildSrc/build_dependencies.gradle
index 2503895..28e2999 100644
--- a/buildSrc/build_dependencies.gradle
+++ b/buildSrc/build_dependencies.gradle
@@ -29,7 +29,7 @@
     build_versions.lint = '26.6.0-beta04'
 }
 
-build_versions.dokka = '0.9.17-g002'
+build_versions.dokka = '0.9.17-g004'
 
 rootProject.ext['build_versions'] = build_versions
 
diff --git a/buildSrc/repos.gradle b/buildSrc/repos.gradle
index 54d76bd..06dc65b 100644
--- a/buildSrc/repos.gradle
+++ b/buildSrc/repos.gradle
@@ -27,8 +27,7 @@
 ext.repos.prebuiltsRoot = "${checkoutRoot}/prebuilts"
 
 ext.repoNames = ["${repos.prebuiltsRoot}/androidx/internal",
-                 "${repos.prebuiltsRoot}/androidx/external",
-                 "${checkoutRoot}/external/dokka/maven",]
+                 "${repos.prebuiltsRoot}/androidx/external"]
 
 /**
  * Adds maven repositories to the given repository handler.
diff --git a/buildSrc/src/main/kotlin/androidx/build/AndroidXPlugin.kt b/buildSrc/src/main/kotlin/androidx/build/AndroidXPlugin.kt
index 9b3fdc4..408b48b 100644
--- a/buildSrc/src/main/kotlin/androidx/build/AndroidXPlugin.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/AndroidXPlugin.kt
@@ -175,7 +175,7 @@
                     val reportLibraryMetrics = project.tasks.register(
                         REPORT_LIBRARY_METRICS, ReportLibraryMetricsTask::class.java
                     )
-
+                    project.addToBuildOnServer(reportLibraryMetrics)
                     extension.defaultPublishVariant { libraryVariant ->
                         reportLibraryMetrics.configure {
                             it.jarFiles.from(libraryVariant.packageLibraryProvider.map { zip ->
@@ -258,20 +258,20 @@
         if (isRunningOnBuildServer()) {
             gradle.startParameter.showStacktrace = ShowStacktrace.ALWAYS
         }
-        val createAggregateBuildInfoFilesTask =
-            tasks.register(CREATE_AGGREGATE_BUILD_INFO_FILES_TASK,
-                CreateAggregateLibraryBuildInfoFileTask::class.java)
-        val createLibraryBuildInfoFilesTask =
+        val buildOnServerTask = tasks.create(BUILD_ON_SERVER_TASK, BuildOnServer::class.java)
+        buildOnServerTask.dependsOn(
+            tasks.register(
+                CREATE_AGGREGATE_BUILD_INFO_FILES_TASK,
+                CreateAggregateLibraryBuildInfoFileTask::class.java
+            )
+        )
+        buildOnServerTask.dependsOn(
             tasks.register(CREATE_LIBRARY_BUILD_INFO_FILES_TASK)
+        )
 
         extra.set("versionChecker", GMavenVersionChecker(logger))
         val createArchiveTask = Release.getGlobalFullZipTask(this)
-
-        val buildOnServerTask = tasks.create(BUILD_ON_SERVER_TASK, BuildOnServer::class.java)
         buildOnServerTask.dependsOn(createArchiveTask)
-        buildOnServerTask.dependsOn(createAggregateBuildInfoFilesTask)
-        buildOnServerTask.dependsOn(createLibraryBuildInfoFilesTask)
-
         val partiallyDejetifyArchiveTask = partiallyDejetifyArchiveTask(
             createArchiveTask.get().archiveFile)
         if (partiallyDejetifyArchiveTask != null)
@@ -299,9 +299,6 @@
                     buildOnServerTask.dependsOn("${project.path}:lintDebug")
                 }
             }
-            project.plugins.withType(LibraryPlugin::class.java) {
-                buildOnServerTask.dependsOn("${project.path}:reportLibraryMetrics")
-            }
             project.plugins.withType(JavaPlugin::class.java) {
                 buildOnServerTask.dependsOn("${project.path}:jar")
             }
@@ -319,27 +316,22 @@
         }
 
         val createCoverageJarTask = Jacoco.createCoverageJarTask(this)
-        buildOnServerTask.dependsOn(createCoverageJarTask)
-
-        val createZipEcFilesTask = Jacoco.createZipEcFilesTask(this)
-        buildOnServerTask.dependsOn(createZipEcFilesTask)
-
         tasks.register(BUILD_TEST_APKS) {
             it.dependsOn(createCoverageJarTask)
         }
+        buildOnServerTask.dependsOn(createCoverageJarTask)
+        buildOnServerTask.dependsOn(Jacoco.createZipEcFilesTask(this))
 
         val rootProjectDir = SupportConfig.getSupportRoot(rootProject).canonicalFile
         val allDocsTask = DiffAndDocs.configureDiffAndDocs(this, rootProjectDir,
                 DacOptions("androidx", "ANDROIDX_DATA"),
                 listOf(RELEASE_RULE))
         buildOnServerTask.dependsOn(allDocsTask)
-
-        val jacocoUberJar = Jacoco.createUberJarTask(this)
-        buildOnServerTask.dependsOn(jacocoUberJar)
-        val checkSameVersionLibraryGroupsTask = tasks.register(
+        buildOnServerTask.dependsOn(Jacoco.createUberJarTask(this))
+        buildOnServerTask.dependsOn(tasks.register(
             CHECK_SAME_VERSION_LIBRARY_GROUPS,
             CheckSameVersionLibraryGroupsTask::class.java)
-        buildOnServerTask.dependsOn(checkSameVersionLibraryGroupsTask)
+        )
 
         AffectedModuleDetector.configure(gradle, this)
 
diff --git a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
index ec7ed31..db61c15 100644
--- a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
@@ -59,7 +59,7 @@
     val DYNAMICANIMATION_KTX = Version("1.0.0-alpha03")
     val EMOJI = Version("1.1.0-alpha01")
     val ENTERPRISE = Version("1.1.0-alpha01")
-    val EXIFINTERFACE = Version("1.2.0-alpha01")
+    val EXIFINTERFACE = Version("1.2.0-beta01")
     val FRAGMENT = Version("1.3.0-alpha01")
     val FUTURES = Version("1.1.0-alpha01")
     val GRIDLAYOUT = Version("1.1.0-alpha01")
diff --git a/buildSrc/src/main/kotlin/androidx/build/ListTaskOutputsTask.kt b/buildSrc/src/main/kotlin/androidx/build/ListTaskOutputsTask.kt
index c4c9cc7..772f6f4 100644
--- a/buildSrc/src/main/kotlin/androidx/build/ListTaskOutputsTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/ListTaskOutputsTask.kt
@@ -19,6 +19,7 @@
 import org.gradle.api.DefaultTask
 import org.gradle.api.Task
 import org.gradle.api.provider.Property
+import org.gradle.api.tasks.Input
 import org.gradle.api.tasks.OutputFile
 import org.gradle.api.tasks.TaskAction
 import java.io.File
@@ -29,7 +30,9 @@
 abstract class ListTaskOutputsTask() : DefaultTask() {
     @OutputFile
     val outputFile: Property<File> = project.objects.property(File::class.java)
+    @Input
     val removePrefixes: MutableList<String> = mutableListOf()
+    @Input
     val tasks: MutableList<Task> = mutableListOf()
 
     init {
diff --git a/buildSrc/src/main/kotlin/androidx/build/MavenUploadHelper.kt b/buildSrc/src/main/kotlin/androidx/build/MavenUploadHelper.kt
index 427c11a..7218e30 100644
--- a/buildSrc/src/main/kotlin/androidx/build/MavenUploadHelper.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/MavenUploadHelper.kt
@@ -28,6 +28,7 @@
 import org.gradle.api.publish.PublishingExtension
 import org.gradle.api.publish.maven.MavenPom
 import org.gradle.api.publish.maven.MavenPublication
+import org.gradle.api.publish.tasks.GenerateModuleMetadata
 import org.gradle.kotlin.dsl.configure
 import org.gradle.kotlin.dsl.create
 import java.io.File
@@ -49,6 +50,9 @@
     if (extension.publish.shouldPublish() && component.isAndroidOrJavaReleaseComponent()) {
         val androidxGroup = validateCoordinatesAndGetGroup(extension)
         group = androidxGroup
+        tasks.withType(GenerateModuleMetadata::class.java) {
+            it.enabled = false
+        }
         configure<PublishingExtension> {
             repositories {
                 it.maven { repo ->
diff --git a/buildSrc/src/main/kotlin/androidx/build/TaskUpToDateValidator.kt b/buildSrc/src/main/kotlin/androidx/build/TaskUpToDateValidator.kt
index cfb72ca..3624a89 100644
--- a/buildSrc/src/main/kotlin/androidx/build/TaskUpToDateValidator.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/TaskUpToDateValidator.kt
@@ -78,6 +78,7 @@
     "partiallyDejetifyArchive",
     "postInstrumentCode",
     "publishBenchmarkPluginMarkerMavenPublicationToMavenRepository",
+    "publishKotlinMultiplatformPublicationToMavenRepository",
     "publishMavenPublicationToMavenRepository",
     "publishMetadataPublicationToMavenRepository",
     "publishPluginMavenPublicationToMavenRepository",
@@ -88,7 +89,8 @@
     "transformClassesWithDexBuilderForPublicDebug",
     "transformClassesWithDexBuilderForTipOfTreeDebug",
     "unzipDokkaPublicDocsDeps",
-    "verifyDependencyVersions"
+    "verifyDependencyVersions",
+    "zipEcFiles"
 )
 class TaskUpToDateValidator {
     companion object {
diff --git a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
index 7a0b5e1..15f20b3 100644
--- a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
@@ -33,6 +33,7 @@
 const val APACHE_COMMONS_CODEC = "commons-codec:commons-codec:1.10"
 const val CHECKER_FRAMEWORK = "org.checkerframework:checker-qual:2.5.3"
 const val CONSTRAINT_LAYOUT = "androidx.constraintlayout:constraintlayout:1.1.0@aar"
+const val CONSTRAINT_LAYOUT_SOLVER = "androidx.constraintlayout:constraintlayout-solver:2.0.0-beta3"
 const val DEXMAKER_MOCKITO = "com.linkedin.dexmaker:dexmaker-mockito:2.25.0"
 const val ESPRESSO_CONTRIB = "androidx.test.espresso:espresso-contrib:3.1.0"
 const val ESPRESSO_CORE = "androidx.test.espresso:espresso-core:3.1.0"
diff --git a/buildSrc/src/main/kotlin/androidx/build/doclava/DoclavaTask.kt b/buildSrc/src/main/kotlin/androidx/build/doclava/DoclavaTask.kt
index ada5665..4adf272 100644
--- a/buildSrc/src/main/kotlin/androidx/build/doclava/DoclavaTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/doclava/DoclavaTask.kt
@@ -23,6 +23,7 @@
 import org.gradle.api.tasks.OutputFile
 import org.gradle.api.tasks.javadoc.Javadoc
 import org.gradle.external.javadoc.CoreJavadocOptions
+import org.gradle.external.javadoc.StandardJavadocDocletOptions
 import java.io.File
 
 // external/doclava/src/com/google/doclava/Errors.java
@@ -145,7 +146,7 @@
      * "Configures" this DoclavaTask with parameters that might not be at their final values
      * until this task is run.
      */
-    private fun configureDoclava() = (options as CoreJavadocOptions).apply {
+    private fun configureDoclava() = (options as StandardJavadocDocletOptions).apply {
 
         docletpath = this@DoclavaTask.docletpath
 
@@ -181,6 +182,9 @@
         }
         // Always treat this as an Android docs task.
         addBooleanOption("android", true)
+
+        // Doclava does not understand -notimestamp option that is default since Gradle 6.0
+        isNoTimestamp = false
     }
 
     fun coreJavadocOptions(configure: CoreJavadocOptions.() -> Unit) =
diff --git a/buildSrc/src/main/kotlin/androidx/build/dokka/DokkaPublicDocs.kt b/buildSrc/src/main/kotlin/androidx/build/dokka/DokkaPublicDocs.kt
index de986d5..b5e4eae 100644
--- a/buildSrc/src/main/kotlin/androidx/build/dokka/DokkaPublicDocs.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/dokka/DokkaPublicDocs.kt
@@ -27,6 +27,8 @@
 import org.gradle.api.Project
 import org.gradle.api.artifacts.ResolveException
 import org.gradle.api.tasks.Copy
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.OutputFiles
 import org.gradle.api.tasks.TaskAction
 import org.gradle.api.tasks.TaskCollection
 import org.gradle.api.tasks.TaskContainer
@@ -41,6 +43,7 @@
     private const val UNZIP_DEPS_TASK_NAME = "unzipDokkaPublicDocsDeps"
 
     val hiddenPackages = listOf(
+        "androidx.animation.samples",
         "androidx.camera.camera2.impl",
         "androidx.camera.camera2.impl.compat",
         "androidx.camera.camera2.impl.compat.params",
@@ -49,8 +52,16 @@
         "androidx.camera.core.impl.utils.executor",
         "androidx.camera.core.impl.utils.futures",
         "androidx.camera.core.impl.utils.futures.internal",
+        "androidx.compose.samples",
         "androidx.core.internal",
         "androidx.preference.internal",
+        "androidx.ui.animation.samples",
+        "androidx.ui.core.samples",
+        "androidx.ui.foundation.samples",
+        "androidx.ui.framework.samples",
+        "androidx.ui.layout.samples",
+        "androidx.ui.material.samples",
+        "androidx.ui.text.samples",
         "androidx.wear.internal.widget.drawer",
         "androidx.webkit.internal",
         "androidx.work.impl",
@@ -64,13 +75,6 @@
         "androidx.work.impl.utils",
         "androidx.work.impl.utils.futures",
         "androidx.work.impl.utils.taskexecutor",
-        "androidx.compose.samples",
-        "androidx.ui.animation.samples",
-        "androidx.ui.foundation.samples",
-        "androidx.ui.framework.samples",
-        "androidx.ui.layout.samples",
-        "androidx.ui.material.samples",
-        "androidx.ui.text.samples",
         "sample",
         "sample.foo")
 
@@ -215,14 +219,22 @@
 // TODO(b/143243490): can this be made to run more quickly, cleanly and clearly via some other
 // approach, such as maybe with an ArtifactTransform?
 open class LocateJarsTask : DefaultTask() {
+    init {
+        // This task does not correctly model inputs and outputs.
+        // Mark it to be never up to date
+        outputs.upToDateWhen { false }
+    }
+
     // dependencies to search for .jar files
+    @get:Input
     val inputDependencies = mutableListOf<String>()
 
     // .jar files found in any dependencies
+    @get:OutputFiles
     val outputJars = mutableListOf<File>()
 
     @TaskAction
-    fun Extract() {
+    fun extract() {
         // setup
         val inputDependencies = checkNotNull(inputDependencies) { "inputDependencies not set" }
         val project = this.project
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiCompatibilityTask.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiCompatibilityTask.kt
index 7c8a6528..d329caa 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiCompatibilityTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiCompatibilityTask.kt
@@ -23,10 +23,14 @@
 import org.gradle.api.tasks.InputFiles
 import org.gradle.api.tasks.OutputFiles
 import org.gradle.api.tasks.TaskAction
+import org.gradle.workers.WorkerExecutor
 import java.io.File
+import javax.inject.Inject
 
 // Validate that the API described in one signature txt file is compatible with the API in another
-abstract class CheckApiCompatibilityTask : MetalavaTask() {
+abstract class CheckApiCompatibilityTask @Inject constructor(
+    workerExecutor: WorkerExecutor
+) : MetalavaTask(workerExecutor) {
     // Text file from which the API signatures will be obtained.
     @get:Input
     abstract val referenceApi: Property<ApiLocation>
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/GenerateApiStubClassesTask.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/GenerateApiStubClassesTask.kt
index 3a2661a..c73f597 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/GenerateApiStubClassesTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/GenerateApiStubClassesTask.kt
@@ -19,9 +19,13 @@
 import org.gradle.api.file.DirectoryProperty
 import org.gradle.api.tasks.OutputDirectory
 import org.gradle.api.tasks.TaskAction
+import org.gradle.workers.WorkerExecutor
 import java.io.File
+import javax.inject.Inject
 
-abstract class GenerateApiStubClassesTask : MetalavaTask() {
+abstract class GenerateApiStubClassesTask @Inject constructor(
+    workerExecutor: WorkerExecutor
+) : MetalavaTask(workerExecutor) {
     @get:OutputDirectory
     abstract val apiStubsDirectory: DirectoryProperty
 
@@ -49,4 +53,4 @@
             )
         )
     }
-}
\ No newline at end of file
+}
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/GenerateApiTask.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/GenerateApiTask.kt
index 4276984..9991331 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/GenerateApiTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/GenerateApiTask.kt
@@ -25,10 +25,14 @@
 import org.gradle.api.tasks.Optional
 import org.gradle.api.tasks.OutputFiles
 import org.gradle.api.tasks.TaskAction
+import org.gradle.workers.WorkerExecutor
 import java.io.File
+import javax.inject.Inject
 
 /** Generate an API signature text file from a set of source files. */
-abstract class GenerateApiTask : MetalavaTask() {
+abstract class GenerateApiTask @Inject constructor(
+    workerExecutor: WorkerExecutor
+) : MetalavaTask(workerExecutor) {
     /** Text file to which API signatures will be written. */
     @get:Input
     abstract val apiLocation: Property<ApiLocation>
@@ -71,7 +75,8 @@
             apiLocation.get(),
             apiLocation.get().publicApiFile.parentFile,
             ApiLintMode.CheckBaseline(baselines.get().apiLintFile),
-            generateRestrictedAPIs
+            generateRestrictedAPIs,
+            workerExecutor
         )
     }
 }
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt
index f02bf3e..2440471 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt
@@ -22,10 +22,56 @@
 import org.gradle.api.Project
 import org.gradle.api.artifacts.Configuration
 import org.gradle.api.file.FileCollection
+import org.gradle.api.provider.ListProperty
+import org.gradle.api.provider.Property
+import org.gradle.process.ExecOperations
+import org.gradle.workers.WorkAction
+import org.gradle.workers.WorkerExecutor
+import org.gradle.workers.WorkParameters
 import java.io.File
+import javax.inject.Inject
 
 // MetalavaRunner stores common configuration for executing Metalava
 
+fun runMetalavaWithArgs(metalavaJar: File, args: List<String>, workerExecutor: WorkerExecutor) {
+    val allArgs = listOf(
+        "--no-banner",
+        "--hide",
+        "HiddenSuperclass" // We allow having a hidden parent class
+    ) + args
+
+    val workQueue = workerExecutor.noIsolation()
+    workQueue.submit(MetalavaWorkAction::class.java) { parameters ->
+        parameters.getArgs().set(allArgs)
+        parameters.getMetalavaJar().set(metalavaJar)
+    }
+}
+
+interface MetalavaParams : WorkParameters {
+    fun getArgs(): ListProperty<String>
+    fun getMetalavaJar(): Property<File>
+}
+
+abstract class MetalavaWorkAction @Inject constructor (
+    private val execOperations: ExecOperations
+) : WorkAction<MetalavaParams> {
+
+    override fun execute() {
+        val allArgs = getParameters().getArgs().get()
+        val metalavaJar = getParameters().getMetalavaJar().get()
+
+        execOperations.javaexec {
+            it.classpath(metalavaJar)
+            it.main = "com.android.tools.metalava.Driver"
+            it.args = allArgs
+        }
+    }
+}
+
+fun Project.getMetalavaJar(): File {
+    return getMetalavaConfiguration().resolvedConfiguration.files.iterator().next()
+}
+
 fun Project.getMetalavaConfiguration(): Configuration {
     return configurations.findByName("metalava") ?: configurations.create("metalava") {
         val dependency = dependencies.create("com.android:metalava:1.3.0:shadow@jar")
@@ -33,18 +79,6 @@
     }
 }
 
-fun Project.runMetalavaWithArgs(configuration: Configuration, args: List<String>) {
-    javaexec {
-        it.classpath = checkNotNull(configuration) { "Configuration not set." }
-        it.main = "com.android.tools.metalava.Driver"
-        it.args = listOf(
-            "--no-banner",
-            "--hide",
-            "HiddenSuperclass" // We allow having a hidden parent class
-        ) + args
-    }
-}
-
 // Metalava arguments to hide all experimental API surfaces.
 val HIDE_EXPERIMENTAL_ARGS: List<String> = listOf(
     "--hide-annotation", "androidx.annotation.experimental.Experimental",
@@ -122,15 +156,18 @@
     apiLocation: ApiLocation,
     tempDir: File,
     apiLintMode: ApiLintMode,
-    includeRestrictedApis: Boolean
+    includeRestrictedApis: Boolean,
+    workerExecutor: WorkerExecutor
 ) {
     generateApi(files.bootClasspath, files.dependencyClasspath, files.sourcePaths.files,
-        apiLocation.publicApiFile, tempDir, GenerateApiMode.PublicApi, apiLintMode)
+        apiLocation.publicApiFile, tempDir, GenerateApiMode.PublicApi, apiLintMode, workerExecutor)
     generateApi(files.bootClasspath, files.dependencyClasspath, files.sourcePaths.files,
-        apiLocation.experimentalApiFile, tempDir, GenerateApiMode.ExperimentalApi, apiLintMode)
+        apiLocation.experimentalApiFile, tempDir, GenerateApiMode.ExperimentalApi, apiLintMode,
+        workerExecutor)
     if (includeRestrictedApis) {
         generateApi(files.bootClasspath, files.dependencyClasspath, files.sourcePaths.files,
-            apiLocation.restrictedApiFile, tempDir, GenerateApiMode.RestrictedApi, ApiLintMode.Skip)
+            apiLocation.restrictedApiFile, tempDir, GenerateApiMode.RestrictedApi, ApiLintMode.Skip,
+            workerExecutor)
     }
 }
 
@@ -142,7 +179,8 @@
     outputFile: File,
     tempDir: File,
     generateApiMode: GenerateApiMode,
-    apiLintMode: ApiLintMode
+    apiLintMode: ApiLintMode,
+    workerExecutor: WorkerExecutor
 ) {
     val tempOutputFile = if (generateApiMode is GenerateApiMode.RestrictedApi) {
         File(tempDir, outputFile.name + ".tmp")
@@ -209,11 +247,13 @@
         }
     }
 
-    val metalavaConfiguration = getMetalavaConfiguration()
-    runMetalavaWithArgs(metalavaConfiguration, args)
-
     if (generateApiMode is GenerateApiMode.RestrictedApi) {
+        runMetalavaWithArgs(getMetalavaJar(), args, workerExecutor)
+        // TODO(119617147): when we no longer need to fix Metalava's output, remove this "await"
+        workerExecutor.await()
         removeRestrictToLibraryLines(tempOutputFile, outputFile)
+    } else {
+        runMetalavaWithArgs(getMetalavaJar(), args, workerExecutor)
     }
 }
 
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaTask.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaTask.kt
index 78480c81..b0d8932 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaTask.kt
@@ -22,9 +22,16 @@
 import org.gradle.api.file.FileCollection
 import org.gradle.api.tasks.Classpath
 import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.Internal
+import org.gradle.workers.WorkerExecutor
+import javax.inject.Inject
 
 /** Base class for invoking Metalava. */
-abstract class MetalavaTask : DefaultTask() {
+abstract class MetalavaTask @Inject constructor(
+    @Internal
+    protected val workerExecutor: WorkerExecutor
+) : DefaultTask() {
+
     /** Configuration containing Metalava and its dependencies. */
     @get:Classpath
     @get:InputFiles
@@ -42,7 +49,7 @@
     @get:InputFiles
     var sourcePaths: Collection<File> = emptyList()
 
-    protected fun runWithArgs(args: List<String>) {
-        project.runMetalavaWithArgs(configuration, args)
+    fun runWithArgs(args: List<String>) {
+        runMetalavaWithArgs(project.getMetalavaJar(), args, workerExecutor)
     }
 }
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/RegenerateOldApisTask.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/RegenerateOldApisTask.kt
index 40bba3c..b02956c 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/RegenerateOldApisTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/RegenerateOldApisTask.kt
@@ -27,10 +27,14 @@
 import org.gradle.api.internal.artifacts.ivyservice.DefaultLenientConfiguration
 import org.gradle.api.tasks.TaskAction
 import org.gradle.api.tasks.util.PatternFilterable
+import org.gradle.workers.WorkerExecutor
 import java.io.File
+import javax.inject.Inject
 
 /** Generate API signature text files using previously built .jar/.aar artifacts. */
-abstract class RegenerateOldApisTask : DefaultTask() {
+abstract class RegenerateOldApisTask @Inject constructor(
+    private val workerExecutor: WorkerExecutor
+) : DefaultTask() {
     @TaskAction
     fun exec() {
         val groupId = project.group.toString()
@@ -84,7 +88,8 @@
             project.logger.lifecycle("Regenerating $mavenId")
             val generateRestrictedAPIs = outputApiLocation.restrictedApiFile.exists()
             project.generateApi(
-                inputs, outputApiLocation, tempDir, ApiLintMode.Skip, generateRestrictedAPIs)
+                inputs, outputApiLocation, tempDir, ApiLintMode.Skip, generateRestrictedAPIs,
+                workerExecutor)
         }
     }
 
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/UpdateBaselineTasks.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/UpdateBaselineTasks.kt
index 1eca2fa..77fe582 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/UpdateBaselineTasks.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/UpdateBaselineTasks.kt
@@ -25,9 +25,13 @@
 import org.gradle.api.tasks.OutputFile
 import org.gradle.api.tasks.OutputFiles
 import org.gradle.api.tasks.TaskAction
+import org.gradle.workers.WorkerExecutor
 import java.io.File
+import javax.inject.Inject
 
-abstract class UpdateApiLintBaselineTask : MetalavaTask() {
+abstract class UpdateApiLintBaselineTask @Inject constructor(
+    workerExecutor: WorkerExecutor
+) : MetalavaTask(workerExecutor) {
     init {
         group = "API"
         description = "Updates an API lint baseline file (api/api_lint.ignore) to match the " +
@@ -60,7 +64,9 @@
     }
 }
 
-abstract class IgnoreApiChangesTask : MetalavaTask() {
+abstract class IgnoreApiChangesTask @Inject constructor(
+    workerExecutor: WorkerExecutor
+) : MetalavaTask(workerExecutor) {
     init {
         description = "Updates an API tracking baseline file (api/X.Y.Z.ignore) to match the " +
                 "current set of violations"
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java
index 3cb85ac..9fe69e6 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java
@@ -38,7 +38,6 @@
 import androidx.camera.core.ImageAnalysis.BackpressureStrategy;
 import androidx.camera.core.ImageAnalysisConfig;
 import androidx.camera.core.ImageProxy;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.UseCase.StateChangeCallback;
 import androidx.camera.core.impl.utils.executor.CameraXExecutors;
 import androidx.camera.testing.CameraUtil;
@@ -107,7 +106,8 @@
         mHandlerThread = new HandlerThread("AnalysisThread");
         mHandlerThread.start();
         mHandler = new Handler(mHandlerThread.getLooper());
-        mCameraSelector = new CameraSelector.Builder().requireLensFacing(LensFacing.BACK).build();
+        mCameraSelector = new CameraSelector.Builder().requireLensFacing(
+                CameraSelector.LENS_FACING_BACK).build();
         mLifecycleOwner = new FakeLifecycleOwner();
     }
 
@@ -154,13 +154,13 @@
     @Test
     public void analyzesImages_withKEEP_ONLY_LATEST_whenCameraIsOpen()
             throws InterruptedException {
-        analyzerAnalyzesImagesWithStrategy(BackpressureStrategy.KEEP_ONLY_LATEST);
+        analyzerAnalyzesImagesWithStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST);
     }
 
     @Test
     public void analyzesImages_withBLOCK_PRODUCER_whenCameraIsOpen()
             throws InterruptedException {
-        analyzerAnalyzesImagesWithStrategy(BackpressureStrategy.BLOCK_PRODUCER);
+        analyzerAnalyzesImagesWithStrategy(ImageAnalysis.STRATEGY_BLOCK_PRODUCER);
     }
 
     private void analyzerAnalyzesImagesWithStrategy(@BackpressureStrategy int backpressureStrategy)
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageCaptureTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageCaptureTest.java
index 4d057f6..3e0e96b 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageCaptureTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageCaptureTest.java
@@ -61,14 +61,11 @@
 import androidx.camera.core.CaptureStage;
 import androidx.camera.core.Exif;
 import androidx.camera.core.ImageCapture;
-import androidx.camera.core.ImageCapture.CaptureMode;
-import androidx.camera.core.ImageCapture.ImageCaptureError;
 import androidx.camera.core.ImageCapture.Metadata;
 import androidx.camera.core.ImageCapture.OnImageCapturedCallback;
 import androidx.camera.core.ImageCapture.OnImageSavedCallback;
 import androidx.camera.core.ImageCaptureConfig;
 import androidx.camera.core.ImageProxy;
-import androidx.camera.core.LensFacing;
 import androidx.camera.testing.CameraUtil;
 import androidx.camera.testing.fakes.FakeCameraControl;
 import androidx.camera.testing.fakes.FakeCaptureStage;
@@ -112,8 +109,8 @@
 
     private static final Size DEFAULT_RESOLUTION = new Size(640, 480);
     private static final Size GUARANTEED_RESOLUTION = new Size(640, 480);
-    @LensFacing
-    private static final int BACK_LENS_FACING = LensFacing.BACK;
+    @CameraSelector.LensFacing
+    private static final int BACK_LENS_FACING = CameraSelector.LENS_FACING_BACK;
     private static final CameraSelector BACK_SELECTOR =
             new CameraSelector.Builder().requireLensFacing(BACK_LENS_FACING).build();
 
@@ -249,7 +246,7 @@
     @Test
     public void canCaptureMultipleImagesWithMaxQuality() {
         ImageCapture useCase = new ImageCapture.Builder()
-                .setCaptureMode(CaptureMode.MAXIMIZE_QUALITY)
+                .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
                 .build();
         mInstrumentation.runOnMainSync(
                 () -> {
@@ -432,7 +429,7 @@
 
         // Wait for the signal that the image has been saved.
         verify(callback, timeout(2000))
-                .onError(eq(ImageCaptureError.FILE_IO_ERROR), anyString(), any(Throwable.class));
+                .onError(eq(ImageCapture.ERROR_FILE_IO), anyString(), any(Throwable.class));
     }
 
     @Test
@@ -605,7 +602,7 @@
         verify(callback, timeout(500).times(1)).onError(errorCaptor.capture(),
                 any(String.class),
                 any(Throwable.class));
-        assertThat(errorCaptor.getValue()).isEqualTo(ImageCaptureError.CAMERA_CLOSED);
+        assertThat(errorCaptor.getValue()).isEqualTo(ImageCapture.ERROR_CAMERA_CLOSED);
     }
 
     @Test
@@ -634,7 +631,7 @@
         verify(callback, timeout(500).times(1)).onError(errorCaptor.capture(),
                 any(String.class),
                 any(Throwable.class));
-        assertThat(errorCaptor.getValue()).isEqualTo(ImageCaptureError.CAPTURE_FAILED);
+        assertThat(errorCaptor.getValue()).isEqualTo(ImageCapture.ERROR_CAPTURE_FAILED);
     }
 
     @Test
@@ -661,9 +658,9 @@
                 any(String.class),
                 any(Throwable.class));
         assertThat(errorCaptor.getAllValues()).containsExactly(
-                ImageCaptureError.CAMERA_CLOSED,
-                ImageCaptureError.CAMERA_CLOSED,
-                ImageCaptureError.CAMERA_CLOSED);
+                ImageCapture.ERROR_CAMERA_CLOSED,
+                ImageCapture.ERROR_CAMERA_CLOSED,
+                ImageCapture.ERROR_CAMERA_CLOSED);
     }
 
     @Test
@@ -676,7 +673,7 @@
         ArgumentCaptor<Integer> errorCaptor = ArgumentCaptor.forClass(Integer.class);
         verify(callback, timeout(500)).onError(errorCaptor.capture(), any(String.class),
                 any(Throwable.class));
-        assertThat(errorCaptor.getValue()).isEqualTo(ImageCaptureError.INVALID_CAMERA);
+        assertThat(errorCaptor.getValue()).isEqualTo(ImageCapture.ERROR_INVALID_CAMERA);
     }
 
     private static final class ImageProperties {
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/PreviewTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/PreviewTest.java
index 3092e16..5904e3d0 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/PreviewTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/PreviewTest.java
@@ -36,7 +36,6 @@
 import androidx.camera.core.CameraX;
 import androidx.camera.core.CameraXConfig;
 import androidx.camera.core.CaptureConfig;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.Preview;
 import androidx.camera.core.SessionConfig;
 import androidx.camera.core.impl.utils.executor.CameraXExecutors;
@@ -110,18 +109,20 @@
         CameraFactory cameraFactory = Preconditions.checkNotNull(cameraXConfig.getCameraFactory(
                 /*valueIfMissing=*/ null));
         try {
-            mCameraId = cameraFactory.cameraIdForLensFacing(LensFacing.BACK);
+            mCameraId = cameraFactory.cameraIdForLensFacing(CameraSelector.LENS_FACING_BACK);
         } catch (Exception e) {
             throw new IllegalArgumentException(
-                    "Unable to attach to camera with LensFacing " + LensFacing.BACK, e);
+                    "Unable to attach to camera with LensFacing " + CameraSelector.LENS_FACING_BACK,
+                    e);
         }
 
         // init CameraX before creating Preview to get preview size with CameraX's context
         mDefaultBuilder = Preview.Builder.fromConfig(
-                Preview.DEFAULT_CONFIG.getConfig(LensFacing.BACK));
+                Preview.DEFAULT_CONFIG.getConfig(CameraSelector.LENS_FACING_BACK));
         mSurfaceFutureSemaphore = new Semaphore(/*permits=*/ 0);
         mSaveToReleaseSemaphore = new Semaphore(/*permits=*/ 0);
-        mCameraSelector = new CameraSelector.Builder().requireLensFacing(LensFacing.BACK).build();
+        mCameraSelector = new CameraSelector.Builder().requireLensFacing(
+                CameraSelector.LENS_FACING_BACK).build();
         mLifecycleOwner = new FakeLifecycleOwner();
     }
 
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/SurfaceOrientedMeteringPointFactoryTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/SurfaceOrientedMeteringPointFactoryTest.java
index 63c7e7a..ca85c1b 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/SurfaceOrientedMeteringPointFactoryTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/SurfaceOrientedMeteringPointFactoryTest.java
@@ -29,7 +29,6 @@
 import androidx.camera.core.CameraX;
 import androidx.camera.core.CameraXConfig;
 import androidx.camera.core.ImageAnalysis;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.MeteringPoint;
 import androidx.camera.core.MeteringPointFactory;
 import androidx.camera.core.SurfaceOrientedMeteringPointFactory;
@@ -112,14 +111,15 @@
 
     @Test
     public void createPointWithFoVUseCase_success() {
-        assumeTrue(CameraUtil.hasCameraWithLensFacing(LensFacing.BACK));
+        assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK));
 
         ImageAnalysis imageAnalysis = new ImageAnalysis.Builder()
                 .setTargetAspectRatio(AspectRatio.RATIO_4_3)
                 .setTargetName("ImageAnalysis")
                 .build();
         CameraSelector cameraSelector =
-                new CameraSelector.Builder().requireLensFacing(LensFacing.BACK).build();
+                new CameraSelector.Builder().requireLensFacing(
+                        CameraSelector.LENS_FACING_BACK).build();
         mInstrumentation.runOnMainSync(new Runnable() {
             @Override
             public void run() {
@@ -135,7 +135,7 @@
 
     @Test(expected = IllegalStateException.class)
     public void createPointWithFoVUseCase_FailedNotBound() {
-        assumeTrue(CameraUtil.hasCameraWithLensFacing(LensFacing.BACK));
+        assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK));
 
         ImageAnalysis imageAnalysis = new ImageAnalysis.Builder()
                 .setTargetAspectRatio(AspectRatio.RATIO_4_3)
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/UseCaseCombinationTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/UseCaseCombinationTest.java
index 4f5e7ea..396efda 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/UseCaseCombinationTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/UseCaseCombinationTest.java
@@ -34,7 +34,6 @@
 import androidx.camera.core.CameraXConfig;
 import androidx.camera.core.ImageAnalysis;
 import androidx.camera.core.ImageCapture;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.Preview;
 import androidx.camera.core.impl.utils.executor.CameraXExecutors;
 import androidx.camera.testing.CameraUtil;
@@ -66,7 +65,7 @@
 @RunWith(AndroidJUnit4.class)
 public final class UseCaseCombinationTest {
     private static final CameraSelector DEFAULT_SELECTOR =
-            new CameraSelector.Builder().requireLensFacing(LensFacing.BACK).build();
+            new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build();
     private final MutableLiveData<Long> mAnalysisResult = new MutableLiveData<>();
     @Rule
     public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/VideoCaptureTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/VideoCaptureTest.java
index f0a93a5..3a4adda 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/VideoCaptureTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/VideoCaptureTest.java
@@ -30,7 +30,6 @@
 import androidx.camera.core.CameraSelector;
 import androidx.camera.core.CameraX;
 import androidx.camera.core.CameraXConfig;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.UseCase;
 import androidx.camera.core.UseCase.StateChangeCallback;
 import androidx.camera.core.VideoCapture;
@@ -101,7 +100,8 @@
         CameraFactory cameraFactory = cameraXConfig.getCameraFactory(/*valueIfMissing=*/ null);
         CameraX.initialize(context, cameraXConfig);
         mLifecycleOwner = new FakeLifecycleOwner();
-        mCameraSelector = new CameraSelector.Builder().requireLensFacing(LensFacing.BACK).build();
+        mCameraSelector = new CameraSelector.Builder().requireLensFacing(
+                CameraSelector.LENS_FACING_BACK).build();
     }
 
     @After
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2CameraControlTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2CameraControlTest.java
index 40dbcb54d..a936757 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2CameraControlTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2CameraControlTest.java
@@ -54,11 +54,10 @@
 import androidx.camera.core.CameraControl;
 import androidx.camera.core.CameraControlInternal;
 import androidx.camera.core.CameraInfoUnavailableException;
+import androidx.camera.core.CameraSelector;
 import androidx.camera.core.CaptureConfig;
-import androidx.camera.core.FlashMode;
 import androidx.camera.core.FocusMeteringAction;
-import androidx.camera.core.FocusMeteringAction.MeteringMode;
-import androidx.camera.core.LensFacing;
+import androidx.camera.core.ImageCapture;
 import androidx.camera.core.SessionConfig;
 import androidx.camera.core.SurfaceOrientedMeteringPointFactory;
 import androidx.camera.core.impl.utils.executor.CameraXExecutors;
@@ -102,14 +101,14 @@
     @Before
     public void setUp() throws InterruptedException, CameraAccessException,
             CameraInfoUnavailableException {
-        assumeTrue(CameraUtil.hasCameraWithLensFacing(LensFacing.BACK));
+        assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK));
 
         Context context = ApplicationProvider.getApplicationContext();
         CameraManager cameraManager = (CameraManager) context.getSystemService(
                 Context.CAMERA_SERVICE);
         Camera2CameraFactory camera2CameraFactory = new Camera2CameraFactory(context);
         mCameraCharacteristics = cameraManager.getCameraCharacteristics(
-                camera2CameraFactory.cameraIdForLensFacing(LensFacing.BACK));
+                camera2CameraFactory.cameraIdForLensFacing(CameraSelector.LENS_FACING_BACK));
         Boolean hasFlashUnit =
                 mCameraCharacteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
         mHasFlashUnit = hasFlashUnit != null && hasFlashUnit.booleanValue();
@@ -177,7 +176,7 @@
 
     @Test
     public void setFlashModeAuto_aeModeSetAndRequestUpdated() throws InterruptedException {
-        mCamera2CameraControl.setFlashMode(FlashMode.AUTO);
+        mCamera2CameraControl.setFlashMode(ImageCapture.FLASH_MODE_AUTO);
 
         HandlerUtil.waitForLooperToIdle(mHandler);
 
@@ -188,12 +187,12 @@
                 sessionConfig.getImplementationOptions());
 
         assertAeMode(camera2Config, CONTROL_AE_MODE_ON_AUTO_FLASH);
-        assertThat(mCamera2CameraControl.getFlashMode()).isEqualTo(FlashMode.AUTO);
+        assertThat(mCamera2CameraControl.getFlashMode()).isEqualTo(ImageCapture.FLASH_MODE_AUTO);
     }
 
     @Test
     public void setFlashModeOff_aeModeSetAndRequestUpdated() throws InterruptedException {
-        mCamera2CameraControl.setFlashMode(FlashMode.OFF);
+        mCamera2CameraControl.setFlashMode(ImageCapture.FLASH_MODE_OFF);
 
         HandlerUtil.waitForLooperToIdle(mHandler);
 
@@ -205,12 +204,12 @@
 
         assertAeMode(camera2Config, CONTROL_AE_MODE_ON);
 
-        assertThat(mCamera2CameraControl.getFlashMode()).isEqualTo(FlashMode.OFF);
+        assertThat(mCamera2CameraControl.getFlashMode()).isEqualTo(ImageCapture.FLASH_MODE_OFF);
     }
 
     @Test
     public void setFlashModeOn_aeModeSetAndRequestUpdated() throws InterruptedException {
-        mCamera2CameraControl.setFlashMode(FlashMode.ON);
+        mCamera2CameraControl.setFlashMode(ImageCapture.FLASH_MODE_ON);
 
         HandlerUtil.waitForLooperToIdle(mHandler);
 
@@ -222,7 +221,7 @@
 
         assertAeMode(camera2Config, CONTROL_AE_MODE_ON_ALWAYS_FLASH);
 
-        assertThat(mCamera2CameraControl.getFlashMode()).isEqualTo(FlashMode.ON);
+        assertThat(mCamera2CameraControl.getFlashMode()).isEqualTo(ImageCapture.FLASH_MODE_ON);
     }
 
     @Test
@@ -249,7 +248,7 @@
     @Test
     public void disableTorchFlashModeAuto_aeModeSetAndRequestUpdated() throws InterruptedException {
         assumeTrue(mHasFlashUnit);
-        mCamera2CameraControl.setFlashMode(FlashMode.AUTO);
+        mCamera2CameraControl.setFlashMode(ImageCapture.FLASH_MODE_AUTO);
         mCamera2CameraControl.enableTorch(false);
 
         HandlerUtil.waitForLooperToIdle(mHandler);
@@ -452,7 +451,7 @@
         SurfaceOrientedMeteringPointFactory factory = new SurfaceOrientedMeteringPointFactory(1.0f,
                 1.0f);
         FocusMeteringAction action = FocusMeteringAction.Builder.from(factory.createPoint(0, 0),
-                MeteringMode.AE | MeteringMode.AWB)
+                FocusMeteringAction.FLAG_AE | FocusMeteringAction.FLAG_AWB)
                 .build();
         mCamera2CameraControl.startFocusAndMetering(action);
         HandlerUtil.waitForLooperToIdle(mHandler);
@@ -546,7 +545,7 @@
         SurfaceOrientedMeteringPointFactory factory = new SurfaceOrientedMeteringPointFactory(1.0f,
                 1.0f);
         FocusMeteringAction action = FocusMeteringAction.Builder.from(factory.createPoint(0, 0),
-                MeteringMode.AE)
+                FocusMeteringAction.FLAG_AE)
                 .build();
         mCamera2CameraControl.startFocusAndMetering(action);
         HandlerUtil.waitForLooperToIdle(mHandler);
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2CameraImplTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2CameraImplTest.java
index 6ea0506..1a8f75c 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2CameraImplTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2CameraImplTest.java
@@ -51,7 +51,6 @@
 import androidx.camera.core.CaptureConfig;
 import androidx.camera.core.DeferrableSurface;
 import androidx.camera.core.ImmediateSurface;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.Observable;
 import androidx.camera.core.SessionConfig;
 import androidx.camera.core.UseCase;
@@ -101,8 +100,8 @@
 @LargeTest
 @RunWith(AndroidJUnit4.class)
 public final class Camera2CameraImplTest {
-    @LensFacing
-    private static final int DEFAULT_LENS_FACING = LensFacing.BACK;
+    @CameraSelector.LensFacing
+    private static final int DEFAULT_LENS_FACING = CameraSelector.LENS_FACING_BACK;
     // For the purpose of this test, always say we have 1 camera available.
     private static final int DEFAULT_AVAILABLE_CAMERA_COUNT = 1;
     private static final Set<CameraInternal.State> STABLE_STATES = new HashSet<>(Arrays.asList(
@@ -124,7 +123,8 @@
     OnImageAvailableListener mMockOnImageAvailableListener;
     String mCameraId;
 
-    private static String getCameraIdForLensFacingUnchecked(@LensFacing int lensFacing) {
+    private static String getCameraIdForLensFacingUnchecked(
+            @CameraSelector.LensFacing int lensFacing) {
         try {
             return sCameraFactory.cameraIdForLensFacing(lensFacing);
         } catch (Exception e) {
@@ -150,8 +150,8 @@
         mSemaphore = new Semaphore(0);
         mAvailableCameras = new SettableObservable<>(DEFAULT_AVAILABLE_CAMERA_COUNT);
         mCamera2CameraImpl = new Camera2CameraImpl(
-                CameraManagerCompat.from(ApplicationProvider.getApplicationContext()),
-                mCameraId, mAvailableCameras, mCameraHandler);
+                CameraManagerCompat.from(ApplicationProvider.getApplicationContext()), mCameraId,
+                mAvailableCameras, mCameraHandler);
     }
 
     @After
@@ -806,7 +806,8 @@
         FakeUseCaseConfig.Builder configBuilder =
                 new FakeUseCaseConfig.Builder().setTargetName("UseCase");
         CameraSelector selector =
-                new CameraSelector.Builder().requireLensFacing(LensFacing.BACK).build();
+                new CameraSelector.Builder().requireLensFacing(
+                        CameraSelector.LENS_FACING_BACK).build();
         TestUseCase testUseCase = new TestUseCase(configBuilder.getUseCaseConfig(), selector,
                 mMockOnImageAvailableListener);
         Map<String, Size> suggestedResolutionMap = new HashMap<>();
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2ImplCameraRepositoryTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2ImplCameraRepositoryTest.java
index cca44f9..188cc0b 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2ImplCameraRepositoryTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2ImplCameraRepositoryTest.java
@@ -32,8 +32,8 @@
 import androidx.camera.camera2.interop.ExperimentalCamera2Interop;
 import androidx.camera.core.CameraFactory;
 import androidx.camera.core.CameraRepository;
+import androidx.camera.core.CameraSelector;
 import androidx.camera.core.ImmediateSurface;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.SessionConfig;
 import androidx.camera.core.UseCaseConfig;
 import androidx.camera.core.UseCaseGroup;
@@ -74,7 +74,7 @@
     private CameraDevice.StateCallback mDeviceStateCallback;
     private String mCameraId;
 
-    private String getCameraIdForLensFacingUnchecked(@LensFacing int lensFacing) {
+    private String getCameraIdForLensFacingUnchecked(@CameraSelector.LensFacing int lensFacing) {
         try {
             return mCameraFactory.cameraIdForLensFacing(lensFacing);
         } catch (Exception e) {
@@ -116,7 +116,7 @@
         FakeUseCaseConfig.Builder configBuilder = new FakeUseCaseConfig.Builder();
         new Camera2Interop.Extender<>(configBuilder).setDeviceStateCallback(mDeviceStateCallback);
         mConfig = configBuilder.getUseCaseConfig();
-        mCameraId = getCameraIdForLensFacingUnchecked(LensFacing.BACK);
+        mCameraId = getCameraIdForLensFacingUnchecked(CameraSelector.LENS_FACING_BACK);
         mUseCase = new CallbackAttachingFakeUseCase(mConfig, mCameraId);
         mUseCaseGroup.addUseCase(mUseCase);
     }
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2ImplCameraXTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2ImplCameraXTest.java
index d0bcc8b..90436af 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2ImplCameraXTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2ImplCameraXTest.java
@@ -49,7 +49,6 @@
 import androidx.camera.core.ImageAnalysis;
 import androidx.camera.core.ImageCapture;
 import androidx.camera.core.ImageProxy;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.impl.utils.executor.CameraXExecutors;
 import androidx.camera.testing.CameraUtil;
 import androidx.camera.testing.fakes.FakeLifecycleOwner;
@@ -82,8 +81,8 @@
 @RunWith(AndroidJUnit4.class)
 @UseExperimental(markerClass = ExperimentalCamera2Interop.class)
 public final class Camera2ImplCameraXTest {
-    @LensFacing
-    private static final int DEFAULT_LENS_FACING = LensFacing.BACK;
+    @CameraSelector.LensFacing
+    private static final int DEFAULT_LENS_FACING = CameraSelector.LENS_FACING_BACK;
     private static final CameraSelector DEFAULT_SELECTOR =
             new CameraSelector.Builder().requireLensFacing(DEFAULT_LENS_FACING).build();
     private final MutableLiveData<Long> mAnalysisResult = new MutableLiveData<>();
@@ -428,7 +427,7 @@
         ImageAnalysis useCase0 = builder.build();
 
         ImageCapture useCase1 = new ImageCapture.Builder()
-                .setCaptureMode(ImageCapture.CaptureMode.MAXIMIZE_QUALITY)
+                .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
                 .build();
 
         mInstrumentation.runOnMainSync(new Runnable() {
@@ -460,7 +459,7 @@
         ImageAnalysis useCase0 = builder.build();
 
         ImageCapture useCase1 = new ImageCapture.Builder()
-                .setCaptureMode(ImageCapture.CaptureMode.MAXIMIZE_QUALITY)
+                .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
                 .build();
 
         mInstrumentation.runOnMainSync(new Runnable() {
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/TorchControlDeviceTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/TorchControlDeviceTest.java
index 56c9277..c50ee68 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/TorchControlDeviceTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/TorchControlDeviceTest.java
@@ -27,7 +27,6 @@
 import androidx.camera.core.CameraX;
 import androidx.camera.core.CameraXConfig;
 import androidx.camera.core.ImageAnalysis;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.impl.utils.executor.CameraXExecutors;
 import androidx.camera.testing.CameraUtil;
 import androidx.camera.testing.fakes.FakeLifecycleOwner;
@@ -50,8 +49,8 @@
 @MediumTest
 @RunWith(AndroidJUnit4.class)
 public class TorchControlDeviceTest {
-    @LensFacing
-    private static final int LENS_FACING = LensFacing.BACK;
+    @CameraSelector.LensFacing
+    private static final int LENS_FACING = CameraSelector.LENS_FACING_BACK;
 
     @Rule
     public GrantPermissionRule mCameraPermissionRule =
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/ZoomControlDeviceTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/ZoomControlDeviceTest.java
index b0ce14ef..2d1be53 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/ZoomControlDeviceTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/ZoomControlDeviceTest.java
@@ -39,9 +39,9 @@
 import androidx.camera.camera2.Camera2Config;
 import androidx.camera.core.CameraControlInternal.ControlUpdateCallback;
 import androidx.camera.core.CameraInfoUnavailableException;
+import androidx.camera.core.CameraSelector;
 import androidx.camera.core.CameraX;
 import androidx.camera.core.CameraXConfig;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.SessionConfig;
 import androidx.camera.core.impl.utils.executor.CameraXExecutors;
 import androidx.camera.testing.CameraUtil;
@@ -84,14 +84,14 @@
     @Before
     public void setUp()
             throws CameraInfoUnavailableException, CameraAccessException, InterruptedException {
-        assumeTrue(CameraUtil.hasCameraWithLensFacing(LensFacing.BACK));
+        assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK));
 
         // Init CameraX
         Context context = ApplicationProvider.getApplicationContext();
         CameraXConfig config = Camera2Config.defaultConfig(context);
         CameraX.initialize(context, config);
 
-        String cameraId = CameraX.getCameraWithLensFacing(LensFacing.BACK);
+        String cameraId = CameraX.getCameraWithLensFacing(CameraSelector.LENS_FACING_BACK);
         CameraManager cameraManager = (CameraManager) context.getSystemService(
                 Context.CAMERA_SERVICE);
         mCameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId);
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2CameraControl.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2CameraControl.java
index 10b8952..3d1258e 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2CameraControl.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2CameraControl.java
@@ -16,6 +16,10 @@
 
 package androidx.camera.camera2.impl;
 
+import static androidx.camera.core.ImageCapture.FLASH_MODE_AUTO;
+import static androidx.camera.core.ImageCapture.FLASH_MODE_OFF;
+import static androidx.camera.core.ImageCapture.FLASH_MODE_ON;
+
 import android.graphics.Rect;
 import android.hardware.camera2.CameraCaptureSession;
 import android.hardware.camera2.CameraCaptureSession.CaptureCallback;
@@ -34,9 +38,9 @@
 import androidx.camera.core.CameraControlInternal;
 import androidx.camera.core.CaptureConfig;
 import androidx.camera.core.Config;
-import androidx.camera.core.FlashMode;
 import androidx.camera.core.FocusMeteringAction;
 import androidx.camera.core.FocusMeteringResult;
+import androidx.camera.core.ImageCapture;
 import androidx.camera.core.SessionConfig;
 import androidx.camera.core.impl.utils.futures.Futures;
 import androidx.core.util.Preconditions;
@@ -72,8 +76,8 @@
     private final TorchControl mTorchControl;
     // use volatile modifier to make these variables in sync in all threads.
     private volatile boolean mIsTorchOn = false;
-    @FlashMode
-    private volatile int mFlashMode = FlashMode.OFF;
+    @ImageCapture.FlashMode
+    private volatile int mFlashMode = FLASH_MODE_OFF;
 
     //******************** Should only be accessed by executor *****************************//
     private Rect mCropRect = null;
@@ -171,7 +175,7 @@
         mExecutor.execute(() -> setCropRegionInternal(crop));
     }
 
-    @FlashMode
+    @ImageCapture.FlashMode
     @Override
     public int getFlashMode() {
         return mFlashMode;
@@ -179,7 +183,7 @@
 
     /** {@inheritDoc} */
     @Override
-    public void setFlashMode(@FlashMode int flashMode) {
+    public void setFlashMode(@ImageCapture.FlashMode int flashMode) {
         // update mFlashMode immediately so that following getFlashMode() returns correct value.
         mFlashMode = flashMode;
 
@@ -323,13 +327,13 @@
                     CaptureRequest.FLASH_MODE_TORCH);
         } else {
             switch (mFlashMode) {
-                case FlashMode.OFF:
+                case FLASH_MODE_OFF:
                     aeMode = CaptureRequest.CONTROL_AE_MODE_ON;
                     break;
-                case FlashMode.ON:
+                case FLASH_MODE_ON:
                     aeMode = CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH;
                     break;
-                case FlashMode.AUTO:
+                case FLASH_MODE_AUTO:
                     aeMode = CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH;
                     break;
             }
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2CameraFactory.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2CameraFactory.java
index 0e5a8b8..b2a2cde 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2CameraFactory.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2CameraFactory.java
@@ -29,8 +29,8 @@
 import androidx.camera.core.CameraFactory;
 import androidx.camera.core.CameraInfoUnavailableException;
 import androidx.camera.core.CameraInternal;
+import androidx.camera.core.CameraSelector;
 import androidx.camera.core.CameraXThreads;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.LensFacingCameraIdFilter;
 import androidx.camera.core.impl.utils.executor.CameraXExecutors;
 
@@ -93,7 +93,7 @@
 
     @Override
     @Nullable
-    public String cameraIdForLensFacing(@LensFacing int lensFacing)
+    public String cameraIdForLensFacing(@CameraSelector.LensFacing int lensFacing)
             throws CameraInfoUnavailableException {
         Set<String> availableCameraIds = getLensFacingCameraIdFilter(
                 lensFacing).filter(getAvailableCameraIds());
@@ -107,7 +107,8 @@
 
     @Override
     @NonNull
-    public LensFacingCameraIdFilter getLensFacingCameraIdFilter(@LensFacing int lensFacing) {
+    public LensFacingCameraIdFilter getLensFacingCameraIdFilter(
+            @CameraSelector.LensFacing int lensFacing) {
         return new Camera2LensFacingCameraIdFilter(lensFacing, mCameraManager.unwrap());
     }
 }
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2CameraInfo.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2CameraInfo.java
index 79225ad..c896054 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2CameraInfo.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2CameraInfo.java
@@ -24,8 +24,8 @@
 import androidx.annotation.Nullable;
 import androidx.camera.core.CameraInfoInternal;
 import androidx.camera.core.CameraOrientationUtil;
+import androidx.camera.core.CameraSelector;
 import androidx.camera.core.ImageOutputConfig.RotationValue;
-import androidx.camera.core.LensFacing;
 import androidx.core.util.Preconditions;
 import androidx.lifecycle.LiveData;
 
@@ -56,9 +56,9 @@
         Preconditions.checkNotNull(lensFacing);
         switch (lensFacing) {
             case CameraCharacteristics.LENS_FACING_FRONT:
-                return LensFacing.FRONT;
+                return CameraSelector.LENS_FACING_FRONT;
             case CameraCharacteristics.LENS_FACING_BACK:
-                return LensFacing.BACK;
+                return CameraSelector.LENS_FACING_BACK;
             default:
                 return null;
         }
@@ -73,7 +73,8 @@
         // This may not be the case for all devices, so in the future we may need to handle that
         // scenario.
         final Integer lensFacing = getLensFacing();
-        boolean isOppositeFacingScreen = (lensFacing != null && LensFacing.BACK == lensFacing);
+        boolean isOppositeFacingScreen =
+                (lensFacing != null && CameraSelector.LENS_FACING_BACK == lensFacing);
         return CameraOrientationUtil.getRelativeImageRotation(
                 relativeRotationDegrees,
                 sensorOrientation,
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2LensFacingCameraIdFilter.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2LensFacingCameraIdFilter.java
index 1a020e7..70fc540 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2LensFacingCameraIdFilter.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2LensFacingCameraIdFilter.java
@@ -24,7 +24,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.RestrictTo;
-import androidx.camera.core.LensFacing;
+import androidx.camera.core.CameraSelector;
 import androidx.camera.core.LensFacingCameraIdFilter;
 
 import java.util.LinkedHashSet;
@@ -40,7 +40,7 @@
     private static final String TAG = "Camera2LensFacingCIF";
     private CameraManager mCameraManager;
 
-    Camera2LensFacingCameraIdFilter(@LensFacing int lensFacing,
+    Camera2LensFacingCameraIdFilter(@CameraSelector.LensFacing int lensFacing,
             @NonNull CameraManager cameraManager) {
         super(lensFacing);
         mCameraManager = cameraManager;
@@ -70,13 +70,14 @@
         return resultCameraIdSet;
     }
 
-    private Integer cameraXLensFacingToCamera2LensFacing(@LensFacing int lensFacing) {
+    private Integer cameraXLensFacingToCamera2LensFacing(
+            @CameraSelector.LensFacing int lensFacing) {
         Integer lensFacingInteger = -1;
         switch (lensFacing) {
-            case LensFacing.BACK:
+            case CameraSelector.LENS_FACING_BACK:
                 lensFacingInteger = CameraMetadata.LENS_FACING_BACK;
                 break;
-            case LensFacing.FRONT:
+            case CameraSelector.LENS_FACING_FRONT:
                 lensFacingInteger = CameraMetadata.LENS_FACING_FRONT;
                 break;
         }
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/ImageCaptureOptionUnpacker.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/ImageCaptureOptionUnpacker.java
index 64993c6..38794ad 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/ImageCaptureOptionUnpacker.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/ImageCaptureOptionUnpacker.java
@@ -22,6 +22,7 @@
 
 import androidx.camera.core.CaptureConfig;
 import androidx.camera.core.DeviceProperties;
+import androidx.camera.core.ImageCapture;
 import androidx.camera.core.ImageCapture.CaptureMode;
 import androidx.camera.core.ImageCaptureConfig;
 import androidx.camera.core.UseCaseConfig;
@@ -69,12 +70,12 @@
                 || "Pixel 3".equals(mDeviceProperties.model()))) {
             if (mDeviceProperties.sdkVersion() >= Build.VERSION_CODES.O) {
                 switch (captureMode) {
-                    case CaptureMode.MAXIMIZE_QUALITY:
+                    case ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY:
                         // enable ZSL to make sure HDR+ is enabled
                         builder.setCaptureRequestOption(
                                 CaptureRequest.CONTROL_ENABLE_ZSL, true);
                         break;
-                    case CaptureMode.MINIMIZE_LATENCY:
+                    case ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY:
                         // disable ZSL to turn off HDR+
                         builder.setCaptureRequestOption(
                                 CaptureRequest.CONTROL_ENABLE_ZSL, false);
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/SupportedSurfaceCombination.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/SupportedSurfaceCombination.java
index c67da97..c9bf8b4 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/SupportedSurfaceCombination.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/SupportedSurfaceCombination.java
@@ -367,7 +367,7 @@
         if (config.hasTargetAspectRatio()) {
             // Checks the sensor orientation.
             boolean isSensorLandscapeOrientation = isRotationNeeded(Surface.ROTATION_0);
-            @AspectRatio int targetAspectRatio = config.getTargetAspectRatio();
+            @AspectRatio.Ratio int targetAspectRatio = config.getTargetAspectRatio();
             switch (targetAspectRatio) {
                 case AspectRatio.RATIO_4_3:
                     aspectRatio =
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/Camera2CameraInfoTest.java b/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/Camera2CameraInfoTest.java
index 6fa063c..bbaa3ec 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/Camera2CameraInfoTest.java
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/Camera2CameraInfoTest.java
@@ -29,7 +29,7 @@
 import android.view.Surface;
 
 import androidx.camera.core.CameraInfoInternal;
-import androidx.camera.core.LensFacing;
+import androidx.camera.core.CameraSelector;
 import androidx.camera.core.TorchState;
 import androidx.lifecycle.MutableLiveData;
 import androidx.test.core.app.ApplicationProvider;
@@ -53,8 +53,8 @@
 
     private static final String CAMERA0_ID = "0";
     private static final int CAMERA0_SENSOR_ORIENTATION = 90;
-    @LensFacing
-    private static final int CAMERA0_LENS_FACING_ENUM = LensFacing.BACK;
+    @CameraSelector.LensFacing
+    private static final int CAMERA0_LENS_FACING_ENUM = CameraSelector.LENS_FACING_BACK;
     private static final int CAMERA0_LENS_FACING_INT = CameraCharacteristics.LENS_FACING_BACK;
     private static final boolean CAMERA0_FLASH_INFO_BOOLEAN = true;
 
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/Camera2DeviceSurfaceManagerTest.java b/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/Camera2DeviceSurfaceManagerTest.java
index aeb71dd..e1ebf57 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/Camera2DeviceSurfaceManagerTest.java
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/Camera2DeviceSurfaceManagerTest.java
@@ -47,7 +47,6 @@
 import androidx.camera.core.ImageCapture;
 import androidx.camera.core.ImageCaptureConfig;
 import androidx.camera.core.ImageFormatConstants;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.Preview;
 import androidx.camera.core.PreviewConfig;
 import androidx.camera.core.SurfaceCombination;
@@ -503,7 +502,8 @@
 
         CameraDeviceConfig deviceConfig =
                 CameraSelectorUtil.toCameraDeviceConfig(
-                        new CameraSelector.Builder().requireLensFacing(LensFacing.FRONT).build());
+                        new CameraSelector.Builder().requireLensFacing(
+                                CameraSelector.LENS_FACING_FRONT).build());
         Rational resultAspectRatio = mSurfaceManager.getCorrectedAspectRatio(deviceConfig,
                 previewConfig.getTargetRotation(Surface.ROTATION_0));
 
@@ -527,13 +527,15 @@
         addCamera(
                 LEGACY_CAMERA_ID, CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY, null,
                 CameraCharacteristics.LENS_FACING_FRONT);
-        mCameraFactory.setDefaultCameraIdForLensFacing(LensFacing.FRONT, LEGACY_CAMERA_ID);
+        mCameraFactory.setDefaultCameraIdForLensFacing(CameraSelector.LENS_FACING_FRONT,
+                LEGACY_CAMERA_ID);
 
         addCamera(
                 LIMITED_CAMERA_ID, CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED,
                 null,
                 CameraCharacteristics.LENS_FACING_BACK);
-        mCameraFactory.setDefaultCameraIdForLensFacing(LensFacing.BACK, LIMITED_CAMERA_ID);
+        mCameraFactory.setDefaultCameraIdForLensFacing(CameraSelector.LENS_FACING_BACK,
+                LIMITED_CAMERA_ID);
 
         addCamera(
                 FULL_CAMERA_ID, CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL, null,
@@ -575,7 +577,8 @@
                 StreamConfigurationMapUtil.generateFakeStreamConfigurationMap(
                         mSupportedFormats, mSupportedSizes));
 
-        @LensFacing int lensFacingEnum = CameraUtil.getLensFacingEnumFromInt(lensFacing);
+        @CameraSelector.LensFacing int lensFacingEnum = CameraUtil.getLensFacingEnumFromInt(
+                lensFacing);
         mCameraFactory.insertCamera(lensFacingEnum, cameraId, () -> new FakeCamera(cameraId, null,
                 new Camera2CameraInfo(characteristics, mock(ZoomControl.class),
                         mock(TorchControl.class))));
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/Camera2LensFacingCameraIdFilterTest.java b/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/Camera2LensFacingCameraIdFilterTest.java
index 28c07188..620eb1c 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/Camera2LensFacingCameraIdFilterTest.java
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/Camera2LensFacingCameraIdFilterTest.java
@@ -23,7 +23,7 @@
 import android.hardware.camera2.CameraManager;
 import android.os.Build;
 
-import androidx.camera.core.LensFacing;
+import androidx.camera.core.CameraSelector;
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.filters.SmallTest;
 
@@ -86,7 +86,8 @@
     @Test
     public void canFilterBackCamera() {
         Camera2LensFacingCameraIdFilter lensFacingCameraIdFilter =
-                new Camera2LensFacingCameraIdFilter(LensFacing.BACK, mCameraManager);
+                new Camera2LensFacingCameraIdFilter(CameraSelector.LENS_FACING_BACK,
+                        mCameraManager);
         mCameraIds = lensFacingCameraIdFilter.filter(mCameraIds);
         assertThat(mCameraIds).contains(CAMERA0_ID);
         assertThat(mCameraIds).doesNotContain(CAMERA1_ID);
@@ -95,7 +96,8 @@
     @Test
     public void canFilterFrontCamera() {
         Camera2LensFacingCameraIdFilter lensFacingCameraIdFilter =
-                new Camera2LensFacingCameraIdFilter(LensFacing.FRONT, mCameraManager);
+                new Camera2LensFacingCameraIdFilter(CameraSelector.LENS_FACING_FRONT,
+                        mCameraManager);
         mCameraIds = lensFacingCameraIdFilter.filter(mCameraIds);
         assertThat(mCameraIds).contains(CAMERA1_ID);
         assertThat(mCameraIds).doesNotContain(CAMERA0_ID);
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/DisplayOrientedMeteringPointFactoryTest.java b/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/DisplayOrientedMeteringPointFactoryTest.java
index 3e27fae..02f4d59 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/DisplayOrientedMeteringPointFactoryTest.java
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/DisplayOrientedMeteringPointFactoryTest.java
@@ -34,7 +34,6 @@
 import androidx.camera.core.ConfigProvider;
 import androidx.camera.core.DisplayOrientedMeteringPointFactory;
 import androidx.camera.core.ExtendableUseCaseConfigFactory;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.MeteringPoint;
 import androidx.camera.core.MeteringPointFactory;
 import androidx.camera.testing.fakes.FakeCamera;
@@ -68,9 +67,10 @@
     private Context mMockContext;
     private Display mMockDisplay;
     private static final CameraSelector FRONT_CAM =
-            new CameraSelector.Builder().requireLensFacing(LensFacing.FRONT).build();
+            new CameraSelector.Builder().requireLensFacing(
+                    CameraSelector.LENS_FACING_FRONT).build();
     private static final CameraSelector BACK_CAM =
-            new CameraSelector.Builder().requireLensFacing(LensFacing.BACK).build();
+            new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build();
 
     @Before
     public void setUp() {
@@ -79,9 +79,11 @@
         // Init CameraX to inject our FakeCamera with FakeCameraInfo.
         FakeCameraFactory fakeCameraFactory = new FakeCameraFactory();
         fakeCameraFactory.insertDefaultBackCamera(BACK_CAMERA_ID,
-                () -> new FakeCamera(null, new FakeCameraInfoInternal(90, LensFacing.BACK)));
+                () -> new FakeCamera(null,
+                        new FakeCameraInfoInternal(90, CameraSelector.LENS_FACING_BACK)));
         fakeCameraFactory.insertDefaultFrontCamera(FRONT_CAMERA_ID,
-                () -> new FakeCamera(null, new FakeCameraInfoInternal(270, LensFacing.FRONT)));
+                () -> new FakeCamera(null,
+                        new FakeCameraInfoInternal(270, CameraSelector.LENS_FACING_FRONT)));
 
         CameraDeviceSurfaceManager surfaceManager = new FakeCameraDeviceSurfaceManager();
         ExtendableUseCaseConfigFactory defaultConfigFactory = new ExtendableUseCaseConfigFactory();
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/FocusMeteringControlTest.java b/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/FocusMeteringControlTest.java
index d122e9f..53efd49 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/FocusMeteringControlTest.java
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/FocusMeteringControlTest.java
@@ -43,7 +43,6 @@
 import androidx.camera.camera2.impl.Camera2CameraControl.CaptureResultListener;
 import androidx.camera.core.CameraControlInternal;
 import androidx.camera.core.FocusMeteringAction;
-import androidx.camera.core.FocusMeteringAction.MeteringMode;
 import androidx.camera.core.FocusMeteringResult;
 import androidx.camera.core.ImageAnalysis;
 import androidx.camera.core.MeteringPoint;
@@ -273,9 +272,11 @@
     @Test
     public void startFocusAndMetering_multiplePointVariousModes() {
         mFocusMeteringControl.startFocusAndMetering(
-                FocusMeteringAction.Builder.from(mPoint1, MeteringMode.AWB)
-                        .addPoint(mPoint2, MeteringMode.AF | MeteringMode.AE)
-                        .addPoint(mPoint3, MeteringMode.AF | MeteringMode.AE | MeteringMode.AWB)
+                FocusMeteringAction.Builder.from(mPoint1, FocusMeteringAction.FLAG_AWB)
+                        .addPoint(mPoint2,
+                                FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AE)
+                        .addPoint(mPoint3, FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AE
+                                | FocusMeteringAction.FLAG_AWB)
                         .build(), PREVIEW_ASPECT_RATIO_4_X_3);
 
         MeteringRectangle[] afRects = getAfRects(mFocusMeteringControl);
@@ -298,9 +299,9 @@
     @Test
     public void startFocusAndMetering_multiplePointVariousModes2() {
         mFocusMeteringControl.startFocusAndMetering(
-                FocusMeteringAction.Builder.from(mPoint1, MeteringMode.AF)
-                        .addPoint(mPoint2, MeteringMode.AWB)
-                        .addPoint(mPoint3, MeteringMode.AE)
+                FocusMeteringAction.Builder.from(mPoint1, FocusMeteringAction.FLAG_AF)
+                        .addPoint(mPoint2, FocusMeteringAction.FLAG_AWB)
+                        .addPoint(mPoint3, FocusMeteringAction.FLAG_AE)
                         .build(), PREVIEW_ASPECT_RATIO_4_X_3);
         MeteringRectangle[] afRects = getAfRects(mFocusMeteringControl);
         MeteringRectangle[] aeRects = getAeRects(mFocusMeteringControl);
@@ -424,7 +425,8 @@
     @Test
     public void withAFPoints_AFIsTriggered() {
         mFocusMeteringControl.startFocusAndMetering(FocusMeteringAction.Builder.from(mPoint1,
-                MeteringMode.AF | MeteringMode.AE | MeteringMode.AWB).build(),
+                FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AE
+                        | FocusMeteringAction.FLAG_AWB).build(),
                 PREVIEW_ASPECT_RATIO_4_X_3);
 
         verify(mFocusMeteringControl).triggerAf();
@@ -432,21 +434,21 @@
 
         mFocusMeteringControl.startFocusAndMetering(
                 FocusMeteringAction.Builder.from(mPoint1,
-                        MeteringMode.AF).build(),
+                        FocusMeteringAction.FLAG_AF).build(),
                 PREVIEW_ASPECT_RATIO_4_X_3);
         verify(mFocusMeteringControl).triggerAf();
         Mockito.reset(mFocusMeteringControl);
 
         mFocusMeteringControl.startFocusAndMetering(
                 FocusMeteringAction.Builder.from(mPoint1,
-                        MeteringMode.AF | MeteringMode.AE).build(),
+                        FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AE).build(),
                 PREVIEW_ASPECT_RATIO_4_X_3);
         verify(mFocusMeteringControl).triggerAf();
         Mockito.reset(mFocusMeteringControl);
 
         mFocusMeteringControl.startFocusAndMetering(
                 FocusMeteringAction.Builder.from(mPoint1,
-                        MeteringMode.AF | MeteringMode.AWB).build(),
+                        FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AWB).build(),
                 PREVIEW_ASPECT_RATIO_4_X_3);
         verify(mFocusMeteringControl).triggerAf();
         Mockito.reset(mFocusMeteringControl);
@@ -455,26 +457,26 @@
     @Test
     public void withoutAFPoints_AFIsNotTriggered() {
         mFocusMeteringControl.startFocusAndMetering(
-                FocusMeteringAction.Builder.from(mPoint1, MeteringMode.AE).build(),
+                FocusMeteringAction.Builder.from(mPoint1, FocusMeteringAction.FLAG_AE).build(),
                 PREVIEW_ASPECT_RATIO_4_X_3);
         verify(mFocusMeteringControl, never()).triggerAf();
         Mockito.reset(mFocusMeteringControl);
 
         mFocusMeteringControl.startFocusAndMetering(
-                FocusMeteringAction.Builder.from(mPoint1, MeteringMode.AWB).build(),
+                FocusMeteringAction.Builder.from(mPoint1, FocusMeteringAction.FLAG_AWB).build(),
                 PREVIEW_ASPECT_RATIO_4_X_3);
         verify(mFocusMeteringControl, never()).triggerAf();
         Mockito.reset(mFocusMeteringControl);
 
         mFocusMeteringControl.startFocusAndMetering(
-                FocusMeteringAction.Builder.from(mPoint1, MeteringMode.AE).build(),
+                FocusMeteringAction.Builder.from(mPoint1, FocusMeteringAction.FLAG_AE).build(),
                 PREVIEW_ASPECT_RATIO_4_X_3);
         verify(mFocusMeteringControl, never()).triggerAf();
         Mockito.reset(mFocusMeteringControl);
 
         mFocusMeteringControl.startFocusAndMetering(
                 FocusMeteringAction.Builder.from(mPoint1,
-                        MeteringMode.AE | MeteringMode.AWB).build(),
+                        FocusMeteringAction.FLAG_AE | FocusMeteringAction.FLAG_AWB).build(),
                 PREVIEW_ASPECT_RATIO_4_X_3);
         verify(mFocusMeteringControl, never()).triggerAf();
         Mockito.reset(mFocusMeteringControl);
@@ -533,7 +535,7 @@
     public void listenableFutureForStart_AEAWB_focusIsFalse()
             throws ExecutionException, InterruptedException {
         FocusMeteringAction action = FocusMeteringAction.Builder.from(mPoint1,
-                MeteringMode.AE | MeteringMode.AWB)
+                FocusMeteringAction.FLAG_AE | FocusMeteringAction.FLAG_AWB)
                 .build();
         ListenableFuture<FocusMeteringResult> future =
                 mFocusMeteringControl.startFocusAndMetering(action,
@@ -544,7 +546,8 @@
     @Test
     public void listenableFutureForStart_AE_focusIsFalse()
             throws ExecutionException, InterruptedException {
-        FocusMeteringAction action = FocusMeteringAction.Builder.from(mPoint1, MeteringMode.AE)
+        FocusMeteringAction action = FocusMeteringAction.Builder.from(mPoint1,
+                FocusMeteringAction.FLAG_AE)
                 .build();
         ListenableFuture<FocusMeteringResult> future2 =
                 mFocusMeteringControl.startFocusAndMetering(action, PREVIEW_ASPECT_RATIO_4_X_3);
@@ -556,7 +559,7 @@
     public void listenableFutureForStart_AWB_focusIsFalse()
             throws ExecutionException, InterruptedException {
         FocusMeteringAction action = FocusMeteringAction.Builder.from(mPoint1,
-                FocusMeteringAction.MeteringMode.AWB)
+                FocusMeteringAction.FLAG_AWB)
                 .build();
         ListenableFuture<FocusMeteringResult> future3 =
                 mFocusMeteringControl.startFocusAndMetering(action, PREVIEW_ASPECT_RATIO_4_X_3);
@@ -617,8 +620,11 @@
     @Test
     public void cancelFocusAndMetering_regionIsReset() {
         FocusMeteringAction action = FocusMeteringAction.Builder.from(mPoint1,
-                MeteringMode.AF | MeteringMode.AE | MeteringMode.AWB)
-                .addPoint(mPoint2, MeteringMode.AF | MeteringMode.AE | MeteringMode.AWB)
+                FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AE
+                        | FocusMeteringAction.FLAG_AWB)
+                .addPoint(mPoint2,
+                        FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AE
+                                | FocusMeteringAction.FLAG_AWB)
                 .build();
 
         mFocusMeteringControl.startFocusAndMetering(action, PREVIEW_ASPECT_RATIO_4_X_3);
@@ -644,8 +650,11 @@
     @Test
     public void cancelFocusAndMetering_updateSessionIsCalled() {
         FocusMeteringAction action = FocusMeteringAction.Builder.from(mPoint1,
-                MeteringMode.AF | MeteringMode.AE | MeteringMode.AWB)
-                .addPoint(mPoint2, MeteringMode.AF | MeteringMode.AE | MeteringMode.AWB)
+                FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AE
+                        | FocusMeteringAction.FLAG_AWB)
+                .addPoint(mPoint2,
+                        FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AE
+                                | FocusMeteringAction.FLAG_AWB)
                 .build();
 
         mFocusMeteringControl.startFocusAndMetering(action, PREVIEW_ASPECT_RATIO_4_X_3);
@@ -660,7 +669,8 @@
     public void cancelFocusAndMetering_triggerCancelAfProperly() {
         // If AF is enabled, cancel operation needs to call cancelAfAeTriggerInternal(true, false)
         FocusMeteringAction action = FocusMeteringAction.Builder.from(mPoint1,
-                MeteringMode.AF | MeteringMode.AE | MeteringMode.AWB)
+                FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AE
+                        | FocusMeteringAction.FLAG_AWB)
                 .build();
 
         mFocusMeteringControl.startFocusAndMetering(action, PREVIEW_ASPECT_RATIO_4_X_3);
@@ -668,21 +678,23 @@
         mFocusMeteringControl.cancelFocusAndMetering();
         verify(mFocusMeteringControl, times(1)).cancelAfAeTrigger(true, false);
 
-        action = FocusMeteringAction.Builder.from(mPoint1, MeteringMode.AF | MeteringMode.AE)
+        action = FocusMeteringAction.Builder.from(mPoint1,
+                FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AE)
                 .build();
         mFocusMeteringControl.startFocusAndMetering(action, PREVIEW_ASPECT_RATIO_4_X_3);
         Mockito.reset(mFocusMeteringControl);
         mFocusMeteringControl.cancelFocusAndMetering();
         verify(mFocusMeteringControl, times(1)).cancelAfAeTrigger(true, false);
 
-        action = FocusMeteringAction.Builder.from(mPoint1, MeteringMode.AF | MeteringMode.AWB)
+        action = FocusMeteringAction.Builder.from(mPoint1,
+                FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AWB)
                 .build();
         mFocusMeteringControl.startFocusAndMetering(action, PREVIEW_ASPECT_RATIO_4_X_3);
         Mockito.reset(mFocusMeteringControl);
         mFocusMeteringControl.cancelFocusAndMetering();
         verify(mFocusMeteringControl, times(1)).cancelAfAeTrigger(true, false);
 
-        action = FocusMeteringAction.Builder.from(mPoint1, MeteringMode.AF)
+        action = FocusMeteringAction.Builder.from(mPoint1, FocusMeteringAction.FLAG_AF)
                 .build();
         mFocusMeteringControl.startFocusAndMetering(action, PREVIEW_ASPECT_RATIO_4_X_3);
         Mockito.reset(mFocusMeteringControl);
@@ -692,7 +704,8 @@
 
     @Test
     public void cancelFocusAndMetering_AFNotInvolved_cancelAfNotTriggered() {
-        FocusMeteringAction action = FocusMeteringAction.Builder.from(mPoint1, MeteringMode.AE)
+        FocusMeteringAction action = FocusMeteringAction.Builder.from(mPoint1,
+                FocusMeteringAction.FLAG_AE)
                 .build();
 
         mFocusMeteringControl.startFocusAndMetering(action, PREVIEW_ASPECT_RATIO_4_X_3);
@@ -700,14 +713,15 @@
         mFocusMeteringControl.cancelFocusAndMetering();
         verify(mFocusMeteringControl, never()).cancelAfAeTrigger(true, false);
 
-        action = FocusMeteringAction.Builder.from(mPoint1, MeteringMode.AWB)
+        action = FocusMeteringAction.Builder.from(mPoint1, FocusMeteringAction.FLAG_AWB)
                 .build();
         mFocusMeteringControl.startFocusAndMetering(action, PREVIEW_ASPECT_RATIO_4_X_3);
         Mockito.reset(mFocusMeteringControl);
         mFocusMeteringControl.cancelFocusAndMetering();
         verify(mFocusMeteringControl, never()).cancelAfAeTrigger(true, false);
 
-        action = FocusMeteringAction.Builder.from(mPoint1, MeteringMode.AE | MeteringMode.AWB)
+        action = FocusMeteringAction.Builder.from(mPoint1,
+                FocusMeteringAction.FLAG_AE | FocusMeteringAction.FLAG_AWB)
                 .build();
         mFocusMeteringControl.startFocusAndMetering(action, PREVIEW_ASPECT_RATIO_4_X_3);
         Mockito.reset(mFocusMeteringControl);
@@ -757,7 +771,7 @@
     @Test
     public void startFocusMetering_AfNotInvolved_isAfAutoModeIsSet() {
         FocusMeteringAction action = FocusMeteringAction.Builder.from(mPoint1,
-                MeteringMode.AE | MeteringMode.AWB).build();
+                FocusMeteringAction.FLAG_AE | FocusMeteringAction.FLAG_AWB).build();
 
         verifyAfMode(CaptureResult.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
         mFocusMeteringControl.startFocusAndMetering(action, PREVIEW_ASPECT_RATIO_4_X_3);
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/ImageCaptureOptionUnpackerTest.java b/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/ImageCaptureOptionUnpackerTest.java
index d88c15c..c73fb57 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/ImageCaptureOptionUnpackerTest.java
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/ImageCaptureOptionUnpackerTest.java
@@ -108,7 +108,7 @@
     public void unpackWithValidPixel2AndMinLatency() {
         CaptureConfig.Builder captureBuilder = new CaptureConfig.Builder();
         ImageCaptureConfig imageCaptureConfig = new ImageCapture.Builder()
-                .setCaptureMode(ImageCapture.CaptureMode.MINIMIZE_LATENCY)
+                .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
                 .getUseCaseConfig();
 
         mUnpacker.setDeviceProperty(PROPERTIES_PIXEL_2_API26);
@@ -126,7 +126,7 @@
     public void unpackWithValidPixel2AndMaxQuality() {
         CaptureConfig.Builder captureBuilder = new CaptureConfig.Builder();
         ImageCaptureConfig imageCaptureConfig = new ImageCapture.Builder()
-                .setCaptureMode(ImageCapture.CaptureMode.MAXIMIZE_QUALITY)
+                .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
                 .getUseCaseConfig();
 
         mUnpacker.setDeviceProperty(PROPERTIES_PIXEL_2_API26);
@@ -144,7 +144,7 @@
     public void unpackWithPixel2NotSupportApiLevelAndMinLatency() {
         CaptureConfig.Builder captureBuilder = new CaptureConfig.Builder();
         ImageCaptureConfig imageCaptureConfig = new ImageCapture.Builder()
-                .setCaptureMode(ImageCapture.CaptureMode.MINIMIZE_LATENCY)
+                .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
                 .getUseCaseConfig();
 
         mUnpacker.setDeviceProperty(PROPERTIES_PIXEL_2_NOT_SUPPORT_API);
@@ -162,7 +162,7 @@
     public void unpackWithPixel2NotSupportApiLevelAndMaxQuality() {
         CaptureConfig.Builder captureBuilder = new CaptureConfig.Builder();
         ImageCaptureConfig imageCaptureConfig = new ImageCapture.Builder()
-                .setCaptureMode(ImageCapture.CaptureMode.MAXIMIZE_QUALITY)
+                .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
                 .getUseCaseConfig();
 
         mUnpacker.setDeviceProperty(PROPERTIES_PIXEL_2_NOT_SUPPORT_API);
@@ -180,7 +180,7 @@
     public void unpackWithValidPixel3AndMinLatency() {
         CaptureConfig.Builder captureBuilder = new CaptureConfig.Builder();
         ImageCaptureConfig imageCaptureConfig = new ImageCapture.Builder()
-                .setCaptureMode(ImageCapture.CaptureMode.MINIMIZE_LATENCY)
+                .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
                 .getUseCaseConfig();
 
         mUnpacker.setDeviceProperty(PROPERTIES_PIXEL_3_API26);
@@ -198,7 +198,7 @@
     public void unpackWithValidPixel3AndMaxQuality() {
         CaptureConfig.Builder captureBuilder = new CaptureConfig.Builder();
         ImageCaptureConfig imageCaptureConfig = new ImageCapture.Builder()
-                .setCaptureMode(ImageCapture.CaptureMode.MAXIMIZE_QUALITY)
+                .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
                 .getUseCaseConfig();
 
         mUnpacker.setDeviceProperty(PROPERTIES_PIXEL_3_API26);
@@ -216,7 +216,7 @@
     public void unpackWithPixel3NotSupportApiLevelAndMinLatency() {
         CaptureConfig.Builder captureBuilder = new CaptureConfig.Builder();
         ImageCaptureConfig imageCaptureConfig = new ImageCapture.Builder()
-                .setCaptureMode(ImageCapture.CaptureMode.MINIMIZE_LATENCY)
+                .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
                 .getUseCaseConfig();
 
         mUnpacker.setDeviceProperty(PROPERTIES_PIXEL_3_NOT_SUPPORT_API);
@@ -234,7 +234,7 @@
     public void unpackWithPixel3NotSupportApiLevelAndMaxQuality() {
         CaptureConfig.Builder captureBuilder = new CaptureConfig.Builder();
         ImageCaptureConfig imageCaptureConfig = new ImageCapture.Builder()
-                .setCaptureMode(ImageCapture.CaptureMode.MAXIMIZE_QUALITY)
+                .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
                 .getUseCaseConfig();
 
         mUnpacker.setDeviceProperty(PROPERTIES_PIXEL_3_NOT_SUPPORT_API);
@@ -252,7 +252,7 @@
     public void unpackWithNotSupportManufacture() {
         CaptureConfig.Builder captureBuilder = new CaptureConfig.Builder();
         ImageCaptureConfig imageCaptureConfig = new ImageCapture.Builder()
-                .setCaptureMode(ImageCapture.CaptureMode.MAXIMIZE_QUALITY)
+                .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
                 .getUseCaseConfig();
 
         mUnpacker.setDeviceProperty(PROPERTIES_NOT_GOOGLE);
@@ -270,7 +270,7 @@
     public void unpackWithNotSupportModel() {
         CaptureConfig.Builder captureBuilder = new CaptureConfig.Builder();
         ImageCaptureConfig imageCaptureConfig = new ImageCapture.Builder()
-                .setCaptureMode(ImageCapture.CaptureMode.MAXIMIZE_QUALITY)
+                .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
                 .getUseCaseConfig();
 
         mUnpacker.setDeviceProperty(PROPERTIES_NOT_SUPPORT_MODEL);
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/SupportedSurfaceCombinationTest.java b/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/SupportedSurfaceCombinationTest.java
index 1a91168..e56cf99 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/SupportedSurfaceCombinationTest.java
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/SupportedSurfaceCombinationTest.java
@@ -49,7 +49,6 @@
 import androidx.camera.core.ImageCapture;
 import androidx.camera.core.ImageCaptureConfig;
 import androidx.camera.core.ImageFormatConstants;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.Preview;
 import androidx.camera.core.PreviewConfig;
 import androidx.camera.core.SurfaceCombination;
@@ -484,7 +483,8 @@
         // Ensure we are bound to a camera to ensure aspect ratio correction is applied.
         FakeLifecycleOwner fakeLifecycle = new FakeLifecycleOwner();
         CameraSelector cameraSelector =
-                new CameraSelector.Builder().requireLensFacing(LensFacing.FRONT).build();
+                new CameraSelector.Builder().requireLensFacing(
+                        CameraSelector.LENS_FACING_FRONT).build();
         CameraX.bindToLifecycle(fakeLifecycle, cameraSelector, preview);
 
         PreviewConfig config = (PreviewConfig) preview.getUseCaseConfig();
@@ -1041,13 +1041,15 @@
         addCamera(
                 LEGACY_CAMERA_ID, CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY, null,
                 CameraCharacteristics.LENS_FACING_FRONT);
-        mCameraFactory.setDefaultCameraIdForLensFacing(LensFacing.FRONT, LEGACY_CAMERA_ID);
+        mCameraFactory.setDefaultCameraIdForLensFacing(CameraSelector.LENS_FACING_FRONT,
+                LEGACY_CAMERA_ID);
 
         addCamera(
                 LIMITED_CAMERA_ID,
                 CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED,
                 null, CameraCharacteristics.LENS_FACING_BACK);
-        mCameraFactory.setDefaultCameraIdForLensFacing(LensFacing.BACK, LIMITED_CAMERA_ID);
+        mCameraFactory.setDefaultCameraIdForLensFacing(CameraSelector.LENS_FACING_BACK,
+                LIMITED_CAMERA_ID);
 
         addCamera(
                 FULL_CAMERA_ID, CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL, null,
@@ -1101,7 +1103,8 @@
                 StreamConfigurationMapUtil.generateFakeStreamConfigurationMap(
                         supportedFormats, mSupportedSizes));
 
-        @LensFacing int lensFacingEnum = CameraUtil.getLensFacingEnumFromInt(lensFacing);
+        @CameraSelector.LensFacing int lensFacingEnum = CameraUtil.getLensFacingEnumFromInt(
+                lensFacing);
         mCameraFactory.insertCamera(lensFacingEnum, cameraId, () -> new FakeCamera(cameraId, null,
                 new Camera2CameraInfo(characteristics, mock(ZoomControl.class),
                         mock(TorchControl.class))));
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/CameraXTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/CameraXTest.java
index 67739a6..569b8f0 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/CameraXTest.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/CameraXTest.java
@@ -59,10 +59,10 @@
 @MediumTest
 @RunWith(AndroidJUnit4.class)
 public final class CameraXTest {
-    @LensFacing
-    private static final int CAMERA_LENS_FACING = LensFacing.BACK;
-    @LensFacing
-    private static final int CAMERA_LENS_FACING_FRONT = LensFacing.FRONT;
+    @CameraSelector.LensFacing
+    private static final int CAMERA_LENS_FACING = CameraSelector.LENS_FACING_BACK;
+    @CameraSelector.LensFacing
+    private static final int CAMERA_LENS_FACING_FRONT = CameraSelector.LENS_FACING_FRONT;
     private static final CameraSelector CAMERA_SELECTOR =
             new CameraSelector.Builder().requireLensFacing(CAMERA_LENS_FACING).build();
     private static final String CAMERA_ID = "0";
@@ -306,10 +306,12 @@
         CameraX.initialize(mContext, appConfigBuilder.build());
 
         CameraSelector frontSelector =
-                new CameraSelector.Builder().requireLensFacing(LensFacing.FRONT).build();
+                new CameraSelector.Builder().requireLensFacing(
+                        CameraSelector.LENS_FACING_FRONT).build();
         FakeUseCase fakeUseCase = new FakeUseCaseConfig.Builder().build();
         CameraSelector backSelector =
-                new CameraSelector.Builder().requireLensFacing(LensFacing.BACK).build();
+                new CameraSelector.Builder().requireLensFacing(
+                        CameraSelector.LENS_FACING_BACK).build();
         FakeOtherUseCase fakeOtherUseCase = new FakeOtherUseCaseConfig.Builder().build();
 
         boolean hasException = false;
@@ -336,7 +338,7 @@
     public void bindUseCases_withNotExistedLensFacingCamera() {
         initCameraX();
         CameraSelector frontSelector = new CameraSelector.Builder().requireLensFacing(
-                LensFacing.FRONT).build();
+                CameraSelector.LENS_FACING_FRONT).build();
         FakeUseCaseConfig config0 = new FakeUseCaseConfig.Builder().getUseCaseConfig();
         FakeUseCase fakeUseCase = new FakeUseCase(config0);
 
@@ -464,14 +466,16 @@
     public void checkHasCameraTrueForExistentCamera() throws CameraInfoUnavailableException {
         initCameraX();
         assertThat(CameraX.hasCamera(
-                new CameraSelector.Builder().requireLensFacing(LensFacing.BACK).build())).isTrue();
+                new CameraSelector.Builder().requireLensFacing(
+                        CameraSelector.LENS_FACING_BACK).build())).isTrue();
     }
 
     @Test
     public void checkHasCameraFalseForNonexistentCamera() throws CameraInfoUnavailableException {
         initCameraX();
         assertThat(CameraX.hasCamera(new CameraSelector.Builder().requireLensFacing(
-                LensFacing.BACK).requireLensFacing(LensFacing.FRONT).build())).isFalse();
+                CameraSelector.LENS_FACING_BACK).requireLensFacing(
+                CameraSelector.LENS_FACING_FRONT).build())).isFalse();
     }
 
     private void initCameraX() {
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/FakeOtherUseCaseConfig.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/FakeOtherUseCaseConfig.java
index 37364e5..b24ee22 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/FakeOtherUseCaseConfig.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/FakeOtherUseCaseConfig.java
@@ -115,12 +115,12 @@
 
     @Override
     @Nullable
-    public Integer getLensFacing(@LensFacing Integer valueIfMissing) {
+    public Integer getLensFacing(@CameraSelector.LensFacing Integer valueIfMissing) {
         return retrieveOption(OPTION_LENS_FACING, valueIfMissing);
     }
 
     @Override
-    @LensFacing
+    @CameraSelector.LensFacing
     public int getLensFacing() {
         return retrieveOption(OPTION_LENS_FACING);
     }
@@ -293,7 +293,7 @@
 
         @Override
         @NonNull
-        public Builder setLensFacing(@LensFacing int lensFacing) {
+        public Builder setLensFacing(@CameraSelector.LensFacing int lensFacing) {
             getMutableConfig().insertOption(OPTION_LENS_FACING, lensFacing);
             return this;
         }
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageSaverTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageSaverTest.java
index 51f196e..f24a21d 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageSaverTest.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageSaverTest.java
@@ -111,7 +111,7 @@
                 }
 
                 @Override
-                public void onError(@SaveError int saveError, String message,
+                public void onError(SaveError saveError, String message,
                         @Nullable Throwable cause) {
                     mMockCallback.onError(saveError, message, cause);
                     mSemaphore.release();
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseAttachStateTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseAttachStateTest.java
index c753a5e..7d08df2 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseAttachStateTest.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseAttachStateTest.java
@@ -51,9 +51,10 @@
 @RunWith(AndroidJUnit4.class)
 public class UseCaseAttachStateTest {
     private static final CameraSelector BACK_CAMERA_SELECTOR =
-            new CameraSelector.Builder().requireLensFacing(LensFacing.BACK).build();
+            new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build();
     private static final CameraSelector FRONT_CAMERA_SELECTOR =
-            new CameraSelector.Builder().requireLensFacing(LensFacing.FRONT).build();
+            new CameraSelector.Builder().requireLensFacing(
+                    CameraSelector.LENS_FACING_FRONT).build();
     private final CameraDevice mMockCameraDevice = Mockito.mock(CameraDevice.class);
     private final CameraCaptureSession mMockCameraCaptureSession =
             Mockito.mock(CameraCaptureSession.class);
@@ -65,10 +66,11 @@
         CameraXConfig cameraXConfig = FakeAppConfig.create();
         CameraFactory cameraFactory = cameraXConfig.getCameraFactory(/*valueIfMissing=*/ null);
         try {
-            mCameraId = cameraFactory.cameraIdForLensFacing(LensFacing.BACK);
+            mCameraId = cameraFactory.cameraIdForLensFacing(CameraSelector.LENS_FACING_BACK);
         } catch (Exception e) {
             throw new IllegalArgumentException(
-                    "Unable to attach to camera with LensFacing " + LensFacing.BACK, e);
+                    "Unable to attach to camera with LensFacing " + CameraSelector.LENS_FACING_BACK,
+                    e);
         }
         CameraX.initialize(ApplicationProvider.getApplicationContext(), cameraXConfig);
     }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/AspectRatio.java b/camera/camera-core/src/main/java/androidx/camera/core/AspectRatio.java
index ba82764..3233526 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/AspectRatio.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/AspectRatio.java
@@ -17,19 +17,31 @@
 package androidx.camera.core;
 
 import androidx.annotation.IntDef;
+import androidx.annotation.RestrictTo;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
-/** The aspect ratio of the use case.
+/**
+ * The aspect ratio of the use case.
  *
  * <p>Aspect ratio is the ratio of width to height.
  */
-@IntDef({AspectRatio.RATIO_4_3, AspectRatio.RATIO_16_9})
-@Retention(RetentionPolicy.SOURCE)
-public @interface AspectRatio {
+public class AspectRatio {
     /** 4:3 standard aspect ratio. */
-    int RATIO_4_3 = 0;
+    public static final int RATIO_4_3 = 0;
     /** 16:9 standard aspect ratio. */
-    int RATIO_16_9 = 1;
+    public static final int RATIO_16_9 = 1;
+
+    private AspectRatio() {
+    }
+
+    /**
+     * @hide
+     */
+    @IntDef({RATIO_4_3, RATIO_16_9})
+    @Retention(RetentionPolicy.SOURCE)
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public @interface Ratio {
+    }
 }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/CameraControl.java b/camera/camera-core/src/main/java/androidx/camera/core/CameraControl.java
index 921e399..88cb752 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/CameraControl.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/CameraControl.java
@@ -50,8 +50,8 @@
      * a failed result and the torch state will be {@link TorchState#OFF}.
      *
      * <p>When the torch is enabled, the torch will remain enabled during photo capture regardless
-     * of {@link FlashMode} setting. When the torch is disabled, flash will function as
-     * {@link FlashMode} set by either {@link ImageCapture#setFlashMode(int)} or
+     * of the flashMode setting. When the torch is disabled, flash will function as the flash mode
+     * set by either {@link ImageCapture#setFlashMode(int)} or
      * {@link ImageCapture.Builder#setFlashMode(int)}.
      *
      * @param torch true to turn on the torch, false to turn it off.
@@ -73,10 +73,12 @@
      * {@link FocusMeteringAction} are executed in a row, only the latest one will work and
      * other actions will be cancelled.
      *
-     * <p>If the {@link FocusMeteringAction} specifies more AF/AE/AWB regions than what is
-     * supported on current device, only the first region and then in order up to the number of
-     * regions supported by the device will be enabled. If it turns out no added regions can be
-     * supported on the device, the returned {@link ListenableFuture} in
+     * <p>If the {@link FocusMeteringAction} specifies more AF/AE/AWB points than what is
+     * supported on current device, only the first point and then in order up to the number of
+     * points supported by the device will be enabled.
+     *
+     * <p>If none of the points with either AF/AE/AWB can be supported on the device,
+     * the returned {@link ListenableFuture} in
      * {@link CameraControl#startFocusAndMetering(FocusMeteringAction)} will fail immediately.
      *
      * @see FocusMeteringAction
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/CameraControlInternal.java b/camera/camera-core/src/main/java/androidx/camera/core/CameraControlInternal.java
index 9f34a0b..3fc7787 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/CameraControlInternal.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/CameraControlInternal.java
@@ -16,12 +16,15 @@
 
 package androidx.camera.core;
 
+import static androidx.camera.core.ImageCapture.FLASH_MODE_OFF;
+
 import android.graphics.Rect;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.RestrictTo.Scope;
+import androidx.camera.core.ImageCapture.FlashMode;
 import androidx.camera.core.impl.utils.futures.Futures;
 
 import com.google.common.util.concurrent.ListenableFuture;
@@ -82,7 +85,7 @@
         @FlashMode
         @Override
         public int getFlashMode() {
-            return FlashMode.OFF;
+            return FLASH_MODE_OFF;
         }
 
         @Override
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/CameraDeviceConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/CameraDeviceConfig.java
index e7ffede..fdba1cc 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/CameraDeviceConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/CameraDeviceConfig.java
@@ -75,7 +75,7 @@
      * @hide
      */
     @RestrictTo(Scope.LIBRARY_GROUP)
-    @LensFacing
+    @CameraSelector.LensFacing
     int getLensFacing();
 
     /**
@@ -122,7 +122,7 @@
          */
         @NonNull
         @RestrictTo(Scope.LIBRARY_GROUP)
-        B setLensFacing(@LensFacing int lensFacing);
+        B setLensFacing(@CameraSelector.LensFacing int lensFacing);
 
         /**
          * Sets the {@link CameraIdFilter} that filter out the unavailable camera ids.
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/CameraFactory.java b/camera/camera-core/src/main/java/androidx/camera/core/CameraFactory.java
index eda17a6..c435ecd 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/CameraFactory.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/CameraFactory.java
@@ -41,10 +41,10 @@
      * camera with specified lens facing.
      */
     @Nullable
-    String cameraIdForLensFacing(@LensFacing int lensFacing)
+    String cameraIdForLensFacing(@CameraSelector.LensFacing int lensFacing)
             throws CameraInfoUnavailableException;
 
     /** Gets a {@link LensFacingCameraIdFilter} with specified lens facing. */
     @NonNull
-    LensFacingCameraIdFilter getLensFacingCameraIdFilter(@LensFacing int lensFacing);
+    LensFacingCameraIdFilter getLensFacingCameraIdFilter(@CameraSelector.LensFacing int lensFacing);
 }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/CameraSelector.java b/camera/camera-core/src/main/java/androidx/camera/core/CameraSelector.java
index 5a17a7c..c5ba14a 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/CameraSelector.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/CameraSelector.java
@@ -15,11 +15,14 @@
  */
 package androidx.camera.core;
 
+import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.RestrictTo.Scope;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.LinkedHashSet;
 import java.util.Set;
 
@@ -27,14 +30,20 @@
  * A set of requirements and priorities used to select a camera.
  */
 public final class CameraSelector {
+
+    /** A camera on the device facing the same direction as the device's screen. */
+    public static final int LENS_FACING_FRONT = 0;
+    /** A camera on the device facing the opposite direction as the device's screen. */
+    public static final int LENS_FACING_BACK = 1;
+
     /** A static {@link CameraSelector} that selects the default front facing camera. */
     @NonNull
     public static final CameraSelector DEFAULT_FRONT_CAMERA =
-            new CameraSelector.Builder().requireLensFacing(LensFacing.FRONT).build();
+            new CameraSelector.Builder().requireLensFacing(LENS_FACING_FRONT).build();
     /** A static {@link CameraSelector} that selects the default back facing camera. */
     @NonNull
     public static final CameraSelector DEFAULT_BACK_CAMERA =
-            new CameraSelector.Builder().requireLensFacing(LensFacing.BACK).build();
+            new CameraSelector.Builder().requireLensFacing(LENS_FACING_BACK).build();
 
     private LinkedHashSet<CameraIdFilter> mCameraFilterSet;
 
@@ -175,4 +184,15 @@
             return new CameraSelector(mCameraFilterSet);
         }
     }
+
+    /**
+     * The direction the camera faces relative to device screen.
+     *
+     * @hide
+     */
+    @IntDef({LENS_FACING_FRONT, LENS_FACING_BACK})
+    @Retention(RetentionPolicy.SOURCE)
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public @interface LensFacing {
+    }
 }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java b/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java
index ee75e83..fd76a49 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java
@@ -435,7 +435,7 @@
      */
     @RestrictTo(Scope.LIBRARY_GROUP)
     @Nullable
-    public static String getCameraWithLensFacing(@LensFacing int lensFacing)
+    public static String getCameraWithLensFacing(@CameraSelector.LensFacing int lensFacing)
             throws CameraInfoUnavailableException {
         checkInitialized();
         return getCameraFactory().cameraIdForLensFacing(lensFacing);
@@ -493,12 +493,13 @@
      * @hide
      */
     @RestrictTo(Scope.LIBRARY_GROUP)
-    @LensFacing
+    @CameraSelector.LensFacing
     public static int getDefaultLensFacing() throws CameraInfoUnavailableException {
         checkInitialized();
 
         Integer lensFacingCandidate = null;
-        List<Integer> lensFacingList = Arrays.asList(LensFacing.BACK, LensFacing.FRONT);
+        List<Integer> lensFacingList = Arrays.asList(CameraSelector.LENS_FACING_BACK,
+                CameraSelector.LENS_FACING_FRONT);
         for (Integer lensFacing : lensFacingList) {
             String cameraId = getCameraFactory().cameraIdForLensFacing(lensFacing);
             if (cameraId != null) {
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/DisplayOrientedMeteringPointFactory.java b/camera/camera-core/src/main/java/androidx/camera/core/DisplayOrientedMeteringPointFactory.java
index 4ed7285..fa4fc7b 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/DisplayOrientedMeteringPointFactory.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/DisplayOrientedMeteringPointFactory.java
@@ -36,7 +36,7 @@
  * rotating applied, they can simply use view width and height to create the
  * {@link DisplayOrientedMeteringPointFactory} and then pass {@link View} (x, y) to create a
  * {@link MeteringPoint}. This factory will convert the (x, y) into the sensor (x, y) based on
- * display rotation and {@link LensFacing}.
+ * display rotation and lensFacing.
  *
  * <p>If camera preview is scaled, cropped or rotated in the {@link View}, it is applications'
  * duty to transform the coordinates properly so that the width and height of this
@@ -145,7 +145,8 @@
         float height = mHeight;
 
         final Integer lensFacing = getLensFacing();
-        boolean compensateForMirroring = (lensFacing != null && lensFacing == LensFacing.FRONT);
+        boolean compensateForMirroring =
+                (lensFacing != null && lensFacing == CameraSelector.LENS_FACING_FRONT);
         int relativeCameraOrientation = getRelativeCameraOrientation(compensateForMirroring);
         float outputX = x;
         float outputY = y;
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/FlashMode.java b/camera/camera-core/src/main/java/androidx/camera/core/FlashMode.java
deleted file mode 100644
index 9d63b33..0000000
--- a/camera/camera-core/src/main/java/androidx/camera/core/FlashMode.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2019 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.camera.core;
-
-import androidx.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * The flash mode options when taking a picture using ImageCapture.
- *
- * <p>Applications can check if there is a flash unit via {@link CameraInfo#hasFlashUnit()} and
- * update UI component if necessary. If there is no flash unit, then the FlashMode set to
- * {@link ImageCapture#setFlashMode(int)} will take no effect for the subsequent photo capture
- * requests and they will act like {@link FlashMode#OFF}.
- *
- * <p>When the torch is enabled via {@link CameraControl#enableTorch(boolean)}, the torch
- * will remain enabled during photo capture regardless of flash mode setting. When
- * the torch is disabled, flash will function as specified by
- * {@link ImageCapture#setFlashMode(int)}.
- */
-@IntDef({FlashMode.AUTO, FlashMode.ON, FlashMode.OFF})
-@Retention(RetentionPolicy.SOURCE)
-public @interface FlashMode {
-    /**
-     * Auto flash. The flash will be used according to the camera system's determination when taking
-     * a picture.
-     */
-    int AUTO = 0;
-    /** Always flash. The flash will always be used when taking a picture. */
-    int ON = 1;
-    /** No flash. The flash will never be used when taking a picture. */
-    int OFF = 2;
-}
\ No newline at end of file
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/FlashModeHelper.java b/camera/camera-core/src/main/java/androidx/camera/core/FlashModeHelper.java
index 7b2abc3..c1a8a6d 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/FlashModeHelper.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/FlashModeHelper.java
@@ -16,9 +16,14 @@
 
 package androidx.camera.core;
 
+import static androidx.camera.core.ImageCapture.FLASH_MODE_AUTO;
+import static androidx.camera.core.ImageCapture.FLASH_MODE_OFF;
+import static androidx.camera.core.ImageCapture.FLASH_MODE_ON;
+
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
+import androidx.camera.core.ImageCapture.FlashMode;
 
 /**
  * Helper class that defines certain enum-like methods for {@link FlashMode}
@@ -45,11 +50,11 @@
 
         switch (name) {
             case "AUTO":
-                return FlashMode.AUTO;
+                return FLASH_MODE_AUTO;
             case "ON":
-                return FlashMode.ON;
+                return FLASH_MODE_ON;
             case "OFF":
-                return FlashMode.OFF;
+                return FLASH_MODE_OFF;
             default:
                 throw new IllegalArgumentException("Unknown flash mode name " + name);
         }
@@ -64,11 +69,11 @@
     @NonNull
     public static String nameOf(@FlashMode final int flashMode) {
         switch (flashMode) {
-            case FlashMode.AUTO:
+            case FLASH_MODE_AUTO:
                 return "AUTO";
-            case FlashMode.ON:
+            case FLASH_MODE_ON:
                 return "ON";
-            case FlashMode.OFF:
+            case FLASH_MODE_OFF:
                 return "OFF";
             default:
                 throw new IllegalArgumentException("Unknown flash mode " + flashMode);
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/FocusMeteringAction.java b/camera/camera-core/src/main/java/androidx/camera/core/FocusMeteringAction.java
index 95502661..27b7778 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/FocusMeteringAction.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/FocusMeteringAction.java
@@ -19,6 +19,7 @@
 import androidx.annotation.IntDef;
 import androidx.annotation.IntRange;
 import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
 import androidx.core.util.Preconditions;
 
 import com.google.common.util.concurrent.ListenableFuture;
@@ -40,12 +41,11 @@
  * pass it to {@link CameraControl#startFocusAndMetering(FocusMeteringAction)} to initiate the focus
  * and metering action.
  *
- * <p>The default {@link MeteringMode} is {@link MeteringMode#AF} | {@link MeteringMode#AE} |
- * {@link MeteringMode#AWB} which means the point is used for all AF/AE/AWB regions. Apps can set
- * the proper {@link MeteringMode} to optionally exclude some 3A regions. Multiple regions for
- * specific 3A type are also supported via {@link Builder#addPoint(MeteringPoint)} or
- * {@link Builder#addPoint(MeteringPoint, int)}. App can also this API to enable
- * different region for AF and AE respectively.
+ * <p>The default meteringMode is {@link #FLAG_AF} | {@link #FLAG_AE} | {@link #FLAG_AWB} which
+ * means the point is used for all AF/AE/AWB regions. Apps can set the proper meteringMode to
+ * optionally exclude some 3A regions. Multiple regions for specific 3A type are also supported
+ * via {@link Builder#addPoint(MeteringPoint)} or {@link Builder#addPoint(MeteringPoint, int)}.
+ * App can also this API to enable different region for AF and AE respectively.
  *
  * <p>If any AF points are specified, it will trigger autofocus to start a manual scan. When
  * focus is locked and specified AF/AE/AWB regions are updated in capture result, the returned
@@ -64,8 +64,13 @@
  * to disable auto-cancel.
  */
 public final class FocusMeteringAction {
+
+    public static final int FLAG_AF = 1;
+    public static final int FLAG_AE = 1 << 1;
+    public static final int FLAG_AWB = 1 << 2;
+
     @MeteringMode
-    static final int DEFAULT_METERINGMODE = MeteringMode.AF | MeteringMode.AE | MeteringMode.AWB;
+    static final int DEFAULT_METERINGMODE = FLAG_AF | FLAG_AE | FLAG_AWB;
     static final long DEFAULT_AUTOCANCEL_DURATION = 5000;
     private final List<MeteringPoint> mMeteringPointsAf;
     private final List<MeteringPoint> mMeteringPointsAe;
@@ -121,13 +126,13 @@
     /**
      * Focus/Metering mode used to specify which 3A regions is activated for corresponding
      * {@link MeteringPoint}.
+     *
+     * @hide
      */
-    @IntDef(flag = true, value = {MeteringMode.AF, MeteringMode.AE, MeteringMode.AWB})
+    @IntDef(flag = true, value = {FLAG_AF, FLAG_AE, FLAG_AWB})
     @Retention(RetentionPolicy.SOURCE)
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
     public @interface MeteringMode {
-        int AF = 1;
-        int AE = 1 << 1;
-        int AWB = 1 << 2;
     }
 
     /**
@@ -143,7 +148,7 @@
         @SuppressWarnings("WeakerAccess") /* synthetic accessor */
         final List<MeteringPoint> mMeteringPointsAwb = new ArrayList<>();
         @SuppressWarnings("WeakerAccess") /* synthetic accessor */
-        long mAutoCancelDurationInMillis = DEFAULT_AUTOCANCEL_DURATION;
+                long mAutoCancelDurationInMillis = DEFAULT_AUTOCANCEL_DURATION;
 
         private Builder(@NonNull MeteringPoint point) {
             this(point, DEFAULT_METERINGMODE);
@@ -155,7 +160,7 @@
 
         /**
          * Creates the Builder from a {@link MeteringPoint} with default
-         * mode {@link MeteringMode#AF} | {@link MeteringMode#AE} | {@link MeteringMode#AWB}.
+         * mode {@link #FLAG_AF} | {@link #FLAG_AE} | {@link #FLAG_AWB}.
          */
         @NonNull
         public static Builder from(@NonNull MeteringPoint meteringPoint) {
@@ -163,23 +168,30 @@
         }
 
         /**
-         * Creates the Builder from a {@link MeteringPoint} and {@link MeteringMode}
+         * Creates the Builder from a {@link MeteringPoint} and MeteringMode.
          */
         @NonNull
-        public static Builder from(@NonNull MeteringPoint meteringPoint,
-                @MeteringMode int mode) {
+        public static Builder from(@NonNull MeteringPoint meteringPoint, @MeteringMode int mode) {
             return new Builder(meteringPoint, mode);
         }
 
         /**
-         * Adds another {@link MeteringPoint} with default mode {@link MeteringMode#AF} |
-         * {@link MeteringMode#AE} | {@link MeteringMode#AWB}.
+         * Adds another {@link MeteringPoint} with default mode {@link #FLAG_AF} |
+         * {@link #FLAG_AE} | {@link #FLAG_AWB}.
+         *
+         * <p>The points added here will be appended in order after the point set in
+         * {@link FocusMeteringAction.Builder#from(MeteringPoint)} or
+         * {@link FocusMeteringAction.Builder#from(MeteringPoint, int)}.
          *
          * <p>If more points are added than what current device supports for AF/AE/AWB, only the
-         * first region and then in order up to the number of regions supported by the device
-         * will be enabled. If it turns out no added points can be supported on the device, the
-         * returned {@link ListenableFuture} in
-         * {@link CameraControl#startFocusAndMetering(FocusMeteringAction)} will fail immediately.
+         * first point and then in order up to the number of points supported on the device
+         * will be enabled.
+         *
+         * <p>If none of the points is supported on the device, this
+         * {@link FocusMeteringAction} will cause
+         * {@link CameraControl#startFocusAndMetering(FocusMeteringAction)} to fail.
+         *
+         * @see CameraControl#startFocusAndMetering(FocusMeteringAction)
          */
         @NonNull
         public Builder addPoint(@NonNull MeteringPoint point) {
@@ -187,30 +199,35 @@
         }
 
         /**
-         * Adds another {@link MeteringPoint} with specified {@link MeteringMode}.
+         * Adds another {@link MeteringPoint} with specified meteringMode.
+         *
+         * <p>The points added here will be appended in order after the point set in
+         * {@link FocusMeteringAction.Builder#from(MeteringPoint)} or
+         * {@link FocusMeteringAction.Builder#from(MeteringPoint, int)}.
          *
          * <p>If more points are added than what current device supports for AF/AE/AWB, only the
-         * first region and then in order up to the number of regions supported by the device
-         * will be enabled. If it turns out no added points can be supported on the device, the
-         * returned {@link ListenableFuture} in
-         * {@link CameraControl#startFocusAndMetering(FocusMeteringAction)} will fail immediately.
+         * first point and then in order up to the number of points supported on the device
+         * will be enabled.
          *
-         * @param mode Must be a valid {@link MeteringMode}, otherwise an
-         *             {@link IllegalArgumentException} is thrown.
+         * <p>If none of the points is supported on the device, this
+         * {@link FocusMeteringAction} will cause
+         * {@link CameraControl#startFocusAndMetering(FocusMeteringAction)} to fail.
+         *
+         * @see CameraControl#startFocusAndMetering(FocusMeteringAction)
          */
         @NonNull
         public Builder addPoint(@NonNull MeteringPoint point, @MeteringMode int mode) {
             Preconditions.checkArgument(
-                    (mode >= MeteringMode.AF) && (mode <= (MeteringMode.AF | MeteringMode.AE
-                            | MeteringMode.AWB)), "Invalid metering mode " + mode);
+                    (mode >= FLAG_AF) && (mode <= (FLAG_AF | FLAG_AE | FLAG_AWB)),
+                    "Invalid metering mode " + mode);
 
-            if ((mode & MeteringMode.AF) != 0) {
+            if ((mode & FLAG_AF) != 0) {
                 mMeteringPointsAf.add(point);
             }
-            if ((mode & MeteringMode.AE) != 0) {
+            if ((mode & FLAG_AE) != 0) {
                 mMeteringPointsAe.add(point);
             }
-            if ((mode & MeteringMode.AWB) != 0) {
+            if ((mode & FLAG_AWB) != 0) {
                 mMeteringPointsAwb.add(point);
             }
             return this;
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
index 321c26a..d64bb26 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
@@ -71,11 +71,52 @@
  *
  * <p>The application is responsible for calling {@link ImageProxy#close()} to close the image.
  * Failing to close the image will cause future images to be stalled or dropped depending on the
- * {@link BackpressureStrategy}.
+ * backpressure strategy.
  */
 public final class ImageAnalysis extends UseCase {
 
     /**
+     * Only deliver the latest image to the analyzer, dropping images as they arrive.
+     *
+     * <p>This strategy ignores the value set by {@link Builder#setImageQueueDepth(int)}.
+     * Only one image will be delivered for analysis at a time. If more images are produced
+     * while that image is being analyzed, they will be dropped and not queued for delivery.
+     * Once the image being analyzed is closed by calling {@link ImageProxy#close()}, the
+     * next latest image will be delivered.
+     *
+     * <p>Internally this strategy may make use of an internal {@link Executor} to receive
+     * and drop images from the producer. A performance-tuned executor will be created
+     * internally unless one is explicitly provided by
+     * {@link Builder#setBackgroundExecutor(Executor)}. In order to
+     * ensure smooth operation of this backpressure strategy, any user supplied
+     * {@link Executor} must be able to quickly respond to tasks posted to it, so setting
+     * the executor manually should only be considered in advanced use cases.
+     *
+     * @see Builder#setBackgroundExecutor(Executor)
+     */
+    public static final int STRATEGY_KEEP_ONLY_LATEST = 0;
+    /**
+     * Block the producer from generating new images.
+     *
+     * <p>Once the producer has produced the number of images equal to the image queue depth,
+     * and none have been closed, the producer will stop producing images. Note that images
+     * may be queued internally and not be delivered to the analyzer until the last delivered
+     * image has been closed with {@link ImageProxy#close()}. These internally queued images
+     * will count towards the total number of images that the producer can provide at any one
+     * time.
+     *
+     * <p>When the producer stops producing images, it may also stop producing images for
+     * other use cases, such as {@link Preview}, so it is important for the analyzer to keep
+     * up with frame rate, <i>on average</i>. Failure to keep up with frame rate may lead to
+     * jank in the frame stream and a diminished user experience. If more time is needed for
+     * analysis on <i>some</i> frames, consider increasing the image queue depth with
+     * {@link Builder#setImageQueueDepth(int)}.
+     *
+     * @see Builder#setImageQueueDepth(int)
+     */
+    public static final int STRATEGY_BLOCK_PRODUCER = 1;
+
+    /**
      * Provides a static configuration with implementation-agnostic options.
      *
      * @hide
@@ -113,7 +154,7 @@
         ImageAnalysisConfig combinedConfig = (ImageAnalysisConfig) getUseCaseConfig();
         setImageFormat(ImageReaderFormatRecommender.chooseCombo().imageAnalysisFormat());
 
-        if (combinedConfig.getBackpressureStrategy() == BackpressureStrategy.BLOCK_PRODUCER) {
+        if (combinedConfig.getBackpressureStrategy() == STRATEGY_BLOCK_PRODUCER) {
             mImageAnalysisAbstractAnalyzer = new ImageAnalysisBlockingAnalyzer();
         } else {
             mImageAnalysisAbstractAnalyzer = new ImageAnalysisNonBlockingAnalyzer(
@@ -130,7 +171,7 @@
                 CameraXExecutors.highPriorityExecutor());
 
         int imageQueueDepth =
-                config.getBackpressureStrategy() == BackpressureStrategy.BLOCK_PRODUCER
+                config.getBackpressureStrategy() == STRATEGY_BLOCK_PRODUCER
                         ? config.getImageQueueDepth() : NON_BLOCKING_IMAGE_DEPTH;
 
         mImageReader =
@@ -389,51 +430,13 @@
      * by calling {@link ImageProxy#close()}. However, the image will only be valid when the
      * ImageAnalysis instance is bound to a camera.
      *
+     * @hide
      * @see Builder#setBackpressureStrategy(int)
      */
-    @IntDef({BackpressureStrategy.KEEP_ONLY_LATEST, BackpressureStrategy.BLOCK_PRODUCER})
+    @IntDef({STRATEGY_KEEP_ONLY_LATEST, STRATEGY_BLOCK_PRODUCER})
     @Retention(RetentionPolicy.SOURCE)
+    @RestrictTo(Scope.LIBRARY_GROUP)
     public @interface BackpressureStrategy {
-        /**
-         * Only deliver the latest image to the analyzer, dropping images as they arrive.
-         *
-         * <p>This strategy ignores the value set by {@link Builder#setImageQueueDepth(int)}.
-         * Only one image will be delivered for analysis at a time. If more images are produced
-         * while that image is being analyzed, they will be dropped and not queued for delivery.
-         * Once the image being analyzed is closed by calling {@link ImageProxy#close()}, the
-         * next latest image will be delivered.
-         *
-         * <p>Internally this strategy may make use of an internal {@link Executor} to receive
-         * and drop images from the producer. A performance-tuned executor will be created
-         * internally unless one is explicitly provided by
-         * {@link Builder#setBackgroundExecutor(Executor)}. In order to
-         * ensure smooth operation of this backpressure strategy, any user supplied
-         * {@link Executor} must be able to quickly respond to tasks posted to it, so setting
-         * the executor manually should only be considered in advanced use cases.
-         *
-         * @see Builder#setBackgroundExecutor(Executor)
-         */
-        int KEEP_ONLY_LATEST = 0;
-        /**
-         * Block the producer from generating new images.
-         *
-         * <p>Once the producer has produced the number of images equal to the image queue depth,
-         * and none have been closed, the producer will stop producing images. Note that images
-         * may be queued internally and not be delivered to the analyzer until the last delivered
-         * image has been closed with {@link ImageProxy#close()}. These internally queued images
-         * will count towards the total number of images that the producer can provide at any one
-         * time.
-         *
-         * <p>When the producer stops producing images, it may also stop producing images for
-         * other use cases, such as {@link Preview}, so it is important for the analyzer to keep
-         * up with frame rate, <i>on average</i>. Failure to keep up with frame rate may lead to
-         * jank in the frame stream and a diminished user experience. If more time is needed for
-         * analysis on <i>some</i> frames, consider increasing the image queue depth with
-         * {@link Builder#setImageQueueDepth(int)}.
-         *
-         * @see Builder#setImageQueueDepth(int)
-         */
-        int BLOCK_PRODUCER = 1;
     }
 
     /**
@@ -453,7 +456,7 @@
          * <p>It is the responsibility of the application to close the image once done with it.
          * If the images are not closed then it may block further images from being produced
          * (causing the preview to stall) or drop images as determined by the configured
-         * {@link ImageAnalysis.BackpressureStrategy}. The exact behavior is configurable via
+         * backpressure strategy. The exact behavior is configurable via
          * {@link ImageAnalysis.Builder#setBackpressureStrategy(int)}.
          *
          * <p>Images produced here will no longer be valid after the {@link ImageAnalysis}
@@ -496,8 +499,7 @@
     @RestrictTo(Scope.LIBRARY_GROUP)
     public static final class Defaults implements ConfigProvider<ImageAnalysisConfig> {
         @BackpressureStrategy
-        private static final int DEFAULT_BACKPRESSURE_STRATEGY =
-                BackpressureStrategy.KEEP_ONLY_LATEST;
+        private static final int DEFAULT_BACKPRESSURE_STRATEGY = STRATEGY_KEEP_ONLY_LATEST;
         private static final int DEFAULT_IMAGE_QUEUE_DEPTH = 6;
         private static final Size DEFAULT_TARGET_RESOLUTION = new Size(640, 480);
         private static final Size DEFAULT_MAX_RESOLUTION = new Size(1920, 1080);
@@ -570,11 +572,11 @@
          * Sets the backpressure strategy to apply to the image producer to deal with scenarios
          * where images may be produced faster than they can be analyzed.
          *
-         * <p>The available values are {@link BackpressureStrategy#BLOCK_PRODUCER} and {@link
-         * BackpressureStrategy#KEEP_ONLY_LATEST}.
+         * <p>The available values are {@link #STRATEGY_BLOCK_PRODUCER} and
+         * {@link #STRATEGY_KEEP_ONLY_LATEST}.
          *
          * <p>If not set, the backpressure strategy will default to
-         * {@link BackpressureStrategy#KEEP_ONLY_LATEST}.
+         * {@link #STRATEGY_KEEP_ONLY_LATEST}.
          *
          * @param strategy The strategy to use.
          * @return The current Builder.
@@ -587,24 +589,24 @@
 
         /**
          * Sets the number of images available to the camera pipeline for
-         * {@link BackpressureStrategy#BLOCK_PRODUCER} mode.
+         * {@link #STRATEGY_BLOCK_PRODUCER} mode.
          *
          * <p>The image queue depth is the number of images available to the camera to fill with
          * data. This includes the image currently being analyzed by {@link
          * ImageAnalysis.Analyzer#analyze(ImageProxy, int)}. Increasing the image queue depth
-         * may make camera operation smoother, depending on the {@link BackpressureStrategy}, at
+         * may make camera operation smoother, depending on the backpressure strategy, at
          * the cost of increased memory usage.
          *
-         * <p>When the {@link BackpressureStrategy} is set to
-         * {@link BackpressureStrategy#BLOCK_PRODUCER}, increasing the image queue depth may make
-         * the camera pipeline run smoother on systems under high load. However, the time spent
-         * analyzing an image should still be kept under a single frame period for the current
-         * frame rate, <i>on average</i>, to avoid stalling the camera pipeline.
+         * <p>When the backpressure strategy is set to {@link #STRATEGY_BLOCK_PRODUCER},
+         * increasing the image queue depth may make the camera pipeline run smoother on systems
+         * under high load. However, the time spent analyzing an image should still be kept under
+         * a single frame period for the current frame rate, <i>on average</i>, to avoid stalling
+         * the camera pipeline.
          *
-         * <p>The value only applies to {@link BackpressureStrategy#BLOCK_PRODUCER} mode.
-         * For {@link BackpressureStrategy#KEEP_ONLY_LATEST} the value is ignored.
+         * <p>The value only applies to {@link #STRATEGY_BLOCK_PRODUCER} mode.
+         * For {@link #STRATEGY_KEEP_ONLY_LATEST} the value is ignored.
          *
-         * <p>If not set, and this option is used by the selected {@link BackpressureStrategy},
+         * <p>If not set, and this option is used by the selected backpressure strategy,
          * the default will be a queue depth of 6 images.
          *
          * @param depth The total number of images available to the camera.
@@ -641,7 +643,7 @@
         }
 
         /**
-         * Builds an immutable {@link ImageAnalysis} from the current state.
+         * Builds an {@link ImageAnalysis} from the current state.
          *
          * @return A {@link ImageAnalysis} populated with the current state.
          * @throws IllegalArgumentException if attempting to set both target aspect ratio and
@@ -714,7 +716,7 @@
         @RestrictTo(Scope.LIBRARY_GROUP)
         @Override
         @NonNull
-        public Builder setLensFacing(@LensFacing int lensFacing) {
+        public Builder setLensFacing(@CameraSelector.LensFacing int lensFacing) {
             getMutableConfig().insertOption(OPTION_LENS_FACING, lensFacing);
             return this;
         }
@@ -793,7 +795,7 @@
          */
         @NonNull
         @Override
-        public Builder setTargetAspectRatio(@AspectRatio int aspectRatio) {
+        public Builder setTargetAspectRatio(@AspectRatio.Ratio int aspectRatio) {
             getMutableConfig().insertOption(OPTION_TARGET_ASPECT_RATIO, aspectRatio);
             return this;
         }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisConfig.java
index 6b1ec8d..c97b311 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisConfig.java
@@ -65,8 +65,8 @@
      * Retrieves the backpressure strategy applied to the image producer to deal with scenarios
      * where images may be produced faster than they can be analyzed.
      *
-     * <p>The available values are {@link BackpressureStrategy#BLOCK_PRODUCER} and {@link
-     * BackpressureStrategy#KEEP_ONLY_LATEST}.
+     * <p>The available values are {@link BackpressureStrategy#STRATEGY_BLOCK_PRODUCER} and {@link
+     * BackpressureStrategy#STRATEGY_KEEP_ONLY_LATEST}.
      *
      * @param valueIfMissing The value to return if this configuration option has not been set.
      * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
@@ -81,8 +81,8 @@
     /**
      * Returns the mode that the image is acquired from {@link ImageReader}.
      *
-     * <p>The available values are {@link BackpressureStrategy#BLOCK_PRODUCER} and {@link
-     * BackpressureStrategy#KEEP_ONLY_LATEST}.
+     * <p>The available values are {@link BackpressureStrategy#STRATEGY_BLOCK_PRODUCER} and {@link
+     * BackpressureStrategy#STRATEGY_KEEP_ONLY_LATEST}.
      *
      * @return The stored value, if it exists in this configuration.
      * @throws IllegalArgumentException if the option does not exist in this configuration.
@@ -250,7 +250,7 @@
      */
     @RestrictTo(Scope.LIBRARY_GROUP)
     @Override
-    @LensFacing
+    @CameraSelector.LensFacing
     public int getLensFacing() {
         return retrieveOption(OPTION_LENS_FACING);
     }
@@ -334,7 +334,7 @@
      * @return The stored value, if it exists in this configuration.
      * @throws IllegalArgumentException if the option does not exist in this configuration.
      */
-    @AspectRatio
+    @AspectRatio.Ratio
     @Override
     public int getTargetAspectRatio() {
         return retrieveOption(OPTION_TARGET_ASPECT_RATIO);
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
index 7ed111d..42f3d67 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
@@ -117,6 +117,55 @@
 public class ImageCapture extends UseCase {
 
     /**
+     * An unknown error occurred.
+     *
+     * <p>See message parameter in onError callback or log for more details.
+     */
+    public static final int ERROR_UNKNOWN = 0;
+    /**
+     * An error occurred while attempting to read or write a file, such as when saving an image
+     * to a File.
+     */
+    public static final int ERROR_FILE_IO = 1;
+
+    /**
+     * An error reported by camera framework indicating the capture request is failed.
+     */
+    public static final int ERROR_CAPTURE_FAILED = 2;
+
+    /**
+     * An error indicating the request cannot be done due to camera is closed.
+     */
+    public static final int ERROR_CAMERA_CLOSED = 3;
+
+    /**
+     * An error indicating this ImageCapture is not bound to a valid camera.
+     */
+    public static final int ERROR_INVALID_CAMERA = 4;
+
+    /**
+     * Optimizes capture pipeline to prioritize image quality over latency. When the capture
+     * mode is set to MAX_QUALITY, images may take longer to capture.
+     */
+    public static final int CAPTURE_MODE_MAXIMIZE_QUALITY = 0;
+    /**
+     * Optimizes capture pipeline to prioritize latency over image quality. When the capture
+     * mode is set to MIN_LATENCY, images may capture faster but the image quality may be
+     * reduced.
+     */
+    public static final int CAPTURE_MODE_MINIMIZE_LATENCY = 1;
+
+    /**
+     * Auto flash. The flash will be used according to the camera system's determination when taking
+     * a picture.
+     */
+    public static final int FLASH_MODE_AUTO = 0;
+    /** Always flash. The flash will always be used when taking a picture. */
+    public static final int FLASH_MODE_ON = 1;
+    /** No flash. The flash will never be used when taking a picture. */
+    public static final int FLASH_MODE_OFF = 2;
+
+    /**
      * Provides a static configuration with implementation-agnostic options.
      *
      * @hide
@@ -229,9 +278,9 @@
 
         mIoExecutor = mConfig.getIoExecutor(CameraXExecutors.ioExecutor());
 
-        if (mCaptureMode == CaptureMode.MAXIMIZE_QUALITY) {
+        if (mCaptureMode == CAPTURE_MODE_MAXIMIZE_QUALITY) {
             mEnableCheck3AConverged = true; // check 3A convergence in MAX_QUALITY mode
-        } else if (mCaptureMode == CaptureMode.MINIMIZE_LATENCY) {
+        } else if (mCaptureMode == CAPTURE_MODE_MINIMIZE_LATENCY) {
             mEnableCheck3AConverged = false; // skip 3A convergence in MIN_LATENCY mode
         }
 
@@ -387,7 +436,7 @@
     /**
      * Get the flash mode.
      *
-     * @return the {@link FlashMode}.
+     * @return the flashMode.
      */
     @FlashMode
     public int getFlashMode() {
@@ -397,17 +446,16 @@
     /**
      * Set the flash mode.
      *
-     * <p>The flash control for the subsequent photo capture requests. See
-     * {@link FlashMode} for the optional settings. Applications can check if there is a flash unit
-     * via {@link CameraInfo#hasFlashUnit()} and update UI component if necessary. If there is no
-     * flash unit, then calling this API will take no effect for the subsequent photo capture
-     * requests and they will act like {@link FlashMode#OFF}.
+     * <p>The flash control for the subsequent photo capture requests. Applications can check if
+     * there is a flash unit via {@link CameraInfo#hasFlashUnit()} and update UI component if
+     * necessary. If there is no flash unit, then calling this API will take no effect for the
+     * subsequent photo capture requests and they will act like {@link #FLASH_MODE_OFF}.
      *
      * <p>When the torch is enabled via {@link CameraControl#enableTorch(boolean)}, the torch
-     * will remain enabled during photo capture regardless of {@link FlashMode} setting. When
+     * will remain enabled during photo capture regardless of flashMode setting. When
      * the torch is disabled, flash will function as specified by {@link #setFlashMode(int)}.
      *
-     * @param flashMode the {@link FlashMode}.
+     * @param flashMode the flash mode.
      */
     public void setFlashMode(@FlashMode int flashMode) {
         this.mFlashMode = flashMode;
@@ -517,12 +565,13 @@
      * Captures a new still image and saves to a file.
      *
      * <p>The listener's callback will be called only once for every invocation of this method.
+     *
      * @param saveLocation       Location to store the newly captured image.
      * @param executor           The executor in which the listener callback methods will be run.
      * @param imageSavedCallback Callback to be called for the newly captured image.
-     * Maybe remove after https://issuetracker.google.com/135275901
-     * Todo: b/145130873 - Methods accepting `File` should also accept `FileDescriptor` or streams
      */
+    // Maybe remove after https://issuetracker.google.com/135275901
+    // Todo: b/145130873 - Methods accepting `File` should also accept `FileDescriptor` or streams
     @SuppressLint({"LambdaLast", "StreamFiles"})
     public void takePicture(@NonNull File saveLocation,
             @NonNull Executor executor,
@@ -543,9 +592,9 @@
      *                           be included in the EXIF.
      * @param executor           The executor in which the callback methods will be run.
      * @param imageSavedCallback Callback to be called for the newly captured image.
-     * Maybe remove after https://issuetracker.google.com/135275901
-     * Todo: b/145130873 - Methods accepting `File` should also accept `FileDescriptor` or streams
      */
+    // Maybe remove after https://issuetracker.google.com/135275901
+    // Todo: b/145130873 - Methods accepting `File` should also accept `FileDescriptor` or streams
     @SuppressLint({"LambdaLast", "StreamFiles"})
     public void takePicture(
             final @NonNull File saveLocation,
@@ -585,12 +634,12 @@
                     }
 
                     @Override
-                    public void onError(@ImageSaver.SaveError int error, String message,
+                    public void onError(ImageSaver.SaveError error, String message,
                             @Nullable Throwable cause) {
-                        @ImageCaptureError int imageCaptureError = ImageCaptureError.UNKNOWN_ERROR;
+                        @ImageCaptureError int imageCaptureError = ERROR_UNKNOWN;
                         switch (error) {
-                            case ImageSaver.SaveError.FILE_IO_FAILED:
-                                imageCaptureError = ImageCaptureError.FILE_IO_ERROR;
+                            case FILE_IO_FAILED:
+                                imageCaptureError = ERROR_FILE_IO;
                                 break;
                             default:
                                 // Keep the imageCaptureError as UNKNOWN_ERROR
@@ -668,7 +717,7 @@
             cameraId = getBoundCameraId();
         } catch (Throwable e) {
             // Not bound. Notify callback.
-            callback.onError(ImageCaptureError.INVALID_CAMERA,
+            callback.onError(ERROR_INVALID_CAMERA,
                     "Not bound to a valid Camera [" + ImageCapture.this + "]", e);
             return;
         }
@@ -757,11 +806,11 @@
     @ImageCaptureError
     int getError(Throwable throwable) {
         if (throwable instanceof CameraClosedException) {
-            return ImageCaptureError.CAMERA_CLOSED;
+            return ERROR_CAMERA_CLOSED;
         } else if (throwable instanceof CaptureFailedException) {
-            return ImageCaptureError.CAPTURE_FAILED;
+            return ERROR_CAPTURE_FAILED;
         } else {
-            return ImageCaptureError.UNKNOWN_ERROR;
+            return ERROR_UNKNOWN;
         }
     }
 
@@ -877,7 +926,7 @@
     // If app is in min-latency mode and flash ALWAYS/OFF mode, it can still take picture without
     // checking the capture result. Remove this check once no repeating surface issue is fixed.
     private ListenableFuture<CameraCaptureResult> getPreCaptureStateIfNeeded() {
-        if (mEnableCheck3AConverged || getFlashMode() == FlashMode.AUTO) {
+        if (mEnableCheck3AConverged || getFlashMode() == FLASH_MODE_AUTO) {
             return mSessionCallbackChecker.checkCaptureResult(
                     new CaptureCallbackChecker.CaptureResultChecker<CameraCaptureResult>() {
                         @Override
@@ -892,11 +941,11 @@
 
     boolean isFlashRequired(TakePictureState state) {
         switch (getFlashMode()) {
-            case FlashMode.ON:
+            case FLASH_MODE_ON:
                 return true;
-            case FlashMode.AUTO:
+            case FLASH_MODE_AUTO:
                 return state.mPreCaptureState.getAeState() == AeState.FLASH_REQUIRED;
-            case FlashMode.OFF:
+            case FLASH_MODE_OFF:
                 return false;
         }
         throw new AssertionError(getFlashMode());
@@ -1109,58 +1158,47 @@
      *
      * <p>This is a parameter sent to the error callback functions set in listeners such as {@link
      * ImageCapture.OnImageSavedCallback#onError(int, String, Throwable)}.
+     *
+     * @hide
      */
-    @IntDef({ImageCaptureError.UNKNOWN_ERROR, ImageCaptureError.FILE_IO_ERROR,
-            ImageCaptureError.CAPTURE_FAILED, ImageCaptureError.CAMERA_CLOSED,
-            ImageCaptureError.INVALID_CAMERA})
+    @IntDef({ERROR_UNKNOWN, ERROR_FILE_IO, ERROR_CAPTURE_FAILED, ERROR_CAMERA_CLOSED,
+            ERROR_INVALID_CAMERA})
     @Retention(RetentionPolicy.SOURCE)
+    @RestrictTo(Scope.LIBRARY_GROUP)
     public @interface ImageCaptureError {
-        /**
-         * An unknown error occurred.
-         *
-         * <p>See message parameter in onError callback or log for more details.
-         */
-        int UNKNOWN_ERROR = 0;
-        /**
-         * An error occurred while attempting to read or write a file, such as when saving an image
-         * to a File.
-         */
-        int FILE_IO_ERROR = 1;
-
-        /**
-         * An error reported by camera framework indicating the capture request is failed.
-         */
-        int CAPTURE_FAILED = 2;
-
-        /**
-         * An error indicating the request cannot be done due to camera is closed.
-         */
-        int CAMERA_CLOSED = 3;
-
-        /**
-         * An error indicating this ImageCapture is not bound to a valid camera.
-         */
-        int INVALID_CAMERA = 4;
     }
 
     /**
      * Capture mode options for ImageCapture. A picture will always be taken regardless of
      * mode, and the mode will be used on devices that support it.
+     *
+     * @hide
      */
-    @IntDef({CaptureMode.MAXIMIZE_QUALITY, CaptureMode.MINIMIZE_LATENCY})
+    @IntDef({CAPTURE_MODE_MAXIMIZE_QUALITY, CAPTURE_MODE_MINIMIZE_LATENCY})
     @Retention(RetentionPolicy.SOURCE)
+    @RestrictTo(Scope.LIBRARY_GROUP)
     public @interface CaptureMode {
-        /**
-         * Optimizes capture pipeline to prioritize image quality over latency. When the capture
-         * mode is set to MAX_QUALITY, images may take longer to capture.
-         */
-        int MAXIMIZE_QUALITY = 0;
-        /**
-         * Optimizes capture pipeline to prioritize latency over image quality. When the capture
-         * mode is set to MIN_LATENCY, images may capture faster but the image quality may be
-         * reduced.
-         */
-        int MINIMIZE_LATENCY = 1;
+    }
+
+    /**
+     * The flash mode options when taking a picture using ImageCapture.
+     *
+     * <p>Applications can check if there is a flash unit via {@link CameraInfo#hasFlashUnit()} and
+     * update UI component if necessary. If there is no flash unit, then the FlashMode set to
+     * {@link #setFlashMode(int)} will take no effect for the subsequent photo capture requests
+     * and they will act like {@link #FLASH_MODE_OFF}.
+     *
+     * <p>When the torch is enabled via {@link CameraControl#enableTorch(boolean)}, the torch
+     * will remain enabled during photo capture regardless of flash mode setting. When
+     * the torch is disabled, flash will function as specified by
+     * {@link #setFlashMode(int)}.
+     *
+     * @hide
+     */
+    @IntDef({FLASH_MODE_AUTO, FLASH_MODE_ON, FLASH_MODE_OFF})
+    @Retention(RetentionPolicy.SOURCE)
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public @interface FlashMode {
     }
 
     /** Listener containing callbacks for image file I/O events. */
@@ -1169,8 +1207,8 @@
          * Called when an image has been successfully saved.
          *
          * @param file The file object which the image is saved to
-         * Todo: b/145130873 - Methods accepting `File` should also accept `FileDescriptor`
          */
+        // Todo: b/145130873 - Methods accepting `File` should also accept `FileDescriptor`
         @SuppressLint("StreamFiles")
         void onImageSaved(@NonNull File file);
 
@@ -1251,9 +1289,9 @@
     public static final class Defaults
             implements ConfigProvider<ImageCaptureConfig> {
         @CaptureMode
-        private static final int DEFAULT_CAPTURE_MODE = CaptureMode.MINIMIZE_LATENCY;
+        private static final int DEFAULT_CAPTURE_MODE = CAPTURE_MODE_MINIMIZE_LATENCY;
         @FlashMode
-        private static final int DEFAULT_FLASH_MODE = FlashMode.OFF;
+        private static final int DEFAULT_FLASH_MODE = FLASH_MODE_OFF;
         private static final int DEFAULT_SURFACE_OCCUPANCY_PRIORITY = 4;
 
         private static final ImageCaptureConfig DEFAULT_CONFIG;
@@ -1638,11 +1676,14 @@
         /**
          * Sets the image capture mode.
          *
-         * <p>Valid capture modes are {@link CaptureMode#MINIMIZE_LATENCY}, which prioritizes
-         * latency over image quality, or {@link CaptureMode#MAXIMIZE_QUALITY}, which prioritizes
+         * <p>Valid capture modes are {@link CaptureMode#CAPTURE_MODE_MINIMIZE_LATENCY}, which
+         * prioritizes
+         * latency over image quality, or {@link CaptureMode#CAPTURE_MODE_MAXIMIZE_QUALITY},
+         * which prioritizes
          * image quality over latency.
          *
-         * <p>If not set, the capture mode will default to {@link CaptureMode#MINIMIZE_LATENCY}.
+         * <p>If not set, the capture mode will default to
+         * {@link CaptureMode#CAPTURE_MODE_MINIMIZE_LATENCY}.
          *
          * @param captureMode The requested image capture mode.
          * @return The current Builder.
@@ -1654,9 +1695,9 @@
         }
 
         /**
-         * Sets the {@link FlashMode}.
+         * Sets the flashMode.
          *
-         * <p>If not set, the flash mode will default to {@link FlashMode#OFF}.
+         * <p>If not set, the flash mode will default to {@link #FLASH_MODE_OFF}.
          *
          * <p>See {@link ImageCapture#setFlashMode(int)} for more information.
          *
@@ -1794,7 +1835,7 @@
         @RestrictTo(Scope.LIBRARY_GROUP)
         @Override
         @NonNull
-        public Builder setLensFacing(@LensFacing int lensFacing) {
+        public Builder setLensFacing(@CameraSelector.LensFacing int lensFacing) {
             getMutableConfig().insertOption(OPTION_LENS_FACING, lensFacing);
             return this;
         }
@@ -1878,7 +1919,7 @@
          */
         @NonNull
         @Override
-        public Builder setTargetAspectRatio(@AspectRatio int aspectRatio) {
+        public Builder setTargetAspectRatio(@AspectRatio.Ratio int aspectRatio) {
             getMutableConfig().insertOption(OPTION_TARGET_ASPECT_RATIO, aspectRatio);
             return this;
         }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageCaptureConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageCaptureConfig.java
index 2ec8281..e960f13f 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageCaptureConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageCaptureConfig.java
@@ -52,7 +52,7 @@
             Option.create(
                     "camerax.core.imageCapture.captureMode", int.class);
     static final Option<Integer> OPTION_FLASH_MODE =
-            Option.create("camerax.core.imageCapture.flashMode", FlashMode.class);
+            Option.create("camerax.core.imageCapture.flashMode", int.class);
     static final Option<CaptureBundle> OPTION_CAPTURE_BUNDLE =
             Option.create("camerax.core.imageCapture.captureBundle", CaptureBundle.class);
     static final Option<CaptureProcessor> OPTION_CAPTURE_PROCESSOR =
@@ -93,12 +93,12 @@
     }
 
     /**
-     * Returns the {@link FlashMode}.
+     * Returns the {@link ImageCapture.FlashMode}.
      *
      * @return The stored value, if it exists in this configuration.
      * @throws IllegalArgumentException if the option does not exist in this configuration.
      */
-    @FlashMode
+    @ImageCapture.FlashMode
     public int getFlashMode() {
         return retrieveOption(OPTION_FLASH_MODE);
     }
@@ -338,7 +338,7 @@
      */
     @RestrictTo(Scope.LIBRARY_GROUP)
     @Override
-    @LensFacing
+    @CameraSelector.LensFacing
     public int getLensFacing() {
         return retrieveOption(OPTION_LENS_FACING);
     }
@@ -422,7 +422,7 @@
      * @return The stored value, if it exists in this configuration.
      * @throws IllegalArgumentException if the option does not exist in this configuration.
      */
-    @AspectRatio
+    @AspectRatio.Ratio
     @Override
     public int getTargetAspectRatio() {
         return retrieveOption(OPTION_TARGET_ASPECT_RATIO);
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageOutputConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageOutputConfig.java
index 68431fa..99f6f1f 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageOutputConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageOutputConfig.java
@@ -157,7 +157,7 @@
      * @return The stored value, if it exists in this configuration.
      * @throws IllegalArgumentException if the option does not exist in this configuration.
      */
-    @AspectRatio
+    @AspectRatio.Ratio
     int getTargetAspectRatio();
 
     /**
@@ -331,7 +331,7 @@
          * @return The current Builder.
          */
         @NonNull
-        B setTargetAspectRatio(@AspectRatio int aspectRatio);
+        B setTargetAspectRatio(@AspectRatio.Ratio int aspectRatio);
 
         /**
          * Sets the rotation of the intended target for images from this configuration.
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageSaver.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageSaver.java
index 8500ce9..59d8ba4 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageSaver.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageSaver.java
@@ -18,19 +18,17 @@
 
 import android.location.Location;
 
-import androidx.annotation.IntDef;
 import androidx.annotation.Nullable;
 import androidx.camera.core.ImageUtil.CodecFailedException;
 
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.util.concurrent.Executor;
 
 final class ImageSaver implements Runnable {
     private static final String TAG = "ImageSaver";
+
     @Nullable
     private final Location mLocation;
     // The image that was captured
@@ -71,7 +69,7 @@
     @Override
     public void run() {
         // Finally, we save the file to disk
-        Integer saveError = null;
+        SaveError saveError = null;
         String errorMessage = null;
         Exception exception = null;
         try (ImageProxy imageToClose = mImage;
@@ -131,7 +129,7 @@
         });
     }
 
-    private void postError(final @SaveError int saveError, final String message,
+    private void postError(SaveError saveError, final String message,
             @Nullable final Throwable cause) {
         mExecutor.execute(new Runnable() {
             @Override
@@ -142,23 +140,20 @@
     }
 
     /** Type of error that occurred during save */
-    @IntDef({SaveError.FILE_IO_FAILED, SaveError.ENCODE_FAILED, SaveError.CROP_FAILED,
-            SaveError.UNKNOWN})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface SaveError {
+    public enum SaveError {
         /** Failed to write to or close the file */
-        int FILE_IO_FAILED = 0;
+        FILE_IO_FAILED,
         /** Failure when attempting to encode image */
-        int ENCODE_FAILED = 1;
+        ENCODE_FAILED,
         /** Failure when attempting to crop image */
-        int CROP_FAILED = 2;
-        int UNKNOWN = 3;
+        CROP_FAILED,
+        UNKNOWN
     }
 
     public interface OnImageSavedCallback {
 
         void onImageSaved(File file);
 
-        void onError(@SaveError int saveError, String message, @Nullable Throwable cause);
+        void onError(SaveError saveError, String message, @Nullable Throwable cause);
     }
 }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/LensFacing.java b/camera/camera-core/src/main/java/androidx/camera/core/LensFacing.java
deleted file mode 100644
index af6c7be9..0000000
--- a/camera/camera-core/src/main/java/androidx/camera/core/LensFacing.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2019 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.camera.core;
-
-import androidx.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/** The direction the camera faces relative to device screen. */
-@IntDef({LensFacing.FRONT, LensFacing.BACK})
-@Retention(RetentionPolicy.SOURCE)
-public @interface LensFacing {
-    /** A camera on the device facing the same direction as the device's screen. */
-    int FRONT = 0;
-    /** A camera on the device facing the opposite direction as the device's screen. */
-    int BACK = 1;
-}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/LensFacingCameraIdFilter.java b/camera/camera-core/src/main/java/androidx/camera/core/LensFacingCameraIdFilter.java
index 99de048..9a3ba7e 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/LensFacingCameraIdFilter.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/LensFacingCameraIdFilter.java
@@ -28,10 +28,10 @@
  */
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 public class LensFacingCameraIdFilter implements CameraIdFilter {
-    @LensFacing
+    @CameraSelector.LensFacing
     private int mLensFacing;
 
-    public LensFacingCameraIdFilter(@LensFacing int lensFacing) {
+    public LensFacingCameraIdFilter(@CameraSelector.LensFacing int lensFacing) {
         mLensFacing = lensFacing;
     }
 
@@ -44,7 +44,7 @@
     }
 
     /** Returns the lens facing associated with this lens facing camera id filter. */
-    @LensFacing
+    @CameraSelector.LensFacing
     public int getLensFacing() {
         return mLensFacing;
     }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/LensFacingConverter.java b/camera/camera-core/src/main/java/androidx/camera/core/LensFacingConverter.java
index 66686b0..3f77fcb 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/LensFacingConverter.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/LensFacingConverter.java
@@ -21,7 +21,7 @@
 import androidx.annotation.RestrictTo;
 
 /**
- * Helper class that defines certain enum-like methods for {@link LensFacing}
+ * Helper class that defines certain enum-like methods for {@link CameraSelector.LensFacing}
  *
  * @hide
  */
@@ -32,21 +32,21 @@
     }
 
     /**
-     * @return an array containing the constants of {@link LensFacing} in the order they're
-     * declared.
+     * @return an array containing the constants of {@link CameraSelector.LensFacing} in the
+     * order they're declared.
      */
     @NonNull
     public static Integer[] values() {
-        return new Integer[]{LensFacing.FRONT, LensFacing.BACK};
+        return new Integer[]{CameraSelector.LENS_FACING_FRONT, CameraSelector.LENS_FACING_BACK};
     }
 
     /**
-     * Returns the {@link LensFacing} constant for the specified name
+     * Returns the {@link CameraSelector.LensFacing} constant for the specified name
      *
-     * @param name The name of the {@link LensFacing} to return
-     * @return The {@link LensFacing} constant for the specified name
+     * @param name The name of the {@link CameraSelector.LensFacing} to return
+     * @return The {@link CameraSelector.LensFacing} constant for the specified name
      */
-    @LensFacing
+    @CameraSelector.LensFacing
     public static int valueOf(@Nullable final String name) {
         if (name == null) {
             throw new NullPointerException("name cannot be null");
@@ -54,26 +54,27 @@
 
         switch (name) {
             case "FRONT":
-                return LensFacing.FRONT;
+                return CameraSelector.LENS_FACING_FRONT;
             case "BACK":
-                return LensFacing.BACK;
+                return CameraSelector.LENS_FACING_BACK;
             default:
                 throw new IllegalArgumentException("Unknown len facing name " + name);
         }
     }
 
     /**
-     * Returns the name of the {@link LensFacing} constant, exactly as it is declared.
+     * Returns the name of the {@link CameraSelector.LensFacing} constant, exactly as it is
+     * declared.
      *
-     * @param lensFacing A {@link LensFacing} constant
-     * @return The name of the {@link LensFacing} constant.
+     * @param lensFacing A {@link CameraSelector.LensFacing} constant
+     * @return The name of the {@link CameraSelector.LensFacing} constant.
      */
     @NonNull
-    public static String nameOf(@LensFacing final int lensFacing) {
+    public static String nameOf(@CameraSelector.LensFacing final int lensFacing) {
         switch (lensFacing) {
-            case LensFacing.FRONT:
+            case CameraSelector.LENS_FACING_FRONT:
                 return "FRONT";
-            case LensFacing.BACK:
+            case CameraSelector.LENS_FACING_BACK:
                 return "BACK";
             default:
                 throw new IllegalArgumentException("Unknown lens facing " + lensFacing);
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/Preview.java b/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
index 2df8769..d082b87 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
@@ -470,7 +470,7 @@
          *             public void onFailure(Throwable t) {
          *                 // Should never fail
          *             }
-         *         }, CameraXExecutors.directExecutor());
+         *         }, Executors.newSingleThreadExecutor());
          *
          *         return surfaceFuture;
          *     }
@@ -655,7 +655,7 @@
         @RestrictTo(Scope.LIBRARY_GROUP)
         @Override
         @NonNull
-        public Builder setLensFacing(@LensFacing int lensFacing) {
+        public Builder setLensFacing(@CameraSelector.LensFacing int lensFacing) {
             getMutableConfig().insertOption(OPTION_LENS_FACING, lensFacing);
             return this;
         }
@@ -738,7 +738,7 @@
          */
         @NonNull
         @Override
-        public Builder setTargetAspectRatio(@AspectRatio int aspectRatio) {
+        public Builder setTargetAspectRatio(@AspectRatio.Ratio int aspectRatio) {
             getMutableConfig().insertOption(OPTION_TARGET_ASPECT_RATIO, aspectRatio);
             return this;
         }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/PreviewConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/PreviewConfig.java
index 86e126f..2e49101 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/PreviewConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/PreviewConfig.java
@@ -188,7 +188,7 @@
      */
     @RestrictTo(Scope.LIBRARY_GROUP)
     @Override
-    @LensFacing
+    @CameraSelector.LensFacing
     public int getLensFacing() {
         return retrieveOption(OPTION_LENS_FACING);
     }
@@ -272,7 +272,7 @@
      * @return The stored value, if it exists in this configuration.
      * @throws IllegalArgumentException if the option does not exist in this configuration.
      */
-    @AspectRatio
+    @AspectRatio.Ratio
     @Override
     public int getTargetAspectRatio() {
         return retrieveOption(OPTION_TARGET_ASPECT_RATIO);
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/TorchState.java b/camera/camera-core/src/main/java/androidx/camera/core/TorchState.java
index 5b5462da..b91b28d 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/TorchState.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/TorchState.java
@@ -17,16 +17,27 @@
 package androidx.camera.core;
 
 import androidx.annotation.IntDef;
+import androidx.annotation.RestrictTo;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
 /** The camera flash torch state. */
-@IntDef({TorchState.OFF, TorchState.ON})
-@Retention(RetentionPolicy.SOURCE)
-public @interface TorchState {
+public class TorchState {
     /** Torch is off. */
-    int OFF = 0;
+    public static final int OFF = 0;
     /** Torch is on. */
-    int ON = 1;
+    public static final int ON = 1;
+
+    private TorchState() {
+    }
+
+    /**
+     * @hide
+     */
+    @IntDef({OFF, ON})
+    @Retention(RetentionPolicy.SOURCE)
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public @interface State {
+    }
 }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java b/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
index d7e738e..00464f2 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
@@ -109,8 +109,7 @@
      * the pre-populated builder. If <code>null</code> is returned, then the user-supplied
      * configuration will be used directly.
      *
-     * @param lensFacing The {@link androidx.camera.core.LensFacing} that the default builder
-     *                   will target to.
+     * @param lensFacing The lensFacing that the default builder will target to.
      * @return A builder pre-populated with use case default options.
      * @hide
      */
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/VideoCapture.java b/camera/camera-core/src/main/java/androidx/camera/core/VideoCapture.java
index 79844b7..0a0f265 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/VideoCapture.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/VideoCapture.java
@@ -68,6 +68,24 @@
 public class VideoCapture extends UseCase {
 
     /**
+     * An unknown error occurred.
+     *
+     * <p>See message parameter in onError callback or log for more details.
+     */
+    public static final int ERROR_UNKNOWN = 0;
+    /**
+     * An error occurred with encoder state, either when trying to change state or when an
+     * unexpected state change occurred.
+     */
+    public static final int ERROR_ENCODER = 1;
+    /** An error with muxer state such as during creation or when stopping. */
+    public static final int ERROR_MUXER = 2;
+    /**
+     * An error indicating start recording was called when video recording is still in progress.
+     */
+    public static final int ERROR_RECORDING_IN_PROGRESS = 3;
+
+    /**
      * Provides a static configuration with implementation-agnostic options.
      *
      * @hide
@@ -269,7 +287,7 @@
 
         if (!mEndOfAudioVideoSignal.get()) {
             postListener.onError(
-                    VideoCaptureError.RECORDING_IN_PROGRESS, "It is still in video recording!",
+                    ERROR_RECORDING_IN_PROGRESS, "It is still in video recording!",
                     null);
             return;
         }
@@ -278,7 +296,7 @@
             // audioRecord start
             mAudioRecorder.startRecording();
         } catch (IllegalStateException e) {
-            postListener.onError(VideoCaptureError.ENCODER_ERROR, "AudioRecorder start fail", e);
+            postListener.onError(ERROR_ENCODER, "AudioRecorder start fail", e);
             return;
         }
 
@@ -294,7 +312,7 @@
 
         } catch (IllegalStateException e) {
             setupEncoder(cameraId, resolution);
-            postListener.onError(VideoCaptureError.ENCODER_ERROR, "Audio/Video encoder start fail",
+            postListener.onError(ERROR_ENCODER, "Audio/Video encoder start fail",
                     e);
             return;
         }
@@ -319,7 +337,7 @@
             }
         } catch (IOException e) {
             setupEncoder(cameraId, resolution);
-            postListener.onError(VideoCaptureError.MUXER_ERROR, "MediaMuxer creation failed!", e);
+            postListener.onError(ERROR_MUXER, "MediaMuxer creation failed!", e);
             return;
         }
 
@@ -607,7 +625,7 @@
                 case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
                     if (mMuxerStarted) {
                         videoSavedCallback.onError(
-                                VideoCaptureError.ENCODER_ERROR,
+                                ERROR_ENCODER,
                                 "Unexpected change in video encoding format.",
                                 null);
                         errorOccurred = true;
@@ -637,7 +655,7 @@
             Log.i(TAG, "videoEncoder stop");
             mVideoEncoder.stop();
         } catch (IllegalStateException e) {
-            videoSavedCallback.onError(VideoCaptureError.ENCODER_ERROR,
+            videoSavedCallback.onError(ERROR_ENCODER,
                     "Video encoder stop failed!", e);
             errorOccurred = true;
         }
@@ -654,7 +672,7 @@
                 }
             }
         } catch (IllegalStateException e) {
-            videoSavedCallback.onError(VideoCaptureError.MUXER_ERROR, "Muxer stop failed!", e);
+            videoSavedCallback.onError(ERROR_MUXER, "Muxer stop failed!", e);
             errorOccurred = true;
         }
 
@@ -728,13 +746,13 @@
             mAudioRecorder.stop();
         } catch (IllegalStateException e) {
             videoSavedCallback.onError(
-                    VideoCaptureError.ENCODER_ERROR, "Audio recorder stop failed!", e);
+                    ERROR_ENCODER, "Audio recorder stop failed!", e);
         }
 
         try {
             mAudioEncoder.stop();
         } catch (IllegalStateException e) {
-            videoSavedCallback.onError(VideoCaptureError.ENCODER_ERROR,
+            videoSavedCallback.onError(ERROR_ENCODER,
                     "Audio encoder stop failed!", e);
         }
 
@@ -853,28 +871,13 @@
      * VideoCapture.OnVideoSavedCallback#onError(int, String, Throwable)}.
      *
      * <p>See message parameter in onError callback or log for more details.
+     *
+     * @hide
      */
-    @IntDef({VideoCaptureError.UNKNOWN_ERROR, VideoCaptureError.ENCODER_ERROR,
-            VideoCaptureError.MUXER_ERROR, VideoCaptureError.RECORDING_IN_PROGRESS})
+    @IntDef({ERROR_UNKNOWN, ERROR_ENCODER, ERROR_MUXER, ERROR_RECORDING_IN_PROGRESS})
     @Retention(RetentionPolicy.SOURCE)
+    @RestrictTo(Scope.LIBRARY_GROUP)
     public @interface VideoCaptureError {
-        /**
-         * An unknown error occurred.
-         *
-         * <p>See message parameter in onError callback or log for more details.
-         */
-        int UNKNOWN_ERROR = 0;
-        /**
-         * An error occurred with encoder state, either when trying to change state or when an
-         * unexpected state change occurred.
-         */
-        int ENCODER_ERROR = 1;
-        /** An error with muxer state such as during creation or when stopping. */
-        int MUXER_ERROR = 2;
-        /**
-         * An error indicating start recording was called when video recording is still in progress.
-         */
-        int RECORDING_IN_PROGRESS = 3;
     }
 
     /** Listener containing callbacks for video file I/O events. */
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/VideoCaptureConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/VideoCaptureConfig.java
index 0a6102e..e148b70 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/VideoCaptureConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/VideoCaptureConfig.java
@@ -389,7 +389,7 @@
      */
     @RestrictTo(Scope.LIBRARY_GROUP)
     @Override
-    @LensFacing
+    @CameraSelector.LensFacing
     public int getLensFacing() {
         return retrieveOption(OPTION_LENS_FACING);
     }
@@ -473,7 +473,7 @@
      * @return The stored value, if it exists in this configuration.
      * @throws IllegalArgumentException if the option does not exist in this configuration.
      */
-    @AspectRatio
+    @AspectRatio.Ratio
     @Override
     public int getTargetAspectRatio() {
         return retrieveOption(OPTION_TARGET_ASPECT_RATIO);
@@ -957,7 +957,7 @@
         @RestrictTo(Scope.LIBRARY_GROUP)
         @Override
         @NonNull
-        public Builder setLensFacing(@LensFacing int lensFacing) {
+        public Builder setLensFacing(@CameraSelector.LensFacing int lensFacing) {
             getMutableConfig().insertOption(OPTION_LENS_FACING, lensFacing);
             return this;
         }
@@ -1033,7 +1033,7 @@
          */
         @NonNull
         @Override
-        public Builder setTargetAspectRatio(@AspectRatio int aspectRatio) {
+        public Builder setTargetAspectRatio(@AspectRatio.Ratio int aspectRatio) {
             getMutableConfig().insertOption(OPTION_TARGET_ASPECT_RATIO, aspectRatio);
             return this;
         }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/utils/CameraSelectorUtil.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/utils/CameraSelectorUtil.java
index f29c0ce..cf95b6e 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/utils/CameraSelectorUtil.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/utils/CameraSelectorUtil.java
@@ -28,7 +28,6 @@
 import androidx.camera.core.CameraIdFilterSet;
 import androidx.camera.core.CameraSelector;
 import androidx.camera.core.Config;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.MutableOptionsBundle;
 import androidx.camera.core.OptionsBundle;
 
@@ -106,7 +105,7 @@
          * @throws IllegalArgumentException if the option does not exist in this configuration.
          */
         @Override
-        @LensFacing
+        @CameraSelector.LensFacing
         public int getLensFacing() {
             return retrieveOption(OPTION_LENS_FACING);
         }
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/CameraExecutorTest.java b/camera/camera-core/src/test/java/androidx/camera/core/CameraExecutorTest.java
index ee0a118..239c9ae 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/CameraExecutorTest.java
+++ b/camera/camera-core/src/test/java/androidx/camera/core/CameraExecutorTest.java
@@ -49,10 +49,12 @@
     public void setUp() {
         mCameraExecutor = new CameraExecutor();
         mCameraFactory = new FakeCameraFactory();
-        mCameraFactory.insertCamera(LensFacing.BACK, "0",
-                () -> new FakeCamera(null, new FakeCameraInfoInternal(0, LensFacing.BACK)));
-        mCameraFactory.insertCamera(LensFacing.FRONT, "1",
-                () -> new FakeCamera(null, new FakeCameraInfoInternal(0, LensFacing.FRONT)));
+        mCameraFactory.insertCamera(CameraSelector.LENS_FACING_BACK, "0",
+                () -> new FakeCamera(null,
+                        new FakeCameraInfoInternal(0, CameraSelector.LENS_FACING_BACK)));
+        mCameraFactory.insertCamera(CameraSelector.LENS_FACING_FRONT, "1",
+                () -> new FakeCamera(null,
+                        new FakeCameraInfoInternal(0, CameraSelector.LENS_FACING_FRONT)));
     }
 
     @After
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/CameraRepositoryTest.java b/camera/camera-core/src/test/java/androidx/camera/core/CameraRepositoryTest.java
index 9dc3408..66f1108 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/CameraRepositoryTest.java
+++ b/camera/camera-core/src/test/java/androidx/camera/core/CameraRepositoryTest.java
@@ -55,10 +55,12 @@
         mCameraRepository = new CameraRepository();
         FakeCameraFactory fakeCameraFactory = new FakeCameraFactory();
 
-        fakeCameraFactory.insertCamera(LensFacing.BACK, CAMERA_ID_0,
-                () -> new FakeCamera(null, new FakeCameraInfoInternal(0, LensFacing.BACK)));
-        fakeCameraFactory.insertCamera(LensFacing.FRONT, CAMERA_ID_1,
-                () -> new FakeCamera(null, new FakeCameraInfoInternal(0, LensFacing.FRONT)));
+        fakeCameraFactory.insertCamera(CameraSelector.LENS_FACING_BACK, CAMERA_ID_0,
+                () -> new FakeCamera(null,
+                        new FakeCameraInfoInternal(0, CameraSelector.LENS_FACING_BACK)));
+        fakeCameraFactory.insertCamera(CameraSelector.LENS_FACING_FRONT, CAMERA_ID_1,
+                () -> new FakeCamera(null,
+                        new FakeCameraInfoInternal(0, CameraSelector.LENS_FACING_FRONT)));
 
         mCameraRepository.init(fakeCameraFactory);
     }
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/CameraSelectorTest.java b/camera/camera-core/src/test/java/androidx/camera/core/CameraSelectorTest.java
index dc1cfb9..f96bc39 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/CameraSelectorTest.java
+++ b/camera/camera-core/src/test/java/androidx/camera/core/CameraSelectorTest.java
@@ -69,14 +69,14 @@
         FakeCameraFactory cameraFactory = new FakeCameraFactory();
         mRearCamera = new FakeCamera(mock(CameraControlInternal.class),
                 new FakeCameraInfoInternal(0,
-                        LensFacing.BACK));
-        cameraFactory.insertCamera(LensFacing.BACK, REAR_ID, () -> mRearCamera);
-        cameraFactory.setDefaultCameraIdForLensFacing(LensFacing.BACK, REAR_ID);
+                        CameraSelector.LENS_FACING_BACK));
+        cameraFactory.insertCamera(CameraSelector.LENS_FACING_BACK, REAR_ID, () -> mRearCamera);
+        cameraFactory.setDefaultCameraIdForLensFacing(CameraSelector.LENS_FACING_BACK, REAR_ID);
         mFrontCamera = new FakeCamera(mock(CameraControlInternal.class),
                 new FakeCameraInfoInternal(0,
-                        LensFacing.FRONT));
-        cameraFactory.insertCamera(LensFacing.FRONT, FRONT_ID, () -> mFrontCamera);
-        cameraFactory.setDefaultCameraIdForLensFacing(LensFacing.FRONT, FRONT_ID);
+                        CameraSelector.LENS_FACING_FRONT));
+        cameraFactory.insertCamera(CameraSelector.LENS_FACING_FRONT, FRONT_ID, () -> mFrontCamera);
+        cameraFactory.setDefaultCameraIdForLensFacing(CameraSelector.LENS_FACING_FRONT, FRONT_ID);
         CameraXConfig.Builder appConfigBuilder =
                 new CameraXConfig.Builder()
                         .setCameraFactory(cameraFactory)
@@ -95,7 +95,7 @@
     @Test
     public void canSelectWithLensFacing() {
         CameraSelector.Builder cameraSelectorBuilder = new CameraSelector.Builder();
-        cameraSelectorBuilder.requireLensFacing(LensFacing.BACK);
+        cameraSelectorBuilder.requireLensFacing(CameraSelector.LENS_FACING_BACK);
         String result = cameraSelectorBuilder.build().select(mCameraIds);
         assertThat(result).isEqualTo(REAR_ID);
     }
@@ -103,23 +103,24 @@
     @Test(expected = IllegalArgumentException.class)
     public void exception_ifNoAvailableCamera() {
         CameraSelector.Builder cameraSelectorBuilder = new CameraSelector.Builder();
-        cameraSelectorBuilder.requireLensFacing(LensFacing.BACK).requireLensFacing(
-                LensFacing.FRONT);
+        cameraSelectorBuilder.requireLensFacing(CameraSelector.LENS_FACING_BACK).requireLensFacing(
+                CameraSelector.LENS_FACING_FRONT);
         cameraSelectorBuilder.build().select(mCameraIds);
     }
 
     @Test
     public void canGetLensFacing() {
         CameraSelector.Builder cameraSelectorBuilder = new CameraSelector.Builder();
-        cameraSelectorBuilder.requireLensFacing(LensFacing.BACK);
-        assertThat(cameraSelectorBuilder.build().getLensFacing()).isEqualTo(LensFacing.BACK);
+        cameraSelectorBuilder.requireLensFacing(CameraSelector.LENS_FACING_BACK);
+        assertThat(cameraSelectorBuilder.build().getLensFacing()).isEqualTo(
+                CameraSelector.LENS_FACING_BACK);
     }
 
     @Test(expected = IllegalStateException.class)
     public void exception_ifGetLensFacingConflicted() {
         CameraSelector.Builder cameraSelectorBuilder = new CameraSelector.Builder();
-        cameraSelectorBuilder.requireLensFacing(LensFacing.BACK).requireLensFacing(
-                LensFacing.FRONT);
+        cameraSelectorBuilder.requireLensFacing(CameraSelector.LENS_FACING_BACK).requireLensFacing(
+                CameraSelector.LENS_FACING_FRONT);
         cameraSelectorBuilder.build().getLensFacing();
     }
 
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/FocusMeteringActionTest.java b/camera/camera-core/src/test/java/androidx/camera/core/FocusMeteringActionTest.java
index efffed5..5ae62c87 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/FocusMeteringActionTest.java
+++ b/camera/camera-core/src/test/java/androidx/camera/core/FocusMeteringActionTest.java
@@ -18,7 +18,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import androidx.camera.core.FocusMeteringAction.MeteringMode;
 import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
@@ -54,7 +53,8 @@
     @Test
     public void fromPointWithAFAEAWB() {
         FocusMeteringAction action = FocusMeteringAction.Builder
-                .from(mPoint1, MeteringMode.AF | MeteringMode.AE | MeteringMode.AWB).build();
+                .from(mPoint1, FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AE
+                        | FocusMeteringAction.FLAG_AWB).build();
         assertThat(action.getMeteringPointsAf()).containsExactly(mPoint1);
         assertThat(action.getMeteringPointsAe()).containsExactly(mPoint1);
         assertThat(action.getMeteringPointsAwb()).containsExactly(mPoint1);
@@ -63,7 +63,7 @@
     @Test
     public void fromPointWithAFAE() {
         FocusMeteringAction action = FocusMeteringAction.Builder
-                .from(mPoint1, MeteringMode.AF | MeteringMode.AE).build();
+                .from(mPoint1, FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AE).build();
         assertThat(action.getMeteringPointsAf()).containsExactly(mPoint1);
         assertThat(action.getMeteringPointsAe()).containsExactly(mPoint1);
         assertThat(action.getMeteringPointsAwb()).isEmpty();
@@ -72,7 +72,7 @@
     @Test
     public void fromPointWithAFAWB() {
         FocusMeteringAction action = FocusMeteringAction.Builder
-                .from(mPoint1, MeteringMode.AF | MeteringMode.AWB).build();
+                .from(mPoint1, FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AWB).build();
         assertThat(action.getMeteringPointsAf()).containsExactly(mPoint1);
         assertThat(action.getMeteringPointsAe()).isEmpty();
         assertThat(action.getMeteringPointsAwb()).containsExactly(mPoint1);
@@ -81,7 +81,7 @@
     @Test
     public void fromPointWithAEAWB() {
         FocusMeteringAction action = FocusMeteringAction.Builder
-                .from(mPoint1, MeteringMode.AE | MeteringMode.AWB).build();
+                .from(mPoint1, FocusMeteringAction.FLAG_AE | FocusMeteringAction.FLAG_AWB).build();
         assertThat(action.getMeteringPointsAf()).isEmpty();
         assertThat(action.getMeteringPointsAe()).containsExactly(mPoint1);
         assertThat(action.getMeteringPointsAwb()).containsExactly(mPoint1);
@@ -90,7 +90,7 @@
     @Test
     public void fromPointWithAF() {
         FocusMeteringAction action = FocusMeteringAction.Builder
-                .from(mPoint1, MeteringMode.AF).build();
+                .from(mPoint1, FocusMeteringAction.FLAG_AF).build();
         assertThat(action.getMeteringPointsAf()).containsExactly(mPoint1);
         assertThat(action.getMeteringPointsAe()).isEmpty();
         assertThat(action.getMeteringPointsAwb()).isEmpty();
@@ -99,7 +99,7 @@
     @Test
     public void fromPointWithAE() {
         FocusMeteringAction action = FocusMeteringAction.Builder
-                .from(mPoint1, MeteringMode.AE).build();
+                .from(mPoint1, FocusMeteringAction.FLAG_AE).build();
         assertThat(action.getMeteringPointsAf()).isEmpty();
         assertThat(action.getMeteringPointsAe()).containsExactly(mPoint1);
         assertThat(action.getMeteringPointsAwb()).isEmpty();
@@ -108,7 +108,7 @@
     @Test
     public void fromPointWithAWB() {
         FocusMeteringAction action = FocusMeteringAction.Builder
-                .from(mPoint1, MeteringMode.AWB).build();
+                .from(mPoint1, FocusMeteringAction.FLAG_AWB).build();
         assertThat(action.getMeteringPointsAf()).isEmpty();
         assertThat(action.getMeteringPointsAe()).isEmpty();
         assertThat(action.getMeteringPointsAwb()).containsExactly(mPoint1);
@@ -128,9 +128,15 @@
     @Test
     public void multiplePointsWithSameAF_AE_AWB() {
         FocusMeteringAction action = FocusMeteringAction.Builder
-                .from(mPoint1, MeteringMode.AF | MeteringMode.AE | MeteringMode.AWB)
-                .addPoint(mPoint2, MeteringMode.AF | MeteringMode.AE | MeteringMode.AWB)
-                .addPoint(mPoint3, MeteringMode.AF | MeteringMode.AE | MeteringMode.AWB)
+                .from(mPoint1,
+                        FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AE
+                                | FocusMeteringAction.FLAG_AWB)
+                .addPoint(mPoint2,
+                        FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AE
+                                | FocusMeteringAction.FLAG_AWB)
+                .addPoint(mPoint3,
+                        FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AE
+                                | FocusMeteringAction.FLAG_AWB)
                 .build();
         assertThat(action.getMeteringPointsAf()).containsExactly(mPoint1, mPoint2, mPoint3);
         assertThat(action.getMeteringPointsAe()).containsExactly(mPoint1, mPoint2, mPoint3);
@@ -140,9 +146,9 @@
     @Test
     public void multiplePointsWithSameAF_AE() {
         FocusMeteringAction action = FocusMeteringAction.Builder
-                .from(mPoint1, MeteringMode.AF | MeteringMode.AE)
-                .addPoint(mPoint2, MeteringMode.AF | MeteringMode.AE)
-                .addPoint(mPoint3, MeteringMode.AF | MeteringMode.AE)
+                .from(mPoint1, FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AE)
+                .addPoint(mPoint2, FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AE)
+                .addPoint(mPoint3, FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AE)
                 .build();
         assertThat(action.getMeteringPointsAf()).containsExactly(mPoint1, mPoint2, mPoint3);
         assertThat(action.getMeteringPointsAe()).containsExactly(mPoint1, mPoint2, mPoint3);
@@ -152,9 +158,9 @@
     @Test
     public void multiplePointsWithSameAE_AWB() {
         FocusMeteringAction action = FocusMeteringAction.Builder
-                .from(mPoint1, MeteringMode.AE | MeteringMode.AWB)
-                .addPoint(mPoint2, MeteringMode.AE | MeteringMode.AWB)
-                .addPoint(mPoint3, MeteringMode.AE | MeteringMode.AWB)
+                .from(mPoint1, FocusMeteringAction.FLAG_AE | FocusMeteringAction.FLAG_AWB)
+                .addPoint(mPoint2, FocusMeteringAction.FLAG_AE | FocusMeteringAction.FLAG_AWB)
+                .addPoint(mPoint3, FocusMeteringAction.FLAG_AE | FocusMeteringAction.FLAG_AWB)
                 .build();
         assertThat(action.getMeteringPointsAf()).isEmpty();
         assertThat(action.getMeteringPointsAe()).containsExactly(mPoint1, mPoint2, mPoint3);
@@ -164,9 +170,9 @@
     @Test
     public void multiplePointsWithSameAF_AWB() {
         FocusMeteringAction action = FocusMeteringAction.Builder
-                .from(mPoint1, MeteringMode.AF | MeteringMode.AWB)
-                .addPoint(mPoint2, MeteringMode.AF | MeteringMode.AWB)
-                .addPoint(mPoint3, MeteringMode.AF | MeteringMode.AWB)
+                .from(mPoint1, FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AWB)
+                .addPoint(mPoint2, FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AWB)
+                .addPoint(mPoint3, FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AWB)
                 .build();
         assertThat(action.getMeteringPointsAf()).containsExactly(mPoint1, mPoint2, mPoint3);
         assertThat(action.getMeteringPointsAe()).isEmpty();
@@ -175,9 +181,10 @@
 
     @Test
     public void multiplePointsWithSameAWBOnly() {
-        FocusMeteringAction action = FocusMeteringAction.Builder.from(mPoint1, MeteringMode.AWB)
-                .addPoint(mPoint2, MeteringMode.AWB)
-                .addPoint(mPoint3, MeteringMode.AWB)
+        FocusMeteringAction action = FocusMeteringAction.Builder.from(mPoint1,
+                FocusMeteringAction.FLAG_AWB)
+                .addPoint(mPoint2, FocusMeteringAction.FLAG_AWB)
+                .addPoint(mPoint3, FocusMeteringAction.FLAG_AWB)
                 .build();
         assertThat(action.getMeteringPointsAf()).isEmpty();
         assertThat(action.getMeteringPointsAe()).isEmpty();
@@ -187,9 +194,9 @@
     @Test
     public void multiplePointsWithSameAEOnly() {
         FocusMeteringAction action = FocusMeteringAction.Builder.from(mPoint1,
-                MeteringMode.AE)
-                .addPoint(mPoint2, MeteringMode.AE)
-                .addPoint(mPoint3, MeteringMode.AE)
+                FocusMeteringAction.FLAG_AE)
+                .addPoint(mPoint2, FocusMeteringAction.FLAG_AE)
+                .addPoint(mPoint3, FocusMeteringAction.FLAG_AE)
                 .build();
         assertThat(action.getMeteringPointsAf()).isEmpty();
         assertThat(action.getMeteringPointsAe()).containsExactly(mPoint1, mPoint2, mPoint3);
@@ -199,9 +206,9 @@
     @Test
     public void multiplePointsWithSameAFOnly() {
         FocusMeteringAction action = FocusMeteringAction.Builder.from(mPoint1,
-                MeteringMode.AF)
-                .addPoint(mPoint2, MeteringMode.AF)
-                .addPoint(mPoint3, MeteringMode.AF)
+                FocusMeteringAction.FLAG_AF)
+                .addPoint(mPoint2, FocusMeteringAction.FLAG_AF)
+                .addPoint(mPoint3, FocusMeteringAction.FLAG_AF)
                 .build();
         assertThat(action.getMeteringPointsAf()).containsExactly(mPoint1, mPoint2, mPoint3);
         assertThat(action.getMeteringPointsAe()).isEmpty();
@@ -211,9 +218,9 @@
     @Test
     public void multiplePointsWithAFOnly_AEOnly_AWBOnly() {
         FocusMeteringAction action = FocusMeteringAction.Builder.from(mPoint1,
-                MeteringMode.AF)
-                .addPoint(mPoint2, MeteringMode.AE)
-                .addPoint(mPoint3, MeteringMode.AWB)
+                FocusMeteringAction.FLAG_AF)
+                .addPoint(mPoint2, FocusMeteringAction.FLAG_AE)
+                .addPoint(mPoint3, FocusMeteringAction.FLAG_AWB)
                 .build();
         assertThat(action.getMeteringPointsAf()).containsExactly(mPoint1);
         assertThat(action.getMeteringPointsAe()).containsExactly(mPoint2);
@@ -223,9 +230,9 @@
     @Test
     public void multiplePointsWithAFAE_AEAWB_AFAWB() {
         FocusMeteringAction action = FocusMeteringAction.Builder.from(mPoint1,
-                MeteringMode.AF | MeteringMode.AE)
-                .addPoint(mPoint2, MeteringMode.AE | MeteringMode.AWB)
-                .addPoint(mPoint3, MeteringMode.AF | MeteringMode.AWB)
+                FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AE)
+                .addPoint(mPoint2, FocusMeteringAction.FLAG_AE | FocusMeteringAction.FLAG_AWB)
+                .addPoint(mPoint3, FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AWB)
                 .build();
         assertThat(action.getMeteringPointsAf()).containsExactly(mPoint1, mPoint3);
         assertThat(action.getMeteringPointsAe()).containsExactly(mPoint2, mPoint1);
@@ -235,9 +242,10 @@
     @Test
     public void multiplePointsWithAFAEAWB_AEAWB_AFOnly() {
         FocusMeteringAction action = FocusMeteringAction.Builder.from(mPoint1,
-                MeteringMode.AF | MeteringMode.AE | MeteringMode.AWB)
-                .addPoint(mPoint2, MeteringMode.AE | MeteringMode.AWB)
-                .addPoint(mPoint3, MeteringMode.AF)
+                FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AE
+                        | FocusMeteringAction.FLAG_AWB)
+                .addPoint(mPoint2, FocusMeteringAction.FLAG_AE | FocusMeteringAction.FLAG_AWB)
+                .addPoint(mPoint3, FocusMeteringAction.FLAG_AF)
                 .build();
         assertThat(action.getMeteringPointsAf()).containsExactly(mPoint1, mPoint3);
         assertThat(action.getMeteringPointsAe()).containsExactly(mPoint1, mPoint2);
@@ -247,9 +255,11 @@
     @Test
     public void multiplePointsWithAEOnly_AFAWAEB_AEOnly() {
         FocusMeteringAction action = FocusMeteringAction.Builder.from(mPoint1,
-                MeteringMode.AE)
-                .addPoint(mPoint2, MeteringMode.AF | MeteringMode.AE | MeteringMode.AWB)
-                .addPoint(mPoint3, MeteringMode.AE)
+                FocusMeteringAction.FLAG_AE)
+                .addPoint(mPoint2,
+                        FocusMeteringAction.FLAG_AF | FocusMeteringAction.FLAG_AE
+                                | FocusMeteringAction.FLAG_AWB)
+                .addPoint(mPoint3, FocusMeteringAction.FLAG_AE)
                 .build();
         assertThat(action.getMeteringPointsAf()).containsExactly(mPoint2);
         assertThat(action.getMeteringPointsAe()).containsExactly(mPoint1, mPoint2, mPoint3);
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java b/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java
index 3b27c26c..5ee4fddb 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java
+++ b/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java
@@ -110,7 +110,7 @@
     @Test
     public void nonBlockingAnalyzerClosed_imageNotAnalyzed() {
         // Arrange.
-        setUpImageAnalysisWithStrategy(ImageAnalysis.BackpressureStrategy.KEEP_ONLY_LATEST);
+        setUpImageAnalysisWithStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST);
 
         // Act.
         // Receive images from camera feed.
@@ -138,7 +138,7 @@
     @Test
     public void blockingAnalyzerClosed_imageNotAnalyzed() {
         // Arrange.
-        setUpImageAnalysisWithStrategy(ImageAnalysis.BackpressureStrategy.BLOCK_PRODUCER);
+        setUpImageAnalysisWithStrategy(ImageAnalysis.STRATEGY_BLOCK_PRODUCER);
 
         // Act.
         // Receive images from camera feed.
@@ -158,7 +158,7 @@
     @Test
     public void keepOnlyLatestStrategy_doesNotBlock() {
         // Arrange.
-        setUpImageAnalysisWithStrategy(ImageAnalysis.BackpressureStrategy.KEEP_ONLY_LATEST);
+        setUpImageAnalysisWithStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST);
 
         // Act.
         // Receive images from camera feed.
@@ -192,7 +192,7 @@
     @Test
     public void blockProducerStrategy_doesNotDropFrames() {
         // Arrange.
-        setUpImageAnalysisWithStrategy(ImageAnalysis.BackpressureStrategy.BLOCK_PRODUCER);
+        setUpImageAnalysisWithStrategy(ImageAnalysis.STRATEGY_BLOCK_PRODUCER);
 
         // Act.
         // Receive images from camera feed.
@@ -229,7 +229,8 @@
 
         FakeLifecycleOwner lifecycleOwner = new FakeLifecycleOwner();
         CameraSelector cameraSelector =
-                new CameraSelector.Builder().requireLensFacing(LensFacing.BACK).build();
+                new CameraSelector.Builder().requireLensFacing(
+                        CameraSelector.LENS_FACING_BACK).build();
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
             CameraX.bindToLifecycle(lifecycleOwner, cameraSelector, mImageAnalysis);
             lifecycleOwner.startAndResume();
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/ShadowCameraX.java b/camera/camera-core/src/test/java/androidx/camera/core/ShadowCameraX.java
index 6a55e0d..b2d9d06 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/ShadowCameraX.java
+++ b/camera/camera-core/src/test/java/androidx/camera/core/ShadowCameraX.java
@@ -52,7 +52,7 @@
 
         @Override
         public Integer getLensFacing() {
-            return LensFacing.BACK;
+            return CameraSelector.LENS_FACING_BACK;
         }
 
         @Override
@@ -72,7 +72,7 @@
 
         @NonNull
         @Override
-        @TorchState
+        @TorchState.State
         public LiveData<Integer> getTorchState() {
             return mTorchState;
         }
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/impl/utils/CameraSelectorUtilTest.java b/camera/camera-core/src/test/java/androidx/camera/core/impl/utils/CameraSelectorUtilTest.java
index 8e9ca09..8702d5a 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/impl/utils/CameraSelectorUtilTest.java
+++ b/camera/camera-core/src/test/java/androidx/camera/core/impl/utils/CameraSelectorUtilTest.java
@@ -32,7 +32,6 @@
 import androidx.camera.core.CameraSelector;
 import androidx.camera.core.CameraX;
 import androidx.camera.core.CameraXConfig;
-import androidx.camera.core.LensFacing;
 import androidx.camera.testing.fakes.FakeAppConfig;
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.filters.SmallTest;
@@ -72,21 +71,23 @@
     @Test
     public void convertedCameraDeviceConfig_hasFrontLensFacing() {
         CameraSelector cameraSelector =
-                new CameraSelector.Builder().requireLensFacing(LensFacing.FRONT).build();
+                new CameraSelector.Builder().requireLensFacing(
+                        CameraSelector.LENS_FACING_FRONT).build();
         CameraDeviceConfig convertedConfig =
                 CameraSelectorUtil.toCameraDeviceConfig(cameraSelector);
 
-        assertThat(convertedConfig.getLensFacing()).isEqualTo(LensFacing.FRONT);
+        assertThat(convertedConfig.getLensFacing()).isEqualTo(CameraSelector.LENS_FACING_FRONT);
     }
 
     @Test
     public void convertedCameraDeviceConfig_hasBackLensFacing() {
         CameraSelector cameraSelector =
-                new CameraSelector.Builder().requireLensFacing(LensFacing.BACK).build();
+                new CameraSelector.Builder().requireLensFacing(
+                        CameraSelector.LENS_FACING_BACK).build();
         CameraDeviceConfig convertedConfig =
                 CameraSelectorUtil.toCameraDeviceConfig(cameraSelector);
 
-        assertThat(convertedConfig.getLensFacing()).isEqualTo(LensFacing.BACK);
+        assertThat(convertedConfig.getLensFacing()).isEqualTo(CameraSelector.LENS_FACING_BACK);
     }
 
     @Test(expected = IllegalArgumentException.class)
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionTest.java b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionTest.java
index e7cd516..ab61c36 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionTest.java
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionTest.java
@@ -50,7 +50,6 @@
 import androidx.camera.core.ImageCapture;
 import androidx.camera.core.ImageCaptureConfig;
 import androidx.camera.core.ImageProxy;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.Preview;
 import androidx.camera.core.PreviewConfig;
 import androidx.camera.core.impl.utils.executor.CameraXExecutors;
@@ -94,11 +93,11 @@
     private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
 
     private EffectMode mEffectMode;
-    @LensFacing
+    @CameraSelector.LensFacing
     private int mLensFacing;
     private FakeLifecycleOwner mLifecycleOwner;
 
-    public ExtensionTest(EffectMode effectMode, @LensFacing int lensFacing) {
+    public ExtensionTest(EffectMode effectMode, @CameraSelector.LensFacing int lensFacing) {
         mEffectMode = effectMode;
         mLensFacing = lensFacing;
     }
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionsErrorListenerTest.java b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionsErrorListenerTest.java
index b49ce89..5a588d9 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionsErrorListenerTest.java
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionsErrorListenerTest.java
@@ -28,10 +28,10 @@
 
 import androidx.annotation.NonNull;
 import androidx.camera.camera2.Camera2Config;
+import androidx.camera.core.CameraSelector;
 import androidx.camera.core.CameraX;
 import androidx.camera.core.CameraXConfig;
 import androidx.camera.core.ImageCapture;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.Preview;
 import androidx.camera.core.UseCase;
 import androidx.camera.extensions.ExtensionsErrorListener.ExtensionsErrorCode;
@@ -77,7 +77,7 @@
     }
 
     private EffectMode mEffectMode;
-    @LensFacing
+    @CameraSelector.LensFacing
     private int mLensFacing;
     private CountDownLatch mLatch;
 
@@ -90,7 +90,8 @@
         }
     };
 
-    public ExtensionsErrorListenerTest(EffectMode effectMode, @LensFacing int lensFacing) {
+    public ExtensionsErrorListenerTest(EffectMode effectMode,
+            @CameraSelector.LensFacing int lensFacing) {
         mEffectMode = effectMode;
         mLensFacing = lensFacing;
     }
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderTest.java b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderTest.java
index c552813..8d5db5d 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderTest.java
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderTest.java
@@ -46,7 +46,6 @@
 import androidx.camera.core.CameraX;
 import androidx.camera.core.CaptureProcessor;
 import androidx.camera.core.ImageCapture;
-import androidx.camera.core.LensFacing;
 import androidx.camera.extensions.ExtensionsManager.EffectMode;
 import androidx.camera.extensions.impl.CaptureStageImpl;
 import androidx.camera.extensions.impl.ImageCaptureExtenderImpl;
@@ -119,7 +118,7 @@
 
         ImageCapture useCase = builder.build();
 
-        @LensFacing int lensFacing = CameraX.getDefaultLensFacing();
+        @CameraSelector.LensFacing int lensFacing = CameraX.getDefaultLensFacing();
         CameraSelector cameraSelector = new CameraSelector.Builder()
                 .requireLensFacing(lensFacing).build();
         mInstrumentation.runOnMainSync(new Runnable() {
@@ -176,7 +175,7 @@
 
         ImageCapture useCase = configBuilder.build();
 
-        @LensFacing int lensFacing = CameraX.getDefaultLensFacing();
+        @CameraSelector.LensFacing int lensFacing = CameraX.getDefaultLensFacing();
         CameraSelector cameraSelector = new CameraSelector.Builder()
                 .requireLensFacing(lensFacing).build();
         mInstrumentation.runOnMainSync(new Runnable() {
@@ -224,7 +223,7 @@
         // getSupportedResolutions supported since version 1.1
         assumeTrue(ExtensionVersion.getRuntimeVersion().compareTo(Version.VERSION_1_1) >= 0);
 
-        @LensFacing int lensFacing = CameraX.getDefaultLensFacing();
+        @CameraSelector.LensFacing int lensFacing = CameraX.getDefaultLensFacing();
         ImageCapture.Builder builder = new ImageCapture.Builder();
 
         ImageCaptureExtenderImpl mockImageCaptureExtenderImpl = mock(
@@ -265,7 +264,7 @@
     }
 
     private List<Pair<Integer, Size[]>> generateImageCaptureSupportedResolutions(
-            @LensFacing int lensFacing)
+            @CameraSelector.LensFacing int lensFacing)
             throws CameraInfoUnavailableException {
         List<Pair<Integer, Size[]>> formatResolutionsPairList = new ArrayList<>();
         String cameraId =
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderValidationTest.java b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderValidationTest.java
index 3fac963..f5aa758 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderValidationTest.java
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderValidationTest.java
@@ -24,8 +24,8 @@
 
 import androidx.camera.camera2.Camera2Config;
 import androidx.camera.core.CameraInfoUnavailableException;
+import androidx.camera.core.CameraSelector;
 import androidx.camera.core.CameraX;
-import androidx.camera.core.LensFacing;
 import androidx.camera.extensions.impl.ImageCaptureExtenderImpl;
 import androidx.camera.extensions.util.ExtensionsTestUtil;
 import androidx.camera.testing.CameraUtil;
@@ -75,7 +75,7 @@
                 ExtensionsTestUtil.getAllEffectLensFacingCombinations()) {
             ExtensionsManager.EffectMode effectMode =
                     (ExtensionsManager.EffectMode) EffectLensFacingPair[0];
-            @LensFacing int lensFacing = (int) EffectLensFacingPair[1];
+            @CameraSelector.LensFacing int lensFacing = (int) EffectLensFacingPair[1];
 
             assumeTrue(CameraUtil.hasCameraWithLensFacing(lensFacing));
             assumeTrue(ExtensionsManager.isExtensionAvailable(effectMode, lensFacing));
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderTest.java b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderTest.java
index 731ac48..4362c36 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderTest.java
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderTest.java
@@ -48,7 +48,6 @@
 import androidx.camera.core.CameraInfoUnavailableException;
 import androidx.camera.core.CameraSelector;
 import androidx.camera.core.CameraX;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.Preview;
 import androidx.camera.extensions.ExtensionsManager.EffectMode;
 import androidx.camera.extensions.impl.CaptureStageImpl;
@@ -108,7 +107,7 @@
     @Before
     public void setUp() throws InterruptedException, ExecutionException, TimeoutException {
         assumeTrue(CameraUtil.deviceHasCamera());
-        assumeTrue(CameraUtil.hasCameraWithLensFacing(LensFacing.BACK));
+        assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK));
 
         Context context = ApplicationProvider.getApplicationContext();
         CameraX.initialize(context, Camera2Config.defaultConfig(context));
@@ -143,7 +142,8 @@
         FakePreviewExtender fakePreviewExtender = new FakePreviewExtender(configBuilder,
                 mockPreviewExtenderImpl);
         CameraSelector cameraSelector =
-                new CameraSelector.Builder().requireLensFacing(LensFacing.BACK).build();
+                new CameraSelector.Builder().requireLensFacing(
+                        CameraSelector.LENS_FACING_BACK).build();
         fakePreviewExtender.enableExtension(cameraSelector);
 
         Preview useCase = configBuilder.build();
@@ -220,7 +220,8 @@
         FakePreviewExtender fakePreviewExtender = new FakePreviewExtender(configBuilder,
                 mockPreviewExtenderImpl);
         CameraSelector cameraSelector =
-                new CameraSelector.Builder().requireLensFacing(LensFacing.BACK).build();
+                new CameraSelector.Builder().requireLensFacing(
+                        CameraSelector.LENS_FACING_BACK).build();
         fakePreviewExtender.enableExtension(cameraSelector);
 
         Preview preview = configBuilder.build();
@@ -273,7 +274,8 @@
         FakePreviewExtender fakePreviewExtender = new FakePreviewExtender(configBuilder,
                 mockPreviewExtenderImpl);
         CameraSelector cameraSelector =
-                new CameraSelector.Builder().requireLensFacing(LensFacing.BACK).build();
+                new CameraSelector.Builder().requireLensFacing(
+                        CameraSelector.LENS_FACING_BACK).build();
         fakePreviewExtender.enableExtension(cameraSelector);
         Preview preview = configBuilder.build();
         mInstrumentation.runOnMainSync(new Runnable() {
@@ -299,7 +301,7 @@
         // getSupportedResolutions supported since version 1.1
         assumeTrue(ExtensionVersion.getRuntimeVersion().compareTo(Version.VERSION_1_1) >= 0);
 
-        @LensFacing int lensFacing = CameraX.getDefaultLensFacing();
+        @CameraSelector.LensFacing int lensFacing = CameraX.getDefaultLensFacing();
         Preview.Builder configBuilder = new Preview.Builder();
 
         PreviewExtenderImpl mockPreviewExtenderImpl = mock(PreviewExtenderImpl.class);
@@ -342,7 +344,7 @@
     }
 
     private List<Pair<Integer, Size[]>> generatePreviewSupportedResolutions(
-            @LensFacing int lensFacing) throws CameraInfoUnavailableException {
+            @CameraSelector.LensFacing int lensFacing) throws CameraInfoUnavailableException {
         List<Pair<Integer, Size[]>> formatResolutionsPairList = new ArrayList<>();
         String cameraId =
                 androidx.camera.extensions.CameraUtil.getCameraIdSetWithLensFacing(
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderValidationTest.java b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderValidationTest.java
index ccf774d..1fb4d38 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderValidationTest.java
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderValidationTest.java
@@ -24,8 +24,8 @@
 
 import androidx.camera.camera2.Camera2Config;
 import androidx.camera.core.CameraInfoUnavailableException;
+import androidx.camera.core.CameraSelector;
 import androidx.camera.core.CameraX;
-import androidx.camera.core.LensFacing;
 import androidx.camera.extensions.impl.PreviewExtenderImpl;
 import androidx.camera.extensions.util.ExtensionsTestUtil;
 import androidx.camera.testing.CameraUtil;
@@ -75,7 +75,7 @@
                 ExtensionsTestUtil.getAllEffectLensFacingCombinations()) {
             ExtensionsManager.EffectMode effectMode =
                     (ExtensionsManager.EffectMode) EffectLensFacingPair[0];
-            @LensFacing int lensFacing = (int) EffectLensFacingPair[1];
+            @CameraSelector.LensFacing int lensFacing = (int) EffectLensFacingPair[1];
 
             assumeTrue(CameraUtil.hasCameraWithLensFacing(lensFacing));
             assumeTrue(ExtensionsManager.isExtensionAvailable(effectMode, lensFacing));
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/util/ExtensionsTestUtil.java b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/util/ExtensionsTestUtil.java
index 1c8d39a..41ed1c2 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/util/ExtensionsTestUtil.java
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/util/ExtensionsTestUtil.java
@@ -29,7 +29,6 @@
 import androidx.camera.core.CameraX;
 import androidx.camera.core.ImageCapture;
 import androidx.camera.core.ImageCaptureConfig;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.Preview;
 import androidx.camera.core.PreviewConfig;
 import androidx.camera.core.impl.utils.CameraSelectorUtil;
@@ -74,16 +73,16 @@
     @NonNull
     public static Collection<Object[]> getAllEffectLensFacingCombinations() {
         return Arrays.asList(new Object[][]{
-                {EffectMode.BOKEH, LensFacing.FRONT},
-                {EffectMode.BOKEH, LensFacing.BACK},
-                {EffectMode.HDR, LensFacing.FRONT},
-                {EffectMode.HDR, LensFacing.BACK},
-                {EffectMode.BEAUTY, LensFacing.FRONT},
-                {EffectMode.BEAUTY, LensFacing.BACK},
-                {EffectMode.NIGHT, LensFacing.FRONT},
-                {EffectMode.NIGHT, LensFacing.BACK},
-                {EffectMode.AUTO, LensFacing.FRONT},
-                {EffectMode.AUTO, LensFacing.BACK}
+                {EffectMode.BOKEH, CameraSelector.LENS_FACING_FRONT},
+                {EffectMode.BOKEH, CameraSelector.LENS_FACING_BACK},
+                {EffectMode.HDR, CameraSelector.LENS_FACING_FRONT},
+                {EffectMode.HDR, CameraSelector.LENS_FACING_BACK},
+                {EffectMode.BEAUTY, CameraSelector.LENS_FACING_FRONT},
+                {EffectMode.BEAUTY, CameraSelector.LENS_FACING_BACK},
+                {EffectMode.NIGHT, CameraSelector.LENS_FACING_FRONT},
+                {EffectMode.NIGHT, CameraSelector.LENS_FACING_BACK},
+                {EffectMode.AUTO, CameraSelector.LENS_FACING_FRONT},
+                {EffectMode.AUTO, CameraSelector.LENS_FACING_BACK}
         });
     }
 
@@ -110,7 +109,7 @@
 
     /**
      * Creates an {@link ImageCapture.Builder} object for specific {@link EffectMode} and
-     * {@link LensFacing}.
+     * {@link CameraSelector.LensFacing}.
      *
      * @param effectMode The effect mode for the created object.
      * @param lensFacing The lens facing for the created object.
@@ -118,7 +117,7 @@
      */
     @NonNull
     public static ImageCapture.Builder createImageCaptureConfigBuilderWithEffect(
-            @NonNull EffectMode effectMode, @LensFacing int lensFacing) {
+            @NonNull EffectMode effectMode, @CameraSelector.LensFacing int lensFacing) {
         ImageCapture.Builder builder = new ImageCapture.Builder();
         CameraSelector selector =
                 new CameraSelector.Builder().requireLensFacing(lensFacing).build();
@@ -154,7 +153,7 @@
 
     /**
      * Creates a {@link Preview.Builder} object for specific {@link EffectMode} and
-     * {@link LensFacing}.
+     * {@link CameraSelector.LensFacing}.
      *
      * @param effectMode The effect mode for the created object.
      * @param lensFacing The lens facing for the created object.
@@ -162,7 +161,7 @@
      */
     @NonNull
     public static Preview.Builder createPreviewBuilderWithEffect(@NonNull EffectMode effectMode,
-            @LensFacing int lensFacing) {
+            @CameraSelector.LensFacing int lensFacing) {
         Preview.Builder builder = new Preview.Builder();
         CameraSelector selector =
                 new CameraSelector.Builder().requireLensFacing(lensFacing).build();
@@ -198,7 +197,7 @@
 
     /**
      * Creates an {@link ImageCaptureConfig} object for specific {@link EffectMode} and
-     * {@link LensFacing}.
+     * {@link CameraSelector.LensFacing}.
      *
      * @param effectMode The effect mode for the created object.
      * @param lensFacing The lens facing for the created object.
@@ -206,7 +205,7 @@
      */
     @NonNull
     public static ImageCaptureConfig createImageCaptureConfigWithEffect(
-            @NonNull EffectMode effectMode, @LensFacing int lensFacing) {
+            @NonNull EffectMode effectMode, @CameraSelector.LensFacing int lensFacing) {
         ImageCapture.Builder imageCaptureConfigBuilder =
                 createImageCaptureConfigBuilderWithEffect(effectMode, lensFacing);
         return imageCaptureConfigBuilder.getUseCaseConfig();
@@ -214,7 +213,7 @@
 
     /**
      * Creates a {@link PreviewConfig} object for specific {@link EffectMode} and
-     * {@link LensFacing}.
+     * {@link CameraSelector.LensFacing}.
      *
      * @param effectMode The effect mode for the created object.
      * @param lensFacing The lens facing for the created object.
@@ -222,7 +221,7 @@
      */
     @NonNull
     public static PreviewConfig createPreviewConfigWithEffect(@NonNull EffectMode effectMode,
-            @LensFacing int lensFacing) {
+            @CameraSelector.LensFacing int lensFacing) {
         Preview.Builder previewBuilder =
                 createPreviewBuilderWithEffect(effectMode, lensFacing);
         return previewBuilder.getUseCaseConfig();
@@ -230,7 +229,7 @@
 
     /**
      * Creates an {@link ImageCapture} object for specific {@link EffectMode} and
-     * {@link LensFacing}.
+     * {@link CameraSelector.LensFacing}.
      *
      * @param effectMode The effect mode for the created object.
      * @param lensFacing The lens facing for the created object.
@@ -238,12 +237,13 @@
      */
     @NonNull
     public static ImageCapture createImageCaptureWithEffect(@NonNull EffectMode effectMode,
-            @LensFacing int lensFacing) {
+            @CameraSelector.LensFacing int lensFacing) {
         return createImageCaptureConfigBuilderWithEffect(effectMode, lensFacing).build();
     }
 
     /**
-     * Creates a {@link Preview} object for specific {@link EffectMode} and {@link LensFacing}.
+     * Creates a {@link Preview} object for specific {@link EffectMode} and
+     * {@link CameraSelector.LensFacing}.
      *
      * @param effectMode The effect mode for the created object.
      * @param lensFacing The lens facing for the created object.
@@ -251,13 +251,13 @@
      */
     @NonNull
     public static Preview createPreviewWithEffect(@NonNull EffectMode effectMode,
-            @LensFacing int lensFacing) {
+            @CameraSelector.LensFacing int lensFacing) {
         return createPreviewBuilderWithEffect(effectMode, lensFacing).build();
     }
 
     /**
      * Creates an {@link ImageCaptureExtenderImpl} object for specific {@link EffectMode} and
-     * {@link LensFacing}.
+     * {@link CameraSelector.LensFacing}.
      *
      * @param effectMode The effect mode for the created object.
      * @param lensFacing The lens facing for the created object.
@@ -265,7 +265,7 @@
      */
     @NonNull
     public static ImageCaptureExtenderImpl createImageCaptureExtenderImpl(
-            @NonNull EffectMode effectMode, @LensFacing int lensFacing)
+            @NonNull EffectMode effectMode, @CameraSelector.LensFacing int lensFacing)
             throws CameraInfoUnavailableException, CameraAccessException {
         ImageCaptureExtenderImpl impl = null;
 
@@ -304,7 +304,7 @@
 
     /**
      * Creates a {@link PreviewExtenderImpl} object for specific {@link EffectMode} and
-     * {@link LensFacing}.
+     * {@link CameraSelector.LensFacing}.
      *
      * @param effectMode The effect mode for the created object.
      * @param lensFacing The lens facing for the created object.
@@ -312,7 +312,7 @@
      */
     @NonNull
     public static PreviewExtenderImpl createPreviewExtenderImpl(@NonNull EffectMode effectMode,
-            @LensFacing int lensFacing)
+            @CameraSelector.LensFacing int lensFacing)
             throws CameraInfoUnavailableException, CameraAccessException {
         PreviewExtenderImpl impl = null;
 
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsManager.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsManager.java
index 7a8e591..c4385e9 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsManager.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsManager.java
@@ -25,7 +25,6 @@
 import androidx.camera.core.CameraSelector;
 import androidx.camera.core.CameraX;
 import androidx.camera.core.ImageCapture;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.Preview;
 import androidx.camera.core.impl.utils.executor.CameraXExecutors;
 import androidx.camera.core.impl.utils.futures.Futures;
@@ -142,14 +141,15 @@
     }
 
     /**
-     * Indicates whether the camera device with the {@link LensFacing} can support the specific
+     * Indicates whether the camera device with the lensFacing can support the specific
      * extension function.
      *
      * @param effectMode The extension function to be checked.
-     * @param lensFacing The {@link LensFacing} of the camera device to be checked.
+     * @param lensFacing The lensFacing of the camera device to be checked.
      * @return True if the specific extension function is supported for the camera device.
      */
-    public static boolean isExtensionAvailable(EffectMode effectMode, @LensFacing int lensFacing) {
+    public static boolean isExtensionAvailable(EffectMode effectMode,
+            @CameraSelector.LensFacing int lensFacing) {
         boolean isImageCaptureAvailable = checkImageCaptureExtensionCapability(effectMode,
                 lensFacing);
         boolean isPreviewAvailable = checkPreviewExtensionCapability(effectMode, lensFacing);
@@ -163,16 +163,16 @@
     }
 
     /**
-     * Indicates whether the camera device with the {@link LensFacing} can support the specific
+     * Indicates whether the camera device with the lensFacing can support the specific
      * extension function for specific use case.
      *
      * @param klass      The {@link ImageCapture} or {@link Preview} class to be checked.
      * @param effectMode The extension function to be checked.
-     * @param lensFacing The {@link LensFacing} of the camera device to be checked.
+     * @param lensFacing The lensFacing of the camera device to be checked.
      * @return True if the specific extension function is supported for the camera device.
      */
     public static boolean isExtensionAvailable(
-            Class<?> klass, EffectMode effectMode, @LensFacing int lensFacing) {
+            Class<?> klass, EffectMode effectMode, @CameraSelector.LensFacing int lensFacing) {
         boolean isAvailable = false;
 
         if (klass == ImageCapture.class) {
@@ -185,7 +185,7 @@
     }
 
     private static boolean checkImageCaptureExtensionCapability(EffectMode effectMode,
-            @LensFacing int lensFacing) {
+            @CameraSelector.LensFacing int lensFacing) {
         ImageCapture.Builder builder = new ImageCapture.Builder();
         CameraSelector selector =
                 new CameraSelector.Builder().requireLensFacing(lensFacing).build();
@@ -243,7 +243,7 @@
     }
 
     private static boolean checkPreviewExtensionCapability(EffectMode effectMode,
-            @LensFacing int lensFacing) {
+            @CameraSelector.LensFacing int lensFacing) {
         Preview.Builder builder = new Preview.Builder();
         CameraSelector cameraSelector =
                 new CameraSelector.Builder().requireLensFacing(lensFacing).build();
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/CameraUtil.java b/camera/camera-testing/src/main/java/androidx/camera/testing/CameraUtil.java
index 6df63d8..7ca9c78 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/CameraUtil.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/CameraUtil.java
@@ -34,7 +34,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresPermission;
 import androidx.camera.core.CameraInternal;
-import androidx.camera.core.LensFacing;
+import androidx.camera.core.CameraSelector;
 import androidx.camera.core.UseCase;
 import androidx.concurrent.futures.CallbackToFutureAdapter;
 import androidx.core.util.Preconditions;
@@ -293,7 +293,7 @@
      * @return True if the device supports the lensFacing.
      * @throws IllegalStateException if the CAMERA permission is not currently granted.
      */
-    public static boolean hasCameraWithLensFacing(@LensFacing int lensFacing) {
+    public static boolean hasCameraWithLensFacing(@CameraSelector.LensFacing int lensFacing) {
         @SupportedLensFacingInt
         int lensFacingInteger = getLensFacingIntFromEnum(lensFacing);
         for (String cameraId : getCameraIdListOrThrow()) {
@@ -307,13 +307,13 @@
     }
 
     /**
-     * Check if the device has a flash unit with the specified {@link LensFacing}.
+     * Check if the device has a flash unit with the specified lensFacing.
      *
      * @param lensFacing The desired camera lensFacing.
      * @return True if the device has flash unit with the specified LensFacing.
      * @throws IllegalStateException if the CAMERA permission is not currently granted.
      */
-    public static boolean hasFlashUnitWithLensFacing(@LensFacing int lensFacing) {
+    public static boolean hasFlashUnitWithLensFacing(@CameraSelector.LensFacing int lensFacing) {
         @SupportedLensFacingInt
         int lensFacingInteger = getLensFacingIntFromEnum(lensFacing);
         for (String cameraId : getCameraIdListOrThrow()) {
@@ -341,20 +341,19 @@
 
 
     /**
-     * Converts a lens facing direction from a {@link CameraMetadata} integer to a
-     * {@link LensFacing}.
+     * Converts a lens facing direction from a {@link CameraMetadata} integer to a lensFacing.
      *
      * @param lensFacingInteger The lens facing integer, as defined in {@link CameraMetadata}.
      * @return The lens facing enum.
      */
-    @LensFacing
+    @CameraSelector.LensFacing
     public static int getLensFacingEnumFromInt(
             @SupportedLensFacingInt int lensFacingInteger) {
         switch (lensFacingInteger) {
             case CameraMetadata.LENS_FACING_BACK:
-                return LensFacing.BACK;
+                return CameraSelector.LENS_FACING_BACK;
             case CameraMetadata.LENS_FACING_FRONT:
-                return LensFacing.FRONT;
+                return CameraSelector.LENS_FACING_FRONT;
             default:
                 throw new IllegalArgumentException(
                         "Unsupported lens facing integer: " + lensFacingInteger);
@@ -362,18 +361,17 @@
     }
 
     /**
-     * Converts a lens facing direction from a {@link LensFacing} to a {@link CameraMetadata}
-     * integer.
+     * Converts a lens facing direction from a lensFacing to a {@link CameraMetadata} integer.
      *
-     * @param lensFacing The lens facing enum, as defined in {@link LensFacing}.
+     * @param lensFacing The lens facing enum, as defined in {@link CameraSelector}.
      * @return The lens facing integer.
      */
     @SupportedLensFacingInt
-    private static int getLensFacingIntFromEnum(@LensFacing int lensFacing) {
+    private static int getLensFacingIntFromEnum(@CameraSelector.LensFacing int lensFacing) {
         switch (lensFacing) {
-            case LensFacing.BACK:
+            case CameraSelector.LENS_FACING_BACK:
                 return CameraMetadata.LENS_FACING_BACK;
-            case LensFacing.FRONT:
+            case CameraSelector.LENS_FACING_FRONT:
                 return CameraMetadata.LENS_FACING_FRONT;
             default:
                 throw new IllegalArgumentException("Unsupported lens facing enum: " + lensFacing);
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/activity/CameraXTestActivity.java b/camera/camera-testing/src/main/java/androidx/camera/testing/activity/CameraXTestActivity.java
index 689f653..94fa4bf 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/activity/CameraXTestActivity.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/activity/CameraXTestActivity.java
@@ -33,7 +33,6 @@
 import androidx.camera.core.CameraInfoUnavailableException;
 import androidx.camera.core.CameraSelector;
 import androidx.camera.core.CameraX;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.Preview;
 import androidx.camera.core.PreviewConfig;
 import androidx.camera.core.impl.utils.CameraSelectorUtil;
@@ -51,8 +50,8 @@
     private Preview mPreview;
     @Nullable
     public String mCameraId = null;
-    @LensFacing
-    public int mLensFacing = LensFacing.BACK;
+    @CameraSelector.LensFacing
+    public int mLensFacing = CameraSelector.LENS_FACING_BACK;
 
     @VisibleForTesting
     public final CountingIdlingResource mPreviewReady = new CountingIdlingResource("PreviewReady");
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeAppConfig.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeAppConfig.java
index e35c1fd..14a504e 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeAppConfig.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeAppConfig.java
@@ -18,9 +18,9 @@
 
 import androidx.annotation.NonNull;
 import androidx.camera.core.CameraDeviceSurfaceManager;
+import androidx.camera.core.CameraSelector;
 import androidx.camera.core.CameraXConfig;
 import androidx.camera.core.ExtendableUseCaseConfigFactory;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.UseCaseConfigFactory;
 
 /**
@@ -39,10 +39,12 @@
     @NonNull
     public static CameraXConfig create() {
         FakeCameraFactory cameraFactory = new FakeCameraFactory();
-        cameraFactory.insertCamera(LensFacing.BACK, CAMERA_ID_0,
-                () -> new FakeCamera(null, new FakeCameraInfoInternal(0, LensFacing.BACK)));
-        cameraFactory.insertCamera(LensFacing.FRONT, CAMERA_ID_1,
-                () -> new FakeCamera(null, new FakeCameraInfoInternal(0, LensFacing.FRONT)));
+        cameraFactory.insertCamera(CameraSelector.LENS_FACING_BACK, CAMERA_ID_0,
+                () -> new FakeCamera(null,
+                        new FakeCameraInfoInternal(0, CameraSelector.LENS_FACING_BACK)));
+        cameraFactory.insertCamera(CameraSelector.LENS_FACING_FRONT, CAMERA_ID_1,
+                () -> new FakeCamera(null,
+                        new FakeCameraInfoInternal(0, CameraSelector.LENS_FACING_FRONT)));
 
         CameraDeviceSurfaceManager surfaceManager = new FakeCameraDeviceSurfaceManager();
         UseCaseConfigFactory defaultConfigFactory = new ExtendableUseCaseConfigFactory();
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraControl.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraControl.java
index 19fd5ab..754813e 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraControl.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraControl.java
@@ -16,6 +16,8 @@
 
 package androidx.camera.testing.fakes;
 
+import static androidx.camera.core.ImageCapture.FLASH_MODE_OFF;
+
 import android.graphics.Rect;
 import android.util.Log;
 
@@ -26,9 +28,9 @@
 import androidx.camera.core.CameraCaptureResult;
 import androidx.camera.core.CameraControlInternal;
 import androidx.camera.core.CaptureConfig;
-import androidx.camera.core.FlashMode;
 import androidx.camera.core.FocusMeteringAction;
 import androidx.camera.core.FocusMeteringResult;
+import androidx.camera.core.ImageCapture;
 import androidx.camera.core.SessionConfig;
 import androidx.camera.core.impl.utils.futures.Futures;
 
@@ -46,8 +48,8 @@
     private final ControlUpdateCallback mControlUpdateCallback;
     private final SessionConfig.Builder mSessionConfigBuilder = new SessionConfig.Builder();
     private boolean mIsTorchOn = false;
-    @FlashMode
-    private int mFlashMode = FlashMode.OFF;
+    @ImageCapture.FlashMode
+    private int mFlashMode = FLASH_MODE_OFF;
     private ArrayList<CaptureConfig> mSubmittedCaptureRequests = new ArrayList<>();
     private OnNewCaptureRequestListener mOnNewCaptureRequestListener;
 
@@ -96,14 +98,14 @@
         Log.d(TAG, "setCropRegion(" + crop + ")");
     }
 
-    @FlashMode
+    @ImageCapture.FlashMode
     @Override
     public int getFlashMode() {
         return mFlashMode;
     }
 
     @Override
-    public void setFlashMode(@FlashMode int flashMode) {
+    public void setFlashMode(@ImageCapture.FlashMode int flashMode) {
         mFlashMode = flashMode;
         Log.d(TAG, "setFlashMode(" + mFlashMode + ")");
     }
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraFactory.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraFactory.java
index 13b689c..06923b1 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraFactory.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraFactory.java
@@ -22,7 +22,7 @@
 import androidx.annotation.RestrictTo.Scope;
 import androidx.camera.core.CameraFactory;
 import androidx.camera.core.CameraInternal;
-import androidx.camera.core.LensFacing;
+import androidx.camera.core.CameraSelector;
 import androidx.camera.core.LensFacingCameraIdFilter;
 import androidx.camera.core.LensFacingConverter;
 import androidx.core.util.Pair;
@@ -82,7 +82,7 @@
      * @param cameraId       Identifier to use for the camera.
      * @param cameraInternal Callable used to provide the Camera implementation.
      */
-    public void insertCamera(@LensFacing int lensFacing, @NonNull String cameraId,
+    public void insertCamera(@CameraSelector.LensFacing int lensFacing, @NonNull String cameraId,
             @NonNull Callable<CameraInternal> cameraInternal) {
         // Invalidate caches
         mCachedCameraIds = null;
@@ -97,15 +97,15 @@
      * <p>This is a convenience method for calling
      * {@link #insertCamera(int, String, Callable)}
      * followed by {@link #setDefaultCameraIdForLensFacing(int, String)} with
-     * {@link LensFacing#FRONT} for all lens facing arguments.
+     * {@link CameraSelector#LENS_FACING_FRONT} for all lens facing arguments.
      *
      * @param cameraId       Identifier to use for the front camera.
      * @param cameraInternal Camera implementation.
      */
     public void insertDefaultFrontCamera(@NonNull String cameraId,
             @NonNull Callable<CameraInternal> cameraInternal) {
-        insertCamera(LensFacing.FRONT, cameraId, cameraInternal);
-        setDefaultCameraIdForLensFacing(LensFacing.FRONT, cameraId);
+        insertCamera(CameraSelector.LENS_FACING_FRONT, cameraId, cameraInternal);
+        setDefaultCameraIdForLensFacing(CameraSelector.LENS_FACING_FRONT, cameraId);
     }
 
     /**
@@ -114,30 +114,30 @@
      * <p>This is a convenience method for calling
      * {@link #insertCamera(int, String, Callable)}
      * followed by {@link #setDefaultCameraIdForLensFacing(int, String)} with
-     * {@link LensFacing#BACK} for all lens facing arguments.
+     * {@link CameraSelector#LENS_FACING_BACK} for all lens facing arguments.
      *
      * @param cameraId       Identifier to use for the back camera.
      * @param cameraInternal Camera implementation.
      */
     public void insertDefaultBackCamera(@NonNull String cameraId,
             @NonNull Callable<CameraInternal> cameraInternal) {
-        insertCamera(LensFacing.BACK, cameraId, cameraInternal);
-        setDefaultCameraIdForLensFacing(LensFacing.BACK, cameraId);
+        insertCamera(CameraSelector.LENS_FACING_BACK, cameraId, cameraInternal);
+        setDefaultCameraIdForLensFacing(CameraSelector.LENS_FACING_BACK, cameraId);
     }
 
     /**
      * Sets the camera ID which will be returned by {@link #cameraIdForLensFacing(int)}.
      *
-     * @param lensFacing The {@link LensFacing} to set.
+     * @param lensFacing The {@link CameraSelector.LensFacing} to set.
      * @param cameraId   The camera ID which will be returned.
      */
-    public void setDefaultCameraIdForLensFacing(@LensFacing int lensFacing,
+    public void setDefaultCameraIdForLensFacing(@CameraSelector.LensFacing int lensFacing,
             @NonNull String cameraId) {
         switch (lensFacing) {
-            case LensFacing.FRONT:
+            case CameraSelector.LENS_FACING_FRONT:
                 mFrontCameraId = cameraId;
                 break;
-            case LensFacing.BACK:
+            case CameraSelector.LENS_FACING_BACK:
                 mBackCameraId = cameraId;
                 break;
             default:
@@ -159,11 +159,11 @@
 
     @Override
     @Nullable
-    public String cameraIdForLensFacing(@LensFacing int lensFacing) {
+    public String cameraIdForLensFacing(@CameraSelector.LensFacing int lensFacing) {
         switch (lensFacing) {
-            case LensFacing.FRONT:
+            case CameraSelector.LENS_FACING_FRONT:
                 return mFrontCameraId;
-            case LensFacing.BACK:
+            case CameraSelector.LENS_FACING_BACK:
                 return mBackCameraId;
             default:
                 return null;
@@ -172,7 +172,8 @@
 
     @Override
     @NonNull
-    public LensFacingCameraIdFilter getLensFacingCameraIdFilter(@LensFacing int lensFacing) {
+    public LensFacingCameraIdFilter getLensFacingCameraIdFilter(
+            @CameraSelector.LensFacing int lensFacing) {
         // Lazily cache the map of LensFacing to set of camera ids. This cache will be
         // invalidated anytime a new camera is added.
         if (mCachedLensFacingToIdMap == null) {
@@ -201,7 +202,8 @@
         @Nullable
         private final Set<String> mIds;
 
-        SettableLensFacingCameraIdFilter(@LensFacing int lensFacing, @Nullable Set<String> ids) {
+        SettableLensFacingCameraIdFilter(@CameraSelector.LensFacing int lensFacing,
+                @Nullable Set<String> ids) {
             super(lensFacing);
             mIds = ids;
         }
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraInfoInternal.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraInfoInternal.java
index 7e3b65e..ec843ff 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraInfoInternal.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraInfoInternal.java
@@ -22,8 +22,8 @@
 import androidx.annotation.Nullable;
 import androidx.camera.core.CameraInfoInternal;
 import androidx.camera.core.CameraOrientationUtil;
+import androidx.camera.core.CameraSelector;
 import androidx.camera.core.ImageOutputConfig.RotationValue;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.TorchState;
 import androidx.lifecycle.LiveData;
 import androidx.lifecycle.MutableLiveData;
@@ -36,7 +36,7 @@
 public final class FakeCameraInfoInternal implements CameraInfoInternal {
 
     private final int mSensorRotation;
-    @LensFacing
+    @CameraSelector.LensFacing
     private final int mLensFacing;
     private final boolean mHasFlashUnit = true;
     private MutableLiveData<Integer> mTorchState = new MutableLiveData<>(TorchState.OFF);
@@ -47,10 +47,10 @@
 
 
     public FakeCameraInfoInternal() {
-        this(/*sensorRotation=*/ 0, /*lensFacing=*/ LensFacing.BACK);
+        this(/*sensorRotation=*/ 0, /*lensFacing=*/ CameraSelector.LENS_FACING_BACK);
     }
 
-    public FakeCameraInfoInternal(int sensorRotation, @LensFacing int lensFacing) {
+    public FakeCameraInfoInternal(int sensorRotation, @CameraSelector.LensFacing int lensFacing) {
         mSensorRotation = sensorRotation;
         mLensFacing = lensFacing;
     }
@@ -68,7 +68,7 @@
         // Currently this assumes that a back-facing camera is always opposite to the screen.
         // This may not be the case for all devices, so in the future we may need to handle that
         // scenario.
-        boolean isOppositeFacingScreen = (LensFacing.BACK == getLensFacing());
+        boolean isOppositeFacingScreen = (CameraSelector.LENS_FACING_BACK == getLensFacing());
         return CameraOrientationUtil.getRelativeImageRotation(
                 relativeRotationDegrees,
                 mSensorRotation,
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeUseCaseConfig.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeUseCaseConfig.java
index 1e4ab1e..6b54a90 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeUseCaseConfig.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeUseCaseConfig.java
@@ -24,10 +24,10 @@
 import androidx.annotation.Nullable;
 import androidx.camera.core.CameraDeviceConfig;
 import androidx.camera.core.CameraIdFilter;
+import androidx.camera.core.CameraSelector;
 import androidx.camera.core.CaptureConfig;
 import androidx.camera.core.Config;
 import androidx.camera.core.ImageOutputConfig;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.MutableConfig;
 import androidx.camera.core.MutableOptionsBundle;
 import androidx.camera.core.OptionsBundle;
@@ -128,7 +128,7 @@
     }
 
     @Override
-    @LensFacing
+    @CameraSelector.LensFacing
     public int getLensFacing() {
         return retrieveOption(OPTION_LENS_FACING);
     }
@@ -365,7 +365,7 @@
 
         @Override
         @NonNull
-        public Builder setLensFacing(@LensFacing int lensFacing) {
+        public Builder setLensFacing(@CameraSelector.LensFacing int lensFacing) {
             getMutableConfig().insertOption(OPTION_LENS_FACING, lensFacing);
             return this;
         }
diff --git a/camera/camera-testing/src/test/java/androidx/camera/testing/fakes/FakeCameraInfoTest.java b/camera/camera-testing/src/test/java/androidx/camera/testing/fakes/FakeCameraInfoTest.java
index 09a6781..70839eb 100644
--- a/camera/camera-testing/src/test/java/androidx/camera/testing/fakes/FakeCameraInfoTest.java
+++ b/camera/camera-testing/src/test/java/androidx/camera/testing/fakes/FakeCameraInfoTest.java
@@ -21,7 +21,7 @@
 
 import android.os.Build;
 
-import androidx.camera.core.LensFacing;
+import androidx.camera.core.CameraSelector;
 import androidx.test.filters.SmallTest;
 
 import org.junit.Before;
@@ -38,8 +38,8 @@
 public final class FakeCameraInfoTest {
 
     private static final int SENSOR_ROTATION_DEGREES = 90;
-    @LensFacing
-    private static final int LENS_FACING = LensFacing.FRONT;
+    @CameraSelector.LensFacing
+    private static final int LENS_FACING = CameraSelector.LENS_FACING_FRONT;
 
     private FakeCameraInfoInternal mFakeCameraInfo;
 
diff --git a/camera/camera-view/src/androidTest/java/androidx/camera/view/TextureViewMeteringPointFactoryTest.java b/camera/camera-view/src/androidTest/java/androidx/camera/view/TextureViewMeteringPointFactoryTest.java
index 607f6a6..34ddbe3 100644
--- a/camera/camera-view/src/androidTest/java/androidx/camera/view/TextureViewMeteringPointFactoryTest.java
+++ b/camera/camera-view/src/androidTest/java/androidx/camera/view/TextureViewMeteringPointFactoryTest.java
@@ -38,7 +38,6 @@
 import androidx.camera.core.CameraX;
 import androidx.camera.core.CameraXConfig;
 import androidx.camera.core.DisplayOrientedMeteringPointFactory;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.MeteringPoint;
 import androidx.camera.core.MeteringPointFactory;
 import androidx.camera.core.Preview;
@@ -70,9 +69,10 @@
 public class TextureViewMeteringPointFactoryTest {
     public static final float TOLERANCE = 0.000001f;
     private static final CameraSelector FRONT_CAM =
-            new CameraSelector.Builder().requireLensFacing(LensFacing.FRONT).build();
+            new CameraSelector.Builder().requireLensFacing(
+                    CameraSelector.LENS_FACING_FRONT).build();
     private static final CameraSelector BACK_CAM =
-            new CameraSelector.Builder().requireLensFacing(LensFacing.BACK).build();
+            new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build();
     @Rule
     public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
             Manifest.permission.CAMERA);
@@ -123,9 +123,9 @@
 
     @Test
     public void backCamera_translatedPoint_SameAsDisplayOriented() throws Throwable {
-        assumeTrue(CameraUtil.hasCameraWithLensFacing(LensFacing.BACK));
+        assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK));
 
-        startAndWaitForCameraReady(LensFacing.BACK);
+        startAndWaitForCameraReady(CameraSelector.LENS_FACING_BACK);
 
         TextureViewMeteringPointFactory factory = new TextureViewMeteringPointFactory(mTextureView);
 
@@ -142,9 +142,9 @@
 
     @Test
     public void frontCamera_translatedPoint_SameAsDisplayOriented() throws Throwable {
-        assumeTrue(CameraUtil.hasCameraWithLensFacing(LensFacing.FRONT));
+        assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_FRONT));
 
-        startAndWaitForCameraReady(LensFacing.FRONT);
+        startAndWaitForCameraReady(CameraSelector.LENS_FACING_FRONT);
 
         TextureViewMeteringPointFactory factory = new TextureViewMeteringPointFactory(mTextureView);
 
@@ -163,7 +163,7 @@
 
     @Test
     public void xy_OutOfRange() throws Throwable {
-        startAndWaitForCameraReady(LensFacing.BACK);
+        startAndWaitForCameraReady(CameraSelector.LENS_FACING_BACK);
 
         TextureViewMeteringPointFactory factory = new TextureViewMeteringPointFactory(mTextureView);
 
@@ -198,7 +198,7 @@
         return xValid && yValid;
     }
 
-    private void startAndWaitForCameraReady(@LensFacing int lensFacing)
+    private void startAndWaitForCameraReady(@CameraSelector.LensFacing int lensFacing)
             throws InterruptedException {
         Preview preview = new Preview.Builder().build();
         mInstrumentation.runOnMainSync(() -> {
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/CameraView.java b/camera/camera-view/src/main/java/androidx/camera/view/CameraView.java
index 14d1842..5bfc64b 100644
--- a/camera/camera-view/src/main/java/androidx/camera/view/CameraView.java
+++ b/camera/camera-view/src/main/java/androidx/camera/view/CameraView.java
@@ -51,14 +51,13 @@
 import androidx.annotation.RestrictTo.Scope;
 import androidx.annotation.UiThread;
 import androidx.camera.core.Camera;
-import androidx.camera.core.FlashMode;
+import androidx.camera.core.CameraSelector;
 import androidx.camera.core.FlashModeHelper;
 import androidx.camera.core.FocusMeteringAction;
-import androidx.camera.core.FocusMeteringAction.MeteringMode;
+import androidx.camera.core.ImageCapture;
 import androidx.camera.core.ImageCapture.OnImageCapturedCallback;
 import androidx.camera.core.ImageCapture.OnImageSavedCallback;
 import androidx.camera.core.ImageProxy;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.LensFacingConverter;
 import androidx.camera.core.MeteringPoint;
 import androidx.camera.core.VideoCapture.OnVideoSavedCallback;
@@ -219,10 +218,10 @@
                     setCameraLensFacing(null);
                     break;
                 case LENS_FACING_FRONT:
-                    setCameraLensFacing(LensFacing.FRONT);
+                    setCameraLensFacing(CameraSelector.LENS_FACING_FRONT);
                     break;
                 case LENS_FACING_BACK:
-                    setCameraLensFacing(LensFacing.BACK);
+                    setCameraLensFacing(CameraSelector.LENS_FACING_BACK);
                     break;
                 default:
                     // Unhandled event.
@@ -231,13 +230,13 @@
             int flashMode = a.getInt(R.styleable.CameraView_flash, 0);
             switch (flashMode) {
                 case FLASH_MODE_AUTO:
-                    setFlash(FlashMode.AUTO);
+                    setFlash(ImageCapture.FLASH_MODE_AUTO);
                     break;
                 case FLASH_MODE_ON:
-                    setFlash(FlashMode.ON);
+                    setFlash(ImageCapture.FLASH_MODE_ON);
                     break;
                 case FLASH_MODE_OFF:
-                    setFlash(FlashMode.OFF);
+                    setFlash(ImageCapture.FLASH_MODE_OFF);
                     break;
                 default:
                     // Unhandled event.
@@ -686,7 +685,7 @@
      * @throws IllegalStateException if the CAMERA permission is not currently granted.
      */
     @RequiresPermission(permission.CAMERA)
-    public boolean hasCameraWithLensFacing(@LensFacing int lensFacing) {
+    public boolean hasCameraWithLensFacing(@CameraSelector.LensFacing int lensFacing) {
         return mCameraModule.hasCameraWithLensFacing(lensFacing);
     }
 
@@ -719,20 +718,20 @@
         mCameraModule.setCameraLensFacing(lensFacing);
     }
 
-    /** Returns the currently selected {@link LensFacing}. */
+    /** Returns the currently selected lensFacing. */
     @Nullable
     public Integer getCameraLensFacing() {
         return mCameraModule.getLensFacing();
     }
 
     /** Gets the active flash strategy. */
-    @FlashMode
+    @ImageCapture.FlashMode
     public int getFlash() {
         return mCameraModule.getFlash();
     }
 
     /** Sets the active flash strategy. */
-    public void setFlash(@FlashMode int flashMode) {
+    public void setFlash(@ImageCapture.FlashMode int flashMode) {
         mCameraModule.setFlash(flashMode);
     }
 
@@ -799,8 +798,8 @@
         Camera camera = mCameraModule.getCamera();
         if (camera != null) {
             camera.getCameraControl().startFocusAndMetering(
-                    FocusMeteringAction.Builder.from(afPoint, MeteringMode.AF)
-                            .addPoint(aePoint, MeteringMode.AE)
+                    FocusMeteringAction.Builder.from(afPoint, FocusMeteringAction.FLAG_AF)
+                            .addPoint(aePoint, FocusMeteringAction.FLAG_AE)
                             .build());
         } else {
             Log.d(TAG, "cannot access camera");
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/CameraXModule.java b/camera/camera-view/src/main/java/androidx/camera/view/CameraXModule.java
index 2e2a15b..b9b8fa7 100644
--- a/camera/camera-view/src/main/java/androidx/camera/view/CameraXModule.java
+++ b/camera/camera-view/src/main/java/androidx/camera/view/CameraXModule.java
@@ -16,6 +16,8 @@
 
 package androidx.camera.view;
 
+import static androidx.camera.core.ImageCapture.FLASH_MODE_OFF;
+
 import android.Manifest.permission;
 import android.annotation.SuppressLint;
 import android.content.Context;
@@ -36,11 +38,9 @@
 import androidx.camera.core.CameraOrientationUtil;
 import androidx.camera.core.CameraSelector;
 import androidx.camera.core.CameraX;
-import androidx.camera.core.FlashMode;
 import androidx.camera.core.ImageCapture;
 import androidx.camera.core.ImageCapture.OnImageCapturedCallback;
 import androidx.camera.core.ImageCapture.OnImageSavedCallback;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.LensFacingConverter;
 import androidx.camera.core.Preview;
 import androidx.camera.core.TorchState;
@@ -92,8 +92,8 @@
     private CameraView.CaptureMode mCaptureMode = CaptureMode.IMAGE;
     private long mMaxVideoDuration = CameraView.INDEFINITE_VIDEO_DURATION;
     private long mMaxVideoSize = CameraView.INDEFINITE_VIDEO_SIZE;
-    @FlashMode
-    private int mFlash = FlashMode.OFF;
+    @ImageCapture.FlashMode
+    private int mFlash = FLASH_MODE_OFF;
     @Nullable
     @SuppressWarnings("WeakerAccess") /* synthetic accessor */
     Camera mCamera;
@@ -124,7 +124,7 @@
     private LifecycleOwner mNewLifecycle;
     @SuppressWarnings("WeakerAccess") /* synthetic accessor */
     @Nullable
-    Integer mCameraLensFacing = LensFacing.BACK;
+    Integer mCameraLensFacing = CameraSelector.LENS_FACING_BACK;
     @SuppressWarnings("WeakerAccess") /* synthetic accessor */
     @Nullable
     ProcessCameraProvider mCameraProvider;
@@ -351,7 +351,7 @@
 
         ImageCapture.Metadata metadata = new ImageCapture.Metadata();
         metadata.setReversedHorizontal(
-                mCameraLensFacing != null && mCameraLensFacing == LensFacing.FRONT);
+                mCameraLensFacing != null && mCameraLensFacing == CameraSelector.LENS_FACING_FRONT);
         mImageCapture.takePicture(saveLocation, metadata, executor, callback);
     }
 
@@ -420,7 +420,7 @@
     }
 
     @RequiresPermission(permission.CAMERA)
-    public boolean hasCameraWithLensFacing(@LensFacing int lensFacing) {
+    public boolean hasCameraWithLensFacing(@CameraSelector.LensFacing int lensFacing) {
         String cameraId;
         try {
             cameraId = CameraX.getCameraWithLensFacing(lensFacing);
@@ -450,15 +450,15 @@
             return;
         }
 
-        if (mCameraLensFacing == LensFacing.BACK
-                && availableCameraLensFacing.contains(LensFacing.FRONT)) {
-            setCameraLensFacing(LensFacing.FRONT);
+        if (mCameraLensFacing == CameraSelector.LENS_FACING_BACK
+                && availableCameraLensFacing.contains(CameraSelector.LENS_FACING_FRONT)) {
+            setCameraLensFacing(CameraSelector.LENS_FACING_FRONT);
             return;
         }
 
-        if (mCameraLensFacing == LensFacing.FRONT
-                && availableCameraLensFacing.contains(LensFacing.BACK)) {
-            setCameraLensFacing(LensFacing.BACK);
+        if (mCameraLensFacing == CameraSelector.LENS_FACING_FRONT
+                && availableCameraLensFacing.contains(CameraSelector.LENS_FACING_BACK)) {
+            setCameraLensFacing(CameraSelector.LENS_FACING_BACK);
             return;
         }
     }
@@ -593,24 +593,24 @@
 
         // If we're bound to a lifecycle, remove unavailable cameras
         if (mCurrentLifecycle != null) {
-            if (!hasCameraWithLensFacing(LensFacing.BACK)) {
-                available.remove(LensFacing.BACK);
+            if (!hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK)) {
+                available.remove(CameraSelector.LENS_FACING_BACK);
             }
 
-            if (!hasCameraWithLensFacing(LensFacing.FRONT)) {
-                available.remove(LensFacing.FRONT);
+            if (!hasCameraWithLensFacing(CameraSelector.LENS_FACING_FRONT)) {
+                available.remove(CameraSelector.LENS_FACING_FRONT);
             }
         }
 
         return available;
     }
 
-    @FlashMode
+    @ImageCapture.FlashMode
     public int getFlash() {
         return mFlash;
     }
 
-    public void setFlash(@FlashMode int flash) {
+    public void setFlash(@ImageCapture.FlashMode int flash) {
         this.mFlash = flash;
 
         if (mImageCapture == null) {
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ToggleButtonUITest.java b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ToggleButtonUITest.java
index 0dc3561..b056335 100644
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ToggleButtonUITest.java
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ToggleButtonUITest.java
@@ -31,9 +31,8 @@
 import android.content.Intent;
 
 import androidx.camera.core.CameraInfo;
-import androidx.camera.core.FlashMode;
+import androidx.camera.core.CameraSelector;
 import androidx.camera.core.ImageCapture;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.TorchState;
 import androidx.camera.integration.core.idlingresource.ElapsedTimeIdlingResource;
 import androidx.camera.integration.core.idlingresource.WaitForViewToShow;
@@ -121,15 +120,15 @@
         // There are 3 different states of flash mode: ON, OFF and AUTO.
         // By pressing flash mode toggle button, the flash mode would switch to the next state.
         // The flash mode would loop in following sequence: OFF -> AUTO -> ON -> OFF.
-        @FlashMode int mode1 = useCase.getFlashMode();
+        @ImageCapture.FlashMode int mode1 = useCase.getFlashMode();
 
         onView(withId(R.id.flash_toggle)).perform(click());
-        @FlashMode int mode2 = useCase.getFlashMode();
+        @ImageCapture.FlashMode int mode2 = useCase.getFlashMode();
         // After the switch, the mode2 should be different from mode1.
         assertNotEquals(mode2, mode1);
 
         onView(withId(R.id.flash_toggle)).perform(click());
-        @FlashMode int mode3 = useCase.getFlashMode();
+        @ImageCapture.FlashMode int mode3 = useCase.getFlashMode();
         // The mode3 should be different from first and second time.
         assertNotEquals(mode3, mode2);
         assertNotEquals(mode3, mode1);
@@ -158,7 +157,7 @@
 
     @Test
     public void testSwitchCameraToggleButton() {
-        assumeTrue(CameraUtil.hasCameraWithLensFacing(LensFacing.FRONT));
+        assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_FRONT));
         waitFor(new WaitForViewToShow(R.id.direction_toggle));
 
         boolean isPreviewExist = mActivityRule.getActivity().getPreview() != null;
diff --git a/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/CameraXActivity.java b/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/CameraXActivity.java
index c8c8327..2372938 100644
--- a/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/CameraXActivity.java
+++ b/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/CameraXActivity.java
@@ -16,6 +16,10 @@
 
 package androidx.camera.integration.core;
 
+import static androidx.camera.core.ImageCapture.FLASH_MODE_AUTO;
+import static androidx.camera.core.ImageCapture.FLASH_MODE_OFF;
+import static androidx.camera.core.ImageCapture.FLASH_MODE_ON;
+
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -45,16 +49,13 @@
 import androidx.camera.core.CameraControl;
 import androidx.camera.core.CameraInfo;
 import androidx.camera.core.CameraSelector;
-import androidx.camera.core.FlashMode;
 import androidx.camera.core.ImageAnalysis;
 import androidx.camera.core.ImageCapture;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.Preview;
 import androidx.camera.core.TorchState;
 import androidx.camera.core.UseCase;
 import androidx.camera.core.VideoCapture;
 import androidx.camera.core.VideoCaptureConfig;
-import androidx.camera.core.impl.utils.executor.CameraXExecutors;
 import androidx.camera.lifecycle.ProcessCameraProvider;
 import androidx.concurrent.futures.CallbackToFutureAdapter;
 import androidx.core.app.ActivityCompat;
@@ -95,9 +96,10 @@
     // Possible values for this intent key: "backward" or "forward".
     private static final String INTENT_EXTRA_CAMERA_DIRECTION = "camera_direction";
     static final CameraSelector BACK_SELECTOR =
-            new CameraSelector.Builder().requireLensFacing(LensFacing.BACK).build();
+            new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build();
     static final CameraSelector FRONT_SELECTOR =
-            new CameraSelector.Builder().requireLensFacing(LensFacing.FRONT).build();
+            new CameraSelector.Builder().requireLensFacing(
+                    CameraSelector.LENS_FACING_FRONT).build();
 
     private boolean mPermissionsGranted = false;
     private CallbackToFutureAdapter.Completer<Boolean> mPermissionsCompleter;
@@ -106,8 +108,8 @@
     private VideoFileSaver mVideoFileSaver;
     /** The camera to use */
     CameraSelector mCurrentCameraSelector = BACK_SELECTOR;
-    @LensFacing
-    int mCurrentCameraLensFacing = LensFacing.BACK;
+    @CameraSelector.LensFacing
+    int mCurrentCameraLensFacing = CameraSelector.LENS_FACING_BACK;
     ProcessCameraProvider mCameraProvider;
 
     // TODO: Move the analysis processing, capture processing to separate threads, so
@@ -119,7 +121,7 @@
     private VideoCapture mVideoCapture;
     private Camera mCamera;
     @ImageCapture.CaptureMode
-    private int mCaptureMode = ImageCapture.CaptureMode.MINIMIZE_LATENCY;
+    private int mCaptureMode = ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY;
     // Synthetic Accessor
     @SuppressWarnings("WeakerAccess")
     TextureView mTextureView;
@@ -360,7 +362,7 @@
         }
 
         mImageAnalysis.setAnalyzer(
-                CameraXExecutors.mainThreadExecutor(),
+                ContextCompat.getMainExecutor(this),
                 (image, rotationDegrees) -> {
                     // Since we set the callback handler to a main thread handler, we can call
                     // setValue() here. If we weren't on the main thread, we would have to call
@@ -451,7 +453,7 @@
                                         dir,
                                         formatter.format(Calendar.getInstance().getTime())
                                                 + ".jpg"),
-                                CameraXExecutors.mainThreadExecutor(),
+                                ContextCompat.getMainExecutor(CameraXActivity.this),
                                 new ImageCapture.OnImageSavedCallback() {
                                     @Override
                                     public void onImageSaved(@NonNull File file) {
@@ -498,13 +500,13 @@
         Button btnCaptureQuality = this.findViewById(R.id.capture_quality);
         btnCaptureQuality.setVisibility(View.VISIBLE);
         btnCaptureQuality.setText(
-                mCaptureMode == ImageCapture.CaptureMode.MAXIMIZE_QUALITY ? "MAX" : "MIN");
+                mCaptureMode == ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY ? "MAX" : "MIN");
         btnCaptureQuality.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
-                mCaptureMode = (mCaptureMode == ImageCapture.CaptureMode.MAXIMIZE_QUALITY
-                        ? ImageCapture.CaptureMode.MINIMIZE_LATENCY
-                        : ImageCapture.CaptureMode.MAXIMIZE_QUALITY);
+                mCaptureMode = (mCaptureMode == ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY
+                        ? ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY
+                        : ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY);
                 rebindUseCases();
             }
         });
@@ -533,13 +535,13 @@
                 flashToggle.setOnClickListener(new View.OnClickListener() {
                     @Override
                     public void onClick(View v) {
-                        @FlashMode int flashMode = mImageCapture.getFlashMode();
-                        if (flashMode == FlashMode.ON) {
-                            mImageCapture.setFlashMode(FlashMode.OFF);
-                        } else if (flashMode == FlashMode.OFF) {
-                            mImageCapture.setFlashMode(FlashMode.AUTO);
-                        } else if (flashMode == FlashMode.AUTO) {
-                            mImageCapture.setFlashMode(FlashMode.ON);
+                        @ImageCapture.FlashMode int flashMode = mImageCapture.getFlashMode();
+                        if (flashMode == FLASH_MODE_ON) {
+                            mImageCapture.setFlashMode(FLASH_MODE_OFF);
+                        } else if (flashMode == FLASH_MODE_OFF) {
+                            mImageCapture.setFlashMode(FLASH_MODE_AUTO);
+                        } else if (flashMode == FLASH_MODE_AUTO) {
+                            mImageCapture.setFlashMode(FLASH_MODE_ON);
                         }
                         refreshFlashButtonIcon();
                     }
@@ -557,15 +559,15 @@
 
     private void refreshFlashButtonIcon() {
         ImageButton flashToggle = findViewById(R.id.flash_toggle);
-        @FlashMode int flashMode = mImageCapture.getFlashMode();
+        @ImageCapture.FlashMode int flashMode = mImageCapture.getFlashMode();
         switch (flashMode) {
-            case FlashMode.ON:
+            case FLASH_MODE_ON:
                 flashToggle.setImageResource(R.drawable.ic_flash_on);
                 break;
-            case FlashMode.OFF:
+            case FLASH_MODE_OFF:
                 flashToggle.setImageResource(R.drawable.ic_flash_off);
                 break;
-            case FlashMode.AUTO:
+            case FLASH_MODE_AUTO:
                 flashToggle.setImageResource(R.drawable.ic_flash_auto);
                 break;
         }
@@ -640,29 +642,26 @@
         }
 
         Button button = this.findViewById(R.id.Video);
-        button.setOnClickListener(
-                new View.OnClickListener() {
-                    @Override
-                    public void onClick(View view) {
-                        Button buttonView = (Button) view;
-                        String text = button.getText().toString();
-                        if (text.equals("Record") && !mVideoFileSaver.isSaving()) {
-                            mVideoCapture.startRecording(
-                                    mVideoFileSaver.getNewVideoFile(),
-                                    CameraXExecutors.mainThreadExecutor(), mVideoFileSaver);
-                            mVideoFileSaver.setSaving();
-                            buttonView.setText("Stop");
-                        } else if (text.equals("Stop") && mVideoFileSaver.isSaving()) {
-                            buttonView.setText("Record");
-                            mVideoCapture.stopRecording();
-                        } else if (text.equals("Record") && mVideoFileSaver.isSaving()) {
-                            buttonView.setText("Stop");
-                            mVideoFileSaver.setSaving();
-                        } else if (text.equals("Stop") && !mVideoFileSaver.isSaving()) {
-                            buttonView.setText("Record");
-                        }
-                    }
-                });
+        button.setOnClickListener((view) -> {
+            Button buttonView = (Button) view;
+            String text = button.getText().toString();
+            if (text.equals("Record") && !mVideoFileSaver.isSaving()) {
+                mVideoCapture.startRecording(
+                        mVideoFileSaver.getNewVideoFile(),
+                        ContextCompat.getMainExecutor(CameraXActivity.this),
+                        mVideoFileSaver);
+                mVideoFileSaver.setSaving();
+                buttonView.setText("Stop");
+            } else if (text.equals("Stop") && mVideoFileSaver.isSaving()) {
+                buttonView.setText("Record");
+                mVideoCapture.stopRecording();
+            } else if (text.equals("Record") && mVideoFileSaver.isSaving()) {
+                buttonView.setText("Stop");
+                mVideoFileSaver.setSaving();
+            } else if (text.equals("Stop") && !mVideoFileSaver.isSaving()) {
+                buttonView.setText("Record");
+            }
+        });
     }
 
     void disableVideoCapture() {
@@ -741,10 +740,10 @@
         Log.d(TAG, "Camera direction: " + mCurrentCameraDirection);
         if (mCurrentCameraDirection.equalsIgnoreCase("BACKWARD")) {
             mCurrentCameraSelector = BACK_SELECTOR;
-            mCurrentCameraLensFacing = LensFacing.BACK;
+            mCurrentCameraLensFacing = CameraSelector.LENS_FACING_BACK;
         } else if (mCurrentCameraDirection.equalsIgnoreCase("FORWARD")) {
             mCurrentCameraSelector = FRONT_SELECTOR;
-            mCurrentCameraLensFacing = LensFacing.FRONT;
+            mCurrentCameraLensFacing = CameraSelector.LENS_FACING_FRONT;
         } else {
             throw new RuntimeException("Invalid camera direction: " + mCurrentCameraDirection);
         }
@@ -758,12 +757,12 @@
         directionToggle.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                if (mCurrentCameraLensFacing == LensFacing.BACK) {
+                if (mCurrentCameraLensFacing == CameraSelector.LENS_FACING_BACK) {
                     mCurrentCameraSelector = FRONT_SELECTOR;
-                    mCurrentCameraLensFacing = LensFacing.FRONT;
-                } else if (mCurrentCameraLensFacing == LensFacing.FRONT) {
+                    mCurrentCameraLensFacing = CameraSelector.LENS_FACING_FRONT;
+                } else if (mCurrentCameraLensFacing == CameraSelector.LENS_FACING_FRONT) {
                     mCurrentCameraSelector = BACK_SELECTOR;
-                    mCurrentCameraLensFacing = LensFacing.BACK;
+                    mCurrentCameraLensFacing = CameraSelector.LENS_FACING_BACK;
                 }
 
                 Log.d(TAG, "Change camera direction: " + mCurrentCameraSelector);
diff --git a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/PreviewProcessorTimestampTest.java b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/PreviewProcessorTimestampTest.java
index 4062208..1a7a11f 100644
--- a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/PreviewProcessorTimestampTest.java
+++ b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/PreviewProcessorTimestampTest.java
@@ -42,7 +42,6 @@
 import androidx.camera.core.CaptureProcessor;
 import androidx.camera.core.ImageAnalysis;
 import androidx.camera.core.ImageCapture;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.Preview;
 import androidx.camera.core.PreviewConfig;
 import androidx.camera.extensions.AutoImageCaptureExtender;
@@ -96,7 +95,7 @@
     private FakeLifecycleOwner mLifecycleOwner;
     private CameraDevice.StateCallback mCameraStatusCallback;
     private ExtensionsManager.EffectMode mEffectMode;
-    @LensFacing
+    @CameraSelector.LensFacing
     private int mLensFacing;
     private CountDownLatch mLatch;
     private CountDownLatch mInputTimestampsLatch;
@@ -115,21 +114,21 @@
     @Parameterized.Parameters
     public static Collection<Object[]> getParameters() {
         return Arrays.asList(new Object[][]{
-                {ExtensionsManager.EffectMode.BOKEH, LensFacing.FRONT},
-                {ExtensionsManager.EffectMode.BOKEH, LensFacing.BACK},
-                {ExtensionsManager.EffectMode.HDR, LensFacing.FRONT},
-                {ExtensionsManager.EffectMode.HDR, LensFacing.BACK},
-                {ExtensionsManager.EffectMode.BEAUTY, LensFacing.FRONT},
-                {ExtensionsManager.EffectMode.BEAUTY, LensFacing.BACK},
-                {ExtensionsManager.EffectMode.NIGHT, LensFacing.FRONT},
-                {ExtensionsManager.EffectMode.NIGHT, LensFacing.BACK},
-                {ExtensionsManager.EffectMode.AUTO, LensFacing.FRONT},
-                {ExtensionsManager.EffectMode.AUTO, LensFacing.BACK}
+                {ExtensionsManager.EffectMode.BOKEH, CameraSelector.LENS_FACING_FRONT},
+                {ExtensionsManager.EffectMode.BOKEH, CameraSelector.LENS_FACING_BACK},
+                {ExtensionsManager.EffectMode.HDR, CameraSelector.LENS_FACING_FRONT},
+                {ExtensionsManager.EffectMode.HDR, CameraSelector.LENS_FACING_BACK},
+                {ExtensionsManager.EffectMode.BEAUTY, CameraSelector.LENS_FACING_FRONT},
+                {ExtensionsManager.EffectMode.BEAUTY, CameraSelector.LENS_FACING_BACK},
+                {ExtensionsManager.EffectMode.NIGHT, CameraSelector.LENS_FACING_FRONT},
+                {ExtensionsManager.EffectMode.NIGHT, CameraSelector.LENS_FACING_BACK},
+                {ExtensionsManager.EffectMode.AUTO, CameraSelector.LENS_FACING_FRONT},
+                {ExtensionsManager.EffectMode.AUTO, CameraSelector.LENS_FACING_BACK}
         });
     }
 
     public PreviewProcessorTimestampTest(ExtensionsManager.EffectMode effectMode,
-            @LensFacing int lensFacing) {
+            @CameraSelector.LensFacing int lensFacing) {
         mEffectMode = effectMode;
         mLensFacing = lensFacing;
     }
@@ -285,7 +284,7 @@
      * To invoke the enableExtension() method for different effect.
      */
     private void enableExtension(ExtensionsManager.EffectMode effectMode,
-            @LensFacing int lensFacing) {
+            @CameraSelector.LensFacing int lensFacing) {
 
         CameraSelector cameraSelector =
                 new CameraSelector.Builder().requireLensFacing(lensFacing).build();
diff --git a/camera/integration-tests/extensionstestapp/src/main/java/androidx/camera/integration/extensions/CameraExtensionsActivity.java b/camera/integration-tests/extensionstestapp/src/main/java/androidx/camera/integration/extensions/CameraExtensionsActivity.java
index a4723b4..f2ea111 100644
--- a/camera/integration-tests/extensionstestapp/src/main/java/androidx/camera/integration/extensions/CameraExtensionsActivity.java
+++ b/camera/integration-tests/extensionstestapp/src/main/java/androidx/camera/integration/extensions/CameraExtensionsActivity.java
@@ -35,17 +35,14 @@
 import androidx.camera.core.CameraSelector;
 import androidx.camera.core.CameraX;
 import androidx.camera.core.ImageCapture;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.Preview;
 import androidx.camera.core.UseCase;
-import androidx.camera.core.impl.utils.executor.CameraXExecutors;
 import androidx.camera.extensions.AutoImageCaptureExtender;
 import androidx.camera.extensions.AutoPreviewExtender;
 import androidx.camera.extensions.BeautyImageCaptureExtender;
 import androidx.camera.extensions.BeautyPreviewExtender;
 import androidx.camera.extensions.BokehImageCaptureExtender;
 import androidx.camera.extensions.BokehPreviewExtender;
-import androidx.camera.extensions.ExtensionsErrorListener;
 import androidx.camera.extensions.ExtensionsManager;
 import androidx.camera.extensions.HdrImageCaptureExtender;
 import androidx.camera.extensions.HdrPreviewExtender;
@@ -78,7 +75,7 @@
     private static final int PERMISSIONS_REQUEST_CODE = 42;
 
     private static final CameraSelector CAMERA_SELECTOR =
-            new CameraSelector.Builder().requireLensFacing(LensFacing.BACK).build();
+            new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build();
 
     boolean mPermissionsGranted = false;
     private CallbackToFutureAdapter.Completer<Boolean> mPermissionCompleter;
@@ -284,48 +281,44 @@
                                 Environment.DIRECTORY_PICTURES),
                         "ExtensionsPictures");
         dir.mkdirs();
-        captureButton.setOnClickListener(
-                new View.OnClickListener() {
-                    @Override
-                    public void onClick(View view) {
-                        mTakePictureIdlingResource.increment();
-                        mImageCapture.takePicture(
-                                new File(
-                                        dir,
-                                        formatter.format(Calendar.getInstance().getTime())
-                                                + mCurrentImageCaptureType.name()
-                                                + ".jpg"),
-                                CameraXExecutors.mainThreadExecutor(),
-                                new ImageCapture.OnImageSavedCallback() {
-                                    @Override
-                                    public void onImageSaved(@NonNull File file) {
-                                        Log.d(TAG, "Saved image to " + file);
+        captureButton.setOnClickListener((view) -> {
+            mTakePictureIdlingResource.increment();
+            mImageCapture.takePicture(
+                    new File(
+                            dir,
+                            formatter.format(Calendar.getInstance().getTime())
+                                    + mCurrentImageCaptureType.name()
+                                    + ".jpg"),
+                    ContextCompat.getMainExecutor(CameraExtensionsActivity.this),
+                    new ImageCapture.OnImageSavedCallback() {
+                        @Override
+                        public void onImageSaved(@NonNull File file) {
+                            Log.d(TAG, "Saved image to " + file);
 
-                                        if (!mTakePictureIdlingResource.isIdleNow()) {
-                                            mTakePictureIdlingResource.decrement();
-                                        }
+                            if (!mTakePictureIdlingResource.isIdleNow()) {
+                                mTakePictureIdlingResource.decrement();
+                            }
 
-                                        // Trigger MediaScanner to scan the file
-                                        Intent intent = new Intent(
-                                                Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
-                                        intent.setData(Uri.fromFile(file));
-                                        sendBroadcast(intent);
+                            // Trigger MediaScanner to scan the file
+                            Intent intent = new Intent(
+                                    Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
+                            intent.setData(Uri.fromFile(file));
+                            sendBroadcast(intent);
 
-                                        Toast.makeText(getApplicationContext(),
-                                                "Saved image to " + file,
-                                                Toast.LENGTH_SHORT).show();
-                                    }
+                            Toast.makeText(getApplicationContext(),
+                                    "Saved image to " + file,
+                                    Toast.LENGTH_SHORT).show();
+                        }
 
-                                    @Override
-                                    public void onError(
-                                            @ImageCapture.ImageCaptureError int error,
-                                            @NonNull String message,
-                                            Throwable cause) {
-                                        Log.e(TAG, "Failed to save image - " + message, cause);
-                                    }
-                                });
-                    }
-                });
+                        @Override
+                        public void onError(
+                                @ImageCapture.ImageCaptureError int error,
+                                @NonNull String message,
+                                Throwable cause) {
+                            Log.e(TAG, "Failed to save image - " + message, cause);
+                        }
+                    });
+        });
     }
 
     void disableImageCapture() {
@@ -341,12 +334,8 @@
 
     /** Creates all the use cases. */
     private void createUseCases() {
-        ExtensionsManager.setExtensionsErrorListener(new ExtensionsErrorListener() {
-            @Override
-            public void onError(@NonNull ExtensionsErrorCode errorCode) {
-                Log.d(TAG, "Extensions error in error code: " + errorCode);
-            }
-        });
+        ExtensionsManager.setExtensionsErrorListener((errorCode) ->
+                Log.d(TAG, "Extensions error in error code: " + errorCode));
         createImageCapture();
         createPreview();
         bindUseCases();
@@ -428,11 +417,11 @@
 
         try {
             Log.d(TAG, "Camera Facing: " + mCurrentCameraFacing);
-            @LensFacing int facing;
+            @CameraSelector.LensFacing int facing;
             if (mCurrentCameraFacing.equalsIgnoreCase("BACK")) {
-                facing = LensFacing.BACK;
+                facing = CameraSelector.LENS_FACING_BACK;
             } else if (mCurrentCameraFacing.equalsIgnoreCase("FRONT")) {
-                facing = LensFacing.FRONT;
+                facing = CameraSelector.LENS_FACING_FRONT;
             } else {
                 throw new RuntimeException("Invalid lens facing: " + mCurrentCameraFacing);
             }
@@ -460,7 +449,7 @@
 
                     }
                 },
-                CameraXExecutors.mainThreadExecutor()
+                ContextCompat.getMainExecutor(CameraExtensionsActivity.this)
         );
     }
 
diff --git a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXController.kt b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXController.kt
index c16176d..a70eb41 100644
--- a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXController.kt
+++ b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXController.kt
@@ -27,7 +27,6 @@
 import androidx.camera.camera2.interop.ExperimentalCamera2Interop
 import androidx.camera.core.CameraSelector
 import androidx.camera.core.ImageCapture
-import androidx.camera.core.LensFacing
 import androidx.camera.core.Preview
 import androidx.camera.core.impl.utils.executor.CameraXExecutors
 import androidx.camera.integration.antelope.CameraParams
@@ -135,7 +134,11 @@
         // TODO: As of 0.3.0 CameraX can only use front and back cameras.
         //  Update in future versions
         val cameraProviderFuture = ProcessCameraProvider.getInstance(activity)
-        val cameraXcameraID = if (params.id.equals("0")) LensFacing.BACK else LensFacing.FRONT
+        val cameraXcameraID = if (params.id == "0") {
+            CameraSelector.LENS_FACING_BACK
+        } else {
+            CameraSelector.LENS_FACING_FRONT
+        }
         val cameraSelector = CameraSelector.Builder().requireLensFacing(cameraXcameraID).build()
         when (testConfig.currentRunningTest) {
             //  Only the preview is required
@@ -333,8 +336,8 @@
     sessionCaptureCallback: CameraCaptureSession.CaptureCallback
 ): ImageCapture.Builder {
 
-    val configBuilder = ImageCapture.Builder()
-        .setCaptureMode(ImageCapture.CaptureMode.MAXIMIZE_QUALITY)
+    val configBuilder =
+        ImageCapture.Builder().setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
     Camera2Interop.Extender(configBuilder)
         .setDeviceStateCallback(deviceStateCallback)
         .setSessionCaptureCallback(sessionCaptureCallback)
diff --git a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CameraViewFragment.java b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CameraViewFragment.java
index 1c1c84d..000a7eb4 100644
--- a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CameraViewFragment.java
+++ b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CameraViewFragment.java
@@ -30,7 +30,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.camera.core.LensFacing;
+import androidx.camera.core.CameraSelector;
 import androidx.camera.view.CameraView;
 import androidx.camera.view.CameraView.CaptureMode;
 import androidx.camera.view.CameraView.ScaleType;
@@ -100,8 +100,9 @@
                     cameraDirectionString != null && (cameraDirectionString.equalsIgnoreCase("BACK")
                             || cameraDirectionString.equalsIgnoreCase("FRONT"));
             if (isCameraDirectionValid) {
-                @LensFacing int lensFacing = cameraDirectionString.equalsIgnoreCase("BACK")
-                        ? LensFacing.BACK : LensFacing.FRONT;
+                @CameraSelector.LensFacing int lensFacing = cameraDirectionString.equalsIgnoreCase(
+                        "BACK")
+                        ? CameraSelector.LENS_FACING_BACK : CameraSelector.LENS_FACING_FRONT;
                 mCameraView.setCameraLensFacing(lensFacing);
             }
 
@@ -133,11 +134,13 @@
 
         if (mToggleCameraButton != null) {
             mToggleCameraButton.setVisibility(
-                    (mCameraView.hasCameraWithLensFacing(LensFacing.BACK)
-                            && mCameraView.hasCameraWithLensFacing(LensFacing.FRONT))
+                    (mCameraView.hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK)
+                            && mCameraView.hasCameraWithLensFacing(
+                            CameraSelector.LENS_FACING_FRONT))
                             ? View.VISIBLE
                             : View.INVISIBLE);
-            mToggleCameraButton.setChecked(mCameraView.getCameraLensFacing() == LensFacing.FRONT);
+            mToggleCameraButton.setChecked(
+                    mCameraView.getCameraLensFacing() == CameraSelector.LENS_FACING_FRONT);
         }
 
         // Set listeners here, or else restoring state will trigger them.
@@ -147,7 +150,8 @@
                         @Override
                         public void onCheckedChanged(CompoundButton b, boolean checked) {
                             mCameraView.setCameraLensFacing(
-                                    checked ? LensFacing.FRONT : LensFacing.BACK);
+                                    checked ? CameraSelector.LENS_FACING_FRONT
+                                            : CameraSelector.LENS_FACING_BACK);
                         }
                     });
         }
diff --git a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CaptureViewOnTouchListener.java b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CaptureViewOnTouchListener.java
index 6e4e506..e0360e4 100644
--- a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CaptureViewOnTouchListener.java
+++ b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CaptureViewOnTouchListener.java
@@ -36,9 +36,9 @@
 import androidx.camera.core.ImageCapture.OnImageSavedCallback;
 import androidx.camera.core.VideoCapture.OnVideoSavedCallback;
 import androidx.camera.core.VideoCapture.VideoCaptureError;
-import androidx.camera.core.impl.utils.executor.CameraXExecutors;
 import androidx.camera.view.CameraView;
 import androidx.camera.view.CameraView.CaptureMode;
+import androidx.core.content.ContextCompat;
 
 import java.io.File;
 import java.text.SimpleDateFormat;
@@ -104,7 +104,7 @@
         if (mCameraView.getCaptureMode() == CaptureMode.IMAGE
                 || mCameraView.getCaptureMode() == CaptureMode.MIXED) {
             mCameraView.takePicture(createNewFile(PHOTO_EXTENSION),
-                    CameraXExecutors.mainThreadExecutor(), this);
+                    ContextCompat.getMainExecutor(mCameraView.getContext()), this);
         }
     }
 
@@ -113,7 +113,7 @@
         if (mCameraView.getCaptureMode() == CaptureMode.VIDEO
                 || mCameraView.getCaptureMode() == CaptureMode.MIXED) {
             mCameraView.startRecording(createNewFile(VIDEO_EXTENSION),
-                    CameraXExecutors.mainThreadExecutor(), this);
+                    ContextCompat.getMainExecutor(mCameraView.getContext()), this);
         }
     }
 
diff --git a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/PreviewViewFragment.java b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/PreviewViewFragment.java
index ed4a49a..821609b 100644
--- a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/PreviewViewFragment.java
+++ b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/PreviewViewFragment.java
@@ -27,7 +27,6 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.camera.core.CameraSelector;
-import androidx.camera.core.LensFacing;
 import androidx.camera.core.Preview;
 import androidx.camera.lifecycle.ProcessCameraProvider;
 import androidx.camera.view.PreviewView;
@@ -106,7 +105,8 @@
         preview.setPreviewSurfaceProvider(mPreviewView.getPreviewSurfaceProvider());
 
         CameraSelector cameraSelector =
-                new CameraSelector.Builder().requireLensFacing(LensFacing.BACK).build();
+                new CameraSelector.Builder().requireLensFacing(
+                        CameraSelector.LENS_FACING_BACK).build();
         cameraProvider.bindToLifecycle(PreviewViewFragment.this, cameraSelector, preview);
     }
 
diff --git a/cleanBuild.sh b/cleanBuild.sh
index 0672097..6e89563 100755
--- a/cleanBuild.sh
+++ b/cleanBuild.sh
@@ -59,15 +59,17 @@
 }
 confirm
 
-export OUT_DIR=../../out
+scriptDir="$(cd $(dirname $0) && pwd)"
+checkoutDir="$(cd $scriptDir/../.. && pwd)"
+export OUT_DIR="$checkoutDir/out"
 function removeCaches() {
   echo removing caches
   rm -rf .gradle
   rm -rf buildSrc/.gradle
   rm -f local.properties
-  rm -rf ../../out
+  rm -rf $OUT_DIR
 }
 removeCaches
 
 echo running build
-GRADLE_USER_HOME=../../out ./gradlew --no-daemon $goals
+./gradlew --no-daemon $goals
diff --git a/collection/collection-ktx/build.gradle b/collection/collection-ktx/build.gradle
index c080584..72a1cd1 100644
--- a/collection/collection-ktx/build.gradle
+++ b/collection/collection-ktx/build.gradle
@@ -25,11 +25,11 @@
 }
 
 dependencies {
-    compile(project(":collection:collection"))
-    compile(KOTLIN_STDLIB)
-    testCompile(JUNIT)
-    testCompile(TRUTH)
-    testCompile(project(":internal-testutils-truth"))
+    api(project(":collection:collection"))
+    api(KOTLIN_STDLIB)
+    testImplementation(JUNIT)
+    testImplementation(TRUTH)
+    testImplementation(project(":internal-testutils-truth"))
 }
 
 androidx {
diff --git a/collection/collection/build.gradle b/collection/collection/build.gradle
index d6dc85b..376fc06 100644
--- a/collection/collection/build.gradle
+++ b/collection/collection/build.gradle
@@ -28,9 +28,9 @@
 sourceCompatibility = JavaVersion.VERSION_1_7
 
 dependencies {
-    compile("androidx.annotation:annotation:1.1.0")
+    api("androidx.annotation:annotation:1.1.0")
     annotationProcessor(NULLAWAY)
-    testCompile(JUNIT)
+    testImplementation(JUNIT)
 }
 
 androidx {
diff --git a/concurrent/futures/build.gradle b/concurrent/futures/build.gradle
index 0fecae1..b2027a5 100644
--- a/concurrent/futures/build.gradle
+++ b/concurrent/futures/build.gradle
@@ -26,10 +26,10 @@
 }
 
 dependencies {
-    compile("androidx.annotation:annotation:1.1.0")
-    compile(GUAVA_LISTENABLE_FUTURE)
-    testCompile(JUNIT)
-    testCompile(TRUTH)
+    api("androidx.annotation:annotation:1.1.0")
+    api(GUAVA_LISTENABLE_FUTURE)
+    testImplementation(JUNIT)
+    testImplementation(TRUTH)
 }
 
 sourceCompatibility = JavaVersion.VERSION_1_7
diff --git a/development/apilint.py b/development/apilint.py
index ad3d8d5..e523d26 100755
--- a/development/apilint.py
+++ b/development/apilint.py
@@ -19,19 +19,28 @@
 """Script that will remind developers to run updateApi."""
 
 import argparse
+import os.path
 import sys
 
 
-WARNING_COLOR = '\033[93m'
+
+WARNING_COLOR = '\033[33m'
 END_COLOR = '\033[0m'
 
-WARNING = """
+WARNING_NO_API_FILES = """
 {}**********************************************************************
 You changed library classes, but you have no current.txt changes.
 Did you forget to run ./gradlew updateApi?
 **********************************************************************{}
 """.format(WARNING_COLOR, END_COLOR)
 
+WARNING_OLD_API_FILES = """
+{}**********************************************************************
+Your current.txt is older than your current changes in library classes.
+Did you forget to re-run ./gradlew updateApi?
+**********************************************************************{}
+""".format(WARNING_COLOR, END_COLOR)
+
 
 def main(args=None):
   parser = argparse.ArgumentParser()
@@ -40,16 +49,24 @@
   args = parser.parse_args()
   api_files = [f for f in args.file
                if f.endswith('.txt') and '/api/' in f]
-  if len(api_files) > 0:
+  source_files = [f for f in args.file
+               if (not "buildSrc/" in f and
+                  "/src/main/" in f or
+                  "/src/commonMain/" in f or
+                  "/src/androidMain/" in f)]
+  if len(source_files) == 0:
     sys.exit(0)
 
-  for f in args.file:
-    if (not "buildSrc/" in f and
-        "/src/main/" in f or
-        "/src/commonMain/" in f or
-        "/src/androidMain/" in f):
-      print(WARNING)
-      sys.exit(77) # 77 is a warning code in repohooks
+  if len(api_files) == 0:
+    print(WARNING_NO_API_FILES)
+    sys.exit(77) # 77 is a warning code in repohooks
+
+  last_source_timestamp = max([os.path.getmtime(f) for f in source_files])
+  last_api_timestamp = max([os.path.getmtime(f) for f in api_files])
+
+  if last_source_timestamp > last_api_timestamp:
+    print(WARNING_OLD_API_FILES)
+    sys.exit(77) # 77 is a warning code in repohooks
   sys.exit(0)
 
 if __name__ == '__main__':
diff --git a/development/importMaven/build.gradle.kts b/development/importMaven/build.gradle.kts
index 1195623..ca40116 100644
--- a/development/importMaven/build.gradle.kts
+++ b/development/importMaven/build.gradle.kts
@@ -149,6 +149,31 @@
     mavenCentral()
     google()
     gradlePluginPortal()
+
+    ivy {
+        setUrl("https://download.jetbrains.com/kotlin/native/builds/releases")
+        patternLayout {
+            artifact("[revision]/macos/[artifact]-[revision].[ext]")
+        }
+        metadataSources {
+            artifact()
+        }
+        content {
+            includeGroup("")
+        }
+    }
+    ivy {
+        setUrl("https://download.jetbrains.com/kotlin/native/builds/releases")
+        patternLayout {
+            artifact("[revision]/linux/[artifact]-[revision].[ext]")
+        }
+        metadataSources {
+            artifact()
+        }
+        content {
+            includeGroup("")
+        }
+    }
 }
 
 if (artifactName != null) {
@@ -386,7 +411,7 @@
     val folder = if (internal) internalFolder else externalFolder
     val moduleVersionId = artifact.moduleVersion.id
     val group = moduleVersionId.group
-    val groupPath = group.split(".").joinToString("/")
+    val groupPath = groupToPath(group)
     val pathComponents = listOf(
         prebuiltsLocation,
         folder,
@@ -436,7 +461,7 @@
     internal: Boolean = false
 ) {
     val folder = if (internal) internalFolder else externalFolder
-    val groupPath = group.split(".").joinToString("/")
+    val groupPath = groupToPath(group)
     val pathComponents = listOf(
         prebuiltsLocation,
         folder,
@@ -476,6 +501,17 @@
     }
 }
 
+/**
+ * Given a groupId, returns a relative filepath telling where to place that group
+ */
+fun groupToPath(group: String): String {
+    if (group != "") {
+        return group.split(".").joinToString("/")
+    } else {
+        return "no-group"
+    }
+}
+
 tasks {
     val fetchArtifacts by creating {
         doLast {
diff --git a/development/importMaven/import_maven_artifacts.py b/development/importMaven/import_maven_artifacts.py
index ea24127..319a600 100755
--- a/development/importMaven/import_maven_artifacts.py
+++ b/development/importMaven/import_maven_artifacts.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 """
 Copyright 2018 The Android Open Source Project
@@ -23,6 +23,7 @@
   E.g. android.arch.work:work-runtime-ktx:1.0.0-alpha07
 '''
 
+if sys.version_info[0] < 3: raise Exception("Python 2 is not supported by this script. If your system python calls python 2 after python 2 end-of-life on Jan 1 2020, you should probably change it.")
 
 def main():
     """Parses the command line arguments, and executes the gradle script
@@ -35,13 +36,39 @@
                         required=True, dest='name')
     parse_result = parser.parse_args()
     artifact_name = parse_result.name
+    if ("kotlin-native-linux" in artifact_name): artifact_name = fix_kotlin_native(artifact_name)
+
     command = './gradlew --build-file build.gradle.kts -PartifactName=%s' % (
         artifact_name)
     process = subprocess.Popen(command,
                                shell=True,
                                stdin=subprocess.PIPE)
     process.communicate()
+    assert not process.returncode
 
+    # Generate our own .pom file so Gradle will use this artifact without also checking the internet.
+    # This can be removed once https://youtrack.jetbrains.com/issue/KT-35049 is resolved
+    if ("kotlin-native-linux" in artifact_name):
+      version = artifact_name.split("@")[0].split(":")[2]
+      output_file = open(f"../../../.././prebuilts/androidx/external/no-group/kotlin-native-linux/{version}/kotlin-native-linux-{version}.pom", 'w+')
+      output_file.write(f"""
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.jetbrains.kotlin</groupId>
+  <artifactId>kotlin-native-linux</artifactId>
+  <version>{version}</version>
+  <name>kotlin-native-linux</name>
+  <url>https://download.jetbrains.com/kotlin/native/builds</url>
+</project>\n""")
+      output_file.close()
+
+#kotlin-native-linux has weird syntax requirements; needs to be :kotlin-native-linux:VERSION@tar.gz
+def fix_kotlin_native(name_arg):
+  if name_arg[0]!=":": name_arg = ":"+name_arg
+  if not name_arg.endswith("@tar.gz"): name_arg += "@tar.gz"
+  return name_arg
 
 if __name__ == '__main__':
     main()
diff --git a/exifinterface/api/1.2.0-beta01.txt b/exifinterface/api/1.2.0-beta01.txt
new file mode 100644
index 0000000..4bbc2ba
--- /dev/null
+++ b/exifinterface/api/1.2.0-beta01.txt
@@ -0,0 +1,347 @@
+// Signature format: 3.0
+package androidx.exifinterface.media {
+
+  public class ExifInterface {
+    ctor public ExifInterface(java.io.File) throws java.io.IOException;
+    ctor public ExifInterface(String) throws java.io.IOException;
+    ctor public ExifInterface(java.io.FileDescriptor) throws java.io.IOException;
+    ctor public ExifInterface(java.io.InputStream) throws java.io.IOException;
+    ctor public ExifInterface(java.io.InputStream, int) throws java.io.IOException;
+    method public void flipHorizontally();
+    method public void flipVertically();
+    method public double getAltitude(double);
+    method public String? getAttribute(String);
+    method public byte[]? getAttributeBytes(String);
+    method public double getAttributeDouble(String, double);
+    method public int getAttributeInt(String, int);
+    method public long[]? getAttributeRange(String);
+    method @Deprecated public boolean getLatLong(float[]!);
+    method public double[]? getLatLong();
+    method public int getRotationDegrees();
+    method public byte[]? getThumbnail();
+    method public android.graphics.Bitmap? getThumbnailBitmap();
+    method public byte[]? getThumbnailBytes();
+    method public long[]? getThumbnailRange();
+    method public boolean hasAttribute(String);
+    method public boolean hasThumbnail();
+    method public boolean isFlipped();
+    method public static boolean isSupportedMimeType(String);
+    method public boolean isThumbnailCompressed();
+    method public void resetOrientation();
+    method public void rotate(int);
+    method public void saveAttributes() throws java.io.IOException;
+    method public void setAltitude(double);
+    method public void setAttribute(String, String?);
+    method public void setGpsInfo(android.location.Location!);
+    method public void setLatLong(double, double);
+    field public static final short ALTITUDE_ABOVE_SEA_LEVEL = 0; // 0x0
+    field public static final short ALTITUDE_BELOW_SEA_LEVEL = 1; // 0x1
+    field public static final int[]! BITS_PER_SAMPLE_GREYSCALE_1;
+    field public static final int[]! BITS_PER_SAMPLE_GREYSCALE_2;
+    field public static final int[]! BITS_PER_SAMPLE_RGB;
+    field public static final int COLOR_SPACE_S_RGB = 1; // 0x1
+    field public static final int COLOR_SPACE_UNCALIBRATED = 65535; // 0xffff
+    field public static final short CONTRAST_HARD = 2; // 0x2
+    field public static final short CONTRAST_NORMAL = 0; // 0x0
+    field public static final short CONTRAST_SOFT = 1; // 0x1
+    field public static final int DATA_DEFLATE_ZIP = 8; // 0x8
+    field public static final int DATA_HUFFMAN_COMPRESSED = 2; // 0x2
+    field public static final int DATA_JPEG = 6; // 0x6
+    field public static final int DATA_JPEG_COMPRESSED = 7; // 0x7
+    field public static final int DATA_LOSSY_JPEG = 34892; // 0x884c
+    field public static final int DATA_PACK_BITS_COMPRESSED = 32773; // 0x8005
+    field public static final int DATA_UNCOMPRESSED = 1; // 0x1
+    field public static final short EXPOSURE_MODE_AUTO = 0; // 0x0
+    field public static final short EXPOSURE_MODE_AUTO_BRACKET = 2; // 0x2
+    field public static final short EXPOSURE_MODE_MANUAL = 1; // 0x1
+    field public static final short EXPOSURE_PROGRAM_ACTION = 6; // 0x6
+    field public static final short EXPOSURE_PROGRAM_APERTURE_PRIORITY = 3; // 0x3
+    field public static final short EXPOSURE_PROGRAM_CREATIVE = 5; // 0x5
+    field public static final short EXPOSURE_PROGRAM_LANDSCAPE_MODE = 8; // 0x8
+    field public static final short EXPOSURE_PROGRAM_MANUAL = 1; // 0x1
+    field public static final short EXPOSURE_PROGRAM_NORMAL = 2; // 0x2
+    field public static final short EXPOSURE_PROGRAM_NOT_DEFINED = 0; // 0x0
+    field public static final short EXPOSURE_PROGRAM_PORTRAIT_MODE = 7; // 0x7
+    field public static final short EXPOSURE_PROGRAM_SHUTTER_PRIORITY = 4; // 0x4
+    field public static final short FILE_SOURCE_DSC = 3; // 0x3
+    field public static final short FILE_SOURCE_OTHER = 0; // 0x0
+    field public static final short FILE_SOURCE_REFLEX_SCANNER = 2; // 0x2
+    field public static final short FILE_SOURCE_TRANSPARENT_SCANNER = 1; // 0x1
+    field public static final short FLAG_FLASH_FIRED = 1; // 0x1
+    field public static final short FLAG_FLASH_MODE_AUTO = 24; // 0x18
+    field public static final short FLAG_FLASH_MODE_COMPULSORY_FIRING = 8; // 0x8
+    field public static final short FLAG_FLASH_MODE_COMPULSORY_SUPPRESSION = 16; // 0x10
+    field public static final short FLAG_FLASH_NO_FLASH_FUNCTION = 32; // 0x20
+    field public static final short FLAG_FLASH_RED_EYE_SUPPORTED = 64; // 0x40
+    field public static final short FLAG_FLASH_RETURN_LIGHT_DETECTED = 6; // 0x6
+    field public static final short FLAG_FLASH_RETURN_LIGHT_NOT_DETECTED = 4; // 0x4
+    field public static final short FORMAT_CHUNKY = 1; // 0x1
+    field public static final short FORMAT_PLANAR = 2; // 0x2
+    field public static final short GAIN_CONTROL_HIGH_GAIN_DOWN = 4; // 0x4
+    field public static final short GAIN_CONTROL_HIGH_GAIN_UP = 2; // 0x2
+    field public static final short GAIN_CONTROL_LOW_GAIN_DOWN = 3; // 0x3
+    field public static final short GAIN_CONTROL_LOW_GAIN_UP = 1; // 0x1
+    field public static final short GAIN_CONTROL_NONE = 0; // 0x0
+    field public static final String GPS_DIRECTION_MAGNETIC = "M";
+    field public static final String GPS_DIRECTION_TRUE = "T";
+    field public static final String GPS_DISTANCE_KILOMETERS = "K";
+    field public static final String GPS_DISTANCE_MILES = "M";
+    field public static final String GPS_DISTANCE_NAUTICAL_MILES = "N";
+    field public static final String GPS_MEASUREMENT_2D = "2";
+    field public static final String GPS_MEASUREMENT_3D = "3";
+    field public static final short GPS_MEASUREMENT_DIFFERENTIAL_CORRECTED = 1; // 0x1
+    field public static final String GPS_MEASUREMENT_INTERRUPTED = "V";
+    field public static final String GPS_MEASUREMENT_IN_PROGRESS = "A";
+    field public static final short GPS_MEASUREMENT_NO_DIFFERENTIAL = 0; // 0x0
+    field public static final String GPS_SPEED_KILOMETERS_PER_HOUR = "K";
+    field public static final String GPS_SPEED_KNOTS = "N";
+    field public static final String GPS_SPEED_MILES_PER_HOUR = "M";
+    field public static final String LATITUDE_NORTH = "N";
+    field public static final String LATITUDE_SOUTH = "S";
+    field public static final short LIGHT_SOURCE_CLOUDY_WEATHER = 10; // 0xa
+    field public static final short LIGHT_SOURCE_COOL_WHITE_FLUORESCENT = 14; // 0xe
+    field public static final short LIGHT_SOURCE_D50 = 23; // 0x17
+    field public static final short LIGHT_SOURCE_D55 = 20; // 0x14
+    field public static final short LIGHT_SOURCE_D65 = 21; // 0x15
+    field public static final short LIGHT_SOURCE_D75 = 22; // 0x16
+    field public static final short LIGHT_SOURCE_DAYLIGHT = 1; // 0x1
+    field public static final short LIGHT_SOURCE_DAYLIGHT_FLUORESCENT = 12; // 0xc
+    field public static final short LIGHT_SOURCE_DAY_WHITE_FLUORESCENT = 13; // 0xd
+    field public static final short LIGHT_SOURCE_FINE_WEATHER = 9; // 0x9
+    field public static final short LIGHT_SOURCE_FLASH = 4; // 0x4
+    field public static final short LIGHT_SOURCE_FLUORESCENT = 2; // 0x2
+    field public static final short LIGHT_SOURCE_ISO_STUDIO_TUNGSTEN = 24; // 0x18
+    field public static final short LIGHT_SOURCE_OTHER = 255; // 0xff
+    field public static final short LIGHT_SOURCE_SHADE = 11; // 0xb
+    field public static final short LIGHT_SOURCE_STANDARD_LIGHT_A = 17; // 0x11
+    field public static final short LIGHT_SOURCE_STANDARD_LIGHT_B = 18; // 0x12
+    field public static final short LIGHT_SOURCE_STANDARD_LIGHT_C = 19; // 0x13
+    field public static final short LIGHT_SOURCE_TUNGSTEN = 3; // 0x3
+    field public static final short LIGHT_SOURCE_UNKNOWN = 0; // 0x0
+    field public static final short LIGHT_SOURCE_WARM_WHITE_FLUORESCENT = 16; // 0x10
+    field public static final short LIGHT_SOURCE_WHITE_FLUORESCENT = 15; // 0xf
+    field public static final String LONGITUDE_EAST = "E";
+    field public static final String LONGITUDE_WEST = "W";
+    field public static final short METERING_MODE_AVERAGE = 1; // 0x1
+    field public static final short METERING_MODE_CENTER_WEIGHT_AVERAGE = 2; // 0x2
+    field public static final short METERING_MODE_MULTI_SPOT = 4; // 0x4
+    field public static final short METERING_MODE_OTHER = 255; // 0xff
+    field public static final short METERING_MODE_PARTIAL = 6; // 0x6
+    field public static final short METERING_MODE_PATTERN = 5; // 0x5
+    field public static final short METERING_MODE_SPOT = 3; // 0x3
+    field public static final short METERING_MODE_UNKNOWN = 0; // 0x0
+    field public static final int ORIENTATION_FLIP_HORIZONTAL = 2; // 0x2
+    field public static final int ORIENTATION_FLIP_VERTICAL = 4; // 0x4
+    field public static final int ORIENTATION_NORMAL = 1; // 0x1
+    field public static final int ORIENTATION_ROTATE_180 = 3; // 0x3
+    field public static final int ORIENTATION_ROTATE_270 = 8; // 0x8
+    field public static final int ORIENTATION_ROTATE_90 = 6; // 0x6
+    field public static final int ORIENTATION_TRANSPOSE = 5; // 0x5
+    field public static final int ORIENTATION_TRANSVERSE = 7; // 0x7
+    field public static final int ORIENTATION_UNDEFINED = 0; // 0x0
+    field public static final int ORIGINAL_RESOLUTION_IMAGE = 0; // 0x0
+    field public static final int PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO = 1; // 0x1
+    field public static final int PHOTOMETRIC_INTERPRETATION_RGB = 2; // 0x2
+    field public static final int PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO = 0; // 0x0
+    field public static final int PHOTOMETRIC_INTERPRETATION_YCBCR = 6; // 0x6
+    field public static final int REDUCED_RESOLUTION_IMAGE = 1; // 0x1
+    field public static final short RENDERED_PROCESS_CUSTOM = 1; // 0x1
+    field public static final short RENDERED_PROCESS_NORMAL = 0; // 0x0
+    field public static final short RESOLUTION_UNIT_CENTIMETERS = 3; // 0x3
+    field public static final short RESOLUTION_UNIT_INCHES = 2; // 0x2
+    field public static final short SATURATION_HIGH = 0; // 0x0
+    field public static final short SATURATION_LOW = 0; // 0x0
+    field public static final short SATURATION_NORMAL = 0; // 0x0
+    field public static final short SCENE_CAPTURE_TYPE_LANDSCAPE = 1; // 0x1
+    field public static final short SCENE_CAPTURE_TYPE_NIGHT = 3; // 0x3
+    field public static final short SCENE_CAPTURE_TYPE_PORTRAIT = 2; // 0x2
+    field public static final short SCENE_CAPTURE_TYPE_STANDARD = 0; // 0x0
+    field public static final short SCENE_TYPE_DIRECTLY_PHOTOGRAPHED = 1; // 0x1
+    field public static final short SENSITIVITY_TYPE_ISO_SPEED = 3; // 0x3
+    field public static final short SENSITIVITY_TYPE_REI = 2; // 0x2
+    field public static final short SENSITIVITY_TYPE_REI_AND_ISO = 6; // 0x6
+    field public static final short SENSITIVITY_TYPE_SOS = 1; // 0x1
+    field public static final short SENSITIVITY_TYPE_SOS_AND_ISO = 5; // 0x5
+    field public static final short SENSITIVITY_TYPE_SOS_AND_REI = 4; // 0x4
+    field public static final short SENSITIVITY_TYPE_SOS_AND_REI_AND_ISO = 7; // 0x7
+    field public static final short SENSITIVITY_TYPE_UNKNOWN = 0; // 0x0
+    field public static final short SENSOR_TYPE_COLOR_SEQUENTIAL = 5; // 0x5
+    field public static final short SENSOR_TYPE_COLOR_SEQUENTIAL_LINEAR = 8; // 0x8
+    field public static final short SENSOR_TYPE_NOT_DEFINED = 1; // 0x1
+    field public static final short SENSOR_TYPE_ONE_CHIP = 2; // 0x2
+    field public static final short SENSOR_TYPE_THREE_CHIP = 4; // 0x4
+    field public static final short SENSOR_TYPE_TRILINEAR = 7; // 0x7
+    field public static final short SENSOR_TYPE_TWO_CHIP = 3; // 0x3
+    field public static final short SHARPNESS_HARD = 2; // 0x2
+    field public static final short SHARPNESS_NORMAL = 0; // 0x0
+    field public static final short SHARPNESS_SOFT = 1; // 0x1
+    field public static final int STREAM_TYPE_EXIF_DATA_ONLY = 1; // 0x1
+    field public static final int STREAM_TYPE_FULL_IMAGE_DATA = 0; // 0x0
+    field public static final short SUBJECT_DISTANCE_RANGE_CLOSE_VIEW = 2; // 0x2
+    field public static final short SUBJECT_DISTANCE_RANGE_DISTANT_VIEW = 3; // 0x3
+    field public static final short SUBJECT_DISTANCE_RANGE_MACRO = 1; // 0x1
+    field public static final short SUBJECT_DISTANCE_RANGE_UNKNOWN = 0; // 0x0
+    field public static final String TAG_APERTURE_VALUE = "ApertureValue";
+    field public static final String TAG_ARTIST = "Artist";
+    field public static final String TAG_BITS_PER_SAMPLE = "BitsPerSample";
+    field public static final String TAG_BODY_SERIAL_NUMBER = "BodySerialNumber";
+    field public static final String TAG_BRIGHTNESS_VALUE = "BrightnessValue";
+    field @Deprecated public static final String TAG_CAMARA_OWNER_NAME = "CameraOwnerName";
+    field public static final String TAG_CAMERA_OWNER_NAME = "CameraOwnerName";
+    field public static final String TAG_CFA_PATTERN = "CFAPattern";
+    field public static final String TAG_COLOR_SPACE = "ColorSpace";
+    field public static final String TAG_COMPONENTS_CONFIGURATION = "ComponentsConfiguration";
+    field public static final String TAG_COMPRESSED_BITS_PER_PIXEL = "CompressedBitsPerPixel";
+    field public static final String TAG_COMPRESSION = "Compression";
+    field public static final String TAG_CONTRAST = "Contrast";
+    field public static final String TAG_COPYRIGHT = "Copyright";
+    field public static final String TAG_CUSTOM_RENDERED = "CustomRendered";
+    field public static final String TAG_DATETIME = "DateTime";
+    field public static final String TAG_DATETIME_DIGITIZED = "DateTimeDigitized";
+    field public static final String TAG_DATETIME_ORIGINAL = "DateTimeOriginal";
+    field public static final String TAG_DEFAULT_CROP_SIZE = "DefaultCropSize";
+    field public static final String TAG_DEVICE_SETTING_DESCRIPTION = "DeviceSettingDescription";
+    field public static final String TAG_DIGITAL_ZOOM_RATIO = "DigitalZoomRatio";
+    field public static final String TAG_DNG_VERSION = "DNGVersion";
+    field public static final String TAG_EXIF_VERSION = "ExifVersion";
+    field public static final String TAG_EXPOSURE_BIAS_VALUE = "ExposureBiasValue";
+    field public static final String TAG_EXPOSURE_INDEX = "ExposureIndex";
+    field public static final String TAG_EXPOSURE_MODE = "ExposureMode";
+    field public static final String TAG_EXPOSURE_PROGRAM = "ExposureProgram";
+    field public static final String TAG_EXPOSURE_TIME = "ExposureTime";
+    field public static final String TAG_FILE_SOURCE = "FileSource";
+    field public static final String TAG_FLASH = "Flash";
+    field public static final String TAG_FLASHPIX_VERSION = "FlashpixVersion";
+    field public static final String TAG_FLASH_ENERGY = "FlashEnergy";
+    field public static final String TAG_FOCAL_LENGTH = "FocalLength";
+    field public static final String TAG_FOCAL_LENGTH_IN_35MM_FILM = "FocalLengthIn35mmFilm";
+    field public static final String TAG_FOCAL_PLANE_RESOLUTION_UNIT = "FocalPlaneResolutionUnit";
+    field public static final String TAG_FOCAL_PLANE_X_RESOLUTION = "FocalPlaneXResolution";
+    field public static final String TAG_FOCAL_PLANE_Y_RESOLUTION = "FocalPlaneYResolution";
+    field public static final String TAG_F_NUMBER = "FNumber";
+    field public static final String TAG_GAIN_CONTROL = "GainControl";
+    field public static final String TAG_GAMMA = "Gamma";
+    field public static final String TAG_GPS_ALTITUDE = "GPSAltitude";
+    field public static final String TAG_GPS_ALTITUDE_REF = "GPSAltitudeRef";
+    field public static final String TAG_GPS_AREA_INFORMATION = "GPSAreaInformation";
+    field public static final String TAG_GPS_DATESTAMP = "GPSDateStamp";
+    field public static final String TAG_GPS_DEST_BEARING = "GPSDestBearing";
+    field public static final String TAG_GPS_DEST_BEARING_REF = "GPSDestBearingRef";
+    field public static final String TAG_GPS_DEST_DISTANCE = "GPSDestDistance";
+    field public static final String TAG_GPS_DEST_DISTANCE_REF = "GPSDestDistanceRef";
+    field public static final String TAG_GPS_DEST_LATITUDE = "GPSDestLatitude";
+    field public static final String TAG_GPS_DEST_LATITUDE_REF = "GPSDestLatitudeRef";
+    field public static final String TAG_GPS_DEST_LONGITUDE = "GPSDestLongitude";
+    field public static final String TAG_GPS_DEST_LONGITUDE_REF = "GPSDestLongitudeRef";
+    field public static final String TAG_GPS_DIFFERENTIAL = "GPSDifferential";
+    field public static final String TAG_GPS_DOP = "GPSDOP";
+    field public static final String TAG_GPS_H_POSITIONING_ERROR = "GPSHPositioningError";
+    field public static final String TAG_GPS_IMG_DIRECTION = "GPSImgDirection";
+    field public static final String TAG_GPS_IMG_DIRECTION_REF = "GPSImgDirectionRef";
+    field public static final String TAG_GPS_LATITUDE = "GPSLatitude";
+    field public static final String TAG_GPS_LATITUDE_REF = "GPSLatitudeRef";
+    field public static final String TAG_GPS_LONGITUDE = "GPSLongitude";
+    field public static final String TAG_GPS_LONGITUDE_REF = "GPSLongitudeRef";
+    field public static final String TAG_GPS_MAP_DATUM = "GPSMapDatum";
+    field public static final String TAG_GPS_MEASURE_MODE = "GPSMeasureMode";
+    field public static final String TAG_GPS_PROCESSING_METHOD = "GPSProcessingMethod";
+    field public static final String TAG_GPS_SATELLITES = "GPSSatellites";
+    field public static final String TAG_GPS_SPEED = "GPSSpeed";
+    field public static final String TAG_GPS_SPEED_REF = "GPSSpeedRef";
+    field public static final String TAG_GPS_STATUS = "GPSStatus";
+    field public static final String TAG_GPS_TIMESTAMP = "GPSTimeStamp";
+    field public static final String TAG_GPS_TRACK = "GPSTrack";
+    field public static final String TAG_GPS_TRACK_REF = "GPSTrackRef";
+    field public static final String TAG_GPS_VERSION_ID = "GPSVersionID";
+    field public static final String TAG_IMAGE_DESCRIPTION = "ImageDescription";
+    field public static final String TAG_IMAGE_LENGTH = "ImageLength";
+    field public static final String TAG_IMAGE_UNIQUE_ID = "ImageUniqueID";
+    field public static final String TAG_IMAGE_WIDTH = "ImageWidth";
+    field public static final String TAG_INTEROPERABILITY_INDEX = "InteroperabilityIndex";
+    field public static final String TAG_ISO_SPEED = "ISOSpeed";
+    field public static final String TAG_ISO_SPEED_LATITUDE_YYY = "ISOSpeedLatitudeyyy";
+    field public static final String TAG_ISO_SPEED_LATITUDE_ZZZ = "ISOSpeedLatitudezzz";
+    field @Deprecated public static final String TAG_ISO_SPEED_RATINGS = "ISOSpeedRatings";
+    field public static final String TAG_JPEG_INTERCHANGE_FORMAT = "JPEGInterchangeFormat";
+    field public static final String TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = "JPEGInterchangeFormatLength";
+    field public static final String TAG_LENS_MAKE = "LensMake";
+    field public static final String TAG_LENS_MODEL = "LensModel";
+    field public static final String TAG_LENS_SERIAL_NUMBER = "LensSerialNumber";
+    field public static final String TAG_LENS_SPECIFICATION = "LensSpecification";
+    field public static final String TAG_LIGHT_SOURCE = "LightSource";
+    field public static final String TAG_MAKE = "Make";
+    field public static final String TAG_MAKER_NOTE = "MakerNote";
+    field public static final String TAG_MAX_APERTURE_VALUE = "MaxApertureValue";
+    field public static final String TAG_METERING_MODE = "MeteringMode";
+    field public static final String TAG_MODEL = "Model";
+    field public static final String TAG_NEW_SUBFILE_TYPE = "NewSubfileType";
+    field public static final String TAG_OECF = "OECF";
+    field public static final String TAG_OFFSET_TIME = "OffsetTime";
+    field public static final String TAG_OFFSET_TIME_DIGITIZED = "OffsetTimeDigitized";
+    field public static final String TAG_OFFSET_TIME_ORIGINAL = "OffsetTimeOriginal";
+    field public static final String TAG_ORF_ASPECT_FRAME = "AspectFrame";
+    field public static final String TAG_ORF_PREVIEW_IMAGE_LENGTH = "PreviewImageLength";
+    field public static final String TAG_ORF_PREVIEW_IMAGE_START = "PreviewImageStart";
+    field public static final String TAG_ORF_THUMBNAIL_IMAGE = "ThumbnailImage";
+    field public static final String TAG_ORIENTATION = "Orientation";
+    field public static final String TAG_PHOTOGRAPHIC_SENSITIVITY = "PhotographicSensitivity";
+    field public static final String TAG_PHOTOMETRIC_INTERPRETATION = "PhotometricInterpretation";
+    field public static final String TAG_PIXEL_X_DIMENSION = "PixelXDimension";
+    field public static final String TAG_PIXEL_Y_DIMENSION = "PixelYDimension";
+    field public static final String TAG_PLANAR_CONFIGURATION = "PlanarConfiguration";
+    field public static final String TAG_PRIMARY_CHROMATICITIES = "PrimaryChromaticities";
+    field public static final String TAG_RECOMMENDED_EXPOSURE_INDEX = "RecommendedExposureIndex";
+    field public static final String TAG_REFERENCE_BLACK_WHITE = "ReferenceBlackWhite";
+    field public static final String TAG_RELATED_SOUND_FILE = "RelatedSoundFile";
+    field public static final String TAG_RESOLUTION_UNIT = "ResolutionUnit";
+    field public static final String TAG_ROWS_PER_STRIP = "RowsPerStrip";
+    field public static final String TAG_RW2_ISO = "ISO";
+    field public static final String TAG_RW2_JPG_FROM_RAW = "JpgFromRaw";
+    field public static final String TAG_RW2_SENSOR_BOTTOM_BORDER = "SensorBottomBorder";
+    field public static final String TAG_RW2_SENSOR_LEFT_BORDER = "SensorLeftBorder";
+    field public static final String TAG_RW2_SENSOR_RIGHT_BORDER = "SensorRightBorder";
+    field public static final String TAG_RW2_SENSOR_TOP_BORDER = "SensorTopBorder";
+    field public static final String TAG_SAMPLES_PER_PIXEL = "SamplesPerPixel";
+    field public static final String TAG_SATURATION = "Saturation";
+    field public static final String TAG_SCENE_CAPTURE_TYPE = "SceneCaptureType";
+    field public static final String TAG_SCENE_TYPE = "SceneType";
+    field public static final String TAG_SENSING_METHOD = "SensingMethod";
+    field public static final String TAG_SENSITIVITY_TYPE = "SensitivityType";
+    field public static final String TAG_SHARPNESS = "Sharpness";
+    field public static final String TAG_SHUTTER_SPEED_VALUE = "ShutterSpeedValue";
+    field public static final String TAG_SOFTWARE = "Software";
+    field public static final String TAG_SPATIAL_FREQUENCY_RESPONSE = "SpatialFrequencyResponse";
+    field public static final String TAG_SPECTRAL_SENSITIVITY = "SpectralSensitivity";
+    field public static final String TAG_STANDARD_OUTPUT_SENSITIVITY = "StandardOutputSensitivity";
+    field public static final String TAG_STRIP_BYTE_COUNTS = "StripByteCounts";
+    field public static final String TAG_STRIP_OFFSETS = "StripOffsets";
+    field public static final String TAG_SUBFILE_TYPE = "SubfileType";
+    field public static final String TAG_SUBJECT_AREA = "SubjectArea";
+    field public static final String TAG_SUBJECT_DISTANCE = "SubjectDistance";
+    field public static final String TAG_SUBJECT_DISTANCE_RANGE = "SubjectDistanceRange";
+    field public static final String TAG_SUBJECT_LOCATION = "SubjectLocation";
+    field public static final String TAG_SUBSEC_TIME = "SubSecTime";
+    field public static final String TAG_SUBSEC_TIME_DIGITIZED = "SubSecTimeDigitized";
+    field public static final String TAG_SUBSEC_TIME_ORIGINAL = "SubSecTimeOriginal";
+    field public static final String TAG_THUMBNAIL_IMAGE_LENGTH = "ThumbnailImageLength";
+    field public static final String TAG_THUMBNAIL_IMAGE_WIDTH = "ThumbnailImageWidth";
+    field public static final String TAG_TRANSFER_FUNCTION = "TransferFunction";
+    field public static final String TAG_USER_COMMENT = "UserComment";
+    field public static final String TAG_WHITE_BALANCE = "WhiteBalance";
+    field public static final String TAG_WHITE_POINT = "WhitePoint";
+    field public static final String TAG_XMP = "Xmp";
+    field public static final String TAG_X_RESOLUTION = "XResolution";
+    field public static final String TAG_Y_CB_CR_COEFFICIENTS = "YCbCrCoefficients";
+    field public static final String TAG_Y_CB_CR_POSITIONING = "YCbCrPositioning";
+    field public static final String TAG_Y_CB_CR_SUB_SAMPLING = "YCbCrSubSampling";
+    field public static final String TAG_Y_RESOLUTION = "YResolution";
+    field @Deprecated public static final int WHITEBALANCE_AUTO = 0; // 0x0
+    field @Deprecated public static final int WHITEBALANCE_MANUAL = 1; // 0x1
+    field public static final short WHITE_BALANCE_AUTO = 0; // 0x0
+    field public static final short WHITE_BALANCE_MANUAL = 1; // 0x1
+    field public static final short Y_CB_CR_POSITIONING_CENTERED = 1; // 0x1
+    field public static final short Y_CB_CR_POSITIONING_CO_SITED = 2; // 0x2
+  }
+
+}
+
diff --git a/exifinterface/api/public_plus_experimental_1.2.0-beta01.txt b/exifinterface/api/public_plus_experimental_1.2.0-beta01.txt
new file mode 100644
index 0000000..4bbc2ba
--- /dev/null
+++ b/exifinterface/api/public_plus_experimental_1.2.0-beta01.txt
@@ -0,0 +1,347 @@
+// Signature format: 3.0
+package androidx.exifinterface.media {
+
+  public class ExifInterface {
+    ctor public ExifInterface(java.io.File) throws java.io.IOException;
+    ctor public ExifInterface(String) throws java.io.IOException;
+    ctor public ExifInterface(java.io.FileDescriptor) throws java.io.IOException;
+    ctor public ExifInterface(java.io.InputStream) throws java.io.IOException;
+    ctor public ExifInterface(java.io.InputStream, int) throws java.io.IOException;
+    method public void flipHorizontally();
+    method public void flipVertically();
+    method public double getAltitude(double);
+    method public String? getAttribute(String);
+    method public byte[]? getAttributeBytes(String);
+    method public double getAttributeDouble(String, double);
+    method public int getAttributeInt(String, int);
+    method public long[]? getAttributeRange(String);
+    method @Deprecated public boolean getLatLong(float[]!);
+    method public double[]? getLatLong();
+    method public int getRotationDegrees();
+    method public byte[]? getThumbnail();
+    method public android.graphics.Bitmap? getThumbnailBitmap();
+    method public byte[]? getThumbnailBytes();
+    method public long[]? getThumbnailRange();
+    method public boolean hasAttribute(String);
+    method public boolean hasThumbnail();
+    method public boolean isFlipped();
+    method public static boolean isSupportedMimeType(String);
+    method public boolean isThumbnailCompressed();
+    method public void resetOrientation();
+    method public void rotate(int);
+    method public void saveAttributes() throws java.io.IOException;
+    method public void setAltitude(double);
+    method public void setAttribute(String, String?);
+    method public void setGpsInfo(android.location.Location!);
+    method public void setLatLong(double, double);
+    field public static final short ALTITUDE_ABOVE_SEA_LEVEL = 0; // 0x0
+    field public static final short ALTITUDE_BELOW_SEA_LEVEL = 1; // 0x1
+    field public static final int[]! BITS_PER_SAMPLE_GREYSCALE_1;
+    field public static final int[]! BITS_PER_SAMPLE_GREYSCALE_2;
+    field public static final int[]! BITS_PER_SAMPLE_RGB;
+    field public static final int COLOR_SPACE_S_RGB = 1; // 0x1
+    field public static final int COLOR_SPACE_UNCALIBRATED = 65535; // 0xffff
+    field public static final short CONTRAST_HARD = 2; // 0x2
+    field public static final short CONTRAST_NORMAL = 0; // 0x0
+    field public static final short CONTRAST_SOFT = 1; // 0x1
+    field public static final int DATA_DEFLATE_ZIP = 8; // 0x8
+    field public static final int DATA_HUFFMAN_COMPRESSED = 2; // 0x2
+    field public static final int DATA_JPEG = 6; // 0x6
+    field public static final int DATA_JPEG_COMPRESSED = 7; // 0x7
+    field public static final int DATA_LOSSY_JPEG = 34892; // 0x884c
+    field public static final int DATA_PACK_BITS_COMPRESSED = 32773; // 0x8005
+    field public static final int DATA_UNCOMPRESSED = 1; // 0x1
+    field public static final short EXPOSURE_MODE_AUTO = 0; // 0x0
+    field public static final short EXPOSURE_MODE_AUTO_BRACKET = 2; // 0x2
+    field public static final short EXPOSURE_MODE_MANUAL = 1; // 0x1
+    field public static final short EXPOSURE_PROGRAM_ACTION = 6; // 0x6
+    field public static final short EXPOSURE_PROGRAM_APERTURE_PRIORITY = 3; // 0x3
+    field public static final short EXPOSURE_PROGRAM_CREATIVE = 5; // 0x5
+    field public static final short EXPOSURE_PROGRAM_LANDSCAPE_MODE = 8; // 0x8
+    field public static final short EXPOSURE_PROGRAM_MANUAL = 1; // 0x1
+    field public static final short EXPOSURE_PROGRAM_NORMAL = 2; // 0x2
+    field public static final short EXPOSURE_PROGRAM_NOT_DEFINED = 0; // 0x0
+    field public static final short EXPOSURE_PROGRAM_PORTRAIT_MODE = 7; // 0x7
+    field public static final short EXPOSURE_PROGRAM_SHUTTER_PRIORITY = 4; // 0x4
+    field public static final short FILE_SOURCE_DSC = 3; // 0x3
+    field public static final short FILE_SOURCE_OTHER = 0; // 0x0
+    field public static final short FILE_SOURCE_REFLEX_SCANNER = 2; // 0x2
+    field public static final short FILE_SOURCE_TRANSPARENT_SCANNER = 1; // 0x1
+    field public static final short FLAG_FLASH_FIRED = 1; // 0x1
+    field public static final short FLAG_FLASH_MODE_AUTO = 24; // 0x18
+    field public static final short FLAG_FLASH_MODE_COMPULSORY_FIRING = 8; // 0x8
+    field public static final short FLAG_FLASH_MODE_COMPULSORY_SUPPRESSION = 16; // 0x10
+    field public static final short FLAG_FLASH_NO_FLASH_FUNCTION = 32; // 0x20
+    field public static final short FLAG_FLASH_RED_EYE_SUPPORTED = 64; // 0x40
+    field public static final short FLAG_FLASH_RETURN_LIGHT_DETECTED = 6; // 0x6
+    field public static final short FLAG_FLASH_RETURN_LIGHT_NOT_DETECTED = 4; // 0x4
+    field public static final short FORMAT_CHUNKY = 1; // 0x1
+    field public static final short FORMAT_PLANAR = 2; // 0x2
+    field public static final short GAIN_CONTROL_HIGH_GAIN_DOWN = 4; // 0x4
+    field public static final short GAIN_CONTROL_HIGH_GAIN_UP = 2; // 0x2
+    field public static final short GAIN_CONTROL_LOW_GAIN_DOWN = 3; // 0x3
+    field public static final short GAIN_CONTROL_LOW_GAIN_UP = 1; // 0x1
+    field public static final short GAIN_CONTROL_NONE = 0; // 0x0
+    field public static final String GPS_DIRECTION_MAGNETIC = "M";
+    field public static final String GPS_DIRECTION_TRUE = "T";
+    field public static final String GPS_DISTANCE_KILOMETERS = "K";
+    field public static final String GPS_DISTANCE_MILES = "M";
+    field public static final String GPS_DISTANCE_NAUTICAL_MILES = "N";
+    field public static final String GPS_MEASUREMENT_2D = "2";
+    field public static final String GPS_MEASUREMENT_3D = "3";
+    field public static final short GPS_MEASUREMENT_DIFFERENTIAL_CORRECTED = 1; // 0x1
+    field public static final String GPS_MEASUREMENT_INTERRUPTED = "V";
+    field public static final String GPS_MEASUREMENT_IN_PROGRESS = "A";
+    field public static final short GPS_MEASUREMENT_NO_DIFFERENTIAL = 0; // 0x0
+    field public static final String GPS_SPEED_KILOMETERS_PER_HOUR = "K";
+    field public static final String GPS_SPEED_KNOTS = "N";
+    field public static final String GPS_SPEED_MILES_PER_HOUR = "M";
+    field public static final String LATITUDE_NORTH = "N";
+    field public static final String LATITUDE_SOUTH = "S";
+    field public static final short LIGHT_SOURCE_CLOUDY_WEATHER = 10; // 0xa
+    field public static final short LIGHT_SOURCE_COOL_WHITE_FLUORESCENT = 14; // 0xe
+    field public static final short LIGHT_SOURCE_D50 = 23; // 0x17
+    field public static final short LIGHT_SOURCE_D55 = 20; // 0x14
+    field public static final short LIGHT_SOURCE_D65 = 21; // 0x15
+    field public static final short LIGHT_SOURCE_D75 = 22; // 0x16
+    field public static final short LIGHT_SOURCE_DAYLIGHT = 1; // 0x1
+    field public static final short LIGHT_SOURCE_DAYLIGHT_FLUORESCENT = 12; // 0xc
+    field public static final short LIGHT_SOURCE_DAY_WHITE_FLUORESCENT = 13; // 0xd
+    field public static final short LIGHT_SOURCE_FINE_WEATHER = 9; // 0x9
+    field public static final short LIGHT_SOURCE_FLASH = 4; // 0x4
+    field public static final short LIGHT_SOURCE_FLUORESCENT = 2; // 0x2
+    field public static final short LIGHT_SOURCE_ISO_STUDIO_TUNGSTEN = 24; // 0x18
+    field public static final short LIGHT_SOURCE_OTHER = 255; // 0xff
+    field public static final short LIGHT_SOURCE_SHADE = 11; // 0xb
+    field public static final short LIGHT_SOURCE_STANDARD_LIGHT_A = 17; // 0x11
+    field public static final short LIGHT_SOURCE_STANDARD_LIGHT_B = 18; // 0x12
+    field public static final short LIGHT_SOURCE_STANDARD_LIGHT_C = 19; // 0x13
+    field public static final short LIGHT_SOURCE_TUNGSTEN = 3; // 0x3
+    field public static final short LIGHT_SOURCE_UNKNOWN = 0; // 0x0
+    field public static final short LIGHT_SOURCE_WARM_WHITE_FLUORESCENT = 16; // 0x10
+    field public static final short LIGHT_SOURCE_WHITE_FLUORESCENT = 15; // 0xf
+    field public static final String LONGITUDE_EAST = "E";
+    field public static final String LONGITUDE_WEST = "W";
+    field public static final short METERING_MODE_AVERAGE = 1; // 0x1
+    field public static final short METERING_MODE_CENTER_WEIGHT_AVERAGE = 2; // 0x2
+    field public static final short METERING_MODE_MULTI_SPOT = 4; // 0x4
+    field public static final short METERING_MODE_OTHER = 255; // 0xff
+    field public static final short METERING_MODE_PARTIAL = 6; // 0x6
+    field public static final short METERING_MODE_PATTERN = 5; // 0x5
+    field public static final short METERING_MODE_SPOT = 3; // 0x3
+    field public static final short METERING_MODE_UNKNOWN = 0; // 0x0
+    field public static final int ORIENTATION_FLIP_HORIZONTAL = 2; // 0x2
+    field public static final int ORIENTATION_FLIP_VERTICAL = 4; // 0x4
+    field public static final int ORIENTATION_NORMAL = 1; // 0x1
+    field public static final int ORIENTATION_ROTATE_180 = 3; // 0x3
+    field public static final int ORIENTATION_ROTATE_270 = 8; // 0x8
+    field public static final int ORIENTATION_ROTATE_90 = 6; // 0x6
+    field public static final int ORIENTATION_TRANSPOSE = 5; // 0x5
+    field public static final int ORIENTATION_TRANSVERSE = 7; // 0x7
+    field public static final int ORIENTATION_UNDEFINED = 0; // 0x0
+    field public static final int ORIGINAL_RESOLUTION_IMAGE = 0; // 0x0
+    field public static final int PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO = 1; // 0x1
+    field public static final int PHOTOMETRIC_INTERPRETATION_RGB = 2; // 0x2
+    field public static final int PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO = 0; // 0x0
+    field public static final int PHOTOMETRIC_INTERPRETATION_YCBCR = 6; // 0x6
+    field public static final int REDUCED_RESOLUTION_IMAGE = 1; // 0x1
+    field public static final short RENDERED_PROCESS_CUSTOM = 1; // 0x1
+    field public static final short RENDERED_PROCESS_NORMAL = 0; // 0x0
+    field public static final short RESOLUTION_UNIT_CENTIMETERS = 3; // 0x3
+    field public static final short RESOLUTION_UNIT_INCHES = 2; // 0x2
+    field public static final short SATURATION_HIGH = 0; // 0x0
+    field public static final short SATURATION_LOW = 0; // 0x0
+    field public static final short SATURATION_NORMAL = 0; // 0x0
+    field public static final short SCENE_CAPTURE_TYPE_LANDSCAPE = 1; // 0x1
+    field public static final short SCENE_CAPTURE_TYPE_NIGHT = 3; // 0x3
+    field public static final short SCENE_CAPTURE_TYPE_PORTRAIT = 2; // 0x2
+    field public static final short SCENE_CAPTURE_TYPE_STANDARD = 0; // 0x0
+    field public static final short SCENE_TYPE_DIRECTLY_PHOTOGRAPHED = 1; // 0x1
+    field public static final short SENSITIVITY_TYPE_ISO_SPEED = 3; // 0x3
+    field public static final short SENSITIVITY_TYPE_REI = 2; // 0x2
+    field public static final short SENSITIVITY_TYPE_REI_AND_ISO = 6; // 0x6
+    field public static final short SENSITIVITY_TYPE_SOS = 1; // 0x1
+    field public static final short SENSITIVITY_TYPE_SOS_AND_ISO = 5; // 0x5
+    field public static final short SENSITIVITY_TYPE_SOS_AND_REI = 4; // 0x4
+    field public static final short SENSITIVITY_TYPE_SOS_AND_REI_AND_ISO = 7; // 0x7
+    field public static final short SENSITIVITY_TYPE_UNKNOWN = 0; // 0x0
+    field public static final short SENSOR_TYPE_COLOR_SEQUENTIAL = 5; // 0x5
+    field public static final short SENSOR_TYPE_COLOR_SEQUENTIAL_LINEAR = 8; // 0x8
+    field public static final short SENSOR_TYPE_NOT_DEFINED = 1; // 0x1
+    field public static final short SENSOR_TYPE_ONE_CHIP = 2; // 0x2
+    field public static final short SENSOR_TYPE_THREE_CHIP = 4; // 0x4
+    field public static final short SENSOR_TYPE_TRILINEAR = 7; // 0x7
+    field public static final short SENSOR_TYPE_TWO_CHIP = 3; // 0x3
+    field public static final short SHARPNESS_HARD = 2; // 0x2
+    field public static final short SHARPNESS_NORMAL = 0; // 0x0
+    field public static final short SHARPNESS_SOFT = 1; // 0x1
+    field public static final int STREAM_TYPE_EXIF_DATA_ONLY = 1; // 0x1
+    field public static final int STREAM_TYPE_FULL_IMAGE_DATA = 0; // 0x0
+    field public static final short SUBJECT_DISTANCE_RANGE_CLOSE_VIEW = 2; // 0x2
+    field public static final short SUBJECT_DISTANCE_RANGE_DISTANT_VIEW = 3; // 0x3
+    field public static final short SUBJECT_DISTANCE_RANGE_MACRO = 1; // 0x1
+    field public static final short SUBJECT_DISTANCE_RANGE_UNKNOWN = 0; // 0x0
+    field public static final String TAG_APERTURE_VALUE = "ApertureValue";
+    field public static final String TAG_ARTIST = "Artist";
+    field public static final String TAG_BITS_PER_SAMPLE = "BitsPerSample";
+    field public static final String TAG_BODY_SERIAL_NUMBER = "BodySerialNumber";
+    field public static final String TAG_BRIGHTNESS_VALUE = "BrightnessValue";
+    field @Deprecated public static final String TAG_CAMARA_OWNER_NAME = "CameraOwnerName";
+    field public static final String TAG_CAMERA_OWNER_NAME = "CameraOwnerName";
+    field public static final String TAG_CFA_PATTERN = "CFAPattern";
+    field public static final String TAG_COLOR_SPACE = "ColorSpace";
+    field public static final String TAG_COMPONENTS_CONFIGURATION = "ComponentsConfiguration";
+    field public static final String TAG_COMPRESSED_BITS_PER_PIXEL = "CompressedBitsPerPixel";
+    field public static final String TAG_COMPRESSION = "Compression";
+    field public static final String TAG_CONTRAST = "Contrast";
+    field public static final String TAG_COPYRIGHT = "Copyright";
+    field public static final String TAG_CUSTOM_RENDERED = "CustomRendered";
+    field public static final String TAG_DATETIME = "DateTime";
+    field public static final String TAG_DATETIME_DIGITIZED = "DateTimeDigitized";
+    field public static final String TAG_DATETIME_ORIGINAL = "DateTimeOriginal";
+    field public static final String TAG_DEFAULT_CROP_SIZE = "DefaultCropSize";
+    field public static final String TAG_DEVICE_SETTING_DESCRIPTION = "DeviceSettingDescription";
+    field public static final String TAG_DIGITAL_ZOOM_RATIO = "DigitalZoomRatio";
+    field public static final String TAG_DNG_VERSION = "DNGVersion";
+    field public static final String TAG_EXIF_VERSION = "ExifVersion";
+    field public static final String TAG_EXPOSURE_BIAS_VALUE = "ExposureBiasValue";
+    field public static final String TAG_EXPOSURE_INDEX = "ExposureIndex";
+    field public static final String TAG_EXPOSURE_MODE = "ExposureMode";
+    field public static final String TAG_EXPOSURE_PROGRAM = "ExposureProgram";
+    field public static final String TAG_EXPOSURE_TIME = "ExposureTime";
+    field public static final String TAG_FILE_SOURCE = "FileSource";
+    field public static final String TAG_FLASH = "Flash";
+    field public static final String TAG_FLASHPIX_VERSION = "FlashpixVersion";
+    field public static final String TAG_FLASH_ENERGY = "FlashEnergy";
+    field public static final String TAG_FOCAL_LENGTH = "FocalLength";
+    field public static final String TAG_FOCAL_LENGTH_IN_35MM_FILM = "FocalLengthIn35mmFilm";
+    field public static final String TAG_FOCAL_PLANE_RESOLUTION_UNIT = "FocalPlaneResolutionUnit";
+    field public static final String TAG_FOCAL_PLANE_X_RESOLUTION = "FocalPlaneXResolution";
+    field public static final String TAG_FOCAL_PLANE_Y_RESOLUTION = "FocalPlaneYResolution";
+    field public static final String TAG_F_NUMBER = "FNumber";
+    field public static final String TAG_GAIN_CONTROL = "GainControl";
+    field public static final String TAG_GAMMA = "Gamma";
+    field public static final String TAG_GPS_ALTITUDE = "GPSAltitude";
+    field public static final String TAG_GPS_ALTITUDE_REF = "GPSAltitudeRef";
+    field public static final String TAG_GPS_AREA_INFORMATION = "GPSAreaInformation";
+    field public static final String TAG_GPS_DATESTAMP = "GPSDateStamp";
+    field public static final String TAG_GPS_DEST_BEARING = "GPSDestBearing";
+    field public static final String TAG_GPS_DEST_BEARING_REF = "GPSDestBearingRef";
+    field public static final String TAG_GPS_DEST_DISTANCE = "GPSDestDistance";
+    field public static final String TAG_GPS_DEST_DISTANCE_REF = "GPSDestDistanceRef";
+    field public static final String TAG_GPS_DEST_LATITUDE = "GPSDestLatitude";
+    field public static final String TAG_GPS_DEST_LATITUDE_REF = "GPSDestLatitudeRef";
+    field public static final String TAG_GPS_DEST_LONGITUDE = "GPSDestLongitude";
+    field public static final String TAG_GPS_DEST_LONGITUDE_REF = "GPSDestLongitudeRef";
+    field public static final String TAG_GPS_DIFFERENTIAL = "GPSDifferential";
+    field public static final String TAG_GPS_DOP = "GPSDOP";
+    field public static final String TAG_GPS_H_POSITIONING_ERROR = "GPSHPositioningError";
+    field public static final String TAG_GPS_IMG_DIRECTION = "GPSImgDirection";
+    field public static final String TAG_GPS_IMG_DIRECTION_REF = "GPSImgDirectionRef";
+    field public static final String TAG_GPS_LATITUDE = "GPSLatitude";
+    field public static final String TAG_GPS_LATITUDE_REF = "GPSLatitudeRef";
+    field public static final String TAG_GPS_LONGITUDE = "GPSLongitude";
+    field public static final String TAG_GPS_LONGITUDE_REF = "GPSLongitudeRef";
+    field public static final String TAG_GPS_MAP_DATUM = "GPSMapDatum";
+    field public static final String TAG_GPS_MEASURE_MODE = "GPSMeasureMode";
+    field public static final String TAG_GPS_PROCESSING_METHOD = "GPSProcessingMethod";
+    field public static final String TAG_GPS_SATELLITES = "GPSSatellites";
+    field public static final String TAG_GPS_SPEED = "GPSSpeed";
+    field public static final String TAG_GPS_SPEED_REF = "GPSSpeedRef";
+    field public static final String TAG_GPS_STATUS = "GPSStatus";
+    field public static final String TAG_GPS_TIMESTAMP = "GPSTimeStamp";
+    field public static final String TAG_GPS_TRACK = "GPSTrack";
+    field public static final String TAG_GPS_TRACK_REF = "GPSTrackRef";
+    field public static final String TAG_GPS_VERSION_ID = "GPSVersionID";
+    field public static final String TAG_IMAGE_DESCRIPTION = "ImageDescription";
+    field public static final String TAG_IMAGE_LENGTH = "ImageLength";
+    field public static final String TAG_IMAGE_UNIQUE_ID = "ImageUniqueID";
+    field public static final String TAG_IMAGE_WIDTH = "ImageWidth";
+    field public static final String TAG_INTEROPERABILITY_INDEX = "InteroperabilityIndex";
+    field public static final String TAG_ISO_SPEED = "ISOSpeed";
+    field public static final String TAG_ISO_SPEED_LATITUDE_YYY = "ISOSpeedLatitudeyyy";
+    field public static final String TAG_ISO_SPEED_LATITUDE_ZZZ = "ISOSpeedLatitudezzz";
+    field @Deprecated public static final String TAG_ISO_SPEED_RATINGS = "ISOSpeedRatings";
+    field public static final String TAG_JPEG_INTERCHANGE_FORMAT = "JPEGInterchangeFormat";
+    field public static final String TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = "JPEGInterchangeFormatLength";
+    field public static final String TAG_LENS_MAKE = "LensMake";
+    field public static final String TAG_LENS_MODEL = "LensModel";
+    field public static final String TAG_LENS_SERIAL_NUMBER = "LensSerialNumber";
+    field public static final String TAG_LENS_SPECIFICATION = "LensSpecification";
+    field public static final String TAG_LIGHT_SOURCE = "LightSource";
+    field public static final String TAG_MAKE = "Make";
+    field public static final String TAG_MAKER_NOTE = "MakerNote";
+    field public static final String TAG_MAX_APERTURE_VALUE = "MaxApertureValue";
+    field public static final String TAG_METERING_MODE = "MeteringMode";
+    field public static final String TAG_MODEL = "Model";
+    field public static final String TAG_NEW_SUBFILE_TYPE = "NewSubfileType";
+    field public static final String TAG_OECF = "OECF";
+    field public static final String TAG_OFFSET_TIME = "OffsetTime";
+    field public static final String TAG_OFFSET_TIME_DIGITIZED = "OffsetTimeDigitized";
+    field public static final String TAG_OFFSET_TIME_ORIGINAL = "OffsetTimeOriginal";
+    field public static final String TAG_ORF_ASPECT_FRAME = "AspectFrame";
+    field public static final String TAG_ORF_PREVIEW_IMAGE_LENGTH = "PreviewImageLength";
+    field public static final String TAG_ORF_PREVIEW_IMAGE_START = "PreviewImageStart";
+    field public static final String TAG_ORF_THUMBNAIL_IMAGE = "ThumbnailImage";
+    field public static final String TAG_ORIENTATION = "Orientation";
+    field public static final String TAG_PHOTOGRAPHIC_SENSITIVITY = "PhotographicSensitivity";
+    field public static final String TAG_PHOTOMETRIC_INTERPRETATION = "PhotometricInterpretation";
+    field public static final String TAG_PIXEL_X_DIMENSION = "PixelXDimension";
+    field public static final String TAG_PIXEL_Y_DIMENSION = "PixelYDimension";
+    field public static final String TAG_PLANAR_CONFIGURATION = "PlanarConfiguration";
+    field public static final String TAG_PRIMARY_CHROMATICITIES = "PrimaryChromaticities";
+    field public static final String TAG_RECOMMENDED_EXPOSURE_INDEX = "RecommendedExposureIndex";
+    field public static final String TAG_REFERENCE_BLACK_WHITE = "ReferenceBlackWhite";
+    field public static final String TAG_RELATED_SOUND_FILE = "RelatedSoundFile";
+    field public static final String TAG_RESOLUTION_UNIT = "ResolutionUnit";
+    field public static final String TAG_ROWS_PER_STRIP = "RowsPerStrip";
+    field public static final String TAG_RW2_ISO = "ISO";
+    field public static final String TAG_RW2_JPG_FROM_RAW = "JpgFromRaw";
+    field public static final String TAG_RW2_SENSOR_BOTTOM_BORDER = "SensorBottomBorder";
+    field public static final String TAG_RW2_SENSOR_LEFT_BORDER = "SensorLeftBorder";
+    field public static final String TAG_RW2_SENSOR_RIGHT_BORDER = "SensorRightBorder";
+    field public static final String TAG_RW2_SENSOR_TOP_BORDER = "SensorTopBorder";
+    field public static final String TAG_SAMPLES_PER_PIXEL = "SamplesPerPixel";
+    field public static final String TAG_SATURATION = "Saturation";
+    field public static final String TAG_SCENE_CAPTURE_TYPE = "SceneCaptureType";
+    field public static final String TAG_SCENE_TYPE = "SceneType";
+    field public static final String TAG_SENSING_METHOD = "SensingMethod";
+    field public static final String TAG_SENSITIVITY_TYPE = "SensitivityType";
+    field public static final String TAG_SHARPNESS = "Sharpness";
+    field public static final String TAG_SHUTTER_SPEED_VALUE = "ShutterSpeedValue";
+    field public static final String TAG_SOFTWARE = "Software";
+    field public static final String TAG_SPATIAL_FREQUENCY_RESPONSE = "SpatialFrequencyResponse";
+    field public static final String TAG_SPECTRAL_SENSITIVITY = "SpectralSensitivity";
+    field public static final String TAG_STANDARD_OUTPUT_SENSITIVITY = "StandardOutputSensitivity";
+    field public static final String TAG_STRIP_BYTE_COUNTS = "StripByteCounts";
+    field public static final String TAG_STRIP_OFFSETS = "StripOffsets";
+    field public static final String TAG_SUBFILE_TYPE = "SubfileType";
+    field public static final String TAG_SUBJECT_AREA = "SubjectArea";
+    field public static final String TAG_SUBJECT_DISTANCE = "SubjectDistance";
+    field public static final String TAG_SUBJECT_DISTANCE_RANGE = "SubjectDistanceRange";
+    field public static final String TAG_SUBJECT_LOCATION = "SubjectLocation";
+    field public static final String TAG_SUBSEC_TIME = "SubSecTime";
+    field public static final String TAG_SUBSEC_TIME_DIGITIZED = "SubSecTimeDigitized";
+    field public static final String TAG_SUBSEC_TIME_ORIGINAL = "SubSecTimeOriginal";
+    field public static final String TAG_THUMBNAIL_IMAGE_LENGTH = "ThumbnailImageLength";
+    field public static final String TAG_THUMBNAIL_IMAGE_WIDTH = "ThumbnailImageWidth";
+    field public static final String TAG_TRANSFER_FUNCTION = "TransferFunction";
+    field public static final String TAG_USER_COMMENT = "UserComment";
+    field public static final String TAG_WHITE_BALANCE = "WhiteBalance";
+    field public static final String TAG_WHITE_POINT = "WhitePoint";
+    field public static final String TAG_XMP = "Xmp";
+    field public static final String TAG_X_RESOLUTION = "XResolution";
+    field public static final String TAG_Y_CB_CR_COEFFICIENTS = "YCbCrCoefficients";
+    field public static final String TAG_Y_CB_CR_POSITIONING = "YCbCrPositioning";
+    field public static final String TAG_Y_CB_CR_SUB_SAMPLING = "YCbCrSubSampling";
+    field public static final String TAG_Y_RESOLUTION = "YResolution";
+    field @Deprecated public static final int WHITEBALANCE_AUTO = 0; // 0x0
+    field @Deprecated public static final int WHITEBALANCE_MANUAL = 1; // 0x1
+    field public static final short WHITE_BALANCE_AUTO = 0; // 0x0
+    field public static final short WHITE_BALANCE_MANUAL = 1; // 0x1
+    field public static final short Y_CB_CR_POSITIONING_CENTERED = 1; // 0x1
+    field public static final short Y_CB_CR_POSITIONING_CO_SITED = 2; // 0x2
+  }
+
+}
+
diff --git a/exifinterface/api/res-1.2.0-beta01.txt b/exifinterface/api/res-1.2.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/exifinterface/api/res-1.2.0-beta01.txt
diff --git a/exifinterface/api/restricted_1.2.0-beta01.txt b/exifinterface/api/restricted_1.2.0-beta01.txt
new file mode 100644
index 0000000..5aacfe0
--- /dev/null
+++ b/exifinterface/api/restricted_1.2.0-beta01.txt
@@ -0,0 +1,349 @@
+// Signature format: 3.0
+package androidx.exifinterface.media {
+
+  public class ExifInterface {
+    ctor public ExifInterface(java.io.File) throws java.io.IOException;
+    ctor public ExifInterface(String) throws java.io.IOException;
+    ctor public ExifInterface(java.io.FileDescriptor) throws java.io.IOException;
+    ctor public ExifInterface(java.io.InputStream) throws java.io.IOException;
+    ctor public ExifInterface(java.io.InputStream, @androidx.exifinterface.media.ExifInterface.ExifStreamType int) throws java.io.IOException;
+    method public void flipHorizontally();
+    method public void flipVertically();
+    method public double getAltitude(double);
+    method public String? getAttribute(String);
+    method public byte[]? getAttributeBytes(String);
+    method public double getAttributeDouble(String, double);
+    method public int getAttributeInt(String, int);
+    method public long[]? getAttributeRange(String);
+    method @Deprecated public boolean getLatLong(float[]!);
+    method public double[]? getLatLong();
+    method public int getRotationDegrees();
+    method public byte[]? getThumbnail();
+    method public android.graphics.Bitmap? getThumbnailBitmap();
+    method public byte[]? getThumbnailBytes();
+    method public long[]? getThumbnailRange();
+    method public boolean hasAttribute(String);
+    method public boolean hasThumbnail();
+    method public boolean isFlipped();
+    method public static boolean isSupportedMimeType(String);
+    method public boolean isThumbnailCompressed();
+    method public void resetOrientation();
+    method public void rotate(int);
+    method public void saveAttributes() throws java.io.IOException;
+    method public void setAltitude(double);
+    method public void setAttribute(String, String?);
+    method public void setGpsInfo(android.location.Location!);
+    method public void setLatLong(double, double);
+    field public static final short ALTITUDE_ABOVE_SEA_LEVEL = 0; // 0x0
+    field public static final short ALTITUDE_BELOW_SEA_LEVEL = 1; // 0x1
+    field public static final int[]! BITS_PER_SAMPLE_GREYSCALE_1;
+    field public static final int[]! BITS_PER_SAMPLE_GREYSCALE_2;
+    field public static final int[]! BITS_PER_SAMPLE_RGB;
+    field public static final int COLOR_SPACE_S_RGB = 1; // 0x1
+    field public static final int COLOR_SPACE_UNCALIBRATED = 65535; // 0xffff
+    field public static final short CONTRAST_HARD = 2; // 0x2
+    field public static final short CONTRAST_NORMAL = 0; // 0x0
+    field public static final short CONTRAST_SOFT = 1; // 0x1
+    field public static final int DATA_DEFLATE_ZIP = 8; // 0x8
+    field public static final int DATA_HUFFMAN_COMPRESSED = 2; // 0x2
+    field public static final int DATA_JPEG = 6; // 0x6
+    field public static final int DATA_JPEG_COMPRESSED = 7; // 0x7
+    field public static final int DATA_LOSSY_JPEG = 34892; // 0x884c
+    field public static final int DATA_PACK_BITS_COMPRESSED = 32773; // 0x8005
+    field public static final int DATA_UNCOMPRESSED = 1; // 0x1
+    field public static final short EXPOSURE_MODE_AUTO = 0; // 0x0
+    field public static final short EXPOSURE_MODE_AUTO_BRACKET = 2; // 0x2
+    field public static final short EXPOSURE_MODE_MANUAL = 1; // 0x1
+    field public static final short EXPOSURE_PROGRAM_ACTION = 6; // 0x6
+    field public static final short EXPOSURE_PROGRAM_APERTURE_PRIORITY = 3; // 0x3
+    field public static final short EXPOSURE_PROGRAM_CREATIVE = 5; // 0x5
+    field public static final short EXPOSURE_PROGRAM_LANDSCAPE_MODE = 8; // 0x8
+    field public static final short EXPOSURE_PROGRAM_MANUAL = 1; // 0x1
+    field public static final short EXPOSURE_PROGRAM_NORMAL = 2; // 0x2
+    field public static final short EXPOSURE_PROGRAM_NOT_DEFINED = 0; // 0x0
+    field public static final short EXPOSURE_PROGRAM_PORTRAIT_MODE = 7; // 0x7
+    field public static final short EXPOSURE_PROGRAM_SHUTTER_PRIORITY = 4; // 0x4
+    field public static final short FILE_SOURCE_DSC = 3; // 0x3
+    field public static final short FILE_SOURCE_OTHER = 0; // 0x0
+    field public static final short FILE_SOURCE_REFLEX_SCANNER = 2; // 0x2
+    field public static final short FILE_SOURCE_TRANSPARENT_SCANNER = 1; // 0x1
+    field public static final short FLAG_FLASH_FIRED = 1; // 0x1
+    field public static final short FLAG_FLASH_MODE_AUTO = 24; // 0x18
+    field public static final short FLAG_FLASH_MODE_COMPULSORY_FIRING = 8; // 0x8
+    field public static final short FLAG_FLASH_MODE_COMPULSORY_SUPPRESSION = 16; // 0x10
+    field public static final short FLAG_FLASH_NO_FLASH_FUNCTION = 32; // 0x20
+    field public static final short FLAG_FLASH_RED_EYE_SUPPORTED = 64; // 0x40
+    field public static final short FLAG_FLASH_RETURN_LIGHT_DETECTED = 6; // 0x6
+    field public static final short FLAG_FLASH_RETURN_LIGHT_NOT_DETECTED = 4; // 0x4
+    field public static final short FORMAT_CHUNKY = 1; // 0x1
+    field public static final short FORMAT_PLANAR = 2; // 0x2
+    field public static final short GAIN_CONTROL_HIGH_GAIN_DOWN = 4; // 0x4
+    field public static final short GAIN_CONTROL_HIGH_GAIN_UP = 2; // 0x2
+    field public static final short GAIN_CONTROL_LOW_GAIN_DOWN = 3; // 0x3
+    field public static final short GAIN_CONTROL_LOW_GAIN_UP = 1; // 0x1
+    field public static final short GAIN_CONTROL_NONE = 0; // 0x0
+    field public static final String GPS_DIRECTION_MAGNETIC = "M";
+    field public static final String GPS_DIRECTION_TRUE = "T";
+    field public static final String GPS_DISTANCE_KILOMETERS = "K";
+    field public static final String GPS_DISTANCE_MILES = "M";
+    field public static final String GPS_DISTANCE_NAUTICAL_MILES = "N";
+    field public static final String GPS_MEASUREMENT_2D = "2";
+    field public static final String GPS_MEASUREMENT_3D = "3";
+    field public static final short GPS_MEASUREMENT_DIFFERENTIAL_CORRECTED = 1; // 0x1
+    field public static final String GPS_MEASUREMENT_INTERRUPTED = "V";
+    field public static final String GPS_MEASUREMENT_IN_PROGRESS = "A";
+    field public static final short GPS_MEASUREMENT_NO_DIFFERENTIAL = 0; // 0x0
+    field public static final String GPS_SPEED_KILOMETERS_PER_HOUR = "K";
+    field public static final String GPS_SPEED_KNOTS = "N";
+    field public static final String GPS_SPEED_MILES_PER_HOUR = "M";
+    field public static final String LATITUDE_NORTH = "N";
+    field public static final String LATITUDE_SOUTH = "S";
+    field public static final short LIGHT_SOURCE_CLOUDY_WEATHER = 10; // 0xa
+    field public static final short LIGHT_SOURCE_COOL_WHITE_FLUORESCENT = 14; // 0xe
+    field public static final short LIGHT_SOURCE_D50 = 23; // 0x17
+    field public static final short LIGHT_SOURCE_D55 = 20; // 0x14
+    field public static final short LIGHT_SOURCE_D65 = 21; // 0x15
+    field public static final short LIGHT_SOURCE_D75 = 22; // 0x16
+    field public static final short LIGHT_SOURCE_DAYLIGHT = 1; // 0x1
+    field public static final short LIGHT_SOURCE_DAYLIGHT_FLUORESCENT = 12; // 0xc
+    field public static final short LIGHT_SOURCE_DAY_WHITE_FLUORESCENT = 13; // 0xd
+    field public static final short LIGHT_SOURCE_FINE_WEATHER = 9; // 0x9
+    field public static final short LIGHT_SOURCE_FLASH = 4; // 0x4
+    field public static final short LIGHT_SOURCE_FLUORESCENT = 2; // 0x2
+    field public static final short LIGHT_SOURCE_ISO_STUDIO_TUNGSTEN = 24; // 0x18
+    field public static final short LIGHT_SOURCE_OTHER = 255; // 0xff
+    field public static final short LIGHT_SOURCE_SHADE = 11; // 0xb
+    field public static final short LIGHT_SOURCE_STANDARD_LIGHT_A = 17; // 0x11
+    field public static final short LIGHT_SOURCE_STANDARD_LIGHT_B = 18; // 0x12
+    field public static final short LIGHT_SOURCE_STANDARD_LIGHT_C = 19; // 0x13
+    field public static final short LIGHT_SOURCE_TUNGSTEN = 3; // 0x3
+    field public static final short LIGHT_SOURCE_UNKNOWN = 0; // 0x0
+    field public static final short LIGHT_SOURCE_WARM_WHITE_FLUORESCENT = 16; // 0x10
+    field public static final short LIGHT_SOURCE_WHITE_FLUORESCENT = 15; // 0xf
+    field public static final String LONGITUDE_EAST = "E";
+    field public static final String LONGITUDE_WEST = "W";
+    field public static final short METERING_MODE_AVERAGE = 1; // 0x1
+    field public static final short METERING_MODE_CENTER_WEIGHT_AVERAGE = 2; // 0x2
+    field public static final short METERING_MODE_MULTI_SPOT = 4; // 0x4
+    field public static final short METERING_MODE_OTHER = 255; // 0xff
+    field public static final short METERING_MODE_PARTIAL = 6; // 0x6
+    field public static final short METERING_MODE_PATTERN = 5; // 0x5
+    field public static final short METERING_MODE_SPOT = 3; // 0x3
+    field public static final short METERING_MODE_UNKNOWN = 0; // 0x0
+    field public static final int ORIENTATION_FLIP_HORIZONTAL = 2; // 0x2
+    field public static final int ORIENTATION_FLIP_VERTICAL = 4; // 0x4
+    field public static final int ORIENTATION_NORMAL = 1; // 0x1
+    field public static final int ORIENTATION_ROTATE_180 = 3; // 0x3
+    field public static final int ORIENTATION_ROTATE_270 = 8; // 0x8
+    field public static final int ORIENTATION_ROTATE_90 = 6; // 0x6
+    field public static final int ORIENTATION_TRANSPOSE = 5; // 0x5
+    field public static final int ORIENTATION_TRANSVERSE = 7; // 0x7
+    field public static final int ORIENTATION_UNDEFINED = 0; // 0x0
+    field public static final int ORIGINAL_RESOLUTION_IMAGE = 0; // 0x0
+    field public static final int PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO = 1; // 0x1
+    field public static final int PHOTOMETRIC_INTERPRETATION_RGB = 2; // 0x2
+    field public static final int PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO = 0; // 0x0
+    field public static final int PHOTOMETRIC_INTERPRETATION_YCBCR = 6; // 0x6
+    field public static final int REDUCED_RESOLUTION_IMAGE = 1; // 0x1
+    field public static final short RENDERED_PROCESS_CUSTOM = 1; // 0x1
+    field public static final short RENDERED_PROCESS_NORMAL = 0; // 0x0
+    field public static final short RESOLUTION_UNIT_CENTIMETERS = 3; // 0x3
+    field public static final short RESOLUTION_UNIT_INCHES = 2; // 0x2
+    field public static final short SATURATION_HIGH = 0; // 0x0
+    field public static final short SATURATION_LOW = 0; // 0x0
+    field public static final short SATURATION_NORMAL = 0; // 0x0
+    field public static final short SCENE_CAPTURE_TYPE_LANDSCAPE = 1; // 0x1
+    field public static final short SCENE_CAPTURE_TYPE_NIGHT = 3; // 0x3
+    field public static final short SCENE_CAPTURE_TYPE_PORTRAIT = 2; // 0x2
+    field public static final short SCENE_CAPTURE_TYPE_STANDARD = 0; // 0x0
+    field public static final short SCENE_TYPE_DIRECTLY_PHOTOGRAPHED = 1; // 0x1
+    field public static final short SENSITIVITY_TYPE_ISO_SPEED = 3; // 0x3
+    field public static final short SENSITIVITY_TYPE_REI = 2; // 0x2
+    field public static final short SENSITIVITY_TYPE_REI_AND_ISO = 6; // 0x6
+    field public static final short SENSITIVITY_TYPE_SOS = 1; // 0x1
+    field public static final short SENSITIVITY_TYPE_SOS_AND_ISO = 5; // 0x5
+    field public static final short SENSITIVITY_TYPE_SOS_AND_REI = 4; // 0x4
+    field public static final short SENSITIVITY_TYPE_SOS_AND_REI_AND_ISO = 7; // 0x7
+    field public static final short SENSITIVITY_TYPE_UNKNOWN = 0; // 0x0
+    field public static final short SENSOR_TYPE_COLOR_SEQUENTIAL = 5; // 0x5
+    field public static final short SENSOR_TYPE_COLOR_SEQUENTIAL_LINEAR = 8; // 0x8
+    field public static final short SENSOR_TYPE_NOT_DEFINED = 1; // 0x1
+    field public static final short SENSOR_TYPE_ONE_CHIP = 2; // 0x2
+    field public static final short SENSOR_TYPE_THREE_CHIP = 4; // 0x4
+    field public static final short SENSOR_TYPE_TRILINEAR = 7; // 0x7
+    field public static final short SENSOR_TYPE_TWO_CHIP = 3; // 0x3
+    field public static final short SHARPNESS_HARD = 2; // 0x2
+    field public static final short SHARPNESS_NORMAL = 0; // 0x0
+    field public static final short SHARPNESS_SOFT = 1; // 0x1
+    field public static final int STREAM_TYPE_EXIF_DATA_ONLY = 1; // 0x1
+    field public static final int STREAM_TYPE_FULL_IMAGE_DATA = 0; // 0x0
+    field public static final short SUBJECT_DISTANCE_RANGE_CLOSE_VIEW = 2; // 0x2
+    field public static final short SUBJECT_DISTANCE_RANGE_DISTANT_VIEW = 3; // 0x3
+    field public static final short SUBJECT_DISTANCE_RANGE_MACRO = 1; // 0x1
+    field public static final short SUBJECT_DISTANCE_RANGE_UNKNOWN = 0; // 0x0
+    field public static final String TAG_APERTURE_VALUE = "ApertureValue";
+    field public static final String TAG_ARTIST = "Artist";
+    field public static final String TAG_BITS_PER_SAMPLE = "BitsPerSample";
+    field public static final String TAG_BODY_SERIAL_NUMBER = "BodySerialNumber";
+    field public static final String TAG_BRIGHTNESS_VALUE = "BrightnessValue";
+    field @Deprecated public static final String TAG_CAMARA_OWNER_NAME = "CameraOwnerName";
+    field public static final String TAG_CAMERA_OWNER_NAME = "CameraOwnerName";
+    field public static final String TAG_CFA_PATTERN = "CFAPattern";
+    field public static final String TAG_COLOR_SPACE = "ColorSpace";
+    field public static final String TAG_COMPONENTS_CONFIGURATION = "ComponentsConfiguration";
+    field public static final String TAG_COMPRESSED_BITS_PER_PIXEL = "CompressedBitsPerPixel";
+    field public static final String TAG_COMPRESSION = "Compression";
+    field public static final String TAG_CONTRAST = "Contrast";
+    field public static final String TAG_COPYRIGHT = "Copyright";
+    field public static final String TAG_CUSTOM_RENDERED = "CustomRendered";
+    field public static final String TAG_DATETIME = "DateTime";
+    field public static final String TAG_DATETIME_DIGITIZED = "DateTimeDigitized";
+    field public static final String TAG_DATETIME_ORIGINAL = "DateTimeOriginal";
+    field public static final String TAG_DEFAULT_CROP_SIZE = "DefaultCropSize";
+    field public static final String TAG_DEVICE_SETTING_DESCRIPTION = "DeviceSettingDescription";
+    field public static final String TAG_DIGITAL_ZOOM_RATIO = "DigitalZoomRatio";
+    field public static final String TAG_DNG_VERSION = "DNGVersion";
+    field public static final String TAG_EXIF_VERSION = "ExifVersion";
+    field public static final String TAG_EXPOSURE_BIAS_VALUE = "ExposureBiasValue";
+    field public static final String TAG_EXPOSURE_INDEX = "ExposureIndex";
+    field public static final String TAG_EXPOSURE_MODE = "ExposureMode";
+    field public static final String TAG_EXPOSURE_PROGRAM = "ExposureProgram";
+    field public static final String TAG_EXPOSURE_TIME = "ExposureTime";
+    field public static final String TAG_FILE_SOURCE = "FileSource";
+    field public static final String TAG_FLASH = "Flash";
+    field public static final String TAG_FLASHPIX_VERSION = "FlashpixVersion";
+    field public static final String TAG_FLASH_ENERGY = "FlashEnergy";
+    field public static final String TAG_FOCAL_LENGTH = "FocalLength";
+    field public static final String TAG_FOCAL_LENGTH_IN_35MM_FILM = "FocalLengthIn35mmFilm";
+    field public static final String TAG_FOCAL_PLANE_RESOLUTION_UNIT = "FocalPlaneResolutionUnit";
+    field public static final String TAG_FOCAL_PLANE_X_RESOLUTION = "FocalPlaneXResolution";
+    field public static final String TAG_FOCAL_PLANE_Y_RESOLUTION = "FocalPlaneYResolution";
+    field public static final String TAG_F_NUMBER = "FNumber";
+    field public static final String TAG_GAIN_CONTROL = "GainControl";
+    field public static final String TAG_GAMMA = "Gamma";
+    field public static final String TAG_GPS_ALTITUDE = "GPSAltitude";
+    field public static final String TAG_GPS_ALTITUDE_REF = "GPSAltitudeRef";
+    field public static final String TAG_GPS_AREA_INFORMATION = "GPSAreaInformation";
+    field public static final String TAG_GPS_DATESTAMP = "GPSDateStamp";
+    field public static final String TAG_GPS_DEST_BEARING = "GPSDestBearing";
+    field public static final String TAG_GPS_DEST_BEARING_REF = "GPSDestBearingRef";
+    field public static final String TAG_GPS_DEST_DISTANCE = "GPSDestDistance";
+    field public static final String TAG_GPS_DEST_DISTANCE_REF = "GPSDestDistanceRef";
+    field public static final String TAG_GPS_DEST_LATITUDE = "GPSDestLatitude";
+    field public static final String TAG_GPS_DEST_LATITUDE_REF = "GPSDestLatitudeRef";
+    field public static final String TAG_GPS_DEST_LONGITUDE = "GPSDestLongitude";
+    field public static final String TAG_GPS_DEST_LONGITUDE_REF = "GPSDestLongitudeRef";
+    field public static final String TAG_GPS_DIFFERENTIAL = "GPSDifferential";
+    field public static final String TAG_GPS_DOP = "GPSDOP";
+    field public static final String TAG_GPS_H_POSITIONING_ERROR = "GPSHPositioningError";
+    field public static final String TAG_GPS_IMG_DIRECTION = "GPSImgDirection";
+    field public static final String TAG_GPS_IMG_DIRECTION_REF = "GPSImgDirectionRef";
+    field public static final String TAG_GPS_LATITUDE = "GPSLatitude";
+    field public static final String TAG_GPS_LATITUDE_REF = "GPSLatitudeRef";
+    field public static final String TAG_GPS_LONGITUDE = "GPSLongitude";
+    field public static final String TAG_GPS_LONGITUDE_REF = "GPSLongitudeRef";
+    field public static final String TAG_GPS_MAP_DATUM = "GPSMapDatum";
+    field public static final String TAG_GPS_MEASURE_MODE = "GPSMeasureMode";
+    field public static final String TAG_GPS_PROCESSING_METHOD = "GPSProcessingMethod";
+    field public static final String TAG_GPS_SATELLITES = "GPSSatellites";
+    field public static final String TAG_GPS_SPEED = "GPSSpeed";
+    field public static final String TAG_GPS_SPEED_REF = "GPSSpeedRef";
+    field public static final String TAG_GPS_STATUS = "GPSStatus";
+    field public static final String TAG_GPS_TIMESTAMP = "GPSTimeStamp";
+    field public static final String TAG_GPS_TRACK = "GPSTrack";
+    field public static final String TAG_GPS_TRACK_REF = "GPSTrackRef";
+    field public static final String TAG_GPS_VERSION_ID = "GPSVersionID";
+    field public static final String TAG_IMAGE_DESCRIPTION = "ImageDescription";
+    field public static final String TAG_IMAGE_LENGTH = "ImageLength";
+    field public static final String TAG_IMAGE_UNIQUE_ID = "ImageUniqueID";
+    field public static final String TAG_IMAGE_WIDTH = "ImageWidth";
+    field public static final String TAG_INTEROPERABILITY_INDEX = "InteroperabilityIndex";
+    field public static final String TAG_ISO_SPEED = "ISOSpeed";
+    field public static final String TAG_ISO_SPEED_LATITUDE_YYY = "ISOSpeedLatitudeyyy";
+    field public static final String TAG_ISO_SPEED_LATITUDE_ZZZ = "ISOSpeedLatitudezzz";
+    field @Deprecated public static final String TAG_ISO_SPEED_RATINGS = "ISOSpeedRatings";
+    field public static final String TAG_JPEG_INTERCHANGE_FORMAT = "JPEGInterchangeFormat";
+    field public static final String TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = "JPEGInterchangeFormatLength";
+    field public static final String TAG_LENS_MAKE = "LensMake";
+    field public static final String TAG_LENS_MODEL = "LensModel";
+    field public static final String TAG_LENS_SERIAL_NUMBER = "LensSerialNumber";
+    field public static final String TAG_LENS_SPECIFICATION = "LensSpecification";
+    field public static final String TAG_LIGHT_SOURCE = "LightSource";
+    field public static final String TAG_MAKE = "Make";
+    field public static final String TAG_MAKER_NOTE = "MakerNote";
+    field public static final String TAG_MAX_APERTURE_VALUE = "MaxApertureValue";
+    field public static final String TAG_METERING_MODE = "MeteringMode";
+    field public static final String TAG_MODEL = "Model";
+    field public static final String TAG_NEW_SUBFILE_TYPE = "NewSubfileType";
+    field public static final String TAG_OECF = "OECF";
+    field public static final String TAG_OFFSET_TIME = "OffsetTime";
+    field public static final String TAG_OFFSET_TIME_DIGITIZED = "OffsetTimeDigitized";
+    field public static final String TAG_OFFSET_TIME_ORIGINAL = "OffsetTimeOriginal";
+    field public static final String TAG_ORF_ASPECT_FRAME = "AspectFrame";
+    field public static final String TAG_ORF_PREVIEW_IMAGE_LENGTH = "PreviewImageLength";
+    field public static final String TAG_ORF_PREVIEW_IMAGE_START = "PreviewImageStart";
+    field public static final String TAG_ORF_THUMBNAIL_IMAGE = "ThumbnailImage";
+    field public static final String TAG_ORIENTATION = "Orientation";
+    field public static final String TAG_PHOTOGRAPHIC_SENSITIVITY = "PhotographicSensitivity";
+    field public static final String TAG_PHOTOMETRIC_INTERPRETATION = "PhotometricInterpretation";
+    field public static final String TAG_PIXEL_X_DIMENSION = "PixelXDimension";
+    field public static final String TAG_PIXEL_Y_DIMENSION = "PixelYDimension";
+    field public static final String TAG_PLANAR_CONFIGURATION = "PlanarConfiguration";
+    field public static final String TAG_PRIMARY_CHROMATICITIES = "PrimaryChromaticities";
+    field public static final String TAG_RECOMMENDED_EXPOSURE_INDEX = "RecommendedExposureIndex";
+    field public static final String TAG_REFERENCE_BLACK_WHITE = "ReferenceBlackWhite";
+    field public static final String TAG_RELATED_SOUND_FILE = "RelatedSoundFile";
+    field public static final String TAG_RESOLUTION_UNIT = "ResolutionUnit";
+    field public static final String TAG_ROWS_PER_STRIP = "RowsPerStrip";
+    field public static final String TAG_RW2_ISO = "ISO";
+    field public static final String TAG_RW2_JPG_FROM_RAW = "JpgFromRaw";
+    field public static final String TAG_RW2_SENSOR_BOTTOM_BORDER = "SensorBottomBorder";
+    field public static final String TAG_RW2_SENSOR_LEFT_BORDER = "SensorLeftBorder";
+    field public static final String TAG_RW2_SENSOR_RIGHT_BORDER = "SensorRightBorder";
+    field public static final String TAG_RW2_SENSOR_TOP_BORDER = "SensorTopBorder";
+    field public static final String TAG_SAMPLES_PER_PIXEL = "SamplesPerPixel";
+    field public static final String TAG_SATURATION = "Saturation";
+    field public static final String TAG_SCENE_CAPTURE_TYPE = "SceneCaptureType";
+    field public static final String TAG_SCENE_TYPE = "SceneType";
+    field public static final String TAG_SENSING_METHOD = "SensingMethod";
+    field public static final String TAG_SENSITIVITY_TYPE = "SensitivityType";
+    field public static final String TAG_SHARPNESS = "Sharpness";
+    field public static final String TAG_SHUTTER_SPEED_VALUE = "ShutterSpeedValue";
+    field public static final String TAG_SOFTWARE = "Software";
+    field public static final String TAG_SPATIAL_FREQUENCY_RESPONSE = "SpatialFrequencyResponse";
+    field public static final String TAG_SPECTRAL_SENSITIVITY = "SpectralSensitivity";
+    field public static final String TAG_STANDARD_OUTPUT_SENSITIVITY = "StandardOutputSensitivity";
+    field public static final String TAG_STRIP_BYTE_COUNTS = "StripByteCounts";
+    field public static final String TAG_STRIP_OFFSETS = "StripOffsets";
+    field public static final String TAG_SUBFILE_TYPE = "SubfileType";
+    field public static final String TAG_SUBJECT_AREA = "SubjectArea";
+    field public static final String TAG_SUBJECT_DISTANCE = "SubjectDistance";
+    field public static final String TAG_SUBJECT_DISTANCE_RANGE = "SubjectDistanceRange";
+    field public static final String TAG_SUBJECT_LOCATION = "SubjectLocation";
+    field public static final String TAG_SUBSEC_TIME = "SubSecTime";
+    field public static final String TAG_SUBSEC_TIME_DIGITIZED = "SubSecTimeDigitized";
+    field public static final String TAG_SUBSEC_TIME_ORIGINAL = "SubSecTimeOriginal";
+    field public static final String TAG_THUMBNAIL_IMAGE_LENGTH = "ThumbnailImageLength";
+    field public static final String TAG_THUMBNAIL_IMAGE_WIDTH = "ThumbnailImageWidth";
+    field public static final String TAG_TRANSFER_FUNCTION = "TransferFunction";
+    field public static final String TAG_USER_COMMENT = "UserComment";
+    field public static final String TAG_WHITE_BALANCE = "WhiteBalance";
+    field public static final String TAG_WHITE_POINT = "WhitePoint";
+    field public static final String TAG_XMP = "Xmp";
+    field public static final String TAG_X_RESOLUTION = "XResolution";
+    field public static final String TAG_Y_CB_CR_COEFFICIENTS = "YCbCrCoefficients";
+    field public static final String TAG_Y_CB_CR_POSITIONING = "YCbCrPositioning";
+    field public static final String TAG_Y_CB_CR_SUB_SAMPLING = "YCbCrSubSampling";
+    field public static final String TAG_Y_RESOLUTION = "YResolution";
+    field @Deprecated public static final int WHITEBALANCE_AUTO = 0; // 0x0
+    field @Deprecated public static final int WHITEBALANCE_MANUAL = 1; // 0x1
+    field public static final short WHITE_BALANCE_AUTO = 0; // 0x0
+    field public static final short WHITE_BALANCE_MANUAL = 1; // 0x1
+    field public static final short Y_CB_CR_POSITIONING_CENTERED = 1; // 0x1
+    field public static final short Y_CB_CR_POSITIONING_CO_SITED = 2; // 0x2
+  }
+
+
+
+}
+
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index cf3bb85..9817e9f 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -5,4 +5,4 @@
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=../../../../tools/external/gradle/gradle-5.6.2-bin.zip
+distributionUrl=../../../../tools/external/gradle/gradle-6.0-bin.zip
diff --git a/jetifier/jetifier/core/build.gradle b/jetifier/jetifier/core/build.gradle
index 0662cc0..9d8e1ef 100644
--- a/jetifier/jetifier/core/build.gradle
+++ b/jetifier/jetifier/core/build.gradle
@@ -29,10 +29,10 @@
 targetCompatibility = JavaVersion.VERSION_1_7
 
 dependencies {
-    compile("com.google.code.gson:gson:2.8.0")
-    compile(KOTLIN_STDLIB)
-    testCompile("junit:junit:4.12")
-    testCompile(TRUTH)
+    api("com.google.code.gson:gson:2.8.0")
+    api(KOTLIN_STDLIB)
+    testImplementation("junit:junit:4.12")
+    testImplementation(TRUTH)
 }
 
 androidx {
diff --git a/jetifier/jetifier/migration.config b/jetifier/jetifier/migration.config
index dae320b..5a242c3 100644
--- a/jetifier/jetifier/migration.config
+++ b/jetifier/jetifier/migration.config
@@ -31,10 +31,6 @@
       "to": "ignoreInPreprocessorOnly"
     },
     {
-      "from": "android/support/test/((.*)/)?internal/(.*)",
-      "to": "ignore"
-    },
-    {
       "from": "(.*)Parcelizer",
       "to": "{0}Parcelizer"
     },
@@ -409,10 +405,6 @@
     {
       "from": "androidx/activity/(.*)",
       "to": "androidx/activity/{0}"
-    },
-    {
-      "from": "android/support/test/(.*)",
-      "to": "androidx/test/{0}"
     }
   ],
   "slRules": [
@@ -441,6 +433,10 @@
       "to": "ignore"
     },
     {
+      "from": "androidx/test(.*)",
+      "to": "ignore"
+    },
+    {
       "from": "androidx/gridlayout/widget/GridLayout(.*)",
       "to": "ignore"
     },
@@ -3675,107 +3671,6 @@
       "android/support/multidex/MultiDexApplication": "androidx/multidex/MultiDexApplication",
       "android/support/multidex/MultiDexExtractor": "androidx/multidex/MultiDexExtractor",
       "android/support/multidex/ZipUtil": "androidx/multidex/ZipUtil",
-      "android/support/test/InstrumentationRegistry": "androidx/test/InstrumentationRegistry",
-      "android/support/test/annotation/Beta": "androidx/test/annotation/Beta",
-      "android/support/test/annotation/UiThreadTest": "androidx/test/annotation/UiThreadTest",
-      "android/support/test/filters/FlakyTest": "androidx/test/filters/FlakyTest",
-      "android/support/test/filters/LargeTest": "androidx/test/filters/LargeTest",
-      "android/support/test/filters/MediumTest": "androidx/test/filters/MediumTest",
-      "android/support/test/filters/RequiresDevice": "androidx/test/filters/RequiresDevice",
-      "android/support/test/filters/SdkSuppress": "androidx/test/filters/SdkSuppress",
-      "android/support/test/filters/SmallTest": "androidx/test/filters/SmallTest",
-      "android/support/test/filters/Suppress": "androidx/test/filters/Suppress",
-      "android/support/test/jank/GfxMonitor": "androidx/test/jank/GfxMonitor",
-      "android/support/test/jank/JankTest": "androidx/test/jank/JankTest",
-      "android/support/test/jank/JankTestBase": "androidx/test/jank/JankTestBase",
-      "android/support/test/jank/WindowAnimationFrameStatsMonitor": "androidx/test/jank/WindowAnimationFrameStatsMonitor",
-      "android/support/test/jank/WindowContentFrameStatsMonitor": "androidx/test/jank/WindowContentFrameStatsMonitor",
-      "android/support/test/orchestrator/callback/OrchestratorCallback": "androidx/test/orchestrator/callback/OrchestratorCallback",
-      "android/support/test/orchestrator/instrumentationlistener/OrchestratedInstrumentationListener": "androidx/test/orchestrator/instrumentationlistener/OrchestratedInstrumentationListener",
-      "android/support/test/orchestrator/junit/BundleJUnitUtils": "androidx/test/orchestrator/junit/BundleJUnitUtils",
-      "android/support/test/orchestrator/junit/ParcelableDescription": "androidx/test/orchestrator/junit/ParcelableDescription",
-      "android/support/test/orchestrator/junit/ParcelableFailure": "androidx/test/orchestrator/junit/ParcelableFailure",
-      "android/support/test/orchestrator/junit/ParcelableResult": "androidx/test/orchestrator/junit/ParcelableResult",
-      "android/support/test/orchestrator/listeners/OrchestrationListenerManager": "androidx/test/orchestrator/listeners/OrchestrationListenerManager",
-      "android/support/test/orchestrator/listeners/OrchestrationRunListener": "androidx/test/orchestrator/listeners/OrchestrationRunListener",
-      "android/support/test/orchestrator/listeners/result/ITestRunListener": "androidx/test/orchestrator/listeners/result/ITestRunListener",
-      "android/support/test/orchestrator/listeners/result/TestIdentifier": "androidx/test/orchestrator/listeners/result/TestIdentifier",
-      "android/support/test/orchestrator/listeners/result/TestResult": "androidx/test/orchestrator/listeners/result/TestResult",
-      "android/support/test/orchestrator/listeners/result/TestRunResult": "androidx/test/orchestrator/listeners/result/TestRunResult",
-      "android/support/test/rule/ActivityTestRule": "androidx/test/rule/ActivityTestRule",
-      "android/support/test/rule/DisableOnAndroidDebug": "androidx/test/rule/DisableOnAndroidDebug",
-      "android/support/test/rule/GrantPermissionRule": "androidx/test/rule/GrantPermissionRule",
-      "android/support/test/rule/PortForwardingRule": "androidx/test/rule/PortForwardingRule",
-      "android/support/test/rule/ServiceTestRule": "androidx/test/rule/ServiceTestRule",
-      "android/support/test/rule/UiThreadTestRule": "androidx/test/rule/UiThreadTestRule",
-      "android/support/test/rule/logging/AtraceLogger": "androidx/test/rule/logging/AtraceLogger",
-      "android/support/test/rule/provider/DatabaseArgs": "androidx/test/rule/provider/DatabaseArgs",
-      "android/support/test/rule/provider/DelegatingContext": "androidx/test/rule/provider/DelegatingContext",
-      "android/support/test/rule/provider/ProviderArgs": "androidx/test/rule/provider/ProviderArgs",
-      "android/support/test/rule/provider/ProviderTestRule": "androidx/test/rule/provider/ProviderTestRule",
-      "android/support/test/runner/AndroidJUnit4": "androidx/test/runner/AndroidJUnit4",
-      "android/support/test/runner/AndroidJUnitRunner": "androidx/test/runner/AndroidJUnitRunner",
-      "android/support/test/runner/MonitoringInstrumentation": "androidx/test/runner/MonitoringInstrumentation",
-      "android/support/test/runner/UsageTrackerFacilitator": "androidx/test/runner/UsageTrackerFacilitator",
-      "android/support/test/runner/intent/IntentCallback": "androidx/test/runner/intent/IntentCallback",
-      "android/support/test/runner/intent/IntentMonitor": "androidx/test/runner/intent/IntentMonitor",
-      "android/support/test/runner/intent/IntentMonitorRegistry": "androidx/test/runner/intent/IntentMonitorRegistry",
-      "android/support/test/runner/intent/IntentStubber": "androidx/test/runner/intent/IntentStubber",
-      "android/support/test/runner/intent/IntentStubberRegistry": "androidx/test/runner/intent/IntentStubberRegistry",
-      "android/support/test/runner/intercepting/InterceptingActivityFactory": "androidx/test/runner/intercepting/InterceptingActivityFactory",
-      "android/support/test/runner/intercepting/SingleActivityFactory": "androidx/test/runner/intercepting/SingleActivityFactory",
-      "android/support/test/runner/lifecycle/ActivityLifecycleCallback": "androidx/test/runner/lifecycle/ActivityLifecycleCallback",
-      "android/support/test/runner/lifecycle/ActivityLifecycleMonitor": "androidx/test/runner/lifecycle/ActivityLifecycleMonitor",
-      "android/support/test/runner/lifecycle/ActivityLifecycleMonitorRegistry": "androidx/test/runner/lifecycle/ActivityLifecycleMonitorRegistry",
-      "android/support/test/runner/lifecycle/ApplicationLifecycleCallback": "androidx/test/runner/lifecycle/ApplicationLifecycleCallback",
-      "android/support/test/runner/lifecycle/ApplicationLifecycleMonitor": "androidx/test/runner/lifecycle/ApplicationLifecycleMonitor",
-      "android/support/test/runner/lifecycle/ApplicationLifecycleMonitorRegistry": "androidx/test/runner/lifecycle/ApplicationLifecycleMonitorRegistry",
-      "android/support/test/runner/lifecycle/ApplicationStage": "androidx/test/runner/lifecycle/ApplicationStage",
-      "android/support/test/runner/lifecycle/Stage": "androidx/test/runner/lifecycle/Stage",
-      "android/support/test/runner/permission/GrantPermissionCallable": "androidx/test/runner/permission/GrantPermissionCallable",
-      "android/support/test/runner/permission/PermissionRequester": "androidx/test/runner/permission/PermissionRequester",
-      "android/support/test/runner/permission/RequestPermissionCallable": "androidx/test/runner/permission/RequestPermissionCallable",
-      "android/support/test/runner/permission/ShellCommand": "androidx/test/runner/permission/ShellCommand",
-      "android/support/test/runner/permission/UiAutomationShellCommand": "androidx/test/runner/permission/UiAutomationShellCommand",
-      "android/support/test/runner/screenshot/BasicScreenCaptureProcessor": "androidx/test/runner/screenshot/BasicScreenCaptureProcessor",
-      "android/support/test/runner/screenshot/ScreenCapture": "androidx/test/runner/screenshot/ScreenCapture",
-      "android/support/test/runner/screenshot/ScreenCaptureProcessor": "androidx/test/runner/screenshot/ScreenCaptureProcessor",
-      "android/support/test/runner/screenshot/Screenshot": "androidx/test/runner/screenshot/Screenshot",
-      "android/support/test/runner/screenshot/TakeScreenshotCallable": "androidx/test/runner/screenshot/TakeScreenshotCallable",
-      "android/support/test/runner/screenshot/UiAutomationWrapper": "androidx/test/runner/screenshot/UiAutomationWrapper",
-      "android/support/test/uiautomator/AccessibilityNodeInfoDumper": "androidx/test/uiautomator/AccessibilityNodeInfoDumper",
-      "android/support/test/uiautomator/AccessibilityNodeInfoHelper": "androidx/test/uiautomator/AccessibilityNodeInfoHelper",
-      "android/support/test/uiautomator/By": "androidx/test/uiautomator/By",
-      "android/support/test/uiautomator/ByMatcher": "androidx/test/uiautomator/ByMatcher",
-      "android/support/test/uiautomator/BySelector": "androidx/test/uiautomator/BySelector",
-      "android/support/test/uiautomator/Condition": "androidx/test/uiautomator/Condition",
-      "android/support/test/uiautomator/Configurator": "androidx/test/uiautomator/Configurator",
-      "android/support/test/uiautomator/Direction": "androidx/test/uiautomator/Direction",
-      "android/support/test/uiautomator/EventCondition": "androidx/test/uiautomator/EventCondition",
-      "android/support/test/uiautomator/GestureController": "androidx/test/uiautomator/GestureController",
-      "android/support/test/uiautomator/Gestures": "androidx/test/uiautomator/Gestures",
-      "android/support/test/uiautomator/IAutomationSupport": "androidx/test/uiautomator/IAutomationSupport",
-      "android/support/test/uiautomator/InstrumentationAutomationSupport": "androidx/test/uiautomator/InstrumentationAutomationSupport",
-      "android/support/test/uiautomator/InteractionController": "androidx/test/uiautomator/InteractionController",
-      "android/support/test/uiautomator/PointerGesture": "androidx/test/uiautomator/PointerGesture",
-      "android/support/test/uiautomator/QueryController": "androidx/test/uiautomator/QueryController",
-      "android/support/test/uiautomator/SearchCondition": "androidx/test/uiautomator/SearchCondition",
-      "android/support/test/uiautomator/Searchable": "androidx/test/uiautomator/Searchable",
-      "android/support/test/uiautomator/StaleObjectException": "androidx/test/uiautomator/StaleObjectException",
-      "android/support/test/uiautomator/Tracer": "androidx/test/uiautomator/Tracer",
-      "android/support/test/uiautomator/UiAutomatorInstrumentationTestRunner": "androidx/test/uiautomator/UiAutomatorInstrumentationTestRunner",
-      "android/support/test/uiautomator/UiAutomatorTestCase": "androidx/test/uiautomator/UiAutomatorTestCase",
-      "android/support/test/uiautomator/UiCollection": "androidx/test/uiautomator/UiCollection",
-      "android/support/test/uiautomator/UiDevice": "androidx/test/uiautomator/UiDevice",
-      "android/support/test/uiautomator/UiObject": "androidx/test/uiautomator/UiObject",
-      "android/support/test/uiautomator/UiObject2": "androidx/test/uiautomator/UiObject2",
-      "android/support/test/uiautomator/UiObject2Condition": "androidx/test/uiautomator/UiObject2Condition",
-      "android/support/test/uiautomator/UiObjectNotFoundException": "androidx/test/uiautomator/UiObjectNotFoundException",
-      "android/support/test/uiautomator/UiScrollable": "androidx/test/uiautomator/UiScrollable",
-      "android/support/test/uiautomator/UiSelector": "androidx/test/uiautomator/UiSelector",
-      "android/support/test/uiautomator/UiWatcher": "androidx/test/uiautomator/UiWatcher",
-      "android/support/test/uiautomator/Until": "androidx/test/uiautomator/Until",
-      "android/support/test/uiautomator/WaitMixin": "androidx/test/uiautomator/WaitMixin",
       "android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat": "androidx/core/accessibilityservice/AccessibilityServiceInfoCompat",
       "android/support/v4/app/ActivityCompat": "androidx/core/app/ActivityCompat",
       "android/support/v4/app/ActivityManagerCompat": "androidx/core/app/ActivityManagerCompat",
diff --git a/jetifier/jetifier/preprocessor/build.gradle b/jetifier/jetifier/preprocessor/build.gradle
index c38d52f..f478c95 100644
--- a/jetifier/jetifier/preprocessor/build.gradle
+++ b/jetifier/jetifier/preprocessor/build.gradle
@@ -26,6 +26,6 @@
 mainClassName = "com.android.tools.build.jetifier.preprocessor.MainKt"
 
 dependencies {
-    compile project(':jetifier-processor')
-    compile group: 'commons-cli', name: 'commons-cli', version: '1.3.1'
+    api(project(":jetifier-processor"))
+    api("commons-cli:commons-cli:1.3.1")
 }
diff --git a/jetifier/jetifier/processor/build.gradle b/jetifier/jetifier/processor/build.gradle
index fd7d9c6..0fe2cfd 100644
--- a/jetifier/jetifier/processor/build.gradle
+++ b/jetifier/jetifier/processor/build.gradle
@@ -28,14 +28,14 @@
 targetCompatibility = JavaVersion.VERSION_1_7
 
 dependencies {
-    compile project(':jetifier-core')
-    compile("org.ow2.asm:asm:6.0")
-    compile("org.ow2.asm:asm-util:6.0")
-    compile("org.ow2.asm:asm-commons:6.0")
-    compile("org.jdom:jdom2:2.0.6")
-    compile(KOTLIN_STDLIB)
-    testCompile("junit:junit:4.12")
-    testCompile(TRUTH)
+    api(project(":jetifier-core"))
+    api("org.ow2.asm:asm:6.0")
+    api("org.ow2.asm:asm-util:6.0")
+    api("org.ow2.asm:asm-commons:6.0")
+    api("org.jdom:jdom2:2.0.6")
+    api(KOTLIN_STDLIB)
+    testImplementation("junit:junit:4.12")
+    testImplementation(TRUTH)
 }
 
 androidx {
diff --git a/jetifier/jetifier/standalone/build.gradle b/jetifier/jetifier/standalone/build.gradle
index 126f449..73617fc 100644
--- a/jetifier/jetifier/standalone/build.gradle
+++ b/jetifier/jetifier/standalone/build.gradle
@@ -25,8 +25,8 @@
 mainClassName = "com.android.tools.build.jetifier.standalone.Main"
 
 dependencies {
-    compile project(':jetifier-processor')
-    compile group: 'commons-cli', name: 'commons-cli', version: '1.3.1'
+    api(project(":jetifier-processor"))
+    api("commons-cli:commons-cli:1.3.1")
 }
 
 task dist(type: Copy) {
diff --git a/lifecycle/integration-tests/incrementality/build.gradle b/lifecycle/integration-tests/incrementality/build.gradle
index 8207fb4..f036777 100644
--- a/lifecycle/integration-tests/incrementality/build.gradle
+++ b/lifecycle/integration-tests/incrementality/build.gradle
@@ -66,4 +66,5 @@
 // lifecycle-common and annotation are the dependencies of lifecycle-compiler
 tasks.findByPath("test").dependsOn(tasks.findByPath(":lifecycle:lifecycle-compiler:publish"),
         tasks.findByPath(":lifecycle:lifecycle-common:publish"),
+        tasks.findByPath(":lifecycle:lifecycle-runtime:publish"),
         tasks.findByPath(":annotation:annotation:publish"))
diff --git a/lifecycle/lifecycle-common-java8/build.gradle b/lifecycle/lifecycle-common-java8/build.gradle
index 6c0e6e6..d0315593 100644
--- a/lifecycle/lifecycle-common-java8/build.gradle
+++ b/lifecycle/lifecycle-common-java8/build.gradle
@@ -26,11 +26,11 @@
 }
 
 dependencies {
-    compile(project(":lifecycle:lifecycle-common"))
-    compile("androidx.annotation:annotation:1.1.0")
+    api(project(":lifecycle:lifecycle-common"))
+    api("androidx.annotation:annotation:1.1.0")
 
-    testCompile(JUNIT)
-    testCompile(MOCKITO_CORE)
+    testImplementation(JUNIT)
+    testImplementation(MOCKITO_CORE)
 }
 
 androidx {
diff --git a/lifecycle/lifecycle-common/build.gradle b/lifecycle/lifecycle-common/build.gradle
index 2168cfa..bfae8ef 100644
--- a/lifecycle/lifecycle-common/build.gradle
+++ b/lifecycle/lifecycle-common/build.gradle
@@ -30,9 +30,10 @@
 targetCompatibility = JavaVersion.VERSION_1_7
 
 dependencies {
-    testCompile(JUNIT)
-    testCompile(MOCKITO_CORE)
-    compile("androidx.annotation:annotation:1.1.0")
+    api("androidx.annotation:annotation:1.1.0")
+
+    testImplementation(JUNIT)
+    testImplementation(MOCKITO_CORE)
 }
 
 androidx {
diff --git a/lifecycle/lifecycle-compiler/build.gradle b/lifecycle/lifecycle-compiler/build.gradle
index 22594250..4228710 100644
--- a/lifecycle/lifecycle-compiler/build.gradle
+++ b/lifecycle/lifecycle-compiler/build.gradle
@@ -22,13 +22,13 @@
 }
 
 dependencies {
-    compile(project(":lifecycle:lifecycle-common"))
-    compile(KOTLIN_STDLIB)
-    compile(AUTO_COMMON)
-    compile(JAVAPOET)
-    testCompile(GOOGLE_COMPILE_TESTING)
-    testCompile(JSR250)
-    testCompile files(org.gradle.internal.jvm.Jvm.current().getToolsJar())
+    implementation(project(":lifecycle:lifecycle-common"))
+    implementation(KOTLIN_STDLIB)
+    implementation(AUTO_COMMON)
+    implementation(JAVAPOET)
+    testImplementation(GOOGLE_COMPILE_TESTING)
+    testImplementation(JSR250)
+    testImplementation files(org.gradle.internal.jvm.Jvm.current().getToolsJar())
 }
 
 // we actually need to compile :lifecycle:lifecycle-common, but compileJava is easier
diff --git a/lifecycle/lifecycle-runtime-ktx/src/androidTest/java/androidx/lifecycle/LaunchWhenTest.kt b/lifecycle/lifecycle-runtime-ktx/src/androidTest/java/androidx/lifecycle/LaunchWhenTest.kt
index b2dc7b3..7bdc5b8 100644
--- a/lifecycle/lifecycle-runtime-ktx/src/androidTest/java/androidx/lifecycle/LaunchWhenTest.kt
+++ b/lifecycle/lifecycle-runtime-ktx/src/androidTest/java/androidx/lifecycle/LaunchWhenTest.kt
@@ -17,13 +17,13 @@
 package androidx.lifecycle
 
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
+import androidx.test.filters.MediumTest
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.runBlocking
 import org.junit.Test
 import org.junit.runner.RunWith
 
-@SmallTest
+@MediumTest
 @RunWith(AndroidJUnit4::class)
 class LaunchWhenTest {
     private val expectations = Expectations()
diff --git a/media2/player/src/androidTest/java/androidx/media2/player/MediaPlayerTest.java b/media2/player/src/androidTest/java/androidx/media2/player/MediaPlayerTest.java
index d541c90..e58afc2 100644
--- a/media2/player/src/androidTest/java/androidx/media2/player/MediaPlayerTest.java
+++ b/media2/player/src/androidTest/java/androidx/media2/player/MediaPlayerTest.java
@@ -1957,6 +1957,49 @@
         assertTrue(latchFor3rdItem.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
     }
 
+    @Ignore("Test disabled due to flakiness, see b/144972397")
+    @Test
+    @LargeTest
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.KITKAT)
+    public void testSeekToEndOfMediaItem() throws Exception {
+        List<MediaItem> playlist = new ArrayList<>();
+        playlist.add(createMediaItem(R.raw.testmp3));
+        playlist.add(createMediaItem(R.raw.testmp3));
+        playlist.add(createMediaItem(R.raw.testmp3));
+
+        List<CountDownLatch> latches = new ArrayList<>();
+        for (int i = 0; i < playlist.size(); i++) {
+            latches.add(new CountDownLatch(1));
+        }
+
+        MediaPlayer.PlayerCallback callback = new MediaPlayer.PlayerCallback() {
+            @Override
+            public void onCurrentMediaItemChanged(@NonNull SessionPlayer player,
+                    @NonNull MediaItem item) {
+                for (int i = 0; i < playlist.size(); i++) {
+                    if (playlist.get(i) == item) {
+                        latches.get(i).countDown();
+                        break;
+                    }
+                }
+            }
+        };
+        mPlayer.registerPlayerCallback(mExecutor, callback);
+
+        assertNotNull(mPlayer.setPlaylist(playlist, null));
+        assertNotNull(mPlayer.prepare());
+        assertFutureSuccess(mPlayer.play());
+
+        for (int i = 0; i < playlist.size(); i++) {
+            assertTrue("onCurrentMediaItemChanged is not called for item i=" + i,
+                    latches.get(i).await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+            if (i + 1 < playlist.size()) {
+                long duration = mPlayer.getDuration();
+                assertNotEquals(SessionPlayer.UNKNOWN_TIME, duration);
+                assertFutureSuccess(mPlayer.seekTo(duration));
+            }
+        }
+    }
 
     private MediaItem createMediaItem() throws Exception {
         return createMediaItem(R.raw.testvideo);
diff --git a/media2/session/src/main/java/androidx/media2/session/MediaController.java b/media2/session/src/main/java/androidx/media2/session/MediaController.java
index 0a5d41c..9513113 100644
--- a/media2/session/src/main/java/androidx/media2/session/MediaController.java
+++ b/media2/session/src/main/java/androidx/media2/session/MediaController.java
@@ -759,10 +759,9 @@
     }
 
     /**
-     * Requests that the {@link SessionPlayer} associated with the connected {@link MediaSession}
-     * rates the media. This will cause the rating to be set for the
-     * current user. The rating style must follow the user rating style from the session.
-     * You can get the rating style from the session through the
+     * Requests that the connected {@link MediaSession} rates the media. This will cause the rating
+     * to be set for the current user. The rating style must follow the user rating style from the
+     * session.You can get the rating style from the session through the
      * {@link MediaMetadata#getRating(String)} with the key
      * {@link MediaMetadata#METADATA_KEY_USER_RATING}.
      * <p>
diff --git a/media2/widget/src/androidTest/java/androidx/media2/widget/VideoView_WithPlayerTest.java b/media2/widget/src/androidTest/java/androidx/media2/widget/VideoView_WithPlayerTest.java
index c648c91..f074256 100644
--- a/media2/widget/src/androidTest/java/androidx/media2/widget/VideoView_WithPlayerTest.java
+++ b/media2/widget/src/androidTest/java/androidx/media2/widget/VideoView_WithPlayerTest.java
@@ -370,7 +370,7 @@
                 withAspectRatio(videoSizeFor1stItem.getWidth(), videoSizeFor1stItem.getHeight())));
 
         // seekTo instead of skipToNextItem (b/144876689)
-        playerWrapper.seekTo(Long.MAX_VALUE);
+        playerWrapper.seekTo(playerWrapper.getDurationMs());
         assertTrue(latchFor2ndItem.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
         onView(instanceOf(VideoSurfaceView.class)).check(matches(
                 withAspectRatio(videoSizeFor2ndItem.getWidth(), videoSizeFor2ndItem.getHeight())));
diff --git a/mediarouter/src/main/java/androidx/mediarouter/app/MediaRouteButton.java b/mediarouter/src/main/java/androidx/mediarouter/app/MediaRouteButton.java
index ebe8698..bf3d42e 100644
--- a/mediarouter/src/main/java/androidx/mediarouter/app/MediaRouteButton.java
+++ b/mediarouter/src/main/java/androidx/mediarouter/app/MediaRouteButton.java
@@ -30,6 +30,7 @@
 import android.net.ConnectivityManager;
 import android.os.AsyncTask;
 import android.os.Build;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.SparseArray;
@@ -127,6 +128,7 @@
 
     private boolean mUseDynamicGroup;
     private boolean mAlwaysVisible;
+    private boolean mCheatSheetEnabled;
 
     // The checked state is used when connected to a remote route.
     private static final int[] CHECKED_STATE_SET = {
@@ -367,8 +369,10 @@
      * button when the button is long pressed.
      */
     void setCheatSheetEnabled(boolean enable) {
-        TooltipCompat.setTooltipText(this,
-                enable ? getContext().getString(R.string.mr_button_content_description) : null);
+        if (enable != mCheatSheetEnabled) {
+            mCheatSheetEnabled = enable;
+            updateContentDescription();
+        }
     }
 
     @Override
@@ -671,7 +675,11 @@
                 break;
         }
 
-        setContentDescription(getContext().getString(resId));
+        String contentDesc = getContext().getString(resId);
+        setContentDescription(contentDesc);
+
+        TooltipCompat.setTooltipText(this,
+                mCheatSheetEnabled && !TextUtils.isEmpty(contentDesc) ? contentDesc : null);
     }
 
     private final class MediaRouterCallback extends MediaRouter.Callback {
diff --git a/mediarouter/src/main/res/layout/mr_playback_control.xml b/mediarouter/src/main/res/layout/mr_playback_control.xml
index eb9d109..580a234 100644
--- a/mediarouter/src/main/res/layout/mr_playback_control.xml
+++ b/mediarouter/src/main/res/layout/mr_playback_control.xml
@@ -41,16 +41,19 @@
                   android:layout_toStartOf="@id/mr_control_playback_ctrl"
                   android:layout_alignParentLeft="true"
                   android:layout_alignParentStart="true"
+                  android:importantForAccessibility="no"
                   android:layout_centerVertical="true">
         <TextView android:id="@+id/mr_control_title"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
                   android:textAppearance="@style/TextAppearance.MediaRouter.PrimaryText"
+                  android:clickable="false"
                   android:singleLine="true" />
         <TextView android:id="@+id/mr_control_subtitle"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
                   android:textAppearance="@style/TextAppearance.MediaRouter.SecondaryText"
+                  android:clickable="false"
                   android:singleLine="true" />
     </LinearLayout>
 </RelativeLayout>
diff --git a/navigation/integration-tests/safeargs-testapp/build.gradle b/navigation/integration-tests/safeargs-testapp/build.gradle
index 395f8c0..19182c7 100644
--- a/navigation/integration-tests/safeargs-testapp/build.gradle
+++ b/navigation/integration-tests/safeargs-testapp/build.gradle
@@ -66,6 +66,6 @@
 
 dependencies {
     implementation "${LibraryGroups.NAVIGATION}:navigation-runtime:${LibraryVersions.NAVIGATION}"
-    testCompile(JUNIT)
-    testCompile(MOCKITO_CORE)
+    testImplementation(JUNIT)
+    testImplementation(MOCKITO_CORE)
 }
\ No newline at end of file
diff --git a/navigation/navigation-common/build.gradle b/navigation/navigation-common/build.gradle
index 8b6c8e7..47e140b 100644
--- a/navigation/navigation-common/build.gradle
+++ b/navigation/navigation-common/build.gradle
@@ -46,7 +46,7 @@
     androidTestImplementation(KOTLIN_STDLIB)
 }
 
-//used by testCompile safe-args-generator
+//used by testImplementation safe-args-generator
 android.libraryVariants.all { variant ->
     def name = variant.name
     def suffix = name.capitalize()
diff --git a/navigation/navigation-dynamic-features-activity/build.gradle b/navigation/navigation-dynamic-features-activity/build.gradle
index 0358704..971db09 100644
--- a/navigation/navigation-dynamic-features-activity/build.gradle
+++ b/navigation/navigation-dynamic-features-activity/build.gradle
@@ -47,7 +47,7 @@
     androidTestImplementation(TRUTH)
 }
 
-//used by testCompile safe-args-generator
+//used by testImplementation safe-args-generator
 android.libraryVariants.all { variant ->
     def name = variant.name
     def suffix = name.capitalize()
diff --git a/navigation/navigation-dynamic-features-core/build.gradle b/navigation/navigation-dynamic-features-core/build.gradle
index 4a03282..a994947 100644
--- a/navigation/navigation-dynamic-features-core/build.gradle
+++ b/navigation/navigation-dynamic-features-core/build.gradle
@@ -48,7 +48,7 @@
     androidTestImplementation(TRUTH)
 }
 
-//used by testCompile safe-args-generator
+//used by testImplementation safe-args-generator
 android.libraryVariants.all { variant ->
     def name = variant.name
     def suffix = name.capitalize()
diff --git a/navigation/navigation-dynamic-features-fragment/build.gradle b/navigation/navigation-dynamic-features-fragment/build.gradle
index 67faed3..b6c19b2 100644
--- a/navigation/navigation-dynamic-features-fragment/build.gradle
+++ b/navigation/navigation-dynamic-features-fragment/build.gradle
@@ -59,7 +59,7 @@
     }
 }
 
-//used by testCompile safe-args-generator
+//used by testImplementation safe-args-generator
 android.libraryVariants.all { variant ->
     def name = variant.name
     def suffix = name.capitalize()
diff --git a/navigation/navigation-safe-args-generator/build.gradle b/navigation/navigation-safe-args-generator/build.gradle
index 325d701..7f36bfe 100644
--- a/navigation/navigation-safe-args-generator/build.gradle
+++ b/navigation/navigation-safe-args-generator/build.gradle
@@ -36,20 +36,20 @@
 }
 
 dependencies {
-    compile(XPP3)
-    compile(XMLPULL)
-    compile(KOTLIN_STDLIB)
+    implementation(XPP3)
+    implementation(XMLPULL)
+    implementation(KOTLIN_STDLIB)
 
-    compile(JAVAPOET)
-    compile(KOTLINPOET)
+    implementation(JAVAPOET)
+    implementation(KOTLINPOET)
 
-    testCompile(JUNIT)
-    testCompile(GOOGLE_COMPILE_TESTING)
-    testCompile fileTree(dir: "${SdkHelperKt.getSdkPath(project.rootDir)}/platforms/$SupportConfig.COMPILE_SDK_VERSION/",
+    testImplementation(JUNIT)
+    testImplementation(GOOGLE_COMPILE_TESTING)
+    testImplementation fileTree(dir: "${SdkHelperKt.getSdkPath(project.rootDir)}/platforms/$SupportConfig.COMPILE_SDK_VERSION/",
             include : "android.jar")
-    testCompile fileTree(dir: "${new File(project(":navigation:navigation-common").buildDir, "libJar")}",
+    testImplementation fileTree(dir: "${new File(project(":navigation:navigation-common").buildDir, "libJar")}",
             include : "*.jar")
-    testCompile files(Jvm.current().getToolsJar())
+    testImplementation files(Jvm.current().getToolsJar())
 }
 
 tasks.findByName("test").doFirst {
diff --git a/navigation/navigation-safe-args-gradle-plugin/build.gradle b/navigation/navigation-safe-args-gradle-plugin/build.gradle
index 9c382fa..d43cd41 100644
--- a/navigation/navigation-safe-args-gradle-plugin/build.gradle
+++ b/navigation/navigation-safe-args-gradle-plugin/build.gradle
@@ -38,13 +38,13 @@
 }
 
 dependencies {
-    compile(AGP_STABLE)
-    compile(KOTLIN_GRADLE_PLUGIN)
+    implementation(AGP_STABLE)
+    implementation(KOTLIN_GRADLE_PLUGIN)
     compile project(":navigation:navigation-safe-args-generator")
     compile gradleApi()
-    compile(GSON)
-    testCompile gradleTestKit()
-    testCompile(JUNIT)
+    implementation(GSON)
+    testImplementation gradleTestKit()
+    testImplementation(JUNIT)
 }
 
 task generateSdkResource() {
diff --git a/paging/common/build.gradle b/paging/common/build.gradle
index 9fb3baf..7528976 100644
--- a/paging/common/build.gradle
+++ b/paging/common/build.gradle
@@ -28,13 +28,13 @@
 }
 
 dependencies {
-    compile("androidx.annotation:annotation:1.1.0")
-    compile("androidx.arch.core:core-common:2.0.1")
+    api("androidx.annotation:annotation:1.1.0")
+    api("androidx.arch.core:core-common:2.0.1")
     api(KOTLIN_STDLIB)
     api(KOTLIN_COROUTINES_CORE)
 
-    testCompile(JUNIT)
-    testCompile(MOCKITO_CORE)
+    testImplementation(JUNIT)
+    testImplementation(MOCKITO_CORE)
     testImplementation MOCKITO_KOTLIN, {
         exclude group: 'org.mockito' // to keep control on the mockito version
     }
diff --git a/room/common/build.gradle b/room/common/build.gradle
index 3ee72ae..e10ee75 100644
--- a/room/common/build.gradle
+++ b/room/common/build.gradle
@@ -26,11 +26,11 @@
 }
 
 dependencies {
-    compile("androidx.annotation:annotation:1.1.0")
-    testCompile(KOTLIN_STDLIB)
-    testCompile(JUNIT)
-    testCompile(MOCKITO_CORE)
-    testCompile(GUAVA)
+    api("androidx.annotation:annotation:1.1.0")
+    testImplementation(KOTLIN_STDLIB)
+    testImplementation(JUNIT)
+    testImplementation(MOCKITO_CORE)
+    testImplementation(GUAVA)
 }
 
 androidx {
diff --git a/room/compiler/build.gradle b/room/compiler/build.gradle
index e4adab3..a661005 100644
--- a/room/compiler/build.gradle
+++ b/room/compiler/build.gradle
@@ -46,36 +46,36 @@
 }
 
 dependencies {
-    compile(project(":room:room-common"))
-    compile(project(":room:room-migration"))
-    compile(KOTLIN_STDLIB)
-    compile(AUTO_COMMON)
-    compile(AUTO_VALUE_ANNOTATIONS)
-    compile(JAVAPOET)
-    compile(ANTLR)
-    compile(XERIAL)
-    compile(KOTLIN_METADATA_JVM)
-    compile(APACHE_COMMONS_CODEC)
-    compile(INTELLIJ_ANNOTATIONS)
-    testCompile(GOOGLE_COMPILE_TESTING)
-    testCompile project(":paging:paging-common")
-    testCompile(JUNIT)
-    testCompile(JSR250)
-    testCompile(MOCKITO_CORE)
-    testCompile fileTree(dir: "${SdkHelperKt.getSdkPath(project.rootDir)}/platforms/$SupportConfig.COMPILE_SDK_VERSION/",
+    implementation(project(":room:room-common"))
+    implementation(project(":room:room-migration"))
+    implementation(KOTLIN_STDLIB)
+    implementation(AUTO_COMMON)
+    implementation(AUTO_VALUE_ANNOTATIONS)
+    implementation(JAVAPOET)
+    implementation(ANTLR)
+    implementation(XERIAL)
+    implementation(KOTLIN_METADATA_JVM)
+    implementation(APACHE_COMMONS_CODEC)
+    implementation(INTELLIJ_ANNOTATIONS)
+    testImplementation(GOOGLE_COMPILE_TESTING)
+    testImplementation project(":paging:paging-common")
+    testImplementation(JUNIT)
+    testImplementation(JSR250)
+    testImplementation(MOCKITO_CORE)
+    testImplementation fileTree(dir: "${SdkHelperKt.getSdkPath(project.rootDir)}/platforms/$SupportConfig.COMPILE_SDK_VERSION/",
             include : "android.jar")
-    testCompile fileTree(dir: "${new File(project(":room:room-runtime").buildDir, "libJar")}",
+    testImplementation fileTree(dir: "${new File(project(":room:room-runtime").buildDir, "libJar")}",
             include : "*.jar")
-    testCompile fileTree(dir: "${new File(project(":sqlite:sqlite").buildDir, "libJar")}",
+    testImplementation fileTree(dir: "${new File(project(":sqlite:sqlite").buildDir, "libJar")}",
             include : "*.jar")
-    testCompile files(Jvm.current().getToolsJar())
+    testImplementation files(Jvm.current().getToolsJar())
 }
 
 def generateAntlrTask = task('generateAntlrGrammar', type: JavaExec) {
     def outFolder = file(antlrOut)
     outputs.dir(outFolder)
     inputs.file("$projectDir/SQLite.g4")
-    classpath configurations.runtime
+    classpath configurations.compileClasspath
     main "org.antlr.v4.Tool"
     args "SQLite.g4", "-visitor", "-o", new File(outFolder, "androidx/room/parser").path,
             "-package", "androidx.room.parser"
diff --git a/room/integration-tests/incremental-annotation-processing/build.gradle b/room/integration-tests/incremental-annotation-processing/build.gradle
index 21fe960..aeb543f 100644
--- a/room/integration-tests/incremental-annotation-processing/build.gradle
+++ b/room/integration-tests/incremental-annotation-processing/build.gradle
@@ -35,7 +35,7 @@
 
 
 dependencies {
-    compile(KOTLIN_STDLIB)
+    implementation(KOTLIN_STDLIB)
     testImplementation(JUNIT)
     testImplementation(TRUTH)
     testImplementation gradleTestKit()
diff --git a/room/migration/build.gradle b/room/migration/build.gradle
index ecd8634..07b5b1b 100644
--- a/room/migration/build.gradle
+++ b/room/migration/build.gradle
@@ -26,12 +26,12 @@
 }
 
 dependencies {
-    compile(project(":room:room-common"))
-    compile(KOTLIN_STDLIB)
-    compile(GSON)
-    testCompile(JUNIT)
-    testCompile(INTELLIJ_ANNOTATIONS)
-    testCompile(MOCKITO_CORE)
+    implementation(project(":room:room-common"))
+    implementation(KOTLIN_STDLIB)
+    implementation(GSON)
+    testImplementation(JUNIT)
+    testImplementation(INTELLIJ_ANNOTATIONS)
+    testImplementation(MOCKITO_CORE)
 }
 
 androidx {
diff --git a/room/runtime/build.gradle b/room/runtime/build.gradle
index 0f271d7..123977a 100644
--- a/room/runtime/build.gradle
+++ b/room/runtime/build.gradle
@@ -60,7 +60,7 @@
     def name = variant.name
     def suffix = name.capitalize()
 
-    // Create jar<variant> task for testCompile in room-compiler.
+    // Create jar<variant> task for testImplementation in room-compiler.
     project.tasks.create(name: "jar${suffix}", type: Jar){
         dependsOn variant.javaCompileProvider.get()
         from variant.javaCompileProvider.get().destinationDir
diff --git a/samples/Support7Demos/src/main/res/layout/appcompat_night_mode.xml b/samples/Support7Demos/src/main/res/layout/appcompat_night_mode.xml
index cdae523..974ff3f 100644
--- a/samples/Support7Demos/src/main/res/layout/appcompat_night_mode.xml
+++ b/samples/Support7Demos/src/main/res/layout/appcompat_night_mode.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
      Copyright (C) 2015 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,43 +15,48 @@
 -->
 
 <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:padding="16dp">
+
+        <Button
             android:layout_width="match_parent"
-            android:layout_height="match_parent">
+            android:layout_height="wrap_content"
+            android:onClick="setModeNightFollowSystem"
+            android:text="@string/mode_night_follow_system" />
 
-    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                  android:layout_width="match_parent"
-                  android:layout_height="wrap_content"
-                  android:orientation="vertical"
-                  android:padding="16dp">
-
-        <Button android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:text="@string/mode_night_follow_system"
-                android:onClick="setModeNightFollowSystem"/>
-
-        <Button android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:text="@string/mode_night_no"
-                android:onClick="setModeNightNo"/>
-
-        <Button android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:text="@string/mode_night_yes"
-                android:onClick="setModeNightYes"/>
-
-        <Button android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:text="@string/mode_night_auto_time"
-                android:onClick="setModeNightAutoTime"/>
-
-        <Button android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:text="@string/mode_night_auto_battery"
-                android:onClick="setModeNightAutoBattery"/>
-
-        <View
+        <Button
             android:layout_width="match_parent"
-            android:layout_height="100dp" />
+            android:layout_height="wrap_content"
+            android:onClick="setModeNightNo"
+            android:text="@string/mode_night_no" />
+
+        <Button
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:onClick="setModeNightYes"
+            android:text="@string/mode_night_yes" />
+
+        <Button
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:onClick="setModeNightAutoTime"
+            android:text="@string/mode_night_auto_time" />
+
+        <Button
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:onClick="setModeNightAutoBattery"
+            android:text="@string/mode_night_auto_battery" />
+
+        <Space
+            android:layout_width="match_parent"
+            android:layout_height="64dp" />
 
         <TextView
             android:id="@+id/text_night_mode"
@@ -66,6 +70,17 @@
             android:layout_height="100dp"
             android:background="@drawable/test_night_color_conversion_background" />
 
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="16dp"
+            android:text="@string/webview" />
+
+        <WebView
+            android:id="@+id/webview"
+            android:layout_width="match_parent"
+            android:layout_height="100dp" />
+
     </LinearLayout>
 
 </ScrollView>
\ No newline at end of file
diff --git a/samples/Support7Demos/src/main/res/values/strings.xml b/samples/Support7Demos/src/main/res/values/strings.xml
index 238eb78..5ba149b 100644
--- a/samples/Support7Demos/src/main/res/values/strings.xml
+++ b/samples/Support7Demos/src/main/res/values/strings.xml
@@ -276,4 +276,6 @@
 
     <string name="menu_item_icon_tinting">AppCompat/Menu Item Icons</string>
     <string name="popup_group_dividers">Display group dividers</string>
+
+    <string name="webview">WebView</string>
 </resources>
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/GridRowBuilderListV1Impl.java b/slices/builders/src/main/java/androidx/slice/builders/impl/GridRowBuilderListV1Impl.java
index 0a0a64d..b48f106 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/GridRowBuilderListV1Impl.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/GridRowBuilderListV1Impl.java
@@ -179,7 +179,6 @@
 
         /**
          */
-        @NonNull
         private void addText(@NonNull CharSequence text) {
             addText(text, false /* isLoading */);
         }
@@ -195,14 +194,12 @@
 
         /**
          */
-        @NonNull
         private void addTitleText(@NonNull CharSequence text) {
             addTitleText(text, false /* isLoading */);
         }
 
         /**
          */
-        @NonNull
         private void addTitleText(@Nullable CharSequence text, boolean isLoading) {
             @Slice.SliceHint String[] hints = isLoading
                     ? new String[] {HINT_PARTIAL, HINT_TITLE}
@@ -212,14 +209,12 @@
 
         /**
          */
-        @NonNull
         private void addImage(@NonNull IconCompat image, int imageMode) {
             addImage(image, imageMode, false /* isLoading */);
         }
 
         /**
          */
-        @NonNull
         private void addImage(@Nullable IconCompat image, int imageMode, boolean isLoading) {
             ArrayList<String> hints = new ArrayList<>();
             if (imageMode != ICON_IMAGE) {
@@ -236,7 +231,6 @@
 
         /**
          */
-        @NonNull
         private void setContentIntent(@NonNull PendingIntent intent) {
             mContentIntent = intent;
         }
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderImpl.java b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderImpl.java
index 8a8954c..6fffae4 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderImpl.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderImpl.java
@@ -157,7 +157,6 @@
     /**
      * Add a row to list builder.
      */
-    @NonNull
     @Override
     public void addRow(@NonNull RowBuilder builder) {
         RowBuilderImpl impl = new RowBuilderImpl(createChildBuilder());
@@ -169,7 +168,6 @@
     /**
      * Add a row to list builder.
      */
-    @NonNull
     public void addRow(@NonNull RowBuilderImpl builder) {
         checkRow(true, builder.hasText());
         builder.getBuilder().addHints(HINT_LIST_ITEM);
@@ -178,7 +176,6 @@
 
     /**
      */
-    @NonNull
     @Override
     public void addGridRow(@NonNull GridRowBuilder builder) {
         checkRow(false, false);
@@ -260,7 +257,6 @@
 
     /**
      */
-    @NonNull
     @Override
     public void setColor(@ColorInt int color) {
         getBuilder().addInt(color, SUBTYPE_COLOR);
@@ -487,7 +483,6 @@
 
         /**
          */
-        @NonNull
         private void setTitleItem(long timeStamp) {
             mStartItem = new Slice.Builder(getBuilder())
                     .addTimestamp(timeStamp, null).addHints(HINT_TITLE).build();
@@ -495,14 +490,12 @@
 
         /**
          */
-        @NonNull
         protected void setTitleItem(IconCompat icon, int imageMode) {
             setTitleItem(icon, imageMode, false /* isLoading */);
         }
 
         /**
          */
-        @NonNull
         private void setTitleItem(IconCompat icon, int imageMode, boolean isLoading) {
             ArrayList<String> hints = new ArrayList<>();
             if (imageMode != ICON_IMAGE) {
@@ -524,7 +517,6 @@
 
         /**
          */
-        @NonNull
         private void setTitleItem(@NonNull SliceAction action) {
             setTitleItem(action, false /* isLoading */);
         }
@@ -541,14 +533,12 @@
 
         /**
          */
-        @NonNull
         private void setPrimaryAction(@NonNull SliceAction action) {
             mPrimaryAction = action;
         }
 
         /**
          */
-        @NonNull
         private void setTitle(CharSequence title) {
             setTitle(title, false /* isLoading */);
         }
@@ -564,7 +554,6 @@
 
         /**
          */
-        @NonNull
         protected void setSubtitle(CharSequence subtitle) {
             setSubtitle(subtitle, false /* isLoading */);
         }
@@ -580,7 +569,6 @@
 
         /**
          */
-        @NonNull
         protected void addEndItem(long timeStamp) {
             mEndItems.add(new Slice.Builder(getBuilder()).addTimestamp(timeStamp,
                     null, new String[0]).build());
@@ -588,14 +576,12 @@
 
         /**
          */
-        @NonNull
         private void addEndItem(IconCompat icon, int imageMode) {
             addEndItem(icon, imageMode, false /* isLoading */);
         }
 
         /**
          */
-        @NonNull
         private void addEndItem(IconCompat icon, int imageMode, boolean isLoading) {
             ArrayList<String> hints = new ArrayList<>();
             if (imageMode != ICON_IMAGE) {
@@ -617,7 +603,6 @@
 
         /**
          */
-        @NonNull
         private void addEndItem(@NonNull SliceAction action) {
             addEndItem(action, false /* isLoading */);
         }
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingBuilder.java b/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingBuilder.java
index d9214c9..4285eae 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingBuilder.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingBuilder.java
@@ -41,7 +41,7 @@
 
     /**
      */
-    public interface MessageBuilder {
+    interface MessageBuilder {
 
         /**
          * Add the icon used to display contact in the messaging experience
diff --git a/sqlite/sqlite/build.gradle b/sqlite/sqlite/build.gradle
index 648b276..1ef1d1c 100644
--- a/sqlite/sqlite/build.gradle
+++ b/sqlite/sqlite/build.gradle
@@ -31,7 +31,7 @@
     testImplementation(MOCKITO_CORE)
 }
 
-// Used by testCompile in room-compiler
+// Used by testImplementation in room-compiler
 android.libraryVariants.all { variant ->
     def name = variant.name
     def suffix = name.capitalize()
diff --git a/test/screenshot/proto/build.gradle b/test/screenshot/proto/build.gradle
index 728f34c..80b5a2a 100644
--- a/test/screenshot/proto/build.gradle
+++ b/test/screenshot/proto/build.gradle
@@ -30,7 +30,7 @@
 apply(plugin: "com.google.protobuf")
 
 dependencies {
-    compile(PROTOBUF)
+    implementation(PROTOBUF)
 }
 
 tasks.withType(Jar) {
diff --git a/ui/gradle/wrapper/gradle-wrapper.properties b/ui/gradle/wrapper/gradle-wrapper.properties
index c62ad8a..ec9defd 100644
--- a/ui/gradle/wrapper/gradle-wrapper.properties
+++ b/ui/gradle/wrapper/gradle-wrapper.properties
@@ -5,4 +5,4 @@
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=../../../../../tools/external/gradle/gradle-5.6.2-bin.zip
+distributionUrl=../../../../../tools/external/gradle/gradle-6.0-bin.zip
diff --git a/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/RadioGroupBenchmark.kt b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/RadioGroupBenchmark.kt
new file mode 100644
index 0000000..36ed034
--- /dev/null
+++ b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/RadioGroupBenchmark.kt
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2019 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.ui.benchmark.test
+
+import androidx.compose.Composable
+import androidx.compose.Model
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import androidx.ui.benchmark.ComposeBenchmarkRule
+import androidx.ui.benchmark.benchmarkFirstCompose
+import androidx.ui.benchmark.benchmarkFirstDraw
+import androidx.ui.benchmark.benchmarkFirstLayout
+import androidx.ui.benchmark.benchmarkFirstMeasure
+import androidx.ui.benchmark.toggleStateBenchmarkDraw
+import androidx.ui.benchmark.toggleStateBenchmarkLayout
+import androidx.ui.benchmark.toggleStateBenchmarkMeasure
+import androidx.ui.benchmark.toggleStateBenchmarkRecompose
+import androidx.ui.layout.Column
+import androidx.ui.material.MaterialTheme
+import androidx.ui.material.RadioGroup
+import androidx.ui.test.ComposeTestCase
+import androidx.ui.test.ToggleableTestCase
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Benchmark for [RadioGroup].
+ */
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+class RadioGroupBenchmark {
+
+    @get:Rule
+    val benchmarkRule = ComposeBenchmarkRule()
+
+    private val radioCaseFactory = { RadioGroupTestCase() }
+
+    @Test
+    fun first_compose() {
+        benchmarkRule.benchmarkFirstCompose(radioCaseFactory)
+    }
+
+    @Test
+    fun first_measure() {
+        benchmarkRule.benchmarkFirstMeasure(radioCaseFactory)
+    }
+
+    @Test
+    fun first_layout() {
+        benchmarkRule.benchmarkFirstLayout(radioCaseFactory)
+    }
+
+    @Test
+    fun first_draw() {
+        benchmarkRule.benchmarkFirstDraw(radioCaseFactory)
+    }
+
+    @Test
+    fun toggleRadio_recompose() {
+        benchmarkRule.toggleStateBenchmarkRecompose(radioCaseFactory)
+    }
+
+    @Test
+    fun toggleRadio_measure() {
+        benchmarkRule.toggleStateBenchmarkMeasure(radioCaseFactory)
+    }
+
+    @Test
+    fun toggleRadio_layout() {
+        benchmarkRule.toggleStateBenchmarkLayout(radioCaseFactory)
+    }
+
+    @Test
+    fun toggleRadio_draw() {
+        benchmarkRule.toggleStateBenchmarkDraw(radioCaseFactory)
+    }
+}
+
+@Model
+internal class RadioGroupSelectedState<T>(var selected: T)
+
+internal class RadioGroupTestCase : ComposeTestCase, ToggleableTestCase {
+
+    private val radiosCount = 10
+    private val options = (0 until radiosCount).toList()
+    private val select = RadioGroupSelectedState(0)
+
+    override fun toggleState() {
+        select.selected = (select.selected + 1) % radiosCount
+    }
+
+    @Composable
+    override fun emitContent() {
+        MaterialTheme {
+            RadioGroup {
+                Column {
+                    options.forEach { item ->
+                        RadioGroupTextItem(
+                            text = item.toString(),
+                            selected = (select.selected == item),
+                            onSelect = { select.selected = item })
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/core/WithConstraintsBenchmark.kt b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/core/WithConstraintsBenchmark.kt
index af313d2..c84a1c9 100644
--- a/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/core/WithConstraintsBenchmark.kt
+++ b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/core/WithConstraintsBenchmark.kt
@@ -26,6 +26,7 @@
 import androidx.ui.benchmark.toggleStateBenchmarkMeasureLayout
 import androidx.ui.core.Placeable.PlacementScope.place
 import androidx.ui.layout.Container
+import androidx.ui.layout.Size
 import androidx.ui.layout.Spacer
 import androidx.ui.test.ComposeTestCase
 import androidx.ui.test.ToggleableTestCase
@@ -66,7 +67,7 @@
         val size = +state { 200.dp }
         this.state = size
         Container(width = 300.dp, height = 300.dp) {
-            Spacer(androidx.ui.layout.Size(width = size.value, height = size.value))
+            Spacer(Size(width = size.value, height = size.value))
         }
     }
 
@@ -85,7 +86,7 @@
         this.state = size
         WithConstraints {
             Container(width = 300.dp, height = 300.dp) {
-                Spacer(androidx.ui.layout.Size(width = size.value, height = size.value))
+                Spacer(Size(width = size.value, height = size.value))
             }
         }
     }
diff --git a/ui/integration-tests/test/src/main/java/androidx/ui/test/TextBenchmarkHelper.kt b/ui/integration-tests/test/src/main/java/androidx/ui/test/TextBenchmarkHelper.kt
index 8c03978..34dfb00 100644
--- a/ui/integration-tests/test/src/main/java/androidx/ui/test/TextBenchmarkHelper.kt
+++ b/ui/integration-tests/test/src/main/java/androidx/ui/test/TextBenchmarkHelper.kt
@@ -123,7 +123,7 @@
                 AnnotatedString.Item(
                     start = start,
                     end = end,
-                    style = textStyleList[styleIndex++ % textStyleList.size]
+                    item = textStyleList[styleIndex++ % textStyleList.size]
                 )
             }
         }
diff --git a/ui/integration-tests/test/src/main/java/androidx/ui/test/cases/ColorPaletteTestCase.kt b/ui/integration-tests/test/src/main/java/androidx/ui/test/cases/ColorPaletteTestCase.kt
index 907e572..8745eee 100644
--- a/ui/integration-tests/test/src/main/java/androidx/ui/test/cases/ColorPaletteTestCase.kt
+++ b/ui/integration-tests/test/src/main/java/androidx/ui/test/cases/ColorPaletteTestCase.kt
@@ -24,6 +24,7 @@
 import androidx.ui.graphics.Color
 import androidx.ui.material.ColorPalette
 import androidx.ui.material.MaterialTheme
+import androidx.ui.material.lightColorPalette
 import androidx.ui.test.ComposeTestCase
 import androidx.ui.test.ToggleableTestCase
 
@@ -65,7 +66,7 @@
  */
 class ObservableColorPaletteTestCase : ColorPaletteTestCase() {
     override fun createPalette(primary: Color): ColorPalette {
-        return ColorPalette(primary = primary)
+        return lightColorPalette(primary = primary)
     }
 }
 
@@ -89,6 +90,7 @@
         override val onBackground = Color.Black
         override val onSurface = Color.Black
         override val onError = Color.Black
+        override val isLight = true
     }
 }
 
diff --git a/ui/ui-animation/api/0.1.0-dev03.txt b/ui/ui-animation/api/0.1.0-dev03.txt
index e1311a3..fc57f9b 100644
--- a/ui/ui-animation/api/0.1.0-dev03.txt
+++ b/ui/ui-animation/api/0.1.0-dev03.txt
@@ -35,7 +35,7 @@
 
   public final class TransitionKt {
     ctor public TransitionKt();
-    method public static <T> void Transition(androidx.animation.TransitionDefinition<T> definition, T? toState, androidx.animation.AnimationClockObservable clock = +ambient(AnimationClockAmbient), kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? onStateChangeFinished = null, kotlin.jvm.functions.Function1<? super androidx.animation.TransitionState,kotlin.Unit> children);
+    method public static <T> void Transition(androidx.animation.TransitionDefinition<T> definition, T? toState, androidx.animation.AnimationClockObservable clock = +ambient(AnimationClockAmbient), T? initState = toState, kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? onStateChangeFinished = null, kotlin.jvm.functions.Function1<? super androidx.animation.TransitionState,kotlin.Unit> children);
     method public static boolean getTransitionsEnabled();
     method public static void setTransitionsEnabled(boolean p);
   }
diff --git a/ui/ui-animation/api/current.txt b/ui/ui-animation/api/current.txt
index e1311a3..fc57f9b 100644
--- a/ui/ui-animation/api/current.txt
+++ b/ui/ui-animation/api/current.txt
@@ -35,7 +35,7 @@
 
   public final class TransitionKt {
     ctor public TransitionKt();
-    method public static <T> void Transition(androidx.animation.TransitionDefinition<T> definition, T? toState, androidx.animation.AnimationClockObservable clock = +ambient(AnimationClockAmbient), kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? onStateChangeFinished = null, kotlin.jvm.functions.Function1<? super androidx.animation.TransitionState,kotlin.Unit> children);
+    method public static <T> void Transition(androidx.animation.TransitionDefinition<T> definition, T? toState, androidx.animation.AnimationClockObservable clock = +ambient(AnimationClockAmbient), T? initState = toState, kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? onStateChangeFinished = null, kotlin.jvm.functions.Function1<? super androidx.animation.TransitionState,kotlin.Unit> children);
     method public static boolean getTransitionsEnabled();
     method public static void setTransitionsEnabled(boolean p);
   }
diff --git a/ui/ui-animation/api/public_plus_experimental_0.1.0-dev03.txt b/ui/ui-animation/api/public_plus_experimental_0.1.0-dev03.txt
index e1311a3..fc57f9b 100644
--- a/ui/ui-animation/api/public_plus_experimental_0.1.0-dev03.txt
+++ b/ui/ui-animation/api/public_plus_experimental_0.1.0-dev03.txt
@@ -35,7 +35,7 @@
 
   public final class TransitionKt {
     ctor public TransitionKt();
-    method public static <T> void Transition(androidx.animation.TransitionDefinition<T> definition, T? toState, androidx.animation.AnimationClockObservable clock = +ambient(AnimationClockAmbient), kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? onStateChangeFinished = null, kotlin.jvm.functions.Function1<? super androidx.animation.TransitionState,kotlin.Unit> children);
+    method public static <T> void Transition(androidx.animation.TransitionDefinition<T> definition, T? toState, androidx.animation.AnimationClockObservable clock = +ambient(AnimationClockAmbient), T? initState = toState, kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? onStateChangeFinished = null, kotlin.jvm.functions.Function1<? super androidx.animation.TransitionState,kotlin.Unit> children);
     method public static boolean getTransitionsEnabled();
     method public static void setTransitionsEnabled(boolean p);
   }
diff --git a/ui/ui-animation/api/public_plus_experimental_current.txt b/ui/ui-animation/api/public_plus_experimental_current.txt
index e1311a3..fc57f9b 100644
--- a/ui/ui-animation/api/public_plus_experimental_current.txt
+++ b/ui/ui-animation/api/public_plus_experimental_current.txt
@@ -35,7 +35,7 @@
 
   public final class TransitionKt {
     ctor public TransitionKt();
-    method public static <T> void Transition(androidx.animation.TransitionDefinition<T> definition, T? toState, androidx.animation.AnimationClockObservable clock = +ambient(AnimationClockAmbient), kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? onStateChangeFinished = null, kotlin.jvm.functions.Function1<? super androidx.animation.TransitionState,kotlin.Unit> children);
+    method public static <T> void Transition(androidx.animation.TransitionDefinition<T> definition, T? toState, androidx.animation.AnimationClockObservable clock = +ambient(AnimationClockAmbient), T? initState = toState, kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? onStateChangeFinished = null, kotlin.jvm.functions.Function1<? super androidx.animation.TransitionState,kotlin.Unit> children);
     method public static boolean getTransitionsEnabled();
     method public static void setTransitionsEnabled(boolean p);
   }
diff --git a/ui/ui-animation/api/restricted_0.1.0-dev03.txt b/ui/ui-animation/api/restricted_0.1.0-dev03.txt
index e1311a3..fc57f9b 100644
--- a/ui/ui-animation/api/restricted_0.1.0-dev03.txt
+++ b/ui/ui-animation/api/restricted_0.1.0-dev03.txt
@@ -35,7 +35,7 @@
 
   public final class TransitionKt {
     ctor public TransitionKt();
-    method public static <T> void Transition(androidx.animation.TransitionDefinition<T> definition, T? toState, androidx.animation.AnimationClockObservable clock = +ambient(AnimationClockAmbient), kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? onStateChangeFinished = null, kotlin.jvm.functions.Function1<? super androidx.animation.TransitionState,kotlin.Unit> children);
+    method public static <T> void Transition(androidx.animation.TransitionDefinition<T> definition, T? toState, androidx.animation.AnimationClockObservable clock = +ambient(AnimationClockAmbient), T? initState = toState, kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? onStateChangeFinished = null, kotlin.jvm.functions.Function1<? super androidx.animation.TransitionState,kotlin.Unit> children);
     method public static boolean getTransitionsEnabled();
     method public static void setTransitionsEnabled(boolean p);
   }
diff --git a/ui/ui-animation/api/restricted_current.txt b/ui/ui-animation/api/restricted_current.txt
index e1311a3..fc57f9b 100644
--- a/ui/ui-animation/api/restricted_current.txt
+++ b/ui/ui-animation/api/restricted_current.txt
@@ -35,7 +35,7 @@
 
   public final class TransitionKt {
     ctor public TransitionKt();
-    method public static <T> void Transition(androidx.animation.TransitionDefinition<T> definition, T? toState, androidx.animation.AnimationClockObservable clock = +ambient(AnimationClockAmbient), kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? onStateChangeFinished = null, kotlin.jvm.functions.Function1<? super androidx.animation.TransitionState,kotlin.Unit> children);
+    method public static <T> void Transition(androidx.animation.TransitionDefinition<T> definition, T? toState, androidx.animation.AnimationClockObservable clock = +ambient(AnimationClockAmbient), T? initState = toState, kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? onStateChangeFinished = null, kotlin.jvm.functions.Function1<? super androidx.animation.TransitionState,kotlin.Unit> children);
     method public static boolean getTransitionsEnabled();
     method public static void setTransitionsEnabled(boolean p);
   }
diff --git a/ui/ui-animation/integration-tests/samples/src/main/java/androidx/ui/animation/samples/TransitionSamples.kt b/ui/ui-animation/integration-tests/samples/src/main/java/androidx/ui/animation/samples/TransitionSamples.kt
index 8205eda..f2defe1 100644
--- a/ui/ui-animation/integration-tests/samples/src/main/java/androidx/ui/animation/samples/TransitionSamples.kt
+++ b/ui/ui-animation/integration-tests/samples/src/main/java/androidx/ui/animation/samples/TransitionSamples.kt
@@ -43,8 +43,20 @@
 
     @Composable
     fun TransitionBasedColoredRect() {
-        Transition(definition = definition, toState = State.Second) { state ->
+        // This puts the transition in State.First. Any subsequent state change will trigger a
+        // transition animation, as defined in the transition definition.
+        Transition(definition = definition, toState = State.First) { state ->
             ColoredRect(color = state[ColorKey])
         }
     }
-}
\ No newline at end of file
+
+    @Composable
+    fun ColorRectWithInitState() {
+        // This starts the transition going from State.First to State.Second when this composable
+        // gets composed for the first time.
+        Transition(definition = definition, initState = State.First, toState = State.Second) {
+                state ->
+            ColoredRect(color = state[ColorKey])
+        }
+    }
+}
diff --git a/ui/ui-animation/src/main/java/androidx/ui/animation/Transition.kt b/ui/ui-animation/src/main/java/androidx/ui/animation/Transition.kt
index fe609ff..9c20fb4 100644
--- a/ui/ui-animation/src/main/java/androidx/ui/animation/Transition.kt
+++ b/ui/ui-animation/src/main/java/androidx/ui/animation/Transition.kt
@@ -30,21 +30,33 @@
 import androidx.ui.core.AnimationClockAmbient
 
 /**
- * Composable to use with TransitionDefinition-based animations.
+ * Composable to use with [TransitionDefinition]-based animations.
+ *
+ * @param definition Transition definition that defines states and transitions
+ * @param toState New state to transition to
+ * @param clock Animation clock that pulses animations when time changes. By default the clock is
+ *              read from the ambient.
+ * @param initState Optional initial state for the transition. When undefined, the initial state
+ *                  will be set to the first [toState] seen in the transition.
+ * @param onStateChangeFinished An optional listener to get notified when state change animation
+ *                              has completed
+ * @param children The children composables that will be animated
  *
  * @sample androidx.ui.animation.samples.TransitionSample
  */
+// TODO: The list of params is getting a bit long. Consider grouping them.
 @Composable
 fun <T> Transition(
     definition: TransitionDefinition<T>,
     toState: T,
     clock: AnimationClockObservable = +ambient(AnimationClockAmbient),
+    initState: T = toState,
     onStateChangeFinished: ((T) -> Unit)? = null,
     children: @Composable() (state: TransitionState) -> Unit
 ) {
     if (transitionsEnabled) {
         // TODO: This null is workaround for b/132148894
-        val model = +memo(definition, null) { TransitionModel(definition, toState, clock) }
+        val model = +memo(definition, null) { TransitionModel(definition, initState, clock) }
         model.anim.onStateChangeFinished = onStateChangeFinished
         model.anim.toState(toState)
         children(model)
diff --git a/ui/ui-core/api/0.1.0-dev03.txt b/ui/ui-core/api/0.1.0-dev03.txt
index 481f79e..18070d8 100644
--- a/ui/ui-core/api/0.1.0-dev03.txt
+++ b/ui/ui-core/api/0.1.0-dev03.txt
@@ -5,6 +5,7 @@
     ctor public MathHelpersKt();
     method public static float lerp(float start, float stop, float fraction);
     method public static int lerp(int start, int stop, float fraction);
+    method public static long lerp(long start, long stop, float fraction);
     method public static String toHexString(int);
     method public static String toStringAsFixed(float, int digits);
   }
@@ -532,7 +533,7 @@
     method public default androidx.ui.core.IntPx? modifyAlignmentLine(androidx.ui.core.DensityScope, androidx.ui.core.AlignmentLine line, androidx.ui.core.IntPx? value);
     method public default androidx.ui.core.Constraints modifyConstraints(androidx.ui.core.DensityScope, androidx.ui.core.Constraints constraints);
     method public default Object? modifyParentData(androidx.ui.core.DensityScope, Object? parentData);
-    method public default androidx.ui.core.IntPxPosition modifyPosition(androidx.ui.core.DensityScope, androidx.ui.core.IntPxPosition childPosition, androidx.ui.core.IntPxSize childSize, androidx.ui.core.IntPxSize containerSize);
+    method public default androidx.ui.core.IntPxPosition modifyPosition(androidx.ui.core.DensityScope, androidx.ui.core.IntPxSize childSize, androidx.ui.core.IntPxSize containerSize);
     method public default androidx.ui.core.IntPxSize modifySize(androidx.ui.core.DensityScope, androidx.ui.core.Constraints constraints, androidx.ui.core.IntPxSize childSize);
   }
 
diff --git a/ui/ui-core/api/current.txt b/ui/ui-core/api/current.txt
index 481f79e..18070d8 100644
--- a/ui/ui-core/api/current.txt
+++ b/ui/ui-core/api/current.txt
@@ -5,6 +5,7 @@
     ctor public MathHelpersKt();
     method public static float lerp(float start, float stop, float fraction);
     method public static int lerp(int start, int stop, float fraction);
+    method public static long lerp(long start, long stop, float fraction);
     method public static String toHexString(int);
     method public static String toStringAsFixed(float, int digits);
   }
@@ -532,7 +533,7 @@
     method public default androidx.ui.core.IntPx? modifyAlignmentLine(androidx.ui.core.DensityScope, androidx.ui.core.AlignmentLine line, androidx.ui.core.IntPx? value);
     method public default androidx.ui.core.Constraints modifyConstraints(androidx.ui.core.DensityScope, androidx.ui.core.Constraints constraints);
     method public default Object? modifyParentData(androidx.ui.core.DensityScope, Object? parentData);
-    method public default androidx.ui.core.IntPxPosition modifyPosition(androidx.ui.core.DensityScope, androidx.ui.core.IntPxPosition childPosition, androidx.ui.core.IntPxSize childSize, androidx.ui.core.IntPxSize containerSize);
+    method public default androidx.ui.core.IntPxPosition modifyPosition(androidx.ui.core.DensityScope, androidx.ui.core.IntPxSize childSize, androidx.ui.core.IntPxSize containerSize);
     method public default androidx.ui.core.IntPxSize modifySize(androidx.ui.core.DensityScope, androidx.ui.core.Constraints constraints, androidx.ui.core.IntPxSize childSize);
   }
 
diff --git a/ui/ui-core/api/public_plus_experimental_0.1.0-dev03.txt b/ui/ui-core/api/public_plus_experimental_0.1.0-dev03.txt
index 481f79e..18070d8 100644
--- a/ui/ui-core/api/public_plus_experimental_0.1.0-dev03.txt
+++ b/ui/ui-core/api/public_plus_experimental_0.1.0-dev03.txt
@@ -5,6 +5,7 @@
     ctor public MathHelpersKt();
     method public static float lerp(float start, float stop, float fraction);
     method public static int lerp(int start, int stop, float fraction);
+    method public static long lerp(long start, long stop, float fraction);
     method public static String toHexString(int);
     method public static String toStringAsFixed(float, int digits);
   }
@@ -532,7 +533,7 @@
     method public default androidx.ui.core.IntPx? modifyAlignmentLine(androidx.ui.core.DensityScope, androidx.ui.core.AlignmentLine line, androidx.ui.core.IntPx? value);
     method public default androidx.ui.core.Constraints modifyConstraints(androidx.ui.core.DensityScope, androidx.ui.core.Constraints constraints);
     method public default Object? modifyParentData(androidx.ui.core.DensityScope, Object? parentData);
-    method public default androidx.ui.core.IntPxPosition modifyPosition(androidx.ui.core.DensityScope, androidx.ui.core.IntPxPosition childPosition, androidx.ui.core.IntPxSize childSize, androidx.ui.core.IntPxSize containerSize);
+    method public default androidx.ui.core.IntPxPosition modifyPosition(androidx.ui.core.DensityScope, androidx.ui.core.IntPxSize childSize, androidx.ui.core.IntPxSize containerSize);
     method public default androidx.ui.core.IntPxSize modifySize(androidx.ui.core.DensityScope, androidx.ui.core.Constraints constraints, androidx.ui.core.IntPxSize childSize);
   }
 
diff --git a/ui/ui-core/api/public_plus_experimental_current.txt b/ui/ui-core/api/public_plus_experimental_current.txt
index 481f79e..18070d8 100644
--- a/ui/ui-core/api/public_plus_experimental_current.txt
+++ b/ui/ui-core/api/public_plus_experimental_current.txt
@@ -5,6 +5,7 @@
     ctor public MathHelpersKt();
     method public static float lerp(float start, float stop, float fraction);
     method public static int lerp(int start, int stop, float fraction);
+    method public static long lerp(long start, long stop, float fraction);
     method public static String toHexString(int);
     method public static String toStringAsFixed(float, int digits);
   }
@@ -532,7 +533,7 @@
     method public default androidx.ui.core.IntPx? modifyAlignmentLine(androidx.ui.core.DensityScope, androidx.ui.core.AlignmentLine line, androidx.ui.core.IntPx? value);
     method public default androidx.ui.core.Constraints modifyConstraints(androidx.ui.core.DensityScope, androidx.ui.core.Constraints constraints);
     method public default Object? modifyParentData(androidx.ui.core.DensityScope, Object? parentData);
-    method public default androidx.ui.core.IntPxPosition modifyPosition(androidx.ui.core.DensityScope, androidx.ui.core.IntPxPosition childPosition, androidx.ui.core.IntPxSize childSize, androidx.ui.core.IntPxSize containerSize);
+    method public default androidx.ui.core.IntPxPosition modifyPosition(androidx.ui.core.DensityScope, androidx.ui.core.IntPxSize childSize, androidx.ui.core.IntPxSize containerSize);
     method public default androidx.ui.core.IntPxSize modifySize(androidx.ui.core.DensityScope, androidx.ui.core.Constraints constraints, androidx.ui.core.IntPxSize childSize);
   }
 
diff --git a/ui/ui-core/api/restricted_0.1.0-dev03.txt b/ui/ui-core/api/restricted_0.1.0-dev03.txt
index 481f79e..18070d8 100644
--- a/ui/ui-core/api/restricted_0.1.0-dev03.txt
+++ b/ui/ui-core/api/restricted_0.1.0-dev03.txt
@@ -5,6 +5,7 @@
     ctor public MathHelpersKt();
     method public static float lerp(float start, float stop, float fraction);
     method public static int lerp(int start, int stop, float fraction);
+    method public static long lerp(long start, long stop, float fraction);
     method public static String toHexString(int);
     method public static String toStringAsFixed(float, int digits);
   }
@@ -532,7 +533,7 @@
     method public default androidx.ui.core.IntPx? modifyAlignmentLine(androidx.ui.core.DensityScope, androidx.ui.core.AlignmentLine line, androidx.ui.core.IntPx? value);
     method public default androidx.ui.core.Constraints modifyConstraints(androidx.ui.core.DensityScope, androidx.ui.core.Constraints constraints);
     method public default Object? modifyParentData(androidx.ui.core.DensityScope, Object? parentData);
-    method public default androidx.ui.core.IntPxPosition modifyPosition(androidx.ui.core.DensityScope, androidx.ui.core.IntPxPosition childPosition, androidx.ui.core.IntPxSize childSize, androidx.ui.core.IntPxSize containerSize);
+    method public default androidx.ui.core.IntPxPosition modifyPosition(androidx.ui.core.DensityScope, androidx.ui.core.IntPxSize childSize, androidx.ui.core.IntPxSize containerSize);
     method public default androidx.ui.core.IntPxSize modifySize(androidx.ui.core.DensityScope, androidx.ui.core.Constraints constraints, androidx.ui.core.IntPxSize childSize);
   }
 
diff --git a/ui/ui-core/api/restricted_current.txt b/ui/ui-core/api/restricted_current.txt
index 481f79e..18070d8 100644
--- a/ui/ui-core/api/restricted_current.txt
+++ b/ui/ui-core/api/restricted_current.txt
@@ -5,6 +5,7 @@
     ctor public MathHelpersKt();
     method public static float lerp(float start, float stop, float fraction);
     method public static int lerp(int start, int stop, float fraction);
+    method public static long lerp(long start, long stop, float fraction);
     method public static String toHexString(int);
     method public static String toStringAsFixed(float, int digits);
   }
@@ -532,7 +533,7 @@
     method public default androidx.ui.core.IntPx? modifyAlignmentLine(androidx.ui.core.DensityScope, androidx.ui.core.AlignmentLine line, androidx.ui.core.IntPx? value);
     method public default androidx.ui.core.Constraints modifyConstraints(androidx.ui.core.DensityScope, androidx.ui.core.Constraints constraints);
     method public default Object? modifyParentData(androidx.ui.core.DensityScope, Object? parentData);
-    method public default androidx.ui.core.IntPxPosition modifyPosition(androidx.ui.core.DensityScope, androidx.ui.core.IntPxPosition childPosition, androidx.ui.core.IntPxSize childSize, androidx.ui.core.IntPxSize containerSize);
+    method public default androidx.ui.core.IntPxPosition modifyPosition(androidx.ui.core.DensityScope, androidx.ui.core.IntPxSize childSize, androidx.ui.core.IntPxSize containerSize);
     method public default androidx.ui.core.IntPxSize modifySize(androidx.ui.core.DensityScope, androidx.ui.core.Constraints constraints, androidx.ui.core.IntPxSize childSize);
   }
 
diff --git a/ui/ui-core/src/main/java/androidx/ui/MathHelpers.kt b/ui/ui-core/src/main/java/androidx/ui/MathHelpers.kt
index 7b233d5..e707f3d 100644
--- a/ui/ui-core/src/main/java/androidx/ui/MathHelpers.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/MathHelpers.kt
@@ -16,19 +16,27 @@
 package androidx.ui
 
 import kotlin.math.roundToInt
+import kotlin.math.roundToLong
 
 /**
  * Linearly interpolate between [start] and [stop] with [fraction] fraction between them.
  */
 fun lerp(start: Float, stop: Float, fraction: Float): Float {
-    return start + (stop - start) * fraction
+    return (1 - fraction) * start + fraction * stop
 }
 
 /**
  * Linearly interpolate between [start] and [stop] with [fraction] fraction between them.
  */
 fun lerp(start: Int, stop: Int, fraction: Float): Int {
-    return start + ((stop - start) * fraction).roundToInt()
+    return start + ((stop - start) * fraction.toDouble()).roundToInt()
+}
+
+/**
+ * Linearly interpolate between [start] and [stop] with [fraction] fraction between them.
+ */
+fun lerp(start: Long, stop: Long, fraction: Float): Long {
+    return start + ((stop - start) * fraction.toDouble()).roundToLong()
 }
 
 fun Float.toStringAsFixed(digits: Int) = String.format("%.${digits}f", this)
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/Dp.kt b/ui/ui-core/src/main/java/androidx/ui/core/Dp.kt
index 28ecc3f..e8917eb 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/Dp.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/Dp.kt
@@ -180,7 +180,6 @@
 
 /**
  * Ensures that this value is not less than the specified [minimumValue].
- *
  * @return this value if it's greater than or equal to the [minimumValue] or the
  * [minimumValue] otherwise.
  */
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/LayoutModifier.kt b/ui/ui-core/src/main/java/androidx/ui/core/LayoutModifier.kt
index 9a39c3a..8678c06 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/LayoutModifier.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/LayoutModifier.kt
@@ -77,10 +77,9 @@
      * size [containerSize].
      */
     fun DensityScope.modifyPosition(
-        childPosition: IntPxPosition,
         childSize: IntPxSize,
         containerSize: IntPxSize
-    ): IntPxPosition = childPosition
+    ): IntPxPosition = IntPxPosition.Origin
 
     /**
      * Returns the modified position of [line] given its unmodified [value].
diff --git a/ui/ui-core/src/test/java/androidx/ui/MathHelpersTest.kt b/ui/ui-core/src/test/java/androidx/ui/MathHelpersTest.kt
new file mode 100644
index 0000000..598938d
--- /dev/null
+++ b/ui/ui-core/src/test/java/androidx/ui/MathHelpersTest.kt
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2019 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.ui
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class MathHelpersTest {
+
+    // `f = 16777216f` is the first value where `f + 1 == f` due to float imprecision, so that's
+    // where testing floating point errors becomes interesting
+    val testStart = 16777216L
+    val testEnd = testStart + 1000
+
+    @Test
+    fun testLerpLargeFloats() {
+        val from = 1f
+        for (x in testStart until testEnd) {
+            val to = x.toFloat()
+            assertThat(lerp(from, to, 0f)).isEqualTo(from)
+            assertThat(lerp(from, to, 1f)).isEqualTo(to)
+        }
+    }
+
+    @Test
+    fun testLerpLargeInts() {
+        val from = 1
+        for (x in testStart until testEnd) {
+            val to = x.toInt()
+            assertThat(lerp(from, to, 0f)).isEqualTo(from)
+            assertThat(lerp(from, to, 1f)).isEqualTo(to)
+        }
+    }
+
+    @Test
+    fun testLerpLargeLongs() {
+        val from = 1L
+        for (x in testStart until testEnd) {
+            val to = x.toLong()
+            assertThat(lerp(from, to, 0f)).isEqualTo(from)
+            assertThat(lerp(from, to, 1f)).isEqualTo(to)
+        }
+    }
+
+    @Test
+    fun testLerpSimpleFloats() {
+        val from = 0f
+        for (multiplier in 1..1000) {
+            val to = (4 * multiplier).toFloat()
+            assertThat(lerp(from, to, 0.00f)).isEqualTo((0 * multiplier).toFloat())
+            assertThat(lerp(from, to, 0.25f)).isEqualTo((1 * multiplier).toFloat())
+            assertThat(lerp(from, to, 0.50f)).isEqualTo((2 * multiplier).toFloat())
+            assertThat(lerp(from, to, 0.75f)).isEqualTo((3 * multiplier).toFloat())
+            assertThat(lerp(from, to, 1.00f)).isEqualTo((4 * multiplier).toFloat())
+        }
+    }
+
+    @Test
+    fun testLerpSimpleInts() {
+        val from = 0
+        for (multiplier in 1..1000) {
+            val to = (4 * multiplier).toInt()
+            assertThat(lerp(from, to, 0.00f)).isEqualTo((0 * multiplier).toInt())
+            assertThat(lerp(from, to, 0.25f)).isEqualTo((1 * multiplier).toInt())
+            assertThat(lerp(from, to, 0.50f)).isEqualTo((2 * multiplier).toInt())
+            assertThat(lerp(from, to, 0.75f)).isEqualTo((3 * multiplier).toInt())
+            assertThat(lerp(from, to, 1.00f)).isEqualTo((4 * multiplier).toInt())
+        }
+    }
+
+    @Test
+    fun testLerpSimpleLongs() {
+        val from = 0L
+        for (multiplier in 1..1000) {
+            val to = (4 * multiplier).toLong()
+            assertThat(lerp(from, to, 0.00f)).isEqualTo((0 * multiplier).toLong())
+            assertThat(lerp(from, to, 0.25f)).isEqualTo((1 * multiplier).toLong())
+            assertThat(lerp(from, to, 0.50f)).isEqualTo((2 * multiplier).toLong())
+            assertThat(lerp(from, to, 0.75f)).isEqualTo((3 * multiplier).toLong())
+            assertThat(lerp(from, to, 1.00f)).isEqualTo((4 * multiplier).toLong())
+        }
+    }
+}
\ No newline at end of file
diff --git a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/ScrollerTest.kt b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/ScrollerTest.kt
index 7f90d37..50e6c3a 100644
--- a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/ScrollerTest.kt
+++ b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/ScrollerTest.kt
@@ -16,24 +16,33 @@
 package androidx.ui.foundation
 
 import android.graphics.Bitmap
-import android.os.Build
 import android.os.Handler
+import android.os.Looper
 import android.view.PixelCopy
 import android.view.View
 import android.view.ViewGroup
 import android.view.ViewTreeObserver
+import androidx.annotation.RequiresApi
 import androidx.compose.Composable
 import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
 import androidx.ui.core.Alignment
 import androidx.ui.core.AndroidComposeView
+import androidx.ui.core.Dp
 import androidx.ui.core.Draw
 import androidx.ui.core.IntPx
+import androidx.ui.core.Px
+import androidx.ui.core.TestTag
+import androidx.ui.core.Text
+import androidx.ui.core.dp
 import androidx.ui.core.ipx
 import androidx.ui.core.px
 import androidx.ui.core.setContent
+import androidx.ui.core.toPx
 import androidx.ui.core.toRect
 import androidx.ui.core.withDensity
+import androidx.ui.foundation.shape.DrawShape
+import androidx.ui.foundation.shape.RectangleShape
 import androidx.ui.graphics.Color
 import androidx.ui.graphics.Paint
 import androidx.ui.graphics.PaintingStyle
@@ -43,18 +52,23 @@
 import androidx.ui.layout.ConstrainedBox
 import androidx.ui.layout.Container
 import androidx.ui.layout.DpConstraints
-import androidx.ui.core.Text
-import androidx.ui.core.dp
-import androidx.ui.core.sp
-import androidx.ui.layout.Padding
 import androidx.ui.layout.Row
+import androidx.ui.semantics.Semantics
+import androidx.ui.test.GestureScope
+import androidx.ui.test.SemanticsNodeInteraction
 import androidx.ui.test.android.AndroidComposeTestRule
 import androidx.ui.test.assertIsDisplayed
 import androidx.ui.test.assertIsNotDisplayed
 import androidx.ui.test.createComposeRule
+import androidx.ui.test.doGesture
 import androidx.ui.test.doScrollTo
+import androidx.ui.test.findByTag
 import androidx.ui.test.findByText
-import androidx.ui.text.TextStyle
+import androidx.ui.test.sendSwipeDown
+import androidx.ui.test.sendSwipeLeft
+import androidx.ui.test.sendSwipeRight
+import androidx.ui.test.sendSwipeUp
+import com.google.common.truth.Truth.assertThat
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertTrue
 import org.junit.Before
@@ -74,10 +88,14 @@
 
     // TODO(malkov/pavlis) : some tests here require activity access as we need
     // to take screen's bitmap, abstract it better
-    val activity
+    private val activity
         get() = (composeTestRule as AndroidComposeTestRule).activityTestRule.activity
 
-    val colors = listOf(
+    private val defaultCrossAxisSize = 45.ipx
+    private val defaultMainAxisSize = 40.ipx
+    private val defaultCellSize = 5.ipx
+
+    private val colors = listOf(
         Color(red = 0xFF, green = 0, blue = 0, alpha = 0xFF),
         Color(red = 0xFF, green = 0xA5, blue = 0, alpha = 0xFF),
         Color(red = 0xFF, green = 0xFF, blue = 0, alpha = 0xFF),
@@ -88,8 +106,8 @@
         Color(red = 0xA5, green = 0, blue = 0xFF, alpha = 0xFF)
     )
 
-    var drawLatch = CountDownLatch(1)
-    lateinit var handler: Handler
+    private var drawLatch = CountDownLatch(1)
+    private lateinit var handler: Handler
 
     @Before
     fun setupDrawLatch() {
@@ -99,15 +117,16 @@
         }
     }
 
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @SdkSuppress(minSdkVersion = 26)
     @Test
     fun verticalScroller_SmallContent() {
-        composeVerticalScroller()
+        val height = 40.ipx
 
-        validateVerticalScroller(0, 40)
+        composeVerticalScroller(height = height)
+
+        validateVerticalScroller(height = height)
     }
 
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
     @Test
     fun verticalScroller_SmallContent_Unscrollable() {
         val scrollerPosition = ScrollerPosition()
@@ -115,9 +134,8 @@
         // latch to wait for a new max to come on layout
         val newMaxLatch = CountDownLatch(1)
 
-        composeVerticalScroller(
-            scrollerPosition
-        )
+        composeVerticalScroller(scrollerPosition)
+
         val onGlobalLayout = object : ViewTreeObserver.OnGlobalLayoutListener {
             override fun onGlobalLayout() {
                 newMaxLatch.countDown()
@@ -133,22 +151,26 @@
         }
     }
 
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @SdkSuppress(minSdkVersion = 26)
     @Test
     fun verticalScroller_LargeContent_NoScroll() {
-        composeVerticalScroller(height = 30.ipx)
+        val height = 30.ipx
 
-        validateVerticalScroller(0, 30)
+        composeVerticalScroller(height = height)
+
+        validateVerticalScroller(height = height)
     }
 
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @SdkSuppress(minSdkVersion = 26)
     @Test
     fun verticalScroller_LargeContent_ScrollToEnd() {
         val scrollerPosition = ScrollerPosition()
+        val height = 30.ipx
+        val scrollDistance = 10.ipx
 
-        composeVerticalScroller(scrollerPosition, height = 30.ipx)
+        composeVerticalScroller(scrollerPosition, height = height)
 
-        validateVerticalScroller(0, 30)
+        validateVerticalScroller(height = height)
 
         // The 'draw' method will no longer be called because only the position
         // changes during scrolling. Therefore, we should just wait until the draw stage
@@ -161,40 +183,47 @@
         }
         composeTestRule.runOnUiThread {
             activity.window.decorView.viewTreeObserver.addOnDrawListener(onDrawListener)
-            assertEquals(10.px, scrollerPosition.maxPosition)
-            scrollerPosition.scrollTo(10.px)
+            assertEquals(scrollDistance.toPx(), scrollerPosition.maxPosition)
+            scrollerPosition.scrollTo(scrollDistance.toPx())
         }
         assertTrue(latch.await(1, TimeUnit.SECONDS))
         composeTestRule.runOnUiThread {
             activity.window.decorView.viewTreeObserver.removeOnDrawListener(onDrawListener)
         }
-        validateVerticalScroller(10, 30)
+        validateVerticalScroller(offset = scrollDistance, height = height)
     }
 
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @SdkSuppress(minSdkVersion = 26)
     @Test
     fun horizontalScroller_SmallContent() {
-        composeHorizontalScroller()
+        val width = 40.ipx
 
-        validateHorizontalScroller(0, 40)
+        composeHorizontalScroller(width = width)
+
+        validateHorizontalScroller(width = width)
     }
 
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @SdkSuppress(minSdkVersion = 26)
     @Test
     fun horizontalScroller_LargeContent_NoScroll() {
-        composeHorizontalScroller(width = 30.ipx)
+        val width = 30.ipx
 
-        validateHorizontalScroller(0, 30)
+        composeHorizontalScroller(width = width)
+
+        validateHorizontalScroller(width = width)
     }
 
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @SdkSuppress(minSdkVersion = 26)
     @Test
     fun horizontalScroller_LargeContent_ScrollToEnd() {
+        val width = 30.ipx
+        val scrollDistance = 10.ipx
+
         val scrollerPosition = ScrollerPosition()
 
-        composeHorizontalScroller(scrollerPosition, width = 30.ipx)
+        composeHorizontalScroller(scrollerPosition, width = width)
 
-        validateHorizontalScroller(0, 30)
+        validateHorizontalScroller(width = width)
 
         // The 'draw' method will no longer be called because only the position
         // changes during scrolling. Therefore, we should just wait until the draw stage
@@ -207,14 +236,14 @@
         }
         composeTestRule.runOnUiThread {
             activity.window.decorView.viewTreeObserver.addOnDrawListener(onDrawListener)
-            assertEquals(10.px, scrollerPosition.maxPosition)
-            scrollerPosition.scrollTo(10.px)
+            assertEquals(scrollDistance.toPx(), scrollerPosition.maxPosition)
+            scrollerPosition.scrollTo(scrollDistance.toPx())
         }
         assertTrue(latch.await(1, TimeUnit.SECONDS))
         composeTestRule.runOnUiThread {
             activity.window.decorView.viewTreeObserver.removeOnDrawListener(onDrawListener)
         }
-        validateHorizontalScroller(10, 30)
+        validateHorizontalScroller(offset = scrollDistance, width = width)
     }
 
     @Test
@@ -226,6 +255,7 @@
             .doScrollTo()
             .assertIsDisplayed()
     }
+
     @Test
     fun horizontalScroller_scrollTo_scrollForward() {
         createScrollableContent(isVertical = false)
@@ -250,6 +280,7 @@
             .doScrollTo()
             .assertIsDisplayed()
     }
+
     @Test
     fun horizontalScroller_scrollTo_scrollBack() {
         createScrollableContent(isVertical = false)
@@ -265,13 +296,60 @@
             .assertIsDisplayed()
     }
 
+    @Test
+    fun verticalScroller_swipeUp_swipeDown() {
+        swipeScrollerAndBack(true, GestureScope::sendSwipeUp, GestureScope::sendSwipeDown)
+    }
+
+    @Test
+    fun horizontalScroller_swipeLeft_swipeRight() {
+        swipeScrollerAndBack(false, GestureScope::sendSwipeLeft, GestureScope::sendSwipeRight)
+    }
+
+    private fun swipeScrollerAndBack(
+        isVertical: Boolean,
+        firstSwipe: GestureScope.() -> Unit,
+        secondSwipe: GestureScope.() -> Unit
+    ) {
+        val scrollerPosition = ScrollerPosition()
+
+        createScrollableContent(isVertical, scrollerPosition = scrollerPosition)
+        assertThat(scrollerPosition.getValueOnUiThread()).isEqualTo(0.px)
+
+        findByTag("scroller")
+            .doGesture { firstSwipe() }
+            .awaitScrollAnimation(scrollerPosition)
+
+        val scrolledValue = scrollerPosition.getValueOnUiThread()
+        assertThat(scrolledValue).isGreaterThan(0.px)
+
+        findByTag("scroller")
+            .doGesture { secondSwipe() }
+            .awaitScrollAnimation(scrollerPosition)
+
+        assertThat(scrollerPosition.getValueOnUiThread()).isLessThan(scrolledValue)
+    }
+
+    private fun ScrollerPosition.getValueOnUiThread(): Px {
+        var value = 0.px
+        val latch = CountDownLatch(1)
+        composeTestRule.runOnUiThread {
+            value = this.value
+            latch.countDown()
+        }
+        latch.await()
+        return value
+    }
+
     private fun composeVerticalScroller(
         scrollerPosition: ScrollerPosition = ScrollerPosition(),
-        height: IntPx = 40.ipx
+        width: IntPx = defaultCrossAxisSize,
+        height: IntPx = defaultMainAxisSize,
+        rowHeight: IntPx = defaultCellSize
     ) {
         // We assume that the height of the device is more than 45 px
         withDensity(composeTestRule.density) {
-            val constraints = DpConstraints.tightConstraints(45.px.toDp(), height.toDp())
+            val constraints = DpConstraints.tightConstraints(width.toDp(), height.toDp())
             composeTestRule.runOnUiThread {
                 activity.setContent {
                     Align(alignment = Alignment.TopLeft) {
@@ -280,8 +358,8 @@
                                 Column {
                                     colors.forEach { color ->
                                         Container(
-                                            height = 5.px.toDp(),
-                                            width = 45.px.toDp()
+                                            height = rowHeight.toDp(),
+                                            width = width.toDp()
                                         ) {
                                             Draw { canvas, parentSize ->
                                                 val paint = Paint()
@@ -305,11 +383,13 @@
 
     private fun composeHorizontalScroller(
         scrollerPosition: ScrollerPosition = ScrollerPosition(),
-        width: IntPx = 40.ipx
+        width: IntPx = defaultMainAxisSize,
+        height: IntPx = defaultCrossAxisSize,
+        columnWidth: IntPx = defaultCellSize
     ) {
         // We assume that the height of the device is more than 45 px
         withDensity(composeTestRule.density) {
-            val constraints = DpConstraints.tightConstraints(width.toDp(), 45.px.toDp())
+            val constraints = DpConstraints.tightConstraints(width.toDp(), height.toDp())
             composeTestRule.runOnUiThread {
                 activity.setContent {
                     Align(alignment = Alignment.TopLeft) {
@@ -318,8 +398,8 @@
                                 Row {
                                     colors.forEach { color ->
                                         Container(
-                                            width = 5.px.toDp(),
-                                            height = 45.px.toDp()
+                                            width = columnWidth.toDp(),
+                                            height = height.toDp()
                                         ) {
                                             Draw { canvas, parentSize ->
                                                 val paint = Paint()
@@ -341,21 +421,23 @@
         }
     }
 
+    @RequiresApi(api = 26)
     private fun validateVerticalScroller(
-        offset: Int,
-        height: Int,
-        width: Int = 45
+        offset: IntPx = 0.ipx,
+        width: IntPx = 45.ipx,
+        height: IntPx = 40.ipx,
+        rowHeight: IntPx = 5.ipx
     ) {
         assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
 
         val bitmap = waitAndScreenShot()
-        assertTrue(bitmap.height >= height)
-        assertTrue(bitmap.width >= 45)
-        for (y in 0 until height) {
-            val colorIndex = (offset + y) / 5
+        assertTrue(bitmap.height >= height.value)
+        assertTrue(bitmap.width >= width.value)
+        for (y in 0 until height.value) {
+            val colorIndex = (offset.value + y) / rowHeight.value
             val expectedColor = colors[colorIndex]
 
-            for (x in 0 until width) {
+            for (x in 0 until width.value) {
                 val pixel = bitmap.getPixel(x, y)
                 assertEquals(
                     "Expected $expectedColor, but got ${Color(pixel)} at $x, $y",
@@ -365,21 +447,23 @@
         }
     }
 
+    @RequiresApi(api = 26)
     private fun validateHorizontalScroller(
-        offset: Int,
-        width: Int,
-        height: Int = 45
+        offset: IntPx = 0.ipx,
+        width: IntPx = 40.ipx,
+        height: IntPx = 45.ipx,
+        columnWidth: IntPx = 5.ipx
     ) {
         assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
 
         val bitmap = waitAndScreenShot()
-        assertTrue(bitmap.height >= 45)
-        assertTrue(bitmap.width >= width)
-        for (x in 0 until width) {
-            val colorIndex = (offset + x) / 5
+        assertTrue(bitmap.height >= height.value)
+        assertTrue(bitmap.width >= width.value)
+        for (x in 0 until width.value) {
+            val colorIndex = (offset.value + x) / columnWidth.value
             val expectedColor = colors[colorIndex]
 
-            for (y in 0 until height) {
+            for (y in 0 until height.value) {
                 val pixel = bitmap.getPixel(x, y)
                 assertEquals(
                     "Expected $expectedColor, but got ${Color(pixel)} at $x, $y",
@@ -389,25 +473,37 @@
         }
     }
 
-    private fun createScrollableContent(isVertical: Boolean) {
+    private fun createScrollableContent(
+        isVertical: Boolean,
+        itemCount: Int = 100,
+        width: Dp = 100.dp,
+        height: Dp = 100.dp,
+        scrollerPosition: ScrollerPosition = ScrollerPosition()
+    ) {
         composeTestRule.setContent {
-            val style = TextStyle(fontSize = 30.sp)
             val content = @Composable {
-                for (i in 1..100) {
-                    Text(text = i.toString(), style = style)
+                repeat(itemCount) {
+                    Text(text = "$it")
                 }
             }
-            Padding(padding = 10.dp) {
-                if (isVertical) {
-                    VerticalScroller {
-                        Column {
-                            content()
-                        }
-                    }
-                } else {
-                    HorizontalScroller {
-                        Row {
-                            content()
+            Align(alignment = Alignment.TopLeft) {
+                Container(width = width, height = height) {
+                    DrawShape(RectangleShape, Color.White)
+                    TestTag("scroller") {
+                        Semantics {
+                            if (isVertical) {
+                                VerticalScroller(scrollerPosition) {
+                                    Column {
+                                        content()
+                                    }
+                                }
+                            } else {
+                                HorizontalScroller(scrollerPosition) {
+                                    Row {
+                                        content()
+                                    }
+                                }
+                            }
                         }
                     }
                 }
@@ -415,6 +511,7 @@
         }
     }
 
+    @RequiresApi(api = 26) // For PixelCopy.request(Window, Rect, Bitmap, listener, Handler)
     private fun waitAndScreenShot(): Bitmap {
         val view = findAndroidComposeView()
         waitForDraw(view)
@@ -441,14 +538,35 @@
         return dest
     }
 
+    private fun SemanticsNodeInteraction.awaitScrollAnimation(
+        scroller: ScrollerPosition
+    ): SemanticsNodeInteraction {
+        if (!scroller.holder.animatedFloat.isRunning) {
+            return this
+        }
+        val latch = CountDownLatch(1)
+        val handler = Handler(Looper.getMainLooper())
+        handler.post(object : Runnable {
+            override fun run() {
+                if (scroller.holder.animatedFloat.isRunning) {
+                    handler.post(this)
+                } else {
+                    latch.countDown()
+                }
+            }
+        })
+        latch.await()
+        return this
+    }
+
     // TODO(malkov): ALL below is copypaste from LayoutTest as this test in ui-foundation now
 
-    internal fun findAndroidComposeView(): AndroidComposeView {
+    private fun findAndroidComposeView(): AndroidComposeView {
         val contentViewGroup = activity.findViewById<ViewGroup>(android.R.id.content)
         return findAndroidComposeView(contentViewGroup)!!
     }
 
-    internal fun findAndroidComposeView(parent: ViewGroup): AndroidComposeView? {
+    private fun findAndroidComposeView(parent: ViewGroup): AndroidComposeView? {
         for (index in 0 until parent.childCount) {
             val child = parent.getChildAt(index)
             if (child is AndroidComposeView) {
@@ -463,7 +581,7 @@
         return null
     }
 
-    internal fun waitForDraw(view: View) {
+    private fun waitForDraw(view: View) {
         val viewDrawLatch = CountDownLatch(1)
         val listener = object : ViewTreeObserver.OnDrawListener {
             override fun onDraw() {
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/Scroller.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/Scroller.kt
index 7881172..5bb083e 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/Scroller.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/Scroller.kt
@@ -53,7 +53,7 @@
 @Model
 class ScrollerPosition(initial: Float = 0f) {
 
-    internal val holder = AnimatedValueHolder(initial)
+    internal val holder = AnimatedValueHolder(-initial)
 
     /**
      * maxPosition this scroller that consume this ScrollerPosition can reach, or [Px.Infinity]
diff --git a/ui/ui-framework/api/0.1.0-dev03.txt b/ui/ui-framework/api/0.1.0-dev03.txt
index 360ed8b..cfcb917 100644
--- a/ui/ui-framework/api/0.1.0-dev03.txt
+++ b/ui/ui-framework/api/0.1.0-dev03.txt
@@ -39,7 +39,7 @@
     method public static void Layout(kotlin.jvm.functions.Function0<kotlin.Unit>![] childrenArray, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function3<? super androidx.ui.core.MeasureScope,? super androidx.ui.core.MultiComposableMeasurables,? super androidx.ui.core.Constraints,? extends androidx.ui.core.MeasureScope.LayoutResult> measureBlock);
     method public static inline void OnChildPositioned(kotlin.jvm.functions.Function1<? super androidx.ui.core.LayoutCoordinates,kotlin.Unit> onPositioned, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method public static inline void OnPositioned(kotlin.jvm.functions.Function1<? super androidx.ui.core.LayoutCoordinates,kotlin.Unit> onPositioned);
-    method public static void WithConstraints(kotlin.jvm.functions.Function1<? super androidx.ui.core.Constraints,kotlin.Unit> children);
+    method public static void WithConstraints(androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.core.Constraints,kotlin.Unit> children);
   }
 
   public final class MultiComposableMeasurables implements kotlin.jvm.internal.markers.KMappedMarker java.util.List<androidx.ui.core.Measurable> {
diff --git a/ui/ui-framework/api/current.txt b/ui/ui-framework/api/current.txt
index 360ed8b..cfcb917 100644
--- a/ui/ui-framework/api/current.txt
+++ b/ui/ui-framework/api/current.txt
@@ -39,7 +39,7 @@
     method public static void Layout(kotlin.jvm.functions.Function0<kotlin.Unit>![] childrenArray, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function3<? super androidx.ui.core.MeasureScope,? super androidx.ui.core.MultiComposableMeasurables,? super androidx.ui.core.Constraints,? extends androidx.ui.core.MeasureScope.LayoutResult> measureBlock);
     method public static inline void OnChildPositioned(kotlin.jvm.functions.Function1<? super androidx.ui.core.LayoutCoordinates,kotlin.Unit> onPositioned, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method public static inline void OnPositioned(kotlin.jvm.functions.Function1<? super androidx.ui.core.LayoutCoordinates,kotlin.Unit> onPositioned);
-    method public static void WithConstraints(kotlin.jvm.functions.Function1<? super androidx.ui.core.Constraints,kotlin.Unit> children);
+    method public static void WithConstraints(androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.core.Constraints,kotlin.Unit> children);
   }
 
   public final class MultiComposableMeasurables implements kotlin.jvm.internal.markers.KMappedMarker java.util.List<androidx.ui.core.Measurable> {
diff --git a/ui/ui-framework/api/public_plus_experimental_0.1.0-dev03.txt b/ui/ui-framework/api/public_plus_experimental_0.1.0-dev03.txt
index 360ed8b..cfcb917 100644
--- a/ui/ui-framework/api/public_plus_experimental_0.1.0-dev03.txt
+++ b/ui/ui-framework/api/public_plus_experimental_0.1.0-dev03.txt
@@ -39,7 +39,7 @@
     method public static void Layout(kotlin.jvm.functions.Function0<kotlin.Unit>![] childrenArray, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function3<? super androidx.ui.core.MeasureScope,? super androidx.ui.core.MultiComposableMeasurables,? super androidx.ui.core.Constraints,? extends androidx.ui.core.MeasureScope.LayoutResult> measureBlock);
     method public static inline void OnChildPositioned(kotlin.jvm.functions.Function1<? super androidx.ui.core.LayoutCoordinates,kotlin.Unit> onPositioned, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method public static inline void OnPositioned(kotlin.jvm.functions.Function1<? super androidx.ui.core.LayoutCoordinates,kotlin.Unit> onPositioned);
-    method public static void WithConstraints(kotlin.jvm.functions.Function1<? super androidx.ui.core.Constraints,kotlin.Unit> children);
+    method public static void WithConstraints(androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.core.Constraints,kotlin.Unit> children);
   }
 
   public final class MultiComposableMeasurables implements kotlin.jvm.internal.markers.KMappedMarker java.util.List<androidx.ui.core.Measurable> {
diff --git a/ui/ui-framework/api/public_plus_experimental_current.txt b/ui/ui-framework/api/public_plus_experimental_current.txt
index 360ed8b..cfcb917 100644
--- a/ui/ui-framework/api/public_plus_experimental_current.txt
+++ b/ui/ui-framework/api/public_plus_experimental_current.txt
@@ -39,7 +39,7 @@
     method public static void Layout(kotlin.jvm.functions.Function0<kotlin.Unit>![] childrenArray, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function3<? super androidx.ui.core.MeasureScope,? super androidx.ui.core.MultiComposableMeasurables,? super androidx.ui.core.Constraints,? extends androidx.ui.core.MeasureScope.LayoutResult> measureBlock);
     method public static inline void OnChildPositioned(kotlin.jvm.functions.Function1<? super androidx.ui.core.LayoutCoordinates,kotlin.Unit> onPositioned, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method public static inline void OnPositioned(kotlin.jvm.functions.Function1<? super androidx.ui.core.LayoutCoordinates,kotlin.Unit> onPositioned);
-    method public static void WithConstraints(kotlin.jvm.functions.Function1<? super androidx.ui.core.Constraints,kotlin.Unit> children);
+    method public static void WithConstraints(androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.core.Constraints,kotlin.Unit> children);
   }
 
   public final class MultiComposableMeasurables implements kotlin.jvm.internal.markers.KMappedMarker java.util.List<androidx.ui.core.Measurable> {
diff --git a/ui/ui-framework/api/restricted_0.1.0-dev03.txt b/ui/ui-framework/api/restricted_0.1.0-dev03.txt
index 360ed8b..cfcb917 100644
--- a/ui/ui-framework/api/restricted_0.1.0-dev03.txt
+++ b/ui/ui-framework/api/restricted_0.1.0-dev03.txt
@@ -39,7 +39,7 @@
     method public static void Layout(kotlin.jvm.functions.Function0<kotlin.Unit>![] childrenArray, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function3<? super androidx.ui.core.MeasureScope,? super androidx.ui.core.MultiComposableMeasurables,? super androidx.ui.core.Constraints,? extends androidx.ui.core.MeasureScope.LayoutResult> measureBlock);
     method public static inline void OnChildPositioned(kotlin.jvm.functions.Function1<? super androidx.ui.core.LayoutCoordinates,kotlin.Unit> onPositioned, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method public static inline void OnPositioned(kotlin.jvm.functions.Function1<? super androidx.ui.core.LayoutCoordinates,kotlin.Unit> onPositioned);
-    method public static void WithConstraints(kotlin.jvm.functions.Function1<? super androidx.ui.core.Constraints,kotlin.Unit> children);
+    method public static void WithConstraints(androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.core.Constraints,kotlin.Unit> children);
   }
 
   public final class MultiComposableMeasurables implements kotlin.jvm.internal.markers.KMappedMarker java.util.List<androidx.ui.core.Measurable> {
diff --git a/ui/ui-framework/api/restricted_current.txt b/ui/ui-framework/api/restricted_current.txt
index 360ed8b..cfcb917 100644
--- a/ui/ui-framework/api/restricted_current.txt
+++ b/ui/ui-framework/api/restricted_current.txt
@@ -39,7 +39,7 @@
     method public static void Layout(kotlin.jvm.functions.Function0<kotlin.Unit>![] childrenArray, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function3<? super androidx.ui.core.MeasureScope,? super androidx.ui.core.MultiComposableMeasurables,? super androidx.ui.core.Constraints,? extends androidx.ui.core.MeasureScope.LayoutResult> measureBlock);
     method public static inline void OnChildPositioned(kotlin.jvm.functions.Function1<? super androidx.ui.core.LayoutCoordinates,kotlin.Unit> onPositioned, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method public static inline void OnPositioned(kotlin.jvm.functions.Function1<? super androidx.ui.core.LayoutCoordinates,kotlin.Unit> onPositioned);
-    method public static void WithConstraints(kotlin.jvm.functions.Function1<? super androidx.ui.core.Constraints,kotlin.Unit> children);
+    method public static void WithConstraints(androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.core.Constraints,kotlin.Unit> children);
   }
 
   public final class MultiComposableMeasurables implements kotlin.jvm.internal.markers.KMappedMarker java.util.List<androidx.ui.core.Measurable> {
diff --git a/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextFieldOnValueChangeEditorModelTest.kt b/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextFieldOnValueChangeEditorModelTest.kt
index 98e68f7..58aec5d 100644
--- a/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextFieldOnValueChangeEditorModelTest.kt
+++ b/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextFieldOnValueChangeEditorModelTest.kt
@@ -29,8 +29,9 @@
 import androidx.ui.input.SetSelectionEditOp
 import androidx.ui.input.TextInputService
 import androidx.ui.test.createComposeRule
-import androidx.ui.test.doClick
+import androidx.ui.test.doGesture
 import androidx.ui.test.findByTag
+import androidx.ui.test.sendClick
 import androidx.ui.test.waitForIdleCompose
 import androidx.ui.text.TextRange
 import com.google.common.truth.Truth.assertThat
@@ -90,7 +91,7 @@
 
         // Perform click to focus in.
         val element = findByTag("textField")
-        element.doClick()
+        element.doGesture { sendClick(1f, 1f) }
 
         // Verify startInput is called and capture the callback.
         val onEditCommandCaptor = argumentCaptor<(List<EditOperation>) -> Unit>()
diff --git a/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextFieldOnValueChangeFullEditorModelTest.kt b/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextFieldOnValueChangeFullEditorModelTest.kt
index c376455..bc9bb2f 100644
--- a/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextFieldOnValueChangeFullEditorModelTest.kt
+++ b/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextFieldOnValueChangeFullEditorModelTest.kt
@@ -29,8 +29,9 @@
 import androidx.ui.input.SetSelectionEditOp
 import androidx.ui.input.TextInputService
 import androidx.ui.test.createComposeRule
-import androidx.ui.test.doClick
+import androidx.ui.test.doGesture
 import androidx.ui.test.findByTag
+import androidx.ui.test.sendClick
 import androidx.ui.test.waitForIdleCompose
 import androidx.ui.text.TextRange
 import com.google.common.truth.Truth.assertThat
@@ -92,7 +93,7 @@
 
         // Perform click to focus in.
         val element = findByTag("textField")
-        element.doClick()
+        element.doGesture { sendClick(1f, 1f) }
 
         // Verify startInput is called and capture the callback.
         val onEditCommandCaptor = argumentCaptor<(List<EditOperation>) -> Unit>()
diff --git a/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextFieldOnValueChangeStringTest.kt b/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextFieldOnValueChangeStringTest.kt
index 023c015..13e37b5 100644
--- a/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextFieldOnValueChangeStringTest.kt
+++ b/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextFieldOnValueChangeStringTest.kt
@@ -29,8 +29,9 @@
 import androidx.ui.input.SetSelectionEditOp
 import androidx.ui.input.TextInputService
 import androidx.ui.test.createComposeRule
-import androidx.ui.test.doClick
+import androidx.ui.test.doGesture
 import androidx.ui.test.findByTag
+import androidx.ui.test.sendClick
 import androidx.ui.test.waitForIdleCompose
 import com.google.common.truth.Truth.assertThat
 import com.nhaarman.mockitokotlin2.any
@@ -90,7 +91,7 @@
 
         // Perform click to focus in.
         val element = findByTag("textField")
-        element.doClick()
+        element.doGesture { sendClick(1f, 1f) }
 
         // Verify startInput is called and capture the callback.
         val onEditCommandCaptor = argumentCaptor<(List<EditOperation>) -> Unit>()
diff --git a/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/AndroidLayoutDrawTest.kt b/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/AndroidLayoutDrawTest.kt
index edd2878..e6e01f6 100644
--- a/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/AndroidLayoutDrawTest.kt
+++ b/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/AndroidLayoutDrawTest.kt
@@ -33,7 +33,6 @@
 import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
 import androidx.test.rule.ActivityTestRule
-import androidx.ui.core.AlignmentLine
 import androidx.ui.core.AndroidComposeView
 import androidx.ui.core.Constraints
 import androidx.ui.core.ContextAmbient
@@ -2181,15 +2180,9 @@
     )
 
     override fun DensityScope.modifyPosition(
-        childPosition: IntPxPosition,
         childSize: IntPxSize,
         containerSize: IntPxSize
-    ) = IntPxPosition(left + childPosition.x, top + childPosition.y)
-
-    override fun DensityScope.modifyAlignmentLine(line: AlignmentLine, value: IntPx?): IntPx? {
-        if (value == null) return null
-        return if (line.horizontal) value + left else value + top
-    }
+    ) = IntPxPosition(left, top)
 }
 
 @Model
diff --git a/ui/ui-framework/src/main/java/androidx/ui/core/Layout.kt b/ui/ui-framework/src/main/java/androidx/ui/core/Layout.kt
index 4ecfe0e..09558d0 100644
--- a/ui/ui-framework/src/main/java/androidx/ui/core/Layout.kt
+++ b/ui/ui-framework/src/main/java/androidx/ui/core/Layout.kt
@@ -434,9 +434,12 @@
  * children. If the composition yields multiple layout children, these will be all placed at the
  * top left of the WithConstraints, so consider wrapping them in an additional common
  * parent if different positioning is preferred.
+ *
+ * @param modifier Modifier to be applied to the introduced layout.
  */
 @Composable
 fun WithConstraints(
+    modifier: Modifier = Modifier.None,
     children: @Composable() (Constraints) -> Unit
 ) {
     val state = +memo { WithConstrainsState() }
@@ -446,7 +449,7 @@
     // if this code was executed subcomposition must be triggered as well
     state.forceRecompose = true
 
-    LayoutNode(ref = state.nodeRef, measureBlocks = state.measureBlocks)
+    LayoutNode(modifier = modifier, ref = state.nodeRef, measureBlocks = state.measureBlocks)
 
     // if LayoutNode scheduled the remeasuring no further steps are needed - subcomposition
     // will happen later on the measuring stage. otherwise we can assume the LayoutNode
diff --git a/ui/ui-framework/src/main/java/androidx/ui/core/Wrapper.kt b/ui/ui-framework/src/main/java/androidx/ui/core/Wrapper.kt
index fafc275..95bccc2 100644
--- a/ui/ui-framework/src/main/java/androidx/ui/core/Wrapper.kt
+++ b/ui/ui-framework/src/main/java/androidx/ui/core/Wrapper.kt
@@ -40,7 +40,6 @@
 import androidx.compose.unaryPlus
 import androidx.ui.autofill.Autofill
 import androidx.ui.autofill.AutofillTree
-import androidx.ui.core.selection.SelectionContainer
 import androidx.ui.text.font.Font
 import kotlinx.coroutines.Dispatchers
 import kotlin.coroutines.CoroutineContext
@@ -115,22 +114,11 @@
     // kotlinx.coroutines.Dispatchers' not instance of 'Precise Reference: androidx.compose.Ambient'.
     val coroutineContext = Dispatchers.Main
     return Compose.composeInto(composeView.root, this) {
-        WrapWithAmbients(composeView, this, coroutineContext) {
-            WrapWithSelectionContainer(content)
-        }
+        WrapWithAmbients(composeView, this, coroutineContext, content)
     }
 }
 
 /**
- * We want text/image selection to be enabled by default and disabled per widget. Therefore a root
- * level [SelectionContainer] is installed at the root.
- */
-@Composable
-private fun WrapWithSelectionContainer(content: @Composable() () -> Unit) {
-    SelectionContainer(children = content)
-}
-
-/**
  * Composes the given composable into the given view.
  *
  * @param content Composable that will be the content of the view.
@@ -146,9 +134,7 @@
     // kotlinx.coroutines.Dispatchers' not instance of 'Precise Reference: androidx.compose.Ambient'.
     val coroutineContext = Dispatchers.Main
     return Compose.composeInto(composeView.root, context) {
-        WrapWithAmbients(composeView, context, coroutineContext) {
-            WrapWithSelectionContainer(content)
-        }
+        WrapWithAmbients(composeView, context, coroutineContext, content)
     }
 }
 
diff --git a/ui/ui-framework/src/main/java/androidx/ui/core/selection/SelectionContainer.kt b/ui/ui-framework/src/main/java/androidx/ui/core/selection/SelectionContainer.kt
index acdda9e2..445c88f 100644
--- a/ui/ui-framework/src/main/java/androidx/ui/core/selection/SelectionContainer.kt
+++ b/ui/ui-framework/src/main/java/androidx/ui/core/selection/SelectionContainer.kt
@@ -32,7 +32,7 @@
 import androidx.ui.core.Popup
 import androidx.ui.core.enforce
 import androidx.ui.core.gesture.LongPressDragGestureDetector
-import androidx.ui.core.gesture.PressGestureDetector
+import androidx.ui.core.gesture.PressReleasedGestureDetector
 import androidx.ui.core.gesture.TouchSlopDragGestureDetector
 import androidx.ui.core.hasTightHeight
 import androidx.ui.core.hasTightWidth
@@ -81,7 +81,7 @@
             // Get the layout coordinates of the selection container. This is for hit test of
             // cross-composable selection.
             OnPositioned(onPositioned = { manager.containerLayoutCoordinates = it })
-            PressGestureDetector(onRelease = { manager.onRelease() }) {
+            PressReleasedGestureDetector(onRelease = { manager.onRelease() }) {
                 LongPressDragGestureDetector(manager.longPressDragObserver, children = children)
             }
             addHandles(
diff --git a/ui/ui-layout/api/0.1.0-dev03.txt b/ui/ui-layout/api/0.1.0-dev03.txt
index 37f5b57..a9abbf5 100644
--- a/ui/ui-layout/api/0.1.0-dev03.txt
+++ b/ui/ui-layout/api/0.1.0-dev03.txt
@@ -7,6 +7,40 @@
     method public static void Center(kotlin.jvm.functions.Function0<kotlin.Unit> children);
   }
 
+  public final class Aligned {
+    method public androidx.ui.core.LayoutModifier getBottom();
+    method public androidx.ui.core.LayoutModifier getBottomCenter();
+    method public androidx.ui.core.LayoutModifier getBottomLeft();
+    method public androidx.ui.core.LayoutModifier getBottomRight();
+    method public androidx.ui.core.LayoutModifier getCenter();
+    method public androidx.ui.core.LayoutModifier getCenterHorizontally();
+    method public androidx.ui.core.LayoutModifier getCenterLeft();
+    method public androidx.ui.core.LayoutModifier getCenterRight();
+    method public androidx.ui.core.LayoutModifier getCenterVertically();
+    method public androidx.ui.core.LayoutModifier getEnd();
+    method public androidx.ui.core.LayoutModifier getStart();
+    method public androidx.ui.core.LayoutModifier getTop();
+    method public androidx.ui.core.LayoutModifier getTopCenter();
+    method public androidx.ui.core.LayoutModifier getTopLeft();
+    method public androidx.ui.core.LayoutModifier getTopRight();
+    property public final androidx.ui.core.LayoutModifier Bottom;
+    property public final androidx.ui.core.LayoutModifier BottomCenter;
+    property public final androidx.ui.core.LayoutModifier BottomLeft;
+    property public final androidx.ui.core.LayoutModifier BottomRight;
+    property public final androidx.ui.core.LayoutModifier Center;
+    property public final androidx.ui.core.LayoutModifier CenterHorizontally;
+    property public final androidx.ui.core.LayoutModifier CenterLeft;
+    property public final androidx.ui.core.LayoutModifier CenterRight;
+    property public final androidx.ui.core.LayoutModifier CenterVertically;
+    property public final androidx.ui.core.LayoutModifier End;
+    property public final androidx.ui.core.LayoutModifier Start;
+    property public final androidx.ui.core.LayoutModifier Top;
+    property public final androidx.ui.core.LayoutModifier TopCenter;
+    property public final androidx.ui.core.LayoutModifier TopLeft;
+    property public final androidx.ui.core.LayoutModifier TopRight;
+    field public static final androidx.ui.layout.Aligned! INSTANCE;
+  }
+
   public final class AlignmentLineKt {
     ctor public AlignmentLineKt();
     method public static void AlignmentLineOffset(androidx.ui.core.AlignmentLine alignmentLine, androidx.ui.core.Dp before = 0.dp, androidx.ui.core.Dp after = 0.dp, kotlin.jvm.functions.Function0<kotlin.Unit> children);
@@ -357,3 +391,169 @@
 
 }
 
+package androidx.ui.layout.constraintlayout {
+
+  public final class ConstraintLayoutKt {
+    ctor public ConstraintLayoutKt();
+    method public static void ConstraintLayout(androidx.ui.layout.constraintlayout.ConstraintSet constraintSet, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method public static androidx.ui.core.LayoutModifier Tag(Object tag);
+    method public static Object! getTag(androidx.ui.core.Measurable);
+  }
+
+  public final class ConstraintSet {
+    ctor public ConstraintSet(internal kotlin.jvm.functions.Function1<? super androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope,kotlin.Unit> description);
+    method public androidx.ui.layout.constraintlayout.ConstraintSet copy(kotlin.jvm.functions.Function1<? super androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope,kotlin.Unit> description);
+  }
+
+  public final class ConstraintSetBuilderScope {
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createBottomBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalChain createHorizontalChain(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createLeftBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createRightBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createTopBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalChain createVerticalChain(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference getParent();
+    method public Object! getParentDimension();
+    method public Object! getSpreadDimension();
+    method public Object! getWrapDimension();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference tag(Object tag);
+    property public final Object! ParentDimension;
+    property public final Object! SpreadDimension;
+    property public final Object! WrapDimension;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference parent;
+  }
+
+  public static final class ConstraintSetBuilderScope.ChainStyle {
+    field public static final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+  }
+
+  public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle Packed(float bias);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle getPacked();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle getSpread();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle getSpreadInside();
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle Packed;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle Spread;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle SpreadInside;
+  }
+
+  public static final class ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor other);
+    method public androidx.constraintlayout.solver.state.State getState();
+    method public Object getTag();
+  }
+
+  public static final class ConstraintSetBuilderScope.ConstrainedLayoutReference {
+    method public void center();
+    method public void centerHorizontally();
+    method public void centerVertically();
+    method public infix void constrainHorizontallyTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public infix void constrainVerticallyTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor getBaseline();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method public float getHorizontalBias();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+    method public androidx.constraintlayout.solver.state.State getState();
+    method public Object getTag();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+    method public float getVerticalBias();
+    method public void setBaseline(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor p);
+    method public void setBottom(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor p);
+    method public void setHorizontalBias(float value);
+    method public void setRight(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor p);
+    method public void setVerticalBias(float value);
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor baseline;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
+    property public final float horizontalBias;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor left;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor right;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor top;
+    property public final float verticalBias;
+  }
+
+  public abstract static sealed class ConstraintSetBuilderScope.HorizontalAnchor {
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor other);
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+    property public Object tag;
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalChain {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor left;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor right;
+  }
+
+  public abstract static sealed class ConstraintSetBuilderScope.VerticalAnchor {
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor other);
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+    property public Object tag;
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalChain {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor top;
+  }
+
+}
+
diff --git a/ui/ui-layout/api/api_lint.ignore b/ui/ui-layout/api/api_lint.ignore
index f4de926..2295821 100644
--- a/ui/ui-layout/api/api_lint.ignore
+++ b/ui/ui-layout/api/api_lint.ignore
@@ -1,5 +1,21 @@
 // Baseline format: 1.0
+ArrayReturn: androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope#createHorizontalChain(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference[], androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle) parameter #0:
+    Method parameter should be Collection<ConstrainedLayoutReference> (or subclass) instead of raw array; was `androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference[]`
+ArrayReturn: androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope#createVerticalChain(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference[], androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle) parameter #0:
+    Method parameter should be Collection<ConstrainedLayoutReference> (or subclass) instead of raw array; was `androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference[]`
+
+
 DocumentExceptions: androidx.ui.layout.FlexChildren#expanded(float, kotlin.jvm.functions.Function0<kotlin.Unit>):
     Method FlexChildren.expanded appears to be throwing java.lang.IllegalArgumentException; this should be listed in the documentation; see https://android.github.io/kotlin-guides/interop.html#document-exceptions
 DocumentExceptions: androidx.ui.layout.FlexChildren#flexible(float, kotlin.jvm.functions.Function0<kotlin.Unit>):
     Method FlexChildren.flexible appears to be throwing java.lang.IllegalArgumentException; this should be listed in the documentation; see https://android.github.io/kotlin-guides/interop.html#document-exceptions
+
+
+MissingNullability: androidx.ui.layout.constraintlayout.ConstraintLayoutKt#getTag(androidx.ui.core.Measurable):
+    Missing nullability on method `getTag` return
+MissingNullability: androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope#getParentDimension():
+    Missing nullability on method `getParentDimension` return
+MissingNullability: androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope#getSpreadDimension():
+    Missing nullability on method `getSpreadDimension` return
+MissingNullability: androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope#getWrapDimension():
+    Missing nullability on method `getWrapDimension` return
diff --git a/ui/ui-layout/api/current.txt b/ui/ui-layout/api/current.txt
index 37f5b57..a9abbf5 100644
--- a/ui/ui-layout/api/current.txt
+++ b/ui/ui-layout/api/current.txt
@@ -7,6 +7,40 @@
     method public static void Center(kotlin.jvm.functions.Function0<kotlin.Unit> children);
   }
 
+  public final class Aligned {
+    method public androidx.ui.core.LayoutModifier getBottom();
+    method public androidx.ui.core.LayoutModifier getBottomCenter();
+    method public androidx.ui.core.LayoutModifier getBottomLeft();
+    method public androidx.ui.core.LayoutModifier getBottomRight();
+    method public androidx.ui.core.LayoutModifier getCenter();
+    method public androidx.ui.core.LayoutModifier getCenterHorizontally();
+    method public androidx.ui.core.LayoutModifier getCenterLeft();
+    method public androidx.ui.core.LayoutModifier getCenterRight();
+    method public androidx.ui.core.LayoutModifier getCenterVertically();
+    method public androidx.ui.core.LayoutModifier getEnd();
+    method public androidx.ui.core.LayoutModifier getStart();
+    method public androidx.ui.core.LayoutModifier getTop();
+    method public androidx.ui.core.LayoutModifier getTopCenter();
+    method public androidx.ui.core.LayoutModifier getTopLeft();
+    method public androidx.ui.core.LayoutModifier getTopRight();
+    property public final androidx.ui.core.LayoutModifier Bottom;
+    property public final androidx.ui.core.LayoutModifier BottomCenter;
+    property public final androidx.ui.core.LayoutModifier BottomLeft;
+    property public final androidx.ui.core.LayoutModifier BottomRight;
+    property public final androidx.ui.core.LayoutModifier Center;
+    property public final androidx.ui.core.LayoutModifier CenterHorizontally;
+    property public final androidx.ui.core.LayoutModifier CenterLeft;
+    property public final androidx.ui.core.LayoutModifier CenterRight;
+    property public final androidx.ui.core.LayoutModifier CenterVertically;
+    property public final androidx.ui.core.LayoutModifier End;
+    property public final androidx.ui.core.LayoutModifier Start;
+    property public final androidx.ui.core.LayoutModifier Top;
+    property public final androidx.ui.core.LayoutModifier TopCenter;
+    property public final androidx.ui.core.LayoutModifier TopLeft;
+    property public final androidx.ui.core.LayoutModifier TopRight;
+    field public static final androidx.ui.layout.Aligned! INSTANCE;
+  }
+
   public final class AlignmentLineKt {
     ctor public AlignmentLineKt();
     method public static void AlignmentLineOffset(androidx.ui.core.AlignmentLine alignmentLine, androidx.ui.core.Dp before = 0.dp, androidx.ui.core.Dp after = 0.dp, kotlin.jvm.functions.Function0<kotlin.Unit> children);
@@ -357,3 +391,169 @@
 
 }
 
+package androidx.ui.layout.constraintlayout {
+
+  public final class ConstraintLayoutKt {
+    ctor public ConstraintLayoutKt();
+    method public static void ConstraintLayout(androidx.ui.layout.constraintlayout.ConstraintSet constraintSet, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method public static androidx.ui.core.LayoutModifier Tag(Object tag);
+    method public static Object! getTag(androidx.ui.core.Measurable);
+  }
+
+  public final class ConstraintSet {
+    ctor public ConstraintSet(internal kotlin.jvm.functions.Function1<? super androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope,kotlin.Unit> description);
+    method public androidx.ui.layout.constraintlayout.ConstraintSet copy(kotlin.jvm.functions.Function1<? super androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope,kotlin.Unit> description);
+  }
+
+  public final class ConstraintSetBuilderScope {
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createBottomBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalChain createHorizontalChain(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createLeftBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createRightBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createTopBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalChain createVerticalChain(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference getParent();
+    method public Object! getParentDimension();
+    method public Object! getSpreadDimension();
+    method public Object! getWrapDimension();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference tag(Object tag);
+    property public final Object! ParentDimension;
+    property public final Object! SpreadDimension;
+    property public final Object! WrapDimension;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference parent;
+  }
+
+  public static final class ConstraintSetBuilderScope.ChainStyle {
+    field public static final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+  }
+
+  public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle Packed(float bias);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle getPacked();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle getSpread();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle getSpreadInside();
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle Packed;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle Spread;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle SpreadInside;
+  }
+
+  public static final class ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor other);
+    method public androidx.constraintlayout.solver.state.State getState();
+    method public Object getTag();
+  }
+
+  public static final class ConstraintSetBuilderScope.ConstrainedLayoutReference {
+    method public void center();
+    method public void centerHorizontally();
+    method public void centerVertically();
+    method public infix void constrainHorizontallyTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public infix void constrainVerticallyTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor getBaseline();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method public float getHorizontalBias();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+    method public androidx.constraintlayout.solver.state.State getState();
+    method public Object getTag();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+    method public float getVerticalBias();
+    method public void setBaseline(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor p);
+    method public void setBottom(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor p);
+    method public void setHorizontalBias(float value);
+    method public void setRight(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor p);
+    method public void setVerticalBias(float value);
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor baseline;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
+    property public final float horizontalBias;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor left;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor right;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor top;
+    property public final float verticalBias;
+  }
+
+  public abstract static sealed class ConstraintSetBuilderScope.HorizontalAnchor {
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor other);
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+    property public Object tag;
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalChain {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor left;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor right;
+  }
+
+  public abstract static sealed class ConstraintSetBuilderScope.VerticalAnchor {
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor other);
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+    property public Object tag;
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalChain {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor top;
+  }
+
+}
+
diff --git a/ui/ui-layout/api/public_plus_experimental_0.1.0-dev03.txt b/ui/ui-layout/api/public_plus_experimental_0.1.0-dev03.txt
index 37f5b57..a9abbf5 100644
--- a/ui/ui-layout/api/public_plus_experimental_0.1.0-dev03.txt
+++ b/ui/ui-layout/api/public_plus_experimental_0.1.0-dev03.txt
@@ -7,6 +7,40 @@
     method public static void Center(kotlin.jvm.functions.Function0<kotlin.Unit> children);
   }
 
+  public final class Aligned {
+    method public androidx.ui.core.LayoutModifier getBottom();
+    method public androidx.ui.core.LayoutModifier getBottomCenter();
+    method public androidx.ui.core.LayoutModifier getBottomLeft();
+    method public androidx.ui.core.LayoutModifier getBottomRight();
+    method public androidx.ui.core.LayoutModifier getCenter();
+    method public androidx.ui.core.LayoutModifier getCenterHorizontally();
+    method public androidx.ui.core.LayoutModifier getCenterLeft();
+    method public androidx.ui.core.LayoutModifier getCenterRight();
+    method public androidx.ui.core.LayoutModifier getCenterVertically();
+    method public androidx.ui.core.LayoutModifier getEnd();
+    method public androidx.ui.core.LayoutModifier getStart();
+    method public androidx.ui.core.LayoutModifier getTop();
+    method public androidx.ui.core.LayoutModifier getTopCenter();
+    method public androidx.ui.core.LayoutModifier getTopLeft();
+    method public androidx.ui.core.LayoutModifier getTopRight();
+    property public final androidx.ui.core.LayoutModifier Bottom;
+    property public final androidx.ui.core.LayoutModifier BottomCenter;
+    property public final androidx.ui.core.LayoutModifier BottomLeft;
+    property public final androidx.ui.core.LayoutModifier BottomRight;
+    property public final androidx.ui.core.LayoutModifier Center;
+    property public final androidx.ui.core.LayoutModifier CenterHorizontally;
+    property public final androidx.ui.core.LayoutModifier CenterLeft;
+    property public final androidx.ui.core.LayoutModifier CenterRight;
+    property public final androidx.ui.core.LayoutModifier CenterVertically;
+    property public final androidx.ui.core.LayoutModifier End;
+    property public final androidx.ui.core.LayoutModifier Start;
+    property public final androidx.ui.core.LayoutModifier Top;
+    property public final androidx.ui.core.LayoutModifier TopCenter;
+    property public final androidx.ui.core.LayoutModifier TopLeft;
+    property public final androidx.ui.core.LayoutModifier TopRight;
+    field public static final androidx.ui.layout.Aligned! INSTANCE;
+  }
+
   public final class AlignmentLineKt {
     ctor public AlignmentLineKt();
     method public static void AlignmentLineOffset(androidx.ui.core.AlignmentLine alignmentLine, androidx.ui.core.Dp before = 0.dp, androidx.ui.core.Dp after = 0.dp, kotlin.jvm.functions.Function0<kotlin.Unit> children);
@@ -357,3 +391,169 @@
 
 }
 
+package androidx.ui.layout.constraintlayout {
+
+  public final class ConstraintLayoutKt {
+    ctor public ConstraintLayoutKt();
+    method public static void ConstraintLayout(androidx.ui.layout.constraintlayout.ConstraintSet constraintSet, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method public static androidx.ui.core.LayoutModifier Tag(Object tag);
+    method public static Object! getTag(androidx.ui.core.Measurable);
+  }
+
+  public final class ConstraintSet {
+    ctor public ConstraintSet(internal kotlin.jvm.functions.Function1<? super androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope,kotlin.Unit> description);
+    method public androidx.ui.layout.constraintlayout.ConstraintSet copy(kotlin.jvm.functions.Function1<? super androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope,kotlin.Unit> description);
+  }
+
+  public final class ConstraintSetBuilderScope {
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createBottomBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalChain createHorizontalChain(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createLeftBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createRightBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createTopBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalChain createVerticalChain(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference getParent();
+    method public Object! getParentDimension();
+    method public Object! getSpreadDimension();
+    method public Object! getWrapDimension();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference tag(Object tag);
+    property public final Object! ParentDimension;
+    property public final Object! SpreadDimension;
+    property public final Object! WrapDimension;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference parent;
+  }
+
+  public static final class ConstraintSetBuilderScope.ChainStyle {
+    field public static final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+  }
+
+  public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle Packed(float bias);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle getPacked();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle getSpread();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle getSpreadInside();
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle Packed;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle Spread;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle SpreadInside;
+  }
+
+  public static final class ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor other);
+    method public androidx.constraintlayout.solver.state.State getState();
+    method public Object getTag();
+  }
+
+  public static final class ConstraintSetBuilderScope.ConstrainedLayoutReference {
+    method public void center();
+    method public void centerHorizontally();
+    method public void centerVertically();
+    method public infix void constrainHorizontallyTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public infix void constrainVerticallyTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor getBaseline();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method public float getHorizontalBias();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+    method public androidx.constraintlayout.solver.state.State getState();
+    method public Object getTag();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+    method public float getVerticalBias();
+    method public void setBaseline(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor p);
+    method public void setBottom(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor p);
+    method public void setHorizontalBias(float value);
+    method public void setRight(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor p);
+    method public void setVerticalBias(float value);
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor baseline;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
+    property public final float horizontalBias;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor left;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor right;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor top;
+    property public final float verticalBias;
+  }
+
+  public abstract static sealed class ConstraintSetBuilderScope.HorizontalAnchor {
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor other);
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+    property public Object tag;
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalChain {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor left;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor right;
+  }
+
+  public abstract static sealed class ConstraintSetBuilderScope.VerticalAnchor {
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor other);
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+    property public Object tag;
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalChain {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor top;
+  }
+
+}
+
diff --git a/ui/ui-layout/api/public_plus_experimental_current.txt b/ui/ui-layout/api/public_plus_experimental_current.txt
index 37f5b57..a9abbf5 100644
--- a/ui/ui-layout/api/public_plus_experimental_current.txt
+++ b/ui/ui-layout/api/public_plus_experimental_current.txt
@@ -7,6 +7,40 @@
     method public static void Center(kotlin.jvm.functions.Function0<kotlin.Unit> children);
   }
 
+  public final class Aligned {
+    method public androidx.ui.core.LayoutModifier getBottom();
+    method public androidx.ui.core.LayoutModifier getBottomCenter();
+    method public androidx.ui.core.LayoutModifier getBottomLeft();
+    method public androidx.ui.core.LayoutModifier getBottomRight();
+    method public androidx.ui.core.LayoutModifier getCenter();
+    method public androidx.ui.core.LayoutModifier getCenterHorizontally();
+    method public androidx.ui.core.LayoutModifier getCenterLeft();
+    method public androidx.ui.core.LayoutModifier getCenterRight();
+    method public androidx.ui.core.LayoutModifier getCenterVertically();
+    method public androidx.ui.core.LayoutModifier getEnd();
+    method public androidx.ui.core.LayoutModifier getStart();
+    method public androidx.ui.core.LayoutModifier getTop();
+    method public androidx.ui.core.LayoutModifier getTopCenter();
+    method public androidx.ui.core.LayoutModifier getTopLeft();
+    method public androidx.ui.core.LayoutModifier getTopRight();
+    property public final androidx.ui.core.LayoutModifier Bottom;
+    property public final androidx.ui.core.LayoutModifier BottomCenter;
+    property public final androidx.ui.core.LayoutModifier BottomLeft;
+    property public final androidx.ui.core.LayoutModifier BottomRight;
+    property public final androidx.ui.core.LayoutModifier Center;
+    property public final androidx.ui.core.LayoutModifier CenterHorizontally;
+    property public final androidx.ui.core.LayoutModifier CenterLeft;
+    property public final androidx.ui.core.LayoutModifier CenterRight;
+    property public final androidx.ui.core.LayoutModifier CenterVertically;
+    property public final androidx.ui.core.LayoutModifier End;
+    property public final androidx.ui.core.LayoutModifier Start;
+    property public final androidx.ui.core.LayoutModifier Top;
+    property public final androidx.ui.core.LayoutModifier TopCenter;
+    property public final androidx.ui.core.LayoutModifier TopLeft;
+    property public final androidx.ui.core.LayoutModifier TopRight;
+    field public static final androidx.ui.layout.Aligned! INSTANCE;
+  }
+
   public final class AlignmentLineKt {
     ctor public AlignmentLineKt();
     method public static void AlignmentLineOffset(androidx.ui.core.AlignmentLine alignmentLine, androidx.ui.core.Dp before = 0.dp, androidx.ui.core.Dp after = 0.dp, kotlin.jvm.functions.Function0<kotlin.Unit> children);
@@ -357,3 +391,169 @@
 
 }
 
+package androidx.ui.layout.constraintlayout {
+
+  public final class ConstraintLayoutKt {
+    ctor public ConstraintLayoutKt();
+    method public static void ConstraintLayout(androidx.ui.layout.constraintlayout.ConstraintSet constraintSet, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method public static androidx.ui.core.LayoutModifier Tag(Object tag);
+    method public static Object! getTag(androidx.ui.core.Measurable);
+  }
+
+  public final class ConstraintSet {
+    ctor public ConstraintSet(internal kotlin.jvm.functions.Function1<? super androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope,kotlin.Unit> description);
+    method public androidx.ui.layout.constraintlayout.ConstraintSet copy(kotlin.jvm.functions.Function1<? super androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope,kotlin.Unit> description);
+  }
+
+  public final class ConstraintSetBuilderScope {
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createBottomBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalChain createHorizontalChain(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createLeftBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createRightBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createTopBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalChain createVerticalChain(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference getParent();
+    method public Object! getParentDimension();
+    method public Object! getSpreadDimension();
+    method public Object! getWrapDimension();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference tag(Object tag);
+    property public final Object! ParentDimension;
+    property public final Object! SpreadDimension;
+    property public final Object! WrapDimension;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference parent;
+  }
+
+  public static final class ConstraintSetBuilderScope.ChainStyle {
+    field public static final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+  }
+
+  public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle Packed(float bias);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle getPacked();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle getSpread();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle getSpreadInside();
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle Packed;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle Spread;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle SpreadInside;
+  }
+
+  public static final class ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor other);
+    method public androidx.constraintlayout.solver.state.State getState();
+    method public Object getTag();
+  }
+
+  public static final class ConstraintSetBuilderScope.ConstrainedLayoutReference {
+    method public void center();
+    method public void centerHorizontally();
+    method public void centerVertically();
+    method public infix void constrainHorizontallyTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public infix void constrainVerticallyTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor getBaseline();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method public float getHorizontalBias();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+    method public androidx.constraintlayout.solver.state.State getState();
+    method public Object getTag();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+    method public float getVerticalBias();
+    method public void setBaseline(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor p);
+    method public void setBottom(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor p);
+    method public void setHorizontalBias(float value);
+    method public void setRight(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor p);
+    method public void setVerticalBias(float value);
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor baseline;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
+    property public final float horizontalBias;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor left;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor right;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor top;
+    property public final float verticalBias;
+  }
+
+  public abstract static sealed class ConstraintSetBuilderScope.HorizontalAnchor {
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor other);
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+    property public Object tag;
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalChain {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor left;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor right;
+  }
+
+  public abstract static sealed class ConstraintSetBuilderScope.VerticalAnchor {
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor other);
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+    property public Object tag;
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalChain {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor top;
+  }
+
+}
+
diff --git a/ui/ui-layout/api/restricted_0.1.0-dev03.txt b/ui/ui-layout/api/restricted_0.1.0-dev03.txt
index 37f5b57..a9abbf5 100644
--- a/ui/ui-layout/api/restricted_0.1.0-dev03.txt
+++ b/ui/ui-layout/api/restricted_0.1.0-dev03.txt
@@ -7,6 +7,40 @@
     method public static void Center(kotlin.jvm.functions.Function0<kotlin.Unit> children);
   }
 
+  public final class Aligned {
+    method public androidx.ui.core.LayoutModifier getBottom();
+    method public androidx.ui.core.LayoutModifier getBottomCenter();
+    method public androidx.ui.core.LayoutModifier getBottomLeft();
+    method public androidx.ui.core.LayoutModifier getBottomRight();
+    method public androidx.ui.core.LayoutModifier getCenter();
+    method public androidx.ui.core.LayoutModifier getCenterHorizontally();
+    method public androidx.ui.core.LayoutModifier getCenterLeft();
+    method public androidx.ui.core.LayoutModifier getCenterRight();
+    method public androidx.ui.core.LayoutModifier getCenterVertically();
+    method public androidx.ui.core.LayoutModifier getEnd();
+    method public androidx.ui.core.LayoutModifier getStart();
+    method public androidx.ui.core.LayoutModifier getTop();
+    method public androidx.ui.core.LayoutModifier getTopCenter();
+    method public androidx.ui.core.LayoutModifier getTopLeft();
+    method public androidx.ui.core.LayoutModifier getTopRight();
+    property public final androidx.ui.core.LayoutModifier Bottom;
+    property public final androidx.ui.core.LayoutModifier BottomCenter;
+    property public final androidx.ui.core.LayoutModifier BottomLeft;
+    property public final androidx.ui.core.LayoutModifier BottomRight;
+    property public final androidx.ui.core.LayoutModifier Center;
+    property public final androidx.ui.core.LayoutModifier CenterHorizontally;
+    property public final androidx.ui.core.LayoutModifier CenterLeft;
+    property public final androidx.ui.core.LayoutModifier CenterRight;
+    property public final androidx.ui.core.LayoutModifier CenterVertically;
+    property public final androidx.ui.core.LayoutModifier End;
+    property public final androidx.ui.core.LayoutModifier Start;
+    property public final androidx.ui.core.LayoutModifier Top;
+    property public final androidx.ui.core.LayoutModifier TopCenter;
+    property public final androidx.ui.core.LayoutModifier TopLeft;
+    property public final androidx.ui.core.LayoutModifier TopRight;
+    field public static final androidx.ui.layout.Aligned! INSTANCE;
+  }
+
   public final class AlignmentLineKt {
     ctor public AlignmentLineKt();
     method public static void AlignmentLineOffset(androidx.ui.core.AlignmentLine alignmentLine, androidx.ui.core.Dp before = 0.dp, androidx.ui.core.Dp after = 0.dp, kotlin.jvm.functions.Function0<kotlin.Unit> children);
@@ -357,3 +391,169 @@
 
 }
 
+package androidx.ui.layout.constraintlayout {
+
+  public final class ConstraintLayoutKt {
+    ctor public ConstraintLayoutKt();
+    method public static void ConstraintLayout(androidx.ui.layout.constraintlayout.ConstraintSet constraintSet, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method public static androidx.ui.core.LayoutModifier Tag(Object tag);
+    method public static Object! getTag(androidx.ui.core.Measurable);
+  }
+
+  public final class ConstraintSet {
+    ctor public ConstraintSet(internal kotlin.jvm.functions.Function1<? super androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope,kotlin.Unit> description);
+    method public androidx.ui.layout.constraintlayout.ConstraintSet copy(kotlin.jvm.functions.Function1<? super androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope,kotlin.Unit> description);
+  }
+
+  public final class ConstraintSetBuilderScope {
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createBottomBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalChain createHorizontalChain(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createLeftBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createRightBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createTopBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalChain createVerticalChain(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference getParent();
+    method public Object! getParentDimension();
+    method public Object! getSpreadDimension();
+    method public Object! getWrapDimension();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference tag(Object tag);
+    property public final Object! ParentDimension;
+    property public final Object! SpreadDimension;
+    property public final Object! WrapDimension;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference parent;
+  }
+
+  public static final class ConstraintSetBuilderScope.ChainStyle {
+    field public static final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+  }
+
+  public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle Packed(float bias);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle getPacked();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle getSpread();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle getSpreadInside();
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle Packed;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle Spread;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle SpreadInside;
+  }
+
+  public static final class ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor other);
+    method public androidx.constraintlayout.solver.state.State getState();
+    method public Object getTag();
+  }
+
+  public static final class ConstraintSetBuilderScope.ConstrainedLayoutReference {
+    method public void center();
+    method public void centerHorizontally();
+    method public void centerVertically();
+    method public infix void constrainHorizontallyTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public infix void constrainVerticallyTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor getBaseline();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method public float getHorizontalBias();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+    method public androidx.constraintlayout.solver.state.State getState();
+    method public Object getTag();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+    method public float getVerticalBias();
+    method public void setBaseline(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor p);
+    method public void setBottom(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor p);
+    method public void setHorizontalBias(float value);
+    method public void setRight(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor p);
+    method public void setVerticalBias(float value);
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor baseline;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
+    property public final float horizontalBias;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor left;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor right;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor top;
+    property public final float verticalBias;
+  }
+
+  public abstract static sealed class ConstraintSetBuilderScope.HorizontalAnchor {
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor other);
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+    property public Object tag;
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalChain {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor left;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor right;
+  }
+
+  public abstract static sealed class ConstraintSetBuilderScope.VerticalAnchor {
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor other);
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+    property public Object tag;
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalChain {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor top;
+  }
+
+}
+
diff --git a/ui/ui-layout/api/restricted_current.txt b/ui/ui-layout/api/restricted_current.txt
index 37f5b57..a9abbf5 100644
--- a/ui/ui-layout/api/restricted_current.txt
+++ b/ui/ui-layout/api/restricted_current.txt
@@ -7,6 +7,40 @@
     method public static void Center(kotlin.jvm.functions.Function0<kotlin.Unit> children);
   }
 
+  public final class Aligned {
+    method public androidx.ui.core.LayoutModifier getBottom();
+    method public androidx.ui.core.LayoutModifier getBottomCenter();
+    method public androidx.ui.core.LayoutModifier getBottomLeft();
+    method public androidx.ui.core.LayoutModifier getBottomRight();
+    method public androidx.ui.core.LayoutModifier getCenter();
+    method public androidx.ui.core.LayoutModifier getCenterHorizontally();
+    method public androidx.ui.core.LayoutModifier getCenterLeft();
+    method public androidx.ui.core.LayoutModifier getCenterRight();
+    method public androidx.ui.core.LayoutModifier getCenterVertically();
+    method public androidx.ui.core.LayoutModifier getEnd();
+    method public androidx.ui.core.LayoutModifier getStart();
+    method public androidx.ui.core.LayoutModifier getTop();
+    method public androidx.ui.core.LayoutModifier getTopCenter();
+    method public androidx.ui.core.LayoutModifier getTopLeft();
+    method public androidx.ui.core.LayoutModifier getTopRight();
+    property public final androidx.ui.core.LayoutModifier Bottom;
+    property public final androidx.ui.core.LayoutModifier BottomCenter;
+    property public final androidx.ui.core.LayoutModifier BottomLeft;
+    property public final androidx.ui.core.LayoutModifier BottomRight;
+    property public final androidx.ui.core.LayoutModifier Center;
+    property public final androidx.ui.core.LayoutModifier CenterHorizontally;
+    property public final androidx.ui.core.LayoutModifier CenterLeft;
+    property public final androidx.ui.core.LayoutModifier CenterRight;
+    property public final androidx.ui.core.LayoutModifier CenterVertically;
+    property public final androidx.ui.core.LayoutModifier End;
+    property public final androidx.ui.core.LayoutModifier Start;
+    property public final androidx.ui.core.LayoutModifier Top;
+    property public final androidx.ui.core.LayoutModifier TopCenter;
+    property public final androidx.ui.core.LayoutModifier TopLeft;
+    property public final androidx.ui.core.LayoutModifier TopRight;
+    field public static final androidx.ui.layout.Aligned! INSTANCE;
+  }
+
   public final class AlignmentLineKt {
     ctor public AlignmentLineKt();
     method public static void AlignmentLineOffset(androidx.ui.core.AlignmentLine alignmentLine, androidx.ui.core.Dp before = 0.dp, androidx.ui.core.Dp after = 0.dp, kotlin.jvm.functions.Function0<kotlin.Unit> children);
@@ -357,3 +391,169 @@
 
 }
 
+package androidx.ui.layout.constraintlayout {
+
+  public final class ConstraintLayoutKt {
+    ctor public ConstraintLayoutKt();
+    method public static void ConstraintLayout(androidx.ui.layout.constraintlayout.ConstraintSet constraintSet, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method public static androidx.ui.core.LayoutModifier Tag(Object tag);
+    method public static Object! getTag(androidx.ui.core.Measurable);
+  }
+
+  public final class ConstraintSet {
+    ctor public ConstraintSet(internal kotlin.jvm.functions.Function1<? super androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope,kotlin.Unit> description);
+    method public androidx.ui.layout.constraintlayout.ConstraintSet copy(kotlin.jvm.functions.Function1<? super androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope,kotlin.Unit> description);
+  }
+
+  public final class ConstraintSetBuilderScope {
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createBottomBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(androidx.ui.core.Dp offset);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(float percent);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalChain createHorizontalChain(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createLeftBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createRightBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createTopBarrier(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalChain createVerticalChain(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference getParent();
+    method public Object! getParentDimension();
+    method public Object! getSpreadDimension();
+    method public Object! getWrapDimension();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference tag(Object tag);
+    property public final Object! ParentDimension;
+    property public final Object! SpreadDimension;
+    property public final Object! WrapDimension;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference parent;
+  }
+
+  public static final class ConstraintSetBuilderScope.ChainStyle {
+    field public static final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+  }
+
+  public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle Packed(float bias);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle getPacked();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle getSpread();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle getSpreadInside();
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle Packed;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle Spread;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ChainStyle SpreadInside;
+  }
+
+  public static final class ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor other);
+    method public androidx.constraintlayout.solver.state.State getState();
+    method public Object getTag();
+  }
+
+  public static final class ConstraintSetBuilderScope.ConstrainedLayoutReference {
+    method public void center();
+    method public void centerHorizontally();
+    method public void centerVertically();
+    method public infix void constrainHorizontallyTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public infix void constrainVerticallyTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor getBaseline();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method public float getHorizontalBias();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+    method public androidx.constraintlayout.solver.state.State getState();
+    method public Object getTag();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+    method public float getVerticalBias();
+    method public void setBaseline(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor p);
+    method public void setBottom(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor p);
+    method public void setHorizontalBias(float value);
+    method public void setRight(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor p);
+    method public void setVerticalBias(float value);
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor baseline;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
+    property public final float horizontalBias;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor left;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor right;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor top;
+    property public final float verticalBias;
+  }
+
+  public abstract static sealed class ConstraintSetBuilderScope.HorizontalAnchor {
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor other);
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+    property public Object tag;
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+  }
+
+  public static final class ConstraintSetBuilderScope.HorizontalChain {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor left;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor right;
+  }
+
+  public abstract static sealed class ConstraintSetBuilderScope.VerticalAnchor {
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor other);
+    method public int getIndex$lintWithKotlin();
+    method public androidx.ui.core.Dp getMargin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+    method public void setMargin(androidx.ui.core.Dp value);
+    property public final androidx.ui.core.Dp margin;
+    property public Object tag;
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor extends androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.VerticalAnchor {
+    method public int getIndex$lintWithKotlin();
+    method public androidx.constraintlayout.solver.state.State getState$lintWithKotlin();
+    method public Object getTag$lintWithKotlin();
+  }
+
+  public static final class ConstraintSetBuilderScope.VerticalChain {
+    method public infix void constrainTo(androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method public androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
+    property public final androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor top;
+  }
+
+}
+
diff --git a/ui/ui-layout/build.gradle b/ui/ui-layout/build.gradle
index 9beabcf..1c364ba 100644
--- a/ui/ui-layout/build.gradle
+++ b/ui/ui-layout/build.gradle
@@ -39,6 +39,7 @@
     implementation project(":compose:compose-runtime")
     api project(":ui:ui-core")
     implementation project(":ui:ui-framework")
+    implementation(CONSTRAINT_LAYOUT_SOLVER)
 
     testImplementation(ANDROIDX_TEST_RULES)
     testImplementation(ANDROIDX_TEST_RUNNER)
diff --git a/ui/ui-layout/integration-tests/layout-demos/src/main/AndroidManifest.xml b/ui/ui-layout/integration-tests/layout-demos/src/main/AndroidManifest.xml
index 09bb609..41c77fe 100644
--- a/ui/ui-layout/integration-tests/layout-demos/src/main/AndroidManifest.xml
+++ b/ui/ui-layout/integration-tests/layout-demos/src/main/AndroidManifest.xml
@@ -27,7 +27,14 @@
                 <category android:name="androidx.ui.demos.SAMPLE_CODE" />
             </intent-filter>
         </activity>
-
+        <activity android:name=".ConstraintLayoutActivity"
+            android:configChanges="orientation|screenSize"
+            android:label="Layout/ConstraintLayout">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="androidx.ui.demos.SAMPLE_CODE" />
+            </intent-filter>
+        </activity>
         <activity android:name=".ComplexLayoutActivity"
             android:configChanges="orientation|screenSize"
             android:label="Layout/Complex layout">
diff --git a/ui/ui-layout/integration-tests/layout-demos/src/main/java/androidx/ui/layout/demos/ConstraintLayoutActivity.kt b/ui/ui-layout/integration-tests/layout-demos/src/main/java/androidx/ui/layout/demos/ConstraintLayoutActivity.kt
new file mode 100644
index 0000000..c57aacb
--- /dev/null
+++ b/ui/ui-layout/integration-tests/layout-demos/src/main/java/androidx/ui/layout/demos/ConstraintLayoutActivity.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2019 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.ui.layout.demos
+
+import android.app.Activity
+import android.os.Bundle
+import androidx.compose.Composable
+import androidx.ui.core.Draw
+import androidx.ui.core.Text
+import androidx.ui.core.dp
+import androidx.ui.core.setContent
+import androidx.ui.core.sp
+import androidx.ui.core.toRect
+import androidx.ui.graphics.Color
+import androidx.ui.graphics.Paint
+import androidx.ui.layout.constraintlayout.ConstraintLayout
+import androidx.ui.layout.constraintlayout.ConstraintSet
+import androidx.ui.layout.constraintlayout.ConstraintSetBuilderScope
+import androidx.ui.layout.constraintlayout.Tag
+import androidx.ui.text.TextStyle
+
+/**
+ * Simple ConstraintLayout demo
+ */
+class ConstraintLayoutActivity : Activity() {
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setContent {
+            CLDemo()
+        }
+    }
+}
+
+@Composable
+fun CLDemo() {
+    ConstraintLayout(ConstraintSet {
+        val text1 = tag("text1")
+        val text2 = tag("text2")
+        val text3 = tag("text3")
+        val text4 = tag("text4")
+        val text5 = tag("text5")
+
+        text2.center()
+
+        val half = createGuidelineFromLeft(percent = 0.5f)
+        text1.apply {
+            left constrainTo half
+            left.margin = 50.dp
+            bottom constrainTo text2.top
+        }
+
+        text3 constrainHorizontallyTo parent
+        text3.horizontalBias = 0.2f
+        text4 constrainHorizontallyTo parent
+        text4.horizontalBias = 0.8f
+        val chain = createVerticalChain(
+            text3,
+            text4,
+            chainStyle = ConstraintSetBuilderScope.ChainStyle.Spread
+        )
+        chain.top.margin = 100.dp
+        chain.bottom.margin = 100.dp
+
+        val barrier = createBottomBarrier(text2, text3)
+        barrier.margin = 50.dp
+        text5.top constrainTo barrier
+        text5.centerHorizontally()
+    }) {
+        Draw { canvas, parentSize ->
+            canvas.drawRect(parentSize.toRect(), Paint().apply { color = Color.Blue })
+        }
+        Text(modifier = Tag("text1"), text = "Text1", style = TextStyle(fontSize = 10.sp))
+        Text(modifier = Tag("text2"), text = "Text2", style = TextStyle(fontSize = 12.sp))
+        Text(modifier = Tag("text3"), text = "Text3", style = TextStyle(fontSize = 14.sp))
+        Text(modifier = Tag("text4"), text = "Text4", style = TextStyle(fontSize = 16.sp))
+        Text(modifier = Tag("text5"), text = "Text5", style = TextStyle(fontSize = 18.sp))
+    }
+}
diff --git a/ui/ui-layout/integration-tests/samples/src/main/java/androidx/ui/layout/samples/AlignSample.kt b/ui/ui-layout/integration-tests/samples/src/main/java/androidx/ui/layout/samples/AlignSample.kt
index 0e94d80..69af541 100644
--- a/ui/ui-layout/integration-tests/samples/src/main/java/androidx/ui/layout/samples/AlignSample.kt
+++ b/ui/ui-layout/integration-tests/samples/src/main/java/androidx/ui/layout/samples/AlignSample.kt
@@ -22,6 +22,7 @@
 import androidx.ui.core.dp
 import androidx.ui.graphics.Color
 import androidx.ui.layout.Align
+import androidx.ui.layout.Aligned
 import androidx.ui.layout.Center
 import androidx.ui.layout.Column
 import androidx.ui.layout.ExpandedHeight
@@ -47,6 +48,18 @@
 
 @Sampled
 @Composable
+fun SimpleAlignedModifier() {
+    SizedRectangle(modifier = Aligned.TopCenter, color = Color.Blue, width = 20.dp, height = 20.dp)
+}
+
+@Sampled
+@Composable
+fun SimpleVerticallyAlignedModifier() {
+    SizedRectangle(modifier = Aligned.CenterVertically, color = Color.Blue, height = 50.dp)
+}
+
+@Sampled
+@Composable
 fun SimpleGravityInRow() {
     Row(ExpandedHeight) {
         // The child with no gravity modifier is positioned by default so that its top edge is
diff --git a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/AlignTest.kt b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/AlignTest.kt
index 1442e18..2de62fa 100644
--- a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/AlignTest.kt
+++ b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/AlignTest.kt
@@ -32,8 +32,12 @@
 import androidx.ui.core.px
 import androidx.ui.core.withDensity
 import androidx.ui.layout.Align
+import androidx.ui.layout.Aligned
 import androidx.ui.layout.AspectRatio
 import androidx.ui.layout.Container
+import androidx.ui.layout.ExpandedHeight
+import androidx.ui.layout.Size
+import androidx.ui.layout.Width
 import org.junit.Assert.assertEquals
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -85,6 +89,83 @@
     }
 
     @Test
+    fun test2DAlignedModifier() = withDensity(density) {
+        val sizeDp = 50.dp
+        val size = sizeDp.toIntPx()
+
+        val positionedLatch = CountDownLatch(2)
+        val alignSize = Ref<PxSize>()
+        val alignPosition = Ref<PxPosition>()
+        val childSize = Ref<PxSize>()
+        val childPosition = Ref<PxPosition>()
+        show {
+            Container {
+                SaveLayoutInfo(
+                    size = alignSize,
+                    position = alignPosition,
+                    positionedLatch = positionedLatch
+                )
+                Container(modifier = Aligned.BottomRight wraps Size(sizeDp, sizeDp)) {
+                    SaveLayoutInfo(
+                        size = childSize,
+                        position = childPosition,
+                        positionedLatch = positionedLatch
+                    )
+                }
+            }
+        }
+        positionedLatch.await(1, TimeUnit.SECONDS)
+
+        val root = findAndroidComposeView()
+        waitForDraw(root)
+
+        assertEquals(PxSize(root.width.px, root.height.px), alignSize.value)
+        assertEquals(PxPosition(0.px, 0.px), alignPosition.value)
+        assertEquals(PxSize(size, size), childSize.value)
+        assertEquals(
+            PxPosition(root.width.px - size, root.height.px - size),
+            childPosition.value
+        )
+    }
+
+    @Test
+    fun test1DAlignedModifier() = withDensity(density) {
+        val sizeDp = 50.dp
+        val size = sizeDp.toIntPx()
+
+        val positionedLatch = CountDownLatch(2)
+        val alignSize = Ref<PxSize>()
+        val alignPosition = Ref<PxPosition>()
+        val childSize = Ref<PxSize>()
+        val childPosition = Ref<PxPosition>()
+        show {
+            Container {
+                SaveLayoutInfo(
+                    size = alignSize,
+                    position = alignPosition,
+                    positionedLatch = positionedLatch
+                )
+                Container(modifier = Aligned.End wraps ExpandedHeight wraps Width(sizeDp)) {
+                    SaveLayoutInfo(
+                        size = childSize,
+                        position = childPosition,
+                        positionedLatch = positionedLatch
+                    )
+                }
+            }
+        }
+        positionedLatch.await(1, TimeUnit.SECONDS)
+
+        val root = findAndroidComposeView()
+        waitForDraw(root)
+
+        assertEquals(PxSize(root.width.px, root.height.px), alignSize.value)
+        assertEquals(PxPosition(0.px, 0.px), alignPosition.value)
+        assertEquals(PxSize(size, root.height.ipx), childSize.value)
+        assertEquals(PxPosition(root.width.px - size, 0.px), childPosition.value)
+    }
+
+    @Test
     fun testAlign_wrapsContent_whenMeasuredWithInfiniteConstraints() = withDensity(density) {
         val sizeDp = 50.dp
         val size = sizeDp.toIntPx()
@@ -131,6 +212,55 @@
         assertEquals(PxPosition(0.px, 0.px), childPosition.value)
     }
 
+    @Test
+    fun testAlignedModifier_wrapsContent_whenMeasuredWithInfiniteConstraints() = withDensity(
+        density
+    ) {
+        val sizeDp = 50.dp
+        val size = sizeDp.toIntPx()
+
+        val positionedLatch = CountDownLatch(2)
+        val alignSize = Ref<PxSize>()
+        val alignPosition = Ref<PxPosition>()
+        val childSize = Ref<PxSize>()
+        val childPosition = Ref<PxPosition>()
+        show {
+            Layout(
+                children = {
+                    Container {
+                        SaveLayoutInfo(
+                            size = alignSize,
+                            position = alignPosition,
+                            positionedLatch = positionedLatch
+                        )
+                        Container(modifier = Aligned.BottomRight wraps Size(sizeDp, sizeDp)) {
+                            SaveLayoutInfo(
+                                size = childSize,
+                                position = childPosition,
+                                positionedLatch = positionedLatch
+                            )
+                        }
+                    }
+                },
+                measureBlock = { measurables, constraints ->
+                    val placeable = measurables.first().measure(Constraints())
+                    layout(constraints.maxWidth, constraints.maxHeight) {
+                        placeable.place(0.ipx, 0.ipx)
+                    }
+                }
+            )
+        }
+        positionedLatch.await(1, TimeUnit.SECONDS)
+
+        val root = findAndroidComposeView()
+        waitForDraw(root)
+
+        assertEquals(PxSize(size, size), alignSize.value)
+        assertEquals(PxPosition(0.px, 0.px), alignPosition.value)
+        assertEquals(PxSize(size, size), childSize.value)
+        assertEquals(PxPosition(0.px, 0.px), childPosition.value)
+    }
+
     // TODO(popam): this should be unit test instead
     @Test
     fun testAlignmentCoordinates_evenSize() {
@@ -184,6 +314,61 @@
     }
 
     @Test
+    fun test2DAlignedModifier_hasCorrectIntrinsicMeasurements() = withDensity(density) {
+        testIntrinsics(@Composable {
+            Container(Aligned.TopLeft wraps AspectRatio(2f)) { }
+        }) { minIntrinsicWidth, minIntrinsicHeight, maxIntrinsicWidth, maxIntrinsicHeight ->
+            // Min width.
+            assertEquals(0.ipx, minIntrinsicWidth(0.ipx))
+            assertEquals(25.dp.toIntPx() * 2, minIntrinsicWidth(25.dp.toIntPx()))
+            assertEquals(0.dp.toIntPx(), minIntrinsicWidth(IntPx.Infinity))
+
+            // Min height.
+            assertEquals(0.ipx, minIntrinsicWidth(0.ipx))
+            assertEquals(50.dp.toIntPx() / 2, minIntrinsicHeight(50.dp.toIntPx()))
+            assertEquals(0.dp.toIntPx(), minIntrinsicHeight(IntPx.Infinity))
+
+            // Max width.
+            assertEquals(0.ipx, minIntrinsicWidth(0.ipx))
+            assertEquals(25.dp.toIntPx() * 2, maxIntrinsicWidth(25.dp.toIntPx()))
+            assertEquals(0.dp.toIntPx(), maxIntrinsicWidth(IntPx.Infinity))
+
+            // Max height.
+            assertEquals(0.ipx, minIntrinsicWidth(0.ipx))
+            assertEquals(50.dp.toIntPx() / 2, maxIntrinsicHeight(50.dp.toIntPx()))
+            assertEquals(0.dp.toIntPx(), maxIntrinsicHeight(IntPx.Infinity))
+        }
+    }
+
+    @Test
+    fun test1DAlignedModifier_hasCorrectIntrinsicMeasurements() = withDensity(density) {
+        testIntrinsics(@Composable {
+            Container(Aligned.CenterVertically wraps AspectRatio(2f)) { }
+        }) { minIntrinsicWidth, minIntrinsicHeight, maxIntrinsicWidth, maxIntrinsicHeight ->
+
+            // Min width.
+            assertEquals(0.ipx, minIntrinsicWidth(0.ipx))
+            assertEquals(25.dp.toIntPx() * 2, minIntrinsicWidth(25.dp.toIntPx()))
+            assertEquals(0.dp.toIntPx(), minIntrinsicWidth(IntPx.Infinity))
+
+            // Min height.
+            assertEquals(0.ipx, minIntrinsicWidth(0.ipx))
+            assertEquals(50.dp.toIntPx() / 2, minIntrinsicHeight(50.dp.toIntPx()))
+            assertEquals(0.dp.toIntPx(), minIntrinsicHeight(IntPx.Infinity))
+
+            // Max width.
+            assertEquals(0.ipx, minIntrinsicWidth(0.ipx))
+            assertEquals(25.dp.toIntPx() * 2, maxIntrinsicWidth(25.dp.toIntPx()))
+            assertEquals(0.dp.toIntPx(), maxIntrinsicWidth(IntPx.Infinity))
+
+            // Max height.
+            assertEquals(0.ipx, minIntrinsicWidth(0.ipx))
+            assertEquals(50.dp.toIntPx() / 2, maxIntrinsicHeight(50.dp.toIntPx()))
+            assertEquals(0.dp.toIntPx(), maxIntrinsicHeight(IntPx.Infinity))
+        }
+    }
+
+    @Test
     fun testAlign_hasCorrectIntrinsicMeasurements_whenNoChildren() = withDensity(density) {
         testIntrinsics(@Composable {
             Align(alignment = Alignment.TopLeft) { }
@@ -257,4 +442,61 @@
             childPosition.value
         )
     }
+
+    @Test
+    fun testAlignedModifier_alignsCorrectly_whenOddDimensions_endAligned() = withDensity(density) {
+        // Given a 100 x 100 pixel container, we want to make sure that when aligning a 1 x 1 pixel
+        // child to both ends (bottom, and right) we correctly position children at the last
+        // possible pixel, and avoid rounding issues. Previously we first centered the coordinates,
+        // and then aligned after, so the maths would actually be (99 / 2) * 2, which incorrectly
+        // ends up at 100 (IntPx rounds up) - so the last pixels in both directions just wouldn't
+        // be visible.
+        val parentSize = 100.ipx.toDp()
+        val childSizeDp = 1.ipx.toDp()
+        val childSizeIpx = childSizeDp.toIntPx()
+
+        val positionedLatch = CountDownLatch(2)
+        val alignSize = Ref<PxSize>()
+        val alignPosition = Ref<PxPosition>()
+        val childSize = Ref<PxSize>()
+        val childPosition = Ref<PxPosition>()
+        show {
+            Layout(
+                children = {
+                    Container(Size(parentSize, parentSize)) {
+                        SaveLayoutInfo(
+                            size = alignSize,
+                            position = alignPosition,
+                            positionedLatch = positionedLatch
+                        )
+                        Container(Aligned.BottomRight wraps Size(childSizeDp, childSizeDp)) {
+                            SaveLayoutInfo(
+                                size = childSize,
+                                position = childPosition,
+                                positionedLatch = positionedLatch
+                            )
+                        }
+                    }
+                }, measureBlock = { measurables, constraints ->
+                    val placeable = measurables.first().measure(Constraints())
+                    layout(constraints.maxWidth, constraints.maxHeight) {
+                        placeable.place(0.ipx, 0.ipx)
+                    }
+                }
+            )
+        }
+        positionedLatch.await(1, TimeUnit.SECONDS)
+
+        val root = findAndroidComposeView()
+        waitForDraw(root)
+
+        assertEquals(PxSize(childSizeIpx, childSizeIpx), childSize.value)
+        assertEquals(
+            PxPosition(
+                alignSize.value!!.width - childSizeIpx,
+                alignSize.value!!.height - childSizeIpx
+            ),
+            childPosition.value
+        )
+    }
 }
diff --git a/ui/ui-layout/src/main/java/androidx/ui/layout/Align.kt b/ui/ui-layout/src/main/java/androidx/ui/layout/Align.kt
index d272906..1ef4221 100644
--- a/ui/ui-layout/src/main/java/androidx/ui/layout/Align.kt
+++ b/ui/ui-layout/src/main/java/androidx/ui/layout/Align.kt
@@ -22,6 +22,11 @@
 import androidx.ui.core.looseMin
 import androidx.compose.Composable
 import androidx.ui.core.Alignment
+import androidx.ui.core.Constraints
+import androidx.ui.core.DensityScope
+import androidx.ui.core.IntPxPosition
+import androidx.ui.core.LayoutModifier
+import androidx.ui.core.ipx
 
 /**
  * A layout that takes a child and aligns it within itself, according to the alignment parameter.
@@ -90,7 +95,7 @@
  * by the parent layout rather than the child itself. Different layout models allow different
  * [Gravity] options. For example, [Row] provides Top and Bottom, while [Column] provides
  * Start and End.
- * Unlike [Align], layout children with [Gravity] are aligned only after the size
+ * Unlike [Aligned], layout children with [Gravity] are aligned only after the size
  * of the parent is known, therefore not affecting the size of the parent in order to achieve
  * their own alignment.
  *
@@ -101,3 +106,160 @@
  * @sample androidx.ui.layout.samples.SimpleGravityInColumn
  */
 object Gravity
+
+/**
+ * Provides alignment options for a target layout where the alignment is handled by the modifier
+ * itself (rather than by the layout's parent). To achieve this, the modifier tries to fill the
+ * available space and align the target layout within itself. If the incoming constraints are
+ * infinite, the modifier will wrap the child instead and the alignment will not be achieved.
+ *
+ * Example usage:
+ *
+ * @sample androidx.ui.layout.samples.SimpleAlignedModifier
+ * @sample androidx.ui.layout.samples.SimpleVerticallyAlignedModifier
+ */
+object Aligned {
+    /**
+     * A layout modifier that positions the target component inside its parent to the top in
+     * vertical direction and wraps the component in horizontal direction.
+     */
+    val Top: LayoutModifier =
+        AlignmentModifier(alignment = Alignment.TopLeft, direction = Direction.Vertical)
+
+    /**
+     * A layout modifier that positions the target component in the center of the parent in
+     * vertical direction and wraps the component in horizontal direction.
+     */
+    val CenterVertically: LayoutModifier =
+        AlignmentModifier(alignment = Alignment.CenterLeft, direction = Direction.Vertical)
+
+    /**
+     * A layout modifier that positions the target component inside its parent to the bottom in
+     * vertical direction and wraps the component in horizontal direction.
+     */
+    val Bottom: LayoutModifier =
+        AlignmentModifier(alignment = Alignment.BottomLeft, direction = Direction.Vertical)
+
+    /**
+     * A layout modifier that positions the target component inside its parent to the start edge
+     * in horizontal direction and wraps the component in vertical direction.
+     */
+    val Start: LayoutModifier =
+        AlignmentModifier(alignment = Alignment.TopLeft, direction = Direction.Horizontal)
+
+    /**
+     * A layout modifier that positions the target component in the center of the parent in
+     * horizontal direction and wraps the component in vertical direction.
+     */
+    val CenterHorizontally: LayoutModifier =
+        AlignmentModifier(alignment = Alignment.TopCenter, direction = Direction.Horizontal)
+
+    /**
+     * A layout modifier that positions the target component inside its parent to the end edge
+     * in horizontal direction and wraps the component in vertical direction.
+     */
+    val End: LayoutModifier =
+        AlignmentModifier(alignment = Alignment.TopRight, direction = Direction.Horizontal)
+
+    /**
+     * A layout modifier that positions the target component top-left inside its parent.
+     */
+    val TopLeft: LayoutModifier =
+        AlignmentModifier(alignment = Alignment.TopLeft, direction = Direction.Both)
+
+    /**
+     * A layout modifier that positions the target component top-center inside its parent.
+     */
+    val TopCenter: LayoutModifier =
+        AlignmentModifier(alignment = Alignment.TopCenter, direction = Direction.Both)
+
+    /**
+     * A layout modifier that positions the target component top-right inside its parent.
+     */
+    val TopRight: LayoutModifier =
+        AlignmentModifier(alignment = Alignment.TopRight, direction = Direction.Both)
+
+    /**
+     * A layout modifier that positions the target component center-left inside its parent.
+     */
+    val CenterLeft: LayoutModifier =
+        AlignmentModifier(alignment = Alignment.CenterLeft, direction = Direction.Both)
+
+    /**
+     * A layout modifier that positions the target component in the center of its parent.
+     */
+    val Center: LayoutModifier =
+        AlignmentModifier(alignment = Alignment.Center, direction = Direction.Both)
+
+    /**
+     * A layout modifier that positions the target component center-right inside its parent.
+     */
+    val CenterRight: LayoutModifier =
+        AlignmentModifier(alignment = Alignment.CenterRight, direction = Direction.Both)
+
+    /**
+     * A layout modifier that positions the target component bottom-left inside its parent.
+     */
+    val BottomLeft: LayoutModifier =
+        AlignmentModifier(alignment = Alignment.BottomLeft, direction = Direction.Both)
+
+    /**
+     * A layout modifier that positions the target component bottom-center inside its parent.
+     */
+    val BottomCenter: LayoutModifier =
+        AlignmentModifier(alignment = Alignment.BottomCenter, direction = Direction.Both)
+
+    /**
+     * A layout modifier that positions the target component bottom-right inside its parent.
+     */
+    val BottomRight: LayoutModifier =
+        AlignmentModifier(alignment = Alignment.BottomRight, direction = Direction.Both)
+}
+
+private enum class Direction {
+    Vertical, Horizontal, Both
+}
+
+private data class AlignmentModifier(
+    private val alignment: Alignment,
+    private val direction: Direction
+) : LayoutModifier {
+    override fun DensityScope.modifyConstraints(constraints: Constraints) = when (direction) {
+        Direction.Both -> constraints.looseMin()
+        Direction.Horizontal -> constraints.copy(minWidth = 0.ipx)
+        Direction.Vertical -> constraints.copy(minHeight = 0.ipx)
+    }
+
+    override fun DensityScope.modifySize(
+        constraints: Constraints,
+        childSize: IntPxSize
+    ): IntPxSize {
+        val width = if (
+            direction != Direction.Vertical && constraints.maxWidth.isFinite()
+        ) {
+            constraints.maxWidth
+        } else {
+            childSize.width
+        }
+        val height = if (
+            direction != Direction.Horizontal && constraints.maxHeight.isFinite()
+        ) {
+            constraints.maxHeight
+        } else {
+            childSize.height
+        }
+        return IntPxSize(width, height)
+    }
+
+    override fun DensityScope.modifyPosition(
+        childSize: IntPxSize,
+        containerSize: IntPxSize
+    ): IntPxPosition {
+        return alignment.align(
+            IntPxSize(
+                containerSize.width - childSize.width,
+                containerSize.height - childSize.height
+            )
+        )
+    }
+}
\ No newline at end of file
diff --git a/ui/ui-layout/src/main/java/androidx/ui/layout/ConstraintLayout.kt b/ui/ui-layout/src/main/java/androidx/ui/layout/ConstraintLayout.kt
new file mode 100644
index 0000000..3632539
--- /dev/null
+++ b/ui/ui-layout/src/main/java/androidx/ui/layout/ConstraintLayout.kt
@@ -0,0 +1,683 @@
+/*
+ * Copyright 2019 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.ui.layout.constraintlayout
+
+import androidx.compose.Composable
+import androidx.compose.Immutable
+import androidx.compose.memo
+import androidx.compose.unaryPlus
+import androidx.constraintlayout.solver.state.ConstraintReference
+import androidx.constraintlayout.solver.state.Dimension
+import androidx.constraintlayout.solver.state.State
+import androidx.constraintlayout.solver.state.helpers.BarrierReference
+import androidx.constraintlayout.solver.widgets.ConstraintWidget
+import androidx.constraintlayout.solver.widgets.ConstraintWidgetContainer
+import androidx.constraintlayout.solver.widgets.Optimizer
+import androidx.constraintlayout.solver.widgets.analyzer.BasicMeasure
+import androidx.ui.core.AlignmentLine
+import androidx.ui.core.Constraints
+import androidx.ui.core.DensityScope
+import androidx.ui.core.Dp
+import androidx.ui.core.FirstBaseline
+import androidx.ui.core.IntPx
+import androidx.ui.core.IntPxSize
+import androidx.ui.core.Layout
+import androidx.ui.core.LayoutModifier
+import androidx.ui.core.Measurable
+import androidx.ui.core.Placeable
+import androidx.ui.core.Placeable.PlacementScope.place
+import androidx.ui.core.dp
+import androidx.ui.core.hasBoundedHeight
+import androidx.ui.core.hasBoundedWidth
+import androidx.ui.core.ipx
+
+/**
+ * Layout that positions its children according to the constraints between them.
+ */
+@Composable
+fun ConstraintLayout(constraintSet: ConstraintSet, children: @Composable() () -> Unit) {
+    val measurer = +memo { Measurer() }
+    Layout(children) { measurables, constraints ->
+        val layoutSize = measurer.performMeasure(
+            constraints,
+            constraintSet,
+            measurables,
+            this
+        )
+        layout(layoutSize.width, layoutSize.height) {
+            measurer.performLayout()
+        }
+    }
+}
+
+/**
+ * Immutable description of the constraints used to layout the children of a [ConstraintLayout].
+ */
+@Immutable
+data class ConstraintSet(internal val description: ConstraintSetBuilderScope.() -> Unit)
+
+/**
+ * Builder scope for a [ConstraintSet]. The scope should not be created directly - the
+ * [ConstraintSet] function should be used instead.
+ */
+// TODO(popam): support RTL
+class ConstraintSetBuilderScope internal constructor(internal val state: State) {
+    /**
+     * Creates a reference corresponding to the constraint layout children with a specific tag,
+     * which can be used to define the constraints to be imposed to those children.
+     */
+    fun tag(tag: Any) = tags.getOrPut(tag, { ConstrainedLayoutReference(state, tag) })
+    private val tags = mutableMapOf<Any, ConstrainedLayoutReference>()
+
+    /**
+     * Reference to the [ConstraintLayout] itself, which can be used to specify constraints
+     * between itself and its children.
+     */
+    val parent = ConstrainedLayoutReference(state, State.PARENT)
+
+    class ConstrainedLayoutReference internal constructor(val state: State, val tag: Any) {
+        val left = VerticalAnchor.ConstrainedLayoutAnchor(state, this, 0)
+        val top = HorizontalAnchor.ConstrainedLayoutAnchor(state, this, 0)
+        var right = VerticalAnchor.ConstrainedLayoutAnchor(state, this, 1)
+        var bottom = HorizontalAnchor.ConstrainedLayoutAnchor(state, this, 1)
+        var baseline = ConstrainedLayoutBaselineAnchor(state, this)
+
+        /**
+         * Adds constraints between left, top, right and bottom corresponding anchors of
+         * two layout references.
+         */
+        infix fun constrainTo(other: ConstrainedLayoutReference) {
+            left constrainTo other.left
+            top constrainTo other.top
+            right constrainTo other.right
+            bottom constrainTo other.bottom
+        }
+
+        /**
+         * Adds constraints between left and right corresponding anchors of two layout references.
+         */
+        infix fun constrainHorizontallyTo(other: ConstrainedLayoutReference) {
+            left constrainTo other.left
+            right constrainTo other.right
+        }
+
+        /**
+         * Adds constraints between top and bottom corresponding anchors of two layout references.
+         */
+        infix fun constrainVerticallyTo(other: ConstrainedLayoutReference) {
+            top constrainTo other.top
+            bottom constrainTo other.bottom
+        }
+
+        /**
+         * The horizontal bias of the current layout reference.
+         */
+        // TODO(popam): keep the source of truth in ConstraintReference
+        var horizontalBias: Float = 0.5f
+            set(value) {
+                field = value
+                state.constraints(tag).horizontalBias(value)
+            }
+
+        /**
+         * The vertical bias of the current layout reference.
+         */
+        // TODO(popam): keep the source of truth in ConstraintReference
+        var verticalBias: Float = 0.5f
+            set(value) {
+                field = value
+                state.constraints(tag).verticalBias(value)
+            }
+
+        /**
+         * Centers the layout horizontally in its [parent].
+         */
+        fun centerHorizontally() = state.centerHorizontally(tag).also { it.bias(0.5f) }.apply()
+
+        /**
+         * Centers the layout vertically in its [parent].
+         */
+        fun centerVertically() = state.centerVertically(tag).also { it.bias(0.5f) }.apply()
+
+        /**
+         * Centers the layout in its [parent].
+         */
+        fun center() {
+            centerHorizontally()
+            centerVertically()
+        }
+    }
+
+    /**
+     * Represents a horizontal chain.
+     */
+    class HorizontalChain internal constructor(
+        internal val first: ConstrainedLayoutReference,
+        internal val last: ConstrainedLayoutReference
+    ) {
+        val left: VerticalAnchor.ConstrainedLayoutAnchor get() = first.left
+        val right: VerticalAnchor.ConstrainedLayoutAnchor get() = last.right
+
+        infix fun constrainTo(other: ConstrainedLayoutReference) {
+            left constrainTo other.left
+            right constrainTo other.right
+        }
+    }
+
+    /**
+     * Represents a vertical chain.
+     */
+    class VerticalChain internal constructor(
+        internal val first: ConstrainedLayoutReference,
+        internal val last: ConstrainedLayoutReference
+    ) {
+        val top: HorizontalAnchor.ConstrainedLayoutAnchor get() = first.top
+        val bottom: HorizontalAnchor.ConstrainedLayoutAnchor get() = last.bottom
+
+        infix fun constrainTo(other: ConstrainedLayoutReference) {
+            first.top constrainTo other.top
+            last.bottom constrainTo other.bottom
+        }
+    }
+
+    /**
+     * Defines a vertical anchor which can be used for defining constraints. It can correspond:
+     * - to a side or baseline of a child of the [ConstraintLayout]
+     * - to a left barrier or right barrier
+     * - to a vertical guideline
+     */
+    sealed class VerticalAnchor {
+        internal abstract val state: State
+        internal abstract val tag: Any
+        internal abstract val index: Int
+
+        /**
+         * Anchor corresponding to the left or right of a child of the [ConstraintLayout].
+         */
+        class ConstrainedLayoutAnchor internal constructor(
+            override val state: State,
+            internal val constrainedLayoutReference: ConstrainedLayoutReference,
+            override val index: Int
+        ) : VerticalAnchor() {
+            override val tag: Any get() = constrainedLayoutReference.tag
+
+            // TODO(popam): keep the source of truth in ConstraintReference
+            /**
+             * The margin to be applied to the current [ConstrainedLayoutAnchor].
+             */
+            var margin: Dp = 0.dp
+                set(value) {
+                    field = value
+                    state.constraints(tag)
+                        .let { if (index == 0) it.start() else it.end() }
+                        .margin(value)
+                }
+
+            /**
+             * Adds a constraint between a [ConstrainedLayoutAnchor] and a [VerticalAnchor].
+             */
+            infix fun constrainTo(other: VerticalAnchor) {
+                with(state.constraints(this.constrainedLayoutReference.tag)) {
+                    val thisIndex = this@ConstrainedLayoutAnchor.index
+                    val otherIndex = other.index
+                    verticalAnchorFunctions[thisIndex][otherIndex].invoke(this, other.tag)
+                }
+            }
+        }
+
+        /**
+         * Anchor corresponding to a vertical guideline.
+         */
+        class GuidelineAnchor internal constructor(
+            override val state: State,
+            override val tag: Any,
+            override val index: Int = 0
+        ) : VerticalAnchor()
+
+        /**
+         * Anchor corresponding to a left or right barrier.
+         */
+        class BarrierAnchor internal constructor(
+            override val state: State,
+            override val tag: Any,
+            private val barrierReference: BarrierReference,
+            override val index: Int = 0
+        ) : VerticalAnchor() {
+            // TODO(popam): keep the source of truth in ConstraintReference
+            /**
+             * The margin to be applied to the current [BarrierAnchor], in the
+             * direction of the barrier.
+             */
+            var margin: Dp = 0.dp
+                set(value) {
+                    field = value
+                    barrierReference.margin(value)
+                }
+        }
+    }
+
+    /**
+     * Defines an horizontal anchor which can be used for defining constraints. It can correspond:
+     * - to a side or baseline of a child of the [ConstraintLayout]
+     * - to a top or bottom barrier
+     * - to a horizontal guideline
+     */
+    sealed class HorizontalAnchor {
+        internal abstract val state: State
+        internal abstract val tag: Any
+        internal abstract val index: Int
+
+        /**
+         * Anchor corresponding to the top or bottom of a child of the [ConstraintLayout].
+         */
+        class ConstrainedLayoutAnchor internal constructor(
+            override val state: State,
+            internal val constrainedLayoutReference: ConstrainedLayoutReference,
+            override val index: Int
+        ) : HorizontalAnchor() {
+            override val tag: Any get() = constrainedLayoutReference.tag
+
+            // TODO(popam): keep the source of truth in ConstraintReference
+            /**
+             * The margin to be applied to the current [ConstrainedLayoutAnchor].
+             */
+            var margin: Dp = 0.dp
+                set(value) {
+                    field = value
+                    state.constraints(tag)
+                        .let { if (index == 0) it.top() else it.bottom() }
+                        .margin(value)
+                }
+
+            /**
+             * Adds a constraint between a [ConstrainedLayoutAnchor] and a [HorizontalAnchor].
+             */
+            infix fun constrainTo(other: HorizontalAnchor) {
+                with(state.constraints(this.constrainedLayoutReference.tag)) {
+                    val thisIndex = this@ConstrainedLayoutAnchor.index
+                    val otherIndex = other.index
+                    horizontalAnchorFunctions[thisIndex][otherIndex].invoke(this, other.tag)
+                }
+            }
+        }
+
+        /**
+         * Anchor corresponding to a horizontal guideline.
+         */
+        class GuidelineAnchor internal constructor(
+            override val state: State,
+            override val tag: Any,
+            override val index: Int = 0
+        ) : HorizontalAnchor()
+
+        /**
+         * Anchor corresponding to a top or bottom barrier.
+         */
+        class BarrierAnchor internal constructor(
+            override val state: State,
+            override val tag: Any,
+            private val barrierReference: BarrierReference,
+            override val index: Int = 0
+        ) : HorizontalAnchor() {
+            // TODO(popam): keep the source of truth in ConstraintReference
+            var margin: Dp = 0.dp
+                set(value) {
+                    field = value
+                    barrierReference.margin(value)
+                }
+        }
+    }
+
+    /**
+     * Anchor corresponding to the baseline of a [ConstraintLayout] child.
+     */
+    class ConstrainedLayoutBaselineAnchor internal constructor(
+        val state: State,
+        val tag: Any
+    ) {
+        /**
+         * Adds a constraint between two [ConstrainedLayoutBaselineAnchor] anchors.
+         */
+        infix fun constrainTo(other: ConstrainedLayoutBaselineAnchor) {
+            with(state.constraints(tag)) {
+                baselineAnchorFunction.invoke(this, other.tag)
+            }
+        }
+    }
+
+    /**
+     * Creates a horizontal chain including the referenced layouts.
+     */
+    fun createHorizontalChain(
+        vararg elements: ConstrainedLayoutReference,
+        chainStyle: ChainStyle = ChainStyle.Spread
+    ): HorizontalChain {
+        state.horizontalChain(*(elements.map { it.tag }.toTypedArray()))
+            .also { it.style(chainStyle.style) }
+            .apply()
+        if (chainStyle.bias != null) elements[0].horizontalBias = chainStyle.bias
+        return HorizontalChain(elements.first(), elements.last())
+    }
+
+    /**
+     * Creates a vertical chain including the referenced layouts.
+     */
+    fun createVerticalChain(
+        vararg elements: ConstrainedLayoutReference,
+        chainStyle: ChainStyle = ChainStyle.Spread
+    ): VerticalChain {
+        state.verticalChain(*(elements.map { it.tag }.toTypedArray()))
+            .also { it.style(chainStyle.style) }
+            .apply()
+        if (chainStyle.bias != null) elements[0].verticalBias = chainStyle.bias
+        return VerticalChain(elements.first(), elements.last())
+    }
+
+    /**
+     * The style of a horizontal or vertical chain.
+     */
+    class ChainStyle internal constructor(
+        internal val style: State.Chain,
+        internal val bias: Float? = null
+    ) {
+        companion object {
+            val Spread = ChainStyle(State.Chain.SPREAD)
+            val SpreadInside = ChainStyle(State.Chain.SPREAD_INSIDE)
+            val Packed = Packed(0.5f)
+            fun Packed(bias: Float) = ChainStyle(State.Chain.PACKED, bias)
+        }
+    }
+
+    /**
+     * Creates a guideline at a specific offset from the left of the [ConstraintLayout].
+     */
+    fun createGuidelineFromLeft(offset: Dp): VerticalAnchor.GuidelineAnchor {
+        val tag = object : Any() {}
+        state.verticalGuideline(tag).apply { start(offset) }
+        return VerticalAnchor.GuidelineAnchor(state, tag)
+    }
+
+    /**
+     * Creates a guideline at a width percentage from the left of the [ConstraintLayout].
+     */
+    fun createGuidelineFromLeft(percent: Float): VerticalAnchor.GuidelineAnchor {
+        val tag = object : Any() {}
+        state.verticalGuideline(tag).apply { percent(percent) }
+        return VerticalAnchor.GuidelineAnchor(state, tag)
+    }
+
+    /**
+     * Creates a guideline at a specific offset from the right of the [ConstraintLayout].
+     */
+    fun createGuidelineFromRight(offset: Dp): VerticalAnchor.GuidelineAnchor {
+        val tag = object : Any() {}
+        state.verticalGuideline(tag).apply { end(offset) }
+        return VerticalAnchor.GuidelineAnchor(state, tag)
+    }
+
+    /**
+     * Creates a guideline at a width percentage from the right of the [ConstraintLayout].
+     */
+    fun createGuidelineFromRight(percent: Float): VerticalAnchor.GuidelineAnchor {
+        return createGuidelineFromLeft(1f - percent)
+    }
+
+    /**
+     * Creates a guideline at a specific offset from the top of the [ConstraintLayout].
+     */
+    fun createGuidelineFromTop(offset: Dp): HorizontalAnchor.GuidelineAnchor {
+        val tag = object : Any() {}
+        state.horizontalGuideline(tag).apply { start(offset) }
+        return HorizontalAnchor.GuidelineAnchor(state, tag)
+    }
+
+    /**
+     * Creates a guideline at a height percentage from the top of the [ConstraintLayout].
+     */
+    fun createGuidelineFromTop(percent: Float): HorizontalAnchor.GuidelineAnchor {
+        val tag = object : Any() {}
+        state.horizontalGuideline(tag).apply { percent(percent) }
+        return HorizontalAnchor.GuidelineAnchor(state, tag)
+    }
+
+    /**
+     * Creates a guideline at a specific offset from the bottom of the [ConstraintLayout].
+     */
+    fun createGuidelineFromBottom(offset: Dp): HorizontalAnchor.GuidelineAnchor {
+        val tag = object : Any() {}
+        state.horizontalGuideline(tag).apply { end(offset) }
+        return HorizontalAnchor.GuidelineAnchor(state, tag)
+    }
+
+    /**
+     * Creates a guideline at a height percentage from the bottom of the [ConstraintLayout].
+     */
+    fun createGuidelineFromBottom(percent: Float): HorizontalAnchor.GuidelineAnchor {
+        return createGuidelineFromTop(1f - percent)
+    }
+
+    /**
+     * Creates and returns a top barrier, containing the specified elements.
+     */
+    fun createTopBarrier(
+        vararg elements: ConstrainedLayoutReference
+    ): HorizontalAnchor.BarrierAnchor {
+        val tag = object : Any() {}
+        val barrier = state.barrier(tag, State.Direction.TOP).apply {
+            add(*(elements.map { it.tag }.toTypedArray()))
+        }
+        return HorizontalAnchor.BarrierAnchor(state, tag, barrier)
+    }
+
+    /**
+     * Creates and returns a bottom barrier, containing the specified elements.
+     */
+    fun createBottomBarrier(
+        vararg elements: ConstrainedLayoutReference
+    ): HorizontalAnchor.BarrierAnchor {
+        val tag = object : Any() {}
+        val barrier = state.barrier(tag, State.Direction.BOTTOM).apply {
+            add(*(elements.map { it.tag }.toTypedArray()))
+        }
+        return HorizontalAnchor.BarrierAnchor(state, tag, barrier)
+    }
+
+    /**
+     * Creates and returns a left barrier, containing the specified elements.
+     */
+    fun createLeftBarrier(
+        vararg elements: ConstrainedLayoutReference
+    ): VerticalAnchor.BarrierAnchor {
+        val tag = object : Any() {}
+        val barrier = state.barrier(tag, State.Direction.START).apply {
+            add(*(elements.map { it.tag }.toTypedArray()))
+        }
+        return VerticalAnchor.BarrierAnchor(state, tag, barrier)
+    }
+
+    /**
+     * Creates and returns a right barrier, containing the specified elements.
+     */
+    fun createRightBarrier(
+        vararg elements: ConstrainedLayoutReference
+    ): VerticalAnchor.BarrierAnchor {
+        val tag = object : Any() {}
+        val barrier = state.barrier(tag, State.Direction.END).apply {
+            add(*(elements.map { it.tag }.toTypedArray()))
+        }
+        return VerticalAnchor.BarrierAnchor(state, tag, barrier)
+    }
+
+    // TODO(popam): support these
+    val WrapDimension = Dimension.WRAP_DIMENSION
+    val SpreadDimension = Dimension.SPREAD_DIMENSION
+    val ParentDimension = Dimension.PARENT_DIMENSION
+
+    internal companion object {
+        val verticalAnchorFunctions: Array<Array<ConstraintReference.(Any) -> Unit>> = arrayOf(
+            arrayOf(
+                { other -> startToStart(other).apply() },
+                { other -> startToEnd(other).apply() }
+            ),
+            arrayOf(
+                { other -> endToStart(other) },
+                { other -> endToEnd(other) }
+            )
+        )
+        val horizontalAnchorFunctions: Array<Array<ConstraintReference.(Any) -> Unit>> = arrayOf(
+            arrayOf(
+                { other -> topToTop(other) },
+                { other -> topToBottom(other) }
+            ),
+            arrayOf(
+                { other -> bottomToTop(other) },
+                { other -> bottomToBottom(other) }
+            )
+        )
+        val baselineAnchorFunction: ConstraintReference.(Any) -> Unit =
+            { other -> baselineToBaseline(other) }
+    }
+}
+
+/**
+ * Creates a tag that can be used to identify a measurable / child.
+ * TODO(popam): should not be ConstraintLayout specific
+ */
+fun Tag(tag: Any): LayoutModifier = TagModifier(tag)
+
+/**
+ * Returns the tag associated to a measurable using the [Tag] modifier.
+ */
+val Measurable.tag get() = (parentData as? TagModifier)?.tag
+
+private class Measurer internal constructor() : BasicMeasure.Measurer {
+    private val root = ConstraintWidgetContainer(0, 0).also { it.measurer = this }
+    private val placeables = mutableMapOf<Measurable, Placeable>()
+    private lateinit var densityScope: DensityScope
+    private val state = object : State() {
+        override fun convertDimension(value: Any?): Int {
+            return if (value is Dp) {
+                with(densityScope) { value.toIntPx().value }
+            } else {
+                super.convertDimension(value)
+            }
+        }
+    }
+
+    override fun measure(constraintWidget: ConstraintWidget, measure: BasicMeasure.Measure) {
+        val measurable = constraintWidget.companionWidget
+        if (measurable !is Measurable) return
+
+        var measuredWidth = constraintWidget.width
+        var measuredHeight = constraintWidget.height
+
+        val constraints = Constraints(
+            if (measure.wrapsHorizontal) 0.ipx else constraintWidget.width.ipx,
+            if (measure.wrapsHorizontal) IntPx.Infinity else constraintWidget.width.ipx,
+            if (measure.wrapsVertical) 0.ipx else constraintWidget.height.ipx,
+            if (measure.wrapsVertical) IntPx.Infinity else constraintWidget.height.ipx
+        )
+
+        val placeable = measurable.measure(constraints).also { placeables[measurable] = it }
+
+        if (measure.wrapsHorizontal) {
+            measuredWidth = placeable.width.value
+        }
+        if (measure.wrapsVertical) {
+            measuredHeight = placeable.height.value
+        }
+
+        measure.measuredWidth = measuredWidth
+        measure.measuredHeight = measuredHeight
+        val baseline = placeable[FirstBaseline]
+        if (baseline != null) {
+            measure.measuredBaseline = baseline.value
+        } else {
+            measure.measuredBaseline = measuredHeight
+        }
+    }
+
+    fun performMeasure(
+        constraints: Constraints,
+        constraintSet: ConstraintSet,
+        measurables: List<Measurable>,
+        densityScope: DensityScope
+    ): IntPxSize {
+        this.densityScope = densityScope
+        state.reset()
+        measurables.forEach { measurable ->
+            state.map(measurable.tag ?: object : Any() {}, measurable)
+        }
+        state.width(if (constraints.hasBoundedWidth) {
+            Dimension.Fixed(constraints.maxWidth.value)
+        } else {
+            Dimension.Wrap()
+        })
+        state.height(if (constraints.hasBoundedHeight) {
+            Dimension.Fixed(constraints.maxHeight.value)
+        } else {
+            Dimension.Wrap()
+        })
+        constraintSet.description(ConstraintSetBuilderScope(state))
+        state.apply(root)
+
+        root.minWidth = constraints.minWidth.value
+        root.minHeight = constraints.minHeight.value
+        root.measure(
+            Optimizer.OPTIMIZATION_NONE,
+            if (constraints.hasBoundedWidth) BasicMeasure.EXACTLY else BasicMeasure.WRAP_CONTENT,
+            if (constraints.hasBoundedWidth) constraints.maxWidth.value else 0,
+            if (constraints.hasBoundedHeight) BasicMeasure.EXACTLY else BasicMeasure.WRAP_CONTENT,
+            if (constraints.hasBoundedHeight) constraints.maxHeight.value else 0,
+            0,
+            0,
+            0,
+            0
+        )
+        return IntPxSize(root.width.ipx, root.height.ipx)
+    }
+
+    fun performLayout() {
+        for (child in root.children) {
+            val measurable = child.companionWidget
+            if (measurable !is Measurable) continue
+            placeables[measurable]?.place(IntPx(child.x), IntPx(child.y))
+        }
+    }
+
+    override fun didMeasures() { }
+
+    private val BasicMeasure.Measure.wrapsHorizontal
+        get() = horizontalBehavior == ConstraintWidget.DimensionBehaviour.WRAP_CONTENT
+    private val BasicMeasure.Measure.wrapsVertical
+        get() = verticalBehavior == ConstraintWidget.DimensionBehaviour.WRAP_CONTENT
+}
+
+private data class TagModifier(val tag: Any) : LayoutModifier {
+    override fun DensityScope.modifyConstraints(constraints: Constraints) = constraints
+    override fun DensityScope.modifySize(constraints: Constraints, childSize: IntPxSize) = childSize
+    override fun DensityScope.minIntrinsicWidthOf(measurable: Measurable, height: IntPx) =
+        measurable.minIntrinsicWidth(height)
+    override fun DensityScope.maxIntrinsicWidthOf(measurable: Measurable, height: IntPx) =
+        measurable.maxIntrinsicWidth(height)
+    override fun DensityScope.minIntrinsicHeightOf(measurable: Measurable, width: IntPx) =
+        measurable.minIntrinsicHeight(width)
+    override fun DensityScope.maxIntrinsicHeightOf(measurable: Measurable, width: IntPx) =
+        measurable.maxIntrinsicHeight(width)
+    override fun DensityScope.modifyAlignmentLine(line: AlignmentLine, value: IntPx?) = value
+    override fun DensityScope.modifyParentData(parentData: Any?) = this@TagModifier
+}
diff --git a/ui/ui-layout/src/main/java/androidx/ui/layout/Spacing.kt b/ui/ui-layout/src/main/java/androidx/ui/layout/Spacing.kt
index 550d78e..ff997af 100644
--- a/ui/ui-layout/src/main/java/androidx/ui/layout/Spacing.kt
+++ b/ui/ui-layout/src/main/java/androidx/ui/layout/Spacing.kt
@@ -81,10 +81,9 @@
     )
 
     override fun DensityScope.modifyPosition(
-        childPosition: IntPxPosition,
         childSize: IntPxSize,
         containerSize: IntPxSize
-    ) = IntPxPosition(left.toIntPx() + childPosition.x, top.toIntPx() + childPosition.y)
+    ) = IntPxPosition(left.toIntPx(), top.toIntPx())
 }
 
 /**
diff --git a/ui/ui-material/api/0.1.0-dev03.txt b/ui/ui-material/api/0.1.0-dev03.txt
index 0733899..26a3d17 100644
--- a/ui/ui-material/api/0.1.0-dev03.txt
+++ b/ui/ui-material/api/0.1.0-dev03.txt
@@ -70,7 +70,8 @@
 
   public final class ColorKt {
     ctor public ColorKt();
-    method public static androidx.ui.material.ColorPalette ColorPalette(androidx.ui.graphics.Color primary = Color(4284612846), androidx.ui.graphics.Color primaryVariant = Color(4281794739), androidx.ui.graphics.Color secondary = Color(4278442694), androidx.ui.graphics.Color secondaryVariant = Color(4278290310), androidx.ui.graphics.Color background = Color.White, androidx.ui.graphics.Color surface = Color.White, androidx.ui.graphics.Color error = Color(4289724448), androidx.ui.graphics.Color onPrimary = Color.White, androidx.ui.graphics.Color onSecondary = Color.Black, androidx.ui.graphics.Color onBackground = Color.Black, androidx.ui.graphics.Color onSurface = Color.Black, androidx.ui.graphics.Color onError = Color.White);
+    method public static androidx.ui.material.ColorPalette darkColorPalette(androidx.ui.graphics.Color primary = Color(4290479868), androidx.ui.graphics.Color primaryVariant = Color(4281794739), androidx.ui.graphics.Color secondary = Color(4278442694), androidx.ui.graphics.Color background = Color(4279374354), androidx.ui.graphics.Color surface = Color(4279374354), androidx.ui.graphics.Color error = Color(4291782265), androidx.ui.graphics.Color onPrimary = Color.Black, androidx.ui.graphics.Color onSecondary = Color.Black, androidx.ui.graphics.Color onBackground = Color.White, androidx.ui.graphics.Color onSurface = Color.White, androidx.ui.graphics.Color onError = Color.Black);
+    method public static androidx.ui.material.ColorPalette lightColorPalette(androidx.ui.graphics.Color primary = Color(4284612846), androidx.ui.graphics.Color primaryVariant = Color(4281794739), androidx.ui.graphics.Color secondary = Color(4278442694), androidx.ui.graphics.Color secondaryVariant = Color(4278290310), androidx.ui.graphics.Color background = Color.White, androidx.ui.graphics.Color surface = Color.White, androidx.ui.graphics.Color error = Color(4289724448), androidx.ui.graphics.Color onPrimary = Color.White, androidx.ui.graphics.Color onSecondary = Color.Black, androidx.ui.graphics.Color onBackground = Color.Black, androidx.ui.graphics.Color onSurface = Color.Black, androidx.ui.graphics.Color onError = Color.White);
   }
 
   public interface ColorPalette {
@@ -86,8 +87,10 @@
     method public androidx.ui.graphics.Color getSecondary();
     method public androidx.ui.graphics.Color getSecondaryVariant();
     method public androidx.ui.graphics.Color getSurface();
+    method public boolean isLight();
     property public abstract androidx.ui.graphics.Color background;
     property public abstract androidx.ui.graphics.Color error;
+    property public abstract boolean isLight;
     property public abstract androidx.ui.graphics.Color onBackground;
     property public abstract androidx.ui.graphics.Color onError;
     property public abstract androidx.ui.graphics.Color onPrimary;
@@ -161,13 +164,9 @@
 
   public final class FloatingActionButtonKt {
     ctor public FloatingActionButtonKt();
-    method public static void FloatingActionButton(androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.core.Dp minSize = FabSize, androidx.ui.engine.geometry.Shape shape = CircleShape, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method public static void FloatingActionButton(androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.core.Dp minSize = androidx.ui.material.FloatingActionButtonKt.FabSize, androidx.ui.engine.geometry.Shape shape = CircleShape, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method public static void FloatingActionButton(androidx.ui.graphics.Image icon, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.engine.geometry.Shape shape = CircleShape, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp);
     method public static void FloatingActionButton(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.graphics.Image? icon = null, androidx.ui.text.TextStyle? textStyle = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp);
-    method public static androidx.ui.core.Dp getExtendedFabHeight();
-    method public static androidx.ui.core.Dp getExtendedFabIconPadding();
-    method public static androidx.ui.core.Dp getExtendedFabTextPadding();
-    method public static androidx.ui.core.Dp getFabSize();
   }
 
   public final class ListItemKt {
@@ -185,7 +184,7 @@
 
   public final class MaterialThemeKt {
     ctor public MaterialThemeKt();
-    method public static void MaterialTheme(androidx.ui.material.ColorPalette colors = ColorPalette(), androidx.ui.material.Typography typography = androidx.ui.material.Typography(), kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method public static void MaterialTheme(androidx.ui.material.ColorPalette colors = lightColorPalette(), androidx.ui.material.Typography typography = androidx.ui.material.Typography(), kotlin.jvm.functions.Function0<kotlin.Unit> children);
   }
 
   public final class ProgressIndicatorKt {
diff --git a/ui/ui-material/api/current.txt b/ui/ui-material/api/current.txt
index 0733899..26a3d17 100644
--- a/ui/ui-material/api/current.txt
+++ b/ui/ui-material/api/current.txt
@@ -70,7 +70,8 @@
 
   public final class ColorKt {
     ctor public ColorKt();
-    method public static androidx.ui.material.ColorPalette ColorPalette(androidx.ui.graphics.Color primary = Color(4284612846), androidx.ui.graphics.Color primaryVariant = Color(4281794739), androidx.ui.graphics.Color secondary = Color(4278442694), androidx.ui.graphics.Color secondaryVariant = Color(4278290310), androidx.ui.graphics.Color background = Color.White, androidx.ui.graphics.Color surface = Color.White, androidx.ui.graphics.Color error = Color(4289724448), androidx.ui.graphics.Color onPrimary = Color.White, androidx.ui.graphics.Color onSecondary = Color.Black, androidx.ui.graphics.Color onBackground = Color.Black, androidx.ui.graphics.Color onSurface = Color.Black, androidx.ui.graphics.Color onError = Color.White);
+    method public static androidx.ui.material.ColorPalette darkColorPalette(androidx.ui.graphics.Color primary = Color(4290479868), androidx.ui.graphics.Color primaryVariant = Color(4281794739), androidx.ui.graphics.Color secondary = Color(4278442694), androidx.ui.graphics.Color background = Color(4279374354), androidx.ui.graphics.Color surface = Color(4279374354), androidx.ui.graphics.Color error = Color(4291782265), androidx.ui.graphics.Color onPrimary = Color.Black, androidx.ui.graphics.Color onSecondary = Color.Black, androidx.ui.graphics.Color onBackground = Color.White, androidx.ui.graphics.Color onSurface = Color.White, androidx.ui.graphics.Color onError = Color.Black);
+    method public static androidx.ui.material.ColorPalette lightColorPalette(androidx.ui.graphics.Color primary = Color(4284612846), androidx.ui.graphics.Color primaryVariant = Color(4281794739), androidx.ui.graphics.Color secondary = Color(4278442694), androidx.ui.graphics.Color secondaryVariant = Color(4278290310), androidx.ui.graphics.Color background = Color.White, androidx.ui.graphics.Color surface = Color.White, androidx.ui.graphics.Color error = Color(4289724448), androidx.ui.graphics.Color onPrimary = Color.White, androidx.ui.graphics.Color onSecondary = Color.Black, androidx.ui.graphics.Color onBackground = Color.Black, androidx.ui.graphics.Color onSurface = Color.Black, androidx.ui.graphics.Color onError = Color.White);
   }
 
   public interface ColorPalette {
@@ -86,8 +87,10 @@
     method public androidx.ui.graphics.Color getSecondary();
     method public androidx.ui.graphics.Color getSecondaryVariant();
     method public androidx.ui.graphics.Color getSurface();
+    method public boolean isLight();
     property public abstract androidx.ui.graphics.Color background;
     property public abstract androidx.ui.graphics.Color error;
+    property public abstract boolean isLight;
     property public abstract androidx.ui.graphics.Color onBackground;
     property public abstract androidx.ui.graphics.Color onError;
     property public abstract androidx.ui.graphics.Color onPrimary;
@@ -161,13 +164,9 @@
 
   public final class FloatingActionButtonKt {
     ctor public FloatingActionButtonKt();
-    method public static void FloatingActionButton(androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.core.Dp minSize = FabSize, androidx.ui.engine.geometry.Shape shape = CircleShape, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method public static void FloatingActionButton(androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.core.Dp minSize = androidx.ui.material.FloatingActionButtonKt.FabSize, androidx.ui.engine.geometry.Shape shape = CircleShape, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method public static void FloatingActionButton(androidx.ui.graphics.Image icon, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.engine.geometry.Shape shape = CircleShape, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp);
     method public static void FloatingActionButton(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.graphics.Image? icon = null, androidx.ui.text.TextStyle? textStyle = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp);
-    method public static androidx.ui.core.Dp getExtendedFabHeight();
-    method public static androidx.ui.core.Dp getExtendedFabIconPadding();
-    method public static androidx.ui.core.Dp getExtendedFabTextPadding();
-    method public static androidx.ui.core.Dp getFabSize();
   }
 
   public final class ListItemKt {
@@ -185,7 +184,7 @@
 
   public final class MaterialThemeKt {
     ctor public MaterialThemeKt();
-    method public static void MaterialTheme(androidx.ui.material.ColorPalette colors = ColorPalette(), androidx.ui.material.Typography typography = androidx.ui.material.Typography(), kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method public static void MaterialTheme(androidx.ui.material.ColorPalette colors = lightColorPalette(), androidx.ui.material.Typography typography = androidx.ui.material.Typography(), kotlin.jvm.functions.Function0<kotlin.Unit> children);
   }
 
   public final class ProgressIndicatorKt {
diff --git a/ui/ui-material/api/public_plus_experimental_0.1.0-dev03.txt b/ui/ui-material/api/public_plus_experimental_0.1.0-dev03.txt
index 0733899..26a3d17 100644
--- a/ui/ui-material/api/public_plus_experimental_0.1.0-dev03.txt
+++ b/ui/ui-material/api/public_plus_experimental_0.1.0-dev03.txt
@@ -70,7 +70,8 @@
 
   public final class ColorKt {
     ctor public ColorKt();
-    method public static androidx.ui.material.ColorPalette ColorPalette(androidx.ui.graphics.Color primary = Color(4284612846), androidx.ui.graphics.Color primaryVariant = Color(4281794739), androidx.ui.graphics.Color secondary = Color(4278442694), androidx.ui.graphics.Color secondaryVariant = Color(4278290310), androidx.ui.graphics.Color background = Color.White, androidx.ui.graphics.Color surface = Color.White, androidx.ui.graphics.Color error = Color(4289724448), androidx.ui.graphics.Color onPrimary = Color.White, androidx.ui.graphics.Color onSecondary = Color.Black, androidx.ui.graphics.Color onBackground = Color.Black, androidx.ui.graphics.Color onSurface = Color.Black, androidx.ui.graphics.Color onError = Color.White);
+    method public static androidx.ui.material.ColorPalette darkColorPalette(androidx.ui.graphics.Color primary = Color(4290479868), androidx.ui.graphics.Color primaryVariant = Color(4281794739), androidx.ui.graphics.Color secondary = Color(4278442694), androidx.ui.graphics.Color background = Color(4279374354), androidx.ui.graphics.Color surface = Color(4279374354), androidx.ui.graphics.Color error = Color(4291782265), androidx.ui.graphics.Color onPrimary = Color.Black, androidx.ui.graphics.Color onSecondary = Color.Black, androidx.ui.graphics.Color onBackground = Color.White, androidx.ui.graphics.Color onSurface = Color.White, androidx.ui.graphics.Color onError = Color.Black);
+    method public static androidx.ui.material.ColorPalette lightColorPalette(androidx.ui.graphics.Color primary = Color(4284612846), androidx.ui.graphics.Color primaryVariant = Color(4281794739), androidx.ui.graphics.Color secondary = Color(4278442694), androidx.ui.graphics.Color secondaryVariant = Color(4278290310), androidx.ui.graphics.Color background = Color.White, androidx.ui.graphics.Color surface = Color.White, androidx.ui.graphics.Color error = Color(4289724448), androidx.ui.graphics.Color onPrimary = Color.White, androidx.ui.graphics.Color onSecondary = Color.Black, androidx.ui.graphics.Color onBackground = Color.Black, androidx.ui.graphics.Color onSurface = Color.Black, androidx.ui.graphics.Color onError = Color.White);
   }
 
   public interface ColorPalette {
@@ -86,8 +87,10 @@
     method public androidx.ui.graphics.Color getSecondary();
     method public androidx.ui.graphics.Color getSecondaryVariant();
     method public androidx.ui.graphics.Color getSurface();
+    method public boolean isLight();
     property public abstract androidx.ui.graphics.Color background;
     property public abstract androidx.ui.graphics.Color error;
+    property public abstract boolean isLight;
     property public abstract androidx.ui.graphics.Color onBackground;
     property public abstract androidx.ui.graphics.Color onError;
     property public abstract androidx.ui.graphics.Color onPrimary;
@@ -161,13 +164,9 @@
 
   public final class FloatingActionButtonKt {
     ctor public FloatingActionButtonKt();
-    method public static void FloatingActionButton(androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.core.Dp minSize = FabSize, androidx.ui.engine.geometry.Shape shape = CircleShape, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method public static void FloatingActionButton(androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.core.Dp minSize = androidx.ui.material.FloatingActionButtonKt.FabSize, androidx.ui.engine.geometry.Shape shape = CircleShape, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method public static void FloatingActionButton(androidx.ui.graphics.Image icon, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.engine.geometry.Shape shape = CircleShape, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp);
     method public static void FloatingActionButton(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.graphics.Image? icon = null, androidx.ui.text.TextStyle? textStyle = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp);
-    method public static androidx.ui.core.Dp getExtendedFabHeight();
-    method public static androidx.ui.core.Dp getExtendedFabIconPadding();
-    method public static androidx.ui.core.Dp getExtendedFabTextPadding();
-    method public static androidx.ui.core.Dp getFabSize();
   }
 
   public final class ListItemKt {
@@ -185,7 +184,7 @@
 
   public final class MaterialThemeKt {
     ctor public MaterialThemeKt();
-    method public static void MaterialTheme(androidx.ui.material.ColorPalette colors = ColorPalette(), androidx.ui.material.Typography typography = androidx.ui.material.Typography(), kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method public static void MaterialTheme(androidx.ui.material.ColorPalette colors = lightColorPalette(), androidx.ui.material.Typography typography = androidx.ui.material.Typography(), kotlin.jvm.functions.Function0<kotlin.Unit> children);
   }
 
   public final class ProgressIndicatorKt {
diff --git a/ui/ui-material/api/public_plus_experimental_current.txt b/ui/ui-material/api/public_plus_experimental_current.txt
index 0733899..26a3d17 100644
--- a/ui/ui-material/api/public_plus_experimental_current.txt
+++ b/ui/ui-material/api/public_plus_experimental_current.txt
@@ -70,7 +70,8 @@
 
   public final class ColorKt {
     ctor public ColorKt();
-    method public static androidx.ui.material.ColorPalette ColorPalette(androidx.ui.graphics.Color primary = Color(4284612846), androidx.ui.graphics.Color primaryVariant = Color(4281794739), androidx.ui.graphics.Color secondary = Color(4278442694), androidx.ui.graphics.Color secondaryVariant = Color(4278290310), androidx.ui.graphics.Color background = Color.White, androidx.ui.graphics.Color surface = Color.White, androidx.ui.graphics.Color error = Color(4289724448), androidx.ui.graphics.Color onPrimary = Color.White, androidx.ui.graphics.Color onSecondary = Color.Black, androidx.ui.graphics.Color onBackground = Color.Black, androidx.ui.graphics.Color onSurface = Color.Black, androidx.ui.graphics.Color onError = Color.White);
+    method public static androidx.ui.material.ColorPalette darkColorPalette(androidx.ui.graphics.Color primary = Color(4290479868), androidx.ui.graphics.Color primaryVariant = Color(4281794739), androidx.ui.graphics.Color secondary = Color(4278442694), androidx.ui.graphics.Color background = Color(4279374354), androidx.ui.graphics.Color surface = Color(4279374354), androidx.ui.graphics.Color error = Color(4291782265), androidx.ui.graphics.Color onPrimary = Color.Black, androidx.ui.graphics.Color onSecondary = Color.Black, androidx.ui.graphics.Color onBackground = Color.White, androidx.ui.graphics.Color onSurface = Color.White, androidx.ui.graphics.Color onError = Color.Black);
+    method public static androidx.ui.material.ColorPalette lightColorPalette(androidx.ui.graphics.Color primary = Color(4284612846), androidx.ui.graphics.Color primaryVariant = Color(4281794739), androidx.ui.graphics.Color secondary = Color(4278442694), androidx.ui.graphics.Color secondaryVariant = Color(4278290310), androidx.ui.graphics.Color background = Color.White, androidx.ui.graphics.Color surface = Color.White, androidx.ui.graphics.Color error = Color(4289724448), androidx.ui.graphics.Color onPrimary = Color.White, androidx.ui.graphics.Color onSecondary = Color.Black, androidx.ui.graphics.Color onBackground = Color.Black, androidx.ui.graphics.Color onSurface = Color.Black, androidx.ui.graphics.Color onError = Color.White);
   }
 
   public interface ColorPalette {
@@ -86,8 +87,10 @@
     method public androidx.ui.graphics.Color getSecondary();
     method public androidx.ui.graphics.Color getSecondaryVariant();
     method public androidx.ui.graphics.Color getSurface();
+    method public boolean isLight();
     property public abstract androidx.ui.graphics.Color background;
     property public abstract androidx.ui.graphics.Color error;
+    property public abstract boolean isLight;
     property public abstract androidx.ui.graphics.Color onBackground;
     property public abstract androidx.ui.graphics.Color onError;
     property public abstract androidx.ui.graphics.Color onPrimary;
@@ -161,13 +164,9 @@
 
   public final class FloatingActionButtonKt {
     ctor public FloatingActionButtonKt();
-    method public static void FloatingActionButton(androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.core.Dp minSize = FabSize, androidx.ui.engine.geometry.Shape shape = CircleShape, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method public static void FloatingActionButton(androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.core.Dp minSize = androidx.ui.material.FloatingActionButtonKt.FabSize, androidx.ui.engine.geometry.Shape shape = CircleShape, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method public static void FloatingActionButton(androidx.ui.graphics.Image icon, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.engine.geometry.Shape shape = CircleShape, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp);
     method public static void FloatingActionButton(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.graphics.Image? icon = null, androidx.ui.text.TextStyle? textStyle = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp);
-    method public static androidx.ui.core.Dp getExtendedFabHeight();
-    method public static androidx.ui.core.Dp getExtendedFabIconPadding();
-    method public static androidx.ui.core.Dp getExtendedFabTextPadding();
-    method public static androidx.ui.core.Dp getFabSize();
   }
 
   public final class ListItemKt {
@@ -185,7 +184,7 @@
 
   public final class MaterialThemeKt {
     ctor public MaterialThemeKt();
-    method public static void MaterialTheme(androidx.ui.material.ColorPalette colors = ColorPalette(), androidx.ui.material.Typography typography = androidx.ui.material.Typography(), kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method public static void MaterialTheme(androidx.ui.material.ColorPalette colors = lightColorPalette(), androidx.ui.material.Typography typography = androidx.ui.material.Typography(), kotlin.jvm.functions.Function0<kotlin.Unit> children);
   }
 
   public final class ProgressIndicatorKt {
diff --git a/ui/ui-material/api/restricted_0.1.0-dev03.txt b/ui/ui-material/api/restricted_0.1.0-dev03.txt
index 0733899..26a3d17 100644
--- a/ui/ui-material/api/restricted_0.1.0-dev03.txt
+++ b/ui/ui-material/api/restricted_0.1.0-dev03.txt
@@ -70,7 +70,8 @@
 
   public final class ColorKt {
     ctor public ColorKt();
-    method public static androidx.ui.material.ColorPalette ColorPalette(androidx.ui.graphics.Color primary = Color(4284612846), androidx.ui.graphics.Color primaryVariant = Color(4281794739), androidx.ui.graphics.Color secondary = Color(4278442694), androidx.ui.graphics.Color secondaryVariant = Color(4278290310), androidx.ui.graphics.Color background = Color.White, androidx.ui.graphics.Color surface = Color.White, androidx.ui.graphics.Color error = Color(4289724448), androidx.ui.graphics.Color onPrimary = Color.White, androidx.ui.graphics.Color onSecondary = Color.Black, androidx.ui.graphics.Color onBackground = Color.Black, androidx.ui.graphics.Color onSurface = Color.Black, androidx.ui.graphics.Color onError = Color.White);
+    method public static androidx.ui.material.ColorPalette darkColorPalette(androidx.ui.graphics.Color primary = Color(4290479868), androidx.ui.graphics.Color primaryVariant = Color(4281794739), androidx.ui.graphics.Color secondary = Color(4278442694), androidx.ui.graphics.Color background = Color(4279374354), androidx.ui.graphics.Color surface = Color(4279374354), androidx.ui.graphics.Color error = Color(4291782265), androidx.ui.graphics.Color onPrimary = Color.Black, androidx.ui.graphics.Color onSecondary = Color.Black, androidx.ui.graphics.Color onBackground = Color.White, androidx.ui.graphics.Color onSurface = Color.White, androidx.ui.graphics.Color onError = Color.Black);
+    method public static androidx.ui.material.ColorPalette lightColorPalette(androidx.ui.graphics.Color primary = Color(4284612846), androidx.ui.graphics.Color primaryVariant = Color(4281794739), androidx.ui.graphics.Color secondary = Color(4278442694), androidx.ui.graphics.Color secondaryVariant = Color(4278290310), androidx.ui.graphics.Color background = Color.White, androidx.ui.graphics.Color surface = Color.White, androidx.ui.graphics.Color error = Color(4289724448), androidx.ui.graphics.Color onPrimary = Color.White, androidx.ui.graphics.Color onSecondary = Color.Black, androidx.ui.graphics.Color onBackground = Color.Black, androidx.ui.graphics.Color onSurface = Color.Black, androidx.ui.graphics.Color onError = Color.White);
   }
 
   public interface ColorPalette {
@@ -86,8 +87,10 @@
     method public androidx.ui.graphics.Color getSecondary();
     method public androidx.ui.graphics.Color getSecondaryVariant();
     method public androidx.ui.graphics.Color getSurface();
+    method public boolean isLight();
     property public abstract androidx.ui.graphics.Color background;
     property public abstract androidx.ui.graphics.Color error;
+    property public abstract boolean isLight;
     property public abstract androidx.ui.graphics.Color onBackground;
     property public abstract androidx.ui.graphics.Color onError;
     property public abstract androidx.ui.graphics.Color onPrimary;
@@ -161,13 +164,9 @@
 
   public final class FloatingActionButtonKt {
     ctor public FloatingActionButtonKt();
-    method public static void FloatingActionButton(androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.core.Dp minSize = FabSize, androidx.ui.engine.geometry.Shape shape = CircleShape, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method public static void FloatingActionButton(androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.core.Dp minSize = androidx.ui.material.FloatingActionButtonKt.FabSize, androidx.ui.engine.geometry.Shape shape = CircleShape, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method public static void FloatingActionButton(androidx.ui.graphics.Image icon, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.engine.geometry.Shape shape = CircleShape, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp);
     method public static void FloatingActionButton(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.graphics.Image? icon = null, androidx.ui.text.TextStyle? textStyle = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp);
-    method public static androidx.ui.core.Dp getExtendedFabHeight();
-    method public static androidx.ui.core.Dp getExtendedFabIconPadding();
-    method public static androidx.ui.core.Dp getExtendedFabTextPadding();
-    method public static androidx.ui.core.Dp getFabSize();
   }
 
   public final class ListItemKt {
@@ -185,7 +184,7 @@
 
   public final class MaterialThemeKt {
     ctor public MaterialThemeKt();
-    method public static void MaterialTheme(androidx.ui.material.ColorPalette colors = ColorPalette(), androidx.ui.material.Typography typography = androidx.ui.material.Typography(), kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method public static void MaterialTheme(androidx.ui.material.ColorPalette colors = lightColorPalette(), androidx.ui.material.Typography typography = androidx.ui.material.Typography(), kotlin.jvm.functions.Function0<kotlin.Unit> children);
   }
 
   public final class ProgressIndicatorKt {
diff --git a/ui/ui-material/api/restricted_current.txt b/ui/ui-material/api/restricted_current.txt
index 0733899..26a3d17 100644
--- a/ui/ui-material/api/restricted_current.txt
+++ b/ui/ui-material/api/restricted_current.txt
@@ -70,7 +70,8 @@
 
   public final class ColorKt {
     ctor public ColorKt();
-    method public static androidx.ui.material.ColorPalette ColorPalette(androidx.ui.graphics.Color primary = Color(4284612846), androidx.ui.graphics.Color primaryVariant = Color(4281794739), androidx.ui.graphics.Color secondary = Color(4278442694), androidx.ui.graphics.Color secondaryVariant = Color(4278290310), androidx.ui.graphics.Color background = Color.White, androidx.ui.graphics.Color surface = Color.White, androidx.ui.graphics.Color error = Color(4289724448), androidx.ui.graphics.Color onPrimary = Color.White, androidx.ui.graphics.Color onSecondary = Color.Black, androidx.ui.graphics.Color onBackground = Color.Black, androidx.ui.graphics.Color onSurface = Color.Black, androidx.ui.graphics.Color onError = Color.White);
+    method public static androidx.ui.material.ColorPalette darkColorPalette(androidx.ui.graphics.Color primary = Color(4290479868), androidx.ui.graphics.Color primaryVariant = Color(4281794739), androidx.ui.graphics.Color secondary = Color(4278442694), androidx.ui.graphics.Color background = Color(4279374354), androidx.ui.graphics.Color surface = Color(4279374354), androidx.ui.graphics.Color error = Color(4291782265), androidx.ui.graphics.Color onPrimary = Color.Black, androidx.ui.graphics.Color onSecondary = Color.Black, androidx.ui.graphics.Color onBackground = Color.White, androidx.ui.graphics.Color onSurface = Color.White, androidx.ui.graphics.Color onError = Color.Black);
+    method public static androidx.ui.material.ColorPalette lightColorPalette(androidx.ui.graphics.Color primary = Color(4284612846), androidx.ui.graphics.Color primaryVariant = Color(4281794739), androidx.ui.graphics.Color secondary = Color(4278442694), androidx.ui.graphics.Color secondaryVariant = Color(4278290310), androidx.ui.graphics.Color background = Color.White, androidx.ui.graphics.Color surface = Color.White, androidx.ui.graphics.Color error = Color(4289724448), androidx.ui.graphics.Color onPrimary = Color.White, androidx.ui.graphics.Color onSecondary = Color.Black, androidx.ui.graphics.Color onBackground = Color.Black, androidx.ui.graphics.Color onSurface = Color.Black, androidx.ui.graphics.Color onError = Color.White);
   }
 
   public interface ColorPalette {
@@ -86,8 +87,10 @@
     method public androidx.ui.graphics.Color getSecondary();
     method public androidx.ui.graphics.Color getSecondaryVariant();
     method public androidx.ui.graphics.Color getSurface();
+    method public boolean isLight();
     property public abstract androidx.ui.graphics.Color background;
     property public abstract androidx.ui.graphics.Color error;
+    property public abstract boolean isLight;
     property public abstract androidx.ui.graphics.Color onBackground;
     property public abstract androidx.ui.graphics.Color onError;
     property public abstract androidx.ui.graphics.Color onPrimary;
@@ -161,13 +164,9 @@
 
   public final class FloatingActionButtonKt {
     ctor public FloatingActionButtonKt();
-    method public static void FloatingActionButton(androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.core.Dp minSize = FabSize, androidx.ui.engine.geometry.Shape shape = CircleShape, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method public static void FloatingActionButton(androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.core.Dp minSize = androidx.ui.material.FloatingActionButtonKt.FabSize, androidx.ui.engine.geometry.Shape shape = CircleShape, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method public static void FloatingActionButton(androidx.ui.graphics.Image icon, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.engine.geometry.Shape shape = CircleShape, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp);
     method public static void FloatingActionButton(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.graphics.Image? icon = null, androidx.ui.text.TextStyle? textStyle = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, androidx.ui.graphics.Color color = (+MaterialTheme.colors()).primary, androidx.ui.core.Dp elevation = 6.dp);
-    method public static androidx.ui.core.Dp getExtendedFabHeight();
-    method public static androidx.ui.core.Dp getExtendedFabIconPadding();
-    method public static androidx.ui.core.Dp getExtendedFabTextPadding();
-    method public static androidx.ui.core.Dp getFabSize();
   }
 
   public final class ListItemKt {
@@ -185,7 +184,7 @@
 
   public final class MaterialThemeKt {
     ctor public MaterialThemeKt();
-    method public static void MaterialTheme(androidx.ui.material.ColorPalette colors = ColorPalette(), androidx.ui.material.Typography typography = androidx.ui.material.Typography(), kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method public static void MaterialTheme(androidx.ui.material.ColorPalette colors = lightColorPalette(), androidx.ui.material.Typography typography = androidx.ui.material.Typography(), kotlin.jvm.functions.Function0<kotlin.Unit> children);
   }
 
   public final class ProgressIndicatorKt {
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/AppBarActivity.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/AppBarActivity.kt
index cbc2338..69edd80 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/AppBarActivity.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/AppBarActivity.kt
@@ -22,9 +22,13 @@
 import androidx.ui.core.Alignment
 import androidx.ui.core.Text
 import androidx.ui.core.dp
+import androidx.ui.graphics.imageFromResource
+import androidx.ui.layout.Arrangement
 import androidx.ui.layout.Column
 import androidx.ui.layout.Container
+import androidx.ui.layout.ExpandedHeight
 import androidx.ui.layout.FlexColumn
+import androidx.ui.material.MaterialTheme
 import androidx.ui.material.RadioGroup
 import androidx.ui.material.demos.AppBarActivity.BottomAppBarOption.CenterFab
 import androidx.ui.material.demos.AppBarActivity.BottomAppBarOption.CutoutFab
@@ -34,19 +38,14 @@
 import androidx.ui.material.demos.AppBarActivity.BottomAppBarOption.NoFab
 import androidx.ui.material.demos.AppBarActivity.TopAppBarOption.Actions
 import androidx.ui.material.demos.AppBarActivity.TopAppBarOption.Simple
-import androidx.ui.material.samples.SimpleBottomAppBarCutoutFab
 import androidx.ui.material.samples.SimpleBottomAppBarCenterFab
+import androidx.ui.material.samples.SimpleBottomAppBarCutoutFab
 import androidx.ui.material.samples.SimpleBottomAppBarEndFab
 import androidx.ui.material.samples.SimpleBottomAppBarExtendedCutoutFab
 import androidx.ui.material.samples.SimpleBottomAppBarFancyAnimatingCutoutFab
 import androidx.ui.material.samples.SimpleBottomAppBarNoFab
 import androidx.ui.material.samples.SimpleTopAppBarNavIcon
 import androidx.ui.material.samples.SimpleTopAppBarNavIconWithActions
-import androidx.ui.material.surface.Surface
-import androidx.ui.graphics.imageFromResource
-import androidx.ui.layout.Arrangement
-import androidx.ui.layout.ExpandedHeight
-import androidx.ui.material.MaterialTheme
 
 class AppBarActivity : MaterialDemoActivity() {
 
@@ -77,65 +76,63 @@
         var selectedTopAppBar by +state { Simple }
         var selectedBottomAppBar by +state { NoFab }
 
-        Surface {
-            FlexColumn {
-                inflexible {
-                    Container(height = 120.dp, alignment = Alignment.TopCenter) {
-                        when (selectedTopAppBar) {
-                            Simple -> SimpleTopAppBarNavIcon(navigationImage)
-                            Actions -> SimpleTopAppBarNavIconWithActions(
-                                favouriteImage,
-                                navigationImage
+        FlexColumn {
+            inflexible {
+                Container(height = 120.dp, alignment = Alignment.TopCenter) {
+                    when (selectedTopAppBar) {
+                        Simple -> SimpleTopAppBarNavIcon(navigationImage)
+                        Actions -> SimpleTopAppBarNavIconWithActions(
+                            favouriteImage,
+                            navigationImage
+                        )
+                    }
+                }
+            }
+            flexible(1f) {
+                Column(ExpandedHeight, arrangement = Arrangement.SpaceBetween) {
+                    DemoText("TopAppBar options")
+                    RadioGroup {
+                        topAppBarOptions.forEach { topAppBar ->
+                            RadioGroupTextItem(
+                                selected = (topAppBar == selectedTopAppBar),
+                                onSelect = { selectedTopAppBar = topAppBar },
+                                text = topAppBar.description
+                            )
+                        }
+                    }
+                    DemoText("BottomAppBar options")
+                    RadioGroup {
+                        bottomAppBarOptions.forEach { bottomAppBar ->
+                            RadioGroupTextItem(
+                                selected = (bottomAppBar == selectedBottomAppBar),
+                                onSelect = { selectedBottomAppBar = bottomAppBar },
+                                text = bottomAppBar.description
                             )
                         }
                     }
                 }
-                flexible(1f) {
-                    Column(ExpandedHeight, arrangement = Arrangement.SpaceBetween) {
-                        DemoText("TopAppBar options")
-                        RadioGroup {
-                            topAppBarOptions.forEach { topAppBar ->
-                                RadioGroupTextItem(
-                                    selected = (topAppBar == selectedTopAppBar),
-                                    onSelect = { selectedTopAppBar = topAppBar },
-                                    text = topAppBar.description
-                                )
-                            }
-                        }
-                        DemoText("BottomAppBar options")
-                        RadioGroup {
-                            bottomAppBarOptions.forEach { bottomAppBar ->
-                                RadioGroupTextItem(
-                                    selected = (bottomAppBar == selectedBottomAppBar),
-                                    onSelect = { selectedBottomAppBar = bottomAppBar },
-                                    text = bottomAppBar.description
-                                )
-                            }
-                        }
-                    }
-                }
-                inflexible {
-                    Container(height = 120.dp, alignment = Alignment.BottomCenter) {
-                        when (selectedBottomAppBar) {
-                            NoFab -> SimpleBottomAppBarNoFab(favouriteImage, navigationImage)
-                            CenterFab -> SimpleBottomAppBarCenterFab(
-                                favouriteImage,
-                                navigationImage
-                            )
-                            EndFab -> SimpleBottomAppBarEndFab(favouriteImage)
-                            CutoutFab -> SimpleBottomAppBarCutoutFab(
-                                favouriteImage,
-                                navigationImage
-                            )
-                            ExtendedCutoutFab -> SimpleBottomAppBarExtendedCutoutFab(
-                                favouriteImage,
-                                navigationImage
-                            )
-                            FancyAnimatingCutoutFab -> SimpleBottomAppBarFancyAnimatingCutoutFab(
-                                favouriteImage,
-                                navigationImage
-                            )
-                        }
+            }
+            inflexible {
+                Container(height = 120.dp, alignment = Alignment.BottomCenter) {
+                    when (selectedBottomAppBar) {
+                        NoFab -> SimpleBottomAppBarNoFab(favouriteImage, navigationImage)
+                        CenterFab -> SimpleBottomAppBarCenterFab(
+                            favouriteImage,
+                            navigationImage
+                        )
+                        EndFab -> SimpleBottomAppBarEndFab(favouriteImage)
+                        CutoutFab -> SimpleBottomAppBarCutoutFab(
+                            favouriteImage,
+                            navigationImage
+                        )
+                        ExtendedCutoutFab -> SimpleBottomAppBarExtendedCutoutFab(
+                            favouriteImage,
+                            navigationImage
+                        )
+                        FancyAnimatingCutoutFab -> SimpleBottomAppBarFancyAnimatingCutoutFab(
+                            favouriteImage,
+                            navigationImage
+                        )
                     }
                 }
             }
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/DataTableActivity.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/DataTableActivity.kt
index 8d92f88..0c04a5a 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/DataTableActivity.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/DataTableActivity.kt
@@ -18,14 +18,11 @@
 
 import androidx.compose.Composable
 import androidx.ui.material.samples.SimpleDataTable
-import androidx.ui.material.surface.Surface
 
 class DataTableActivity : MaterialDemoActivity() {
 
     @Composable
     override fun materialContent() {
-        Surface {
-            SimpleDataTable()
-        }
+        SimpleDataTable()
     }
 }
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/DynamicThemeActivity.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/DynamicThemeActivity.kt
index 484f12f..ec30f46 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/DynamicThemeActivity.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/DynamicThemeActivity.kt
@@ -50,6 +50,7 @@
 import androidx.ui.material.FloatingActionButton
 import androidx.ui.material.MaterialTheme
 import androidx.ui.material.TopAppBar
+import androidx.ui.material.lightColorPalette
 import androidx.ui.material.surface.Surface
 import androidx.ui.text.TextStyle
 import kotlin.math.round
@@ -166,7 +167,7 @@
     val secondary = lerp(Color(0xFF03DAC6), Color(0xFFBB86FC), interpolatedFraction)
     val background = lerp(Color.White, Color(0xFF121212), interpolatedFraction)
 
-    return ColorPalette(
+    return lightColorPalette(
         primary = primary,
         secondary = secondary,
         background = background
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MaterialDemoActivity.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MaterialDemoActivity.kt
index 98ccd23..4a91328a 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MaterialDemoActivity.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MaterialDemoActivity.kt
@@ -26,21 +26,29 @@
 import androidx.compose.Composable
 import androidx.compose.FrameManager
 import androidx.compose.Model
+import androidx.compose.unaryPlus
 import androidx.preference.EditTextPreference
+import androidx.preference.PreferenceCategory
 import androidx.preference.PreferenceFragmentCompat
 import androidx.preference.PreferenceManager.getDefaultSharedPreferences
 import androidx.ui.core.setContent
+import androidx.ui.foundation.isSystemInDarkTheme
 import androidx.ui.graphics.Color
 import androidx.ui.graphics.toArgb
 import androidx.ui.material.ColorPalette
 import androidx.ui.material.MaterialTheme
+import androidx.ui.material.darkColorPalette
 import androidx.ui.material.demos.MaterialSettingsActivity.SettingsFragment
-import kotlin.random.Random
+import androidx.ui.material.lightColorPalette
+import androidx.ui.material.surface.Surface
 import kotlin.reflect.full.memberProperties
 
 @Model
 class CurrentColorPalette {
-    var colors: ColorPalette = ColorPalette()
+    var lightColors: ColorPalette = lightColorPalette()
+    var darkColors: ColorPalette = darkColorPalette()
+
+    val colors get() = if (+isSystemInDarkTheme()) darkColors else lightColors
 }
 
 /**
@@ -49,16 +57,18 @@
  */
 abstract class MaterialDemoActivity : Activity() {
 
-    private val currentColors = CurrentColorPalette()
+    private var currentColors = CurrentColorPalette()
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         // Ensure we are in a frame, as this is only normally initialized after the setContent call
         FrameManager.ensureStarted()
-        currentColors.colors = getColorsFromSharedPreferences()
+        currentColors.getColorsFromSharedPreferences()
         setContent {
             MaterialTheme(currentColors.colors) {
-                materialContent()
+                Surface {
+                    materialContent()
+                }
             }
         }
     }
@@ -66,14 +76,15 @@
     override fun onResume() {
         super.onResume()
         // Update colors in case we changed something in settings activity
-        currentColors.colors = getColorsFromSharedPreferences()
+        currentColors.getColorsFromSharedPreferences()
     }
 
     override fun onCreateOptionsMenu(menu: Menu?): Boolean {
-        menu?.add(Menu.NONE, SETTINGS, Menu.NONE, "Theme settings")
-        menu?.add(Menu.NONE, SHUFFLE, Menu.NONE, "Shuffle colors")
-        menu?.add(Menu.NONE, INVERT, Menu.NONE, "Invert color mapping")
-        menu?.add(Menu.NONE, RESET, Menu.NONE, "Reset theme to default")
+        menu?.run {
+            add(Menu.NONE, SETTINGS, Menu.NONE, "Theme settings")
+            add(Menu.NONE, SHUFFLE, Menu.NONE, "Shuffle colors")
+            add(Menu.NONE, RESET, Menu.NONE, "Reset theme to default")
+        }
         return true
     }
 
@@ -81,37 +92,13 @@
         when (item.itemId) {
             SETTINGS -> startActivity(Intent(this, MaterialSettingsActivity::class.java))
             SHUFFLE -> {
-                val colors = generateColorPalette(currentColors.colors)
-                colors.saveColors()
-                currentColors.colors = colors
-            }
-            INVERT -> {
-                // Flip all colors
-                val newPrimary = currentColors.colors.onPrimary
-                val newOnPrimary = currentColors.colors.primary
-                val newSecondary = currentColors.colors.onSecondary
-                val newOnSecondary = currentColors.colors.secondary
-                val colors = ColorPalette(
-                    primary = newPrimary,
-                    primaryVariant = currentColors.colors.primaryVariant,
-                    secondary = newSecondary,
-                    secondaryVariant = currentColors.colors.secondaryVariant,
-                    background = currentColors.colors.background,
-                    surface = currentColors.colors.surface,
-                    error = currentColors.colors.error,
-                    onPrimary = newOnPrimary,
-                    onSecondary = newOnSecondary,
-                    onBackground = currentColors.colors.onBackground,
-                    onSurface = currentColors.colors.onSurface,
-                    onError = currentColors.colors.onError
-                )
-                colors.saveColors()
-                currentColors.colors = colors
+                currentColors.shuffleColors()
+                currentColors.saveColors()
             }
             RESET -> {
                 val sharedPreferences = getDefaultSharedPreferences(this)
                 sharedPreferences.edit().clear().apply()
-                currentColors.colors = getColorsFromSharedPreferences()
+                currentColors.getColorsFromSharedPreferences()
             }
         }
         return true
@@ -122,30 +109,41 @@
      * not present in the [SharedPreferences], its default value as defined in [ColorPalette]
      * will be returned.
      */
-    private fun getColorsFromSharedPreferences(): ColorPalette {
-        val sharedPreferences = getDefaultSharedPreferences(this)
-        val function = ::ColorPalette
-        val parametersToSet = function.parameters.mapNotNull { parameter ->
-            val savedValue = sharedPreferences.getString(parameter.name, "")
-            if (savedValue.isNullOrBlank()) {
-                null
-            } else {
-                val parsedColor = Color(java.lang.Long.parseLong(savedValue, 16))
-                parameter to parsedColor
-            }
-        }.toMap()
-        if (parametersToSet.isEmpty()) return ColorPalette()
-        return ::ColorPalette.callBy(parametersToSet)
+    private fun CurrentColorPalette.getColorsFromSharedPreferences() {
+        val sharedPreferences = getDefaultSharedPreferences(this@MaterialDemoActivity)
+
+        fun getColorsFromSharedPreferences(isLightTheme: Boolean): ColorPalette {
+            val function = if (isLightTheme) ::lightColorPalette else ::darkColorPalette
+            val parametersToSet = function.parameters.mapNotNull { parameter ->
+                val savedValue = sharedPreferences.getString(parameter.name + isLightTheme, "")
+                if (savedValue.isNullOrBlank()) {
+                    null
+                } else {
+                    val parsedColor = Color(java.lang.Long.parseLong(savedValue, 16))
+                    parameter to parsedColor
+                }
+            }.toMap()
+            return function.callBy(parametersToSet)
+        }
+
+        lightColors = getColorsFromSharedPreferences(true)
+        darkColors = getColorsFromSharedPreferences(false)
     }
 
     /**
-     * Persists the current [ColorPalette] to [SharedPreferences].
+     * Persists the current [CurrentColorPalette] to [SharedPreferences].
      */
-    private fun ColorPalette.saveColors() {
-        forEachColorProperty { name, color ->
+    private fun CurrentColorPalette.saveColors() {
+        lightColors.forEachColorProperty { name, color ->
             getDefaultSharedPreferences(this@MaterialDemoActivity)
                 .edit()
-                .putString(name, Integer.toHexString(color.toArgb()))
+                .putString(name + true, Integer.toHexString(color.toArgb()))
+                .apply()
+        }
+        darkColors.forEachColorProperty { name, color ->
+            getDefaultSharedPreferences(this@MaterialDemoActivity)
+                .edit()
+                .putString(name + false, Integer.toHexString(color.toArgb()))
                 .apply()
         }
     }
@@ -155,22 +153,37 @@
      * [ColorPalette.secondary] and [ColorPalette.onSecondary] as dark-on-light or light-on-dark
      * pairs.
      */
-    private fun generateColorPalette(currentColors: ColorPalette): ColorPalette {
-        val (primary, onPrimary) = generateColorPair()
-        val (secondary, onSecondary) = generateColorPair()
-        return ColorPalette(
-            primary = primary,
-            primaryVariant = currentColors.primaryVariant,
-            secondary = secondary,
-            secondaryVariant = currentColors.secondaryVariant,
-            background = currentColors.background,
-            surface = currentColors.surface,
-            error = currentColors.error,
-            onPrimary = onPrimary,
-            onSecondary = onSecondary,
-            onBackground = currentColors.onBackground,
-            onSurface = currentColors.onSurface,
-            onError = currentColors.onError
+    private fun CurrentColorPalette.shuffleColors() {
+        val (lightPrimary, lightOnPrimary) = generateColorPair(true)
+        val (lightSecondary, lightOnSecondary) = generateColorPair(true)
+        lightColors = lightColorPalette(
+            primary = lightPrimary,
+            primaryVariant = lightColors.primaryVariant,
+            secondary = lightSecondary,
+            secondaryVariant = lightColors.secondaryVariant,
+            background = lightColors.background,
+            surface = lightColors.surface,
+            error = lightColors.error,
+            onPrimary = lightOnPrimary,
+            onSecondary = lightOnSecondary,
+            onBackground = lightColors.onBackground,
+            onSurface = lightColors.onSurface,
+            onError = lightColors.onError
+        )
+        val (darkPrimary, darkOnPrimary) = generateColorPair(false)
+        val (darkSecondary, darkOnSecondary) = generateColorPair(false)
+        darkColors = darkColorPalette(
+            primary = darkPrimary,
+            primaryVariant = darkColors.primaryVariant,
+            secondary = darkSecondary,
+            background = darkColors.background,
+            surface = darkColors.surface,
+            error = darkColors.error,
+            onPrimary = darkOnPrimary,
+            onSecondary = darkOnSecondary,
+            onBackground = darkColors.onBackground,
+            onSurface = darkColors.onSurface,
+            onError = darkColors.onError
         )
     }
 
@@ -178,14 +191,13 @@
      * Generate a random dark and light color from the palette, and returns either a dark-on-light
      * or light-on-dark color pair.
      */
-    private fun generateColorPair(): Pair<Color, Color> {
+    private fun generateColorPair(isLightTheme: Boolean): Pair<Color, Color> {
         val darkColor = Color(DARK_PALETTE_COLORS.random())
         val lightColor = Color(LIGHT_PALETTE_COLORS.random())
-        val isMainColorLight = Random.nextBoolean()
-        return if (isMainColorLight) {
-            (lightColor to darkColor)
+        return if (isLightTheme) {
+            darkColor to lightColor
         } else {
-            (darkColor to lightColor)
+            lightColor to darkColor
         }
     }
 
@@ -199,8 +211,7 @@
     companion object {
         private const val SETTINGS = 1
         private const val SHUFFLE = 2
-        private const val INVERT = 3
-        private const val RESET = 4
+        private const val RESET = 3
 
         // Colors taken from https://material.io/design/color -> 2014 Material Design color palettes
 
@@ -465,15 +476,35 @@
         override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
             val context = preferenceManager.context
             val screen = preferenceManager.createPreferenceScreen(context)
+
+            val light = PreferenceCategory(context).apply {
+                title = "Light colors"
+                screen.addPreference(this)
+            }
             // Create new ColorPalette to resolve defaults
-            ColorPalette().forEachColorProperty { name, color ->
+            lightColorPalette().forEachColorProperty { name, color ->
                 val preference = EditTextPreference(context)
-                preference.key = name
+                preference.key = name + true
                 preference.title = name
                 // set the default value to be the default for ColorPalette
                 preference.setDefaultValue(Integer.toHexString(color.toArgb()))
                 preference.summaryProvider = EditTextPreference.SimpleSummaryProvider.getInstance()
-                screen.addPreference(preference)
+                light.addPreference(preference)
+            }
+
+            val dark = PreferenceCategory(context).apply {
+                title = "Dark colors"
+                screen.addPreference(this)
+            }
+
+            darkColorPalette().forEachColorProperty { name, color ->
+                val preference = EditTextPreference(context)
+                preference.key = name + false
+                preference.title = name
+                // set the default value to be the default for ColorPalette
+                preference.setDefaultValue(Integer.toHexString(color.toArgb()))
+                preference.summaryProvider = EditTextPreference.SimpleSummaryProvider.getInstance()
+                dark.addPreference(preference)
             }
             preferenceScreen = screen
         }
@@ -490,7 +521,7 @@
 private fun ColorPalette.forEachColorProperty(action: (name: String, color: Color) -> Unit) {
     ColorPalette::class.memberProperties.forEach { property ->
         val name = property.name
-        val color = property.get(this) as Color
+        val color = property.get(this) as? Color ?: return@forEach
         action(name, color)
     }
-}
\ No newline at end of file
+}
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SelectionControlsActivity.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SelectionControlsActivity.kt
index 5fd2c06..109a5e4 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SelectionControlsActivity.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SelectionControlsActivity.kt
@@ -20,7 +20,6 @@
 import androidx.compose.unaryPlus
 import androidx.ui.core.Text
 import androidx.ui.core.dp
-import androidx.ui.graphics.Color
 import androidx.ui.layout.Column
 import androidx.ui.layout.EdgeInsets
 import androidx.ui.layout.Padding
@@ -30,7 +29,6 @@
 import androidx.ui.material.samples.RadioButtonSample
 import androidx.ui.material.samples.SwitchSample
 import androidx.ui.material.samples.TriStateCheckboxSample
-import androidx.ui.material.surface.Surface
 
 class SelectionControlsActivity : MaterialDemoActivity() {
 
@@ -39,29 +37,27 @@
         val headerStyle = (+MaterialTheme.typography()).h6
         val padding = EdgeInsets(10.dp)
 
-        Surface(color = Color.White) {
-            Padding(padding = padding) {
-                Column {
-                    Text(text = "Checkbox", style = headerStyle)
-                    Padding(padding = padding) {
-                        TriStateCheckboxSample()
-                    }
-                    Text(text = "Switch", style = headerStyle)
-                    Padding(padding = padding) {
-                        SwitchSample()
-                    }
-                    Text(text = "RadioButton", style = headerStyle)
-                    Padding(padding = padding) {
-                        RadioButtonSample()
-                    }
-                    Text(text = "Radio group :: Default usage", style = headerStyle)
-                    Padding(padding = padding) {
-                        DefaultRadioGroupSample()
-                    }
-                    Text(text = "Radio group :: Custom usage", style = headerStyle)
-                    Padding(padding = padding) {
-                        CustomRadioGroupSample()
-                    }
+        Padding(padding = padding) {
+            Column {
+                Text(text = "Checkbox", style = headerStyle)
+                Padding(padding = padding) {
+                    TriStateCheckboxSample()
+                }
+                Text(text = "Switch", style = headerStyle)
+                Padding(padding = padding) {
+                    SwitchSample()
+                }
+                Text(text = "RadioButton", style = headerStyle)
+                Padding(padding = padding) {
+                    RadioButtonSample()
+                }
+                Text(text = "Radio group :: Default usage", style = headerStyle)
+                Padding(padding = padding) {
+                    DefaultRadioGroupSample()
+                }
+                Text(text = "Radio group :: Custom usage", style = headerStyle)
+                Padding(padding = padding) {
+                    CustomRadioGroupSample()
                 }
             }
         }
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SliderActivity.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SliderActivity.kt
index 003923b..00327259 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SliderActivity.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SliderActivity.kt
@@ -18,25 +18,21 @@
 
 import androidx.compose.Composable
 import androidx.ui.core.dp
-import androidx.ui.graphics.Color
 import androidx.ui.layout.Column
 import androidx.ui.layout.EdgeInsets
 import androidx.ui.layout.Padding
 import androidx.ui.material.samples.SliderSample
 import androidx.ui.material.samples.StepsSliderSample
-import androidx.ui.material.surface.Surface
 
 class SliderActivity : MaterialDemoActivity() {
     @Composable
     override fun materialContent() {
         val padding = EdgeInsets(10.dp)
 
-        Surface(color = Color.White) {
-            Padding(padding = padding) {
-                Column {
-                    SliderSample()
-                    StepsSliderSample()
-                }
+        Padding(padding = padding) {
+            Column {
+                SliderSample()
+                StepsSliderSample()
             }
         }
     }
diff --git a/ui/ui-material/integration-tests/material-studies/src/main/java/androidx/ui/material/studies/rally/RallyAnimatedCircle.kt b/ui/ui-material/integration-tests/material-studies/src/main/java/androidx/ui/material/studies/rally/RallyAnimatedCircle.kt
index 6e22941..b5e6fa9 100644
--- a/ui/ui-material/integration-tests/material-studies/src/main/java/androidx/ui/material/studies/rally/RallyAnimatedCircle.kt
+++ b/ui/ui-material/integration-tests/material-studies/src/main/java/androidx/ui/material/studies/rally/RallyAnimatedCircle.kt
@@ -65,7 +65,7 @@
 fun DrawAnimatedCircle(proportions: List<Float>, colors: List<Color>) {
     val strokeWidthDp = 5.dp
     val paint = +memo { Paint() }
-    Transition(definition = CircularTransition, toState = 1) { state ->
+    Transition(definition = CircularTransition, initState = 0, toState = 1) { state ->
             Draw { canvas, parentSize ->
                 val strokeWidth = strokeWidthDp.toPx().value
                 paint.style = PaintingStyle.stroke
diff --git a/ui/ui-material/integration-tests/material-studies/src/main/java/androidx/ui/material/studies/rally/RallyTheme.kt b/ui/ui-material/integration-tests/material-studies/src/main/java/androidx/ui/material/studies/rally/RallyTheme.kt
index ff10252..4752bd1 100644
--- a/ui/ui-material/integration-tests/material-studies/src/main/java/androidx/ui/material/studies/rally/RallyTheme.kt
+++ b/ui/ui-material/integration-tests/material-studies/src/main/java/androidx/ui/material/studies/rally/RallyTheme.kt
@@ -21,9 +21,9 @@
 import androidx.ui.core.em
 import androidx.ui.core.sp
 import androidx.ui.graphics.Color
-import androidx.ui.material.ColorPalette
 import androidx.ui.material.MaterialTheme
 import androidx.ui.material.Typography
+import androidx.ui.material.lightColorPalette
 import androidx.ui.text.TextStyle
 import androidx.ui.text.font.FontFamily
 import androidx.ui.text.font.FontWeight
@@ -37,7 +37,7 @@
 
 @Composable
 fun RallyTheme(children: @Composable() () -> Unit) {
-    val colors = ColorPalette(
+    val colors = lightColorPalette(
         primary = rallyGreen,
         surface = Color(0xFF26282F),
         onSurface = Color.White,
@@ -91,7 +91,7 @@
 
 @Composable
 fun RallyDialogThemeOverlay(children: @Composable() () -> Unit) {
-    val dialogColors = ColorPalette(
+    val dialogColors = lightColorPalette(
         primary = Color.White,
         surface = Color(0xFF1E1E1E),
         onSurface = Color.White
diff --git a/ui/ui-material/integration-tests/samples/src/main/java/androidx/ui/material/samples/ThemeSamples.kt b/ui/ui-material/integration-tests/samples/src/main/java/androidx/ui/material/samples/ThemeSamples.kt
index 2a3412f..0b66644 100644
--- a/ui/ui-material/integration-tests/samples/src/main/java/androidx/ui/material/samples/ThemeSamples.kt
+++ b/ui/ui-material/integration-tests/samples/src/main/java/androidx/ui/material/samples/ThemeSamples.kt
@@ -22,11 +22,13 @@
 import androidx.ui.core.Text
 import androidx.ui.core.sp
 import androidx.ui.foundation.ColoredRect
+import androidx.ui.foundation.isSystemInDarkTheme
 import androidx.ui.graphics.Color
-import androidx.ui.material.ColorPalette
 import androidx.ui.material.FloatingActionButton
 import androidx.ui.material.MaterialTheme
 import androidx.ui.material.Typography
+import androidx.ui.material.darkColorPalette
+import androidx.ui.material.lightColorPalette
 import androidx.ui.text.TextStyle
 import androidx.ui.text.font.FontFamily
 import androidx.ui.text.font.FontWeight
@@ -34,12 +36,16 @@
 @Sampled
 @Composable
 fun MaterialThemeSample() {
-    val colors = ColorPalette(
-        primary = Color(0xFF1EB980),
-        surface = Color(0xFF26282F),
-        onSurface = Color.White
+    val lightColors = lightColorPalette(
+        primary = Color(0xFF1EB980)
     )
 
+    val darkColors = darkColorPalette(
+        primary = Color(0xFF66ffc7)
+    )
+
+    val colors = if (+isSystemInDarkTheme()) darkColors else lightColors
+
     val typography = Typography(
         h1 = TextStyle(fontFamily = FontFamily("RobotoCondensed"),
             fontWeight = FontWeight.W100,
@@ -47,11 +53,11 @@
         button = TextStyle(fontFamily = FontFamily("RobotoCondensed"),
             fontWeight = FontWeight.W600,
             fontSize = 14.sp)
-
     )
 
     MaterialTheme(colors = colors, typography = typography) {
-        FloatingActionButton("FAB with text style and color from theme", onClick = {})
+        val currentTheme = if ((+MaterialTheme.colors()).isLight) "light" else "dark"
+        FloatingActionButton("FAB with text style and color from $currentTheme theme", onClick = {})
     }
 }
 
@@ -65,5 +71,6 @@
 @Sampled
 @Composable
 fun ThemeTextStyleSample() {
-    Text(text = "H4 styled text", style = (+MaterialTheme.typography()).h4)
+    val typography = +MaterialTheme.typography()
+    Text(text = "H4 styled text", style = typography.h4)
 }
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/TextColorsTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/TextColorsTest.kt
index b973eea..abd4b27 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/TextColorsTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/TextColorsTest.kt
@@ -36,7 +36,7 @@
 
     @Test
     fun textColorForBackgroundUsesCorrectValues() {
-        val colors = ColorPalette(
+        val colors = lightColorPalette(
             primary = Color(0),
             onPrimary = Color(1),
             secondary = Color(2),
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/Color.kt b/ui/ui-material/src/main/java/androidx/ui/material/Color.kt
index f3fa80c..ee7eb9d 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/Color.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/Color.kt
@@ -27,6 +27,9 @@
 /**
  * Collection of colors in the [Material color specification]
  * [https://material.io/design/color/the-color-system.html#color-theme-creation].
+ *
+ * To create a light set of colors, use [lightColorPalette]
+ * To create a dark set of colors, use [darkColorPalette]
  */
 interface ColorPalette {
     /**
@@ -86,13 +89,22 @@
      * Color used for text and icons displayed on top of the error color.
      */
     val onError: Color
+    /**
+     * Whether this ColorPalette is considered as a 'light' or 'dark' set of colors. This affects
+     * default behavior for some components: for example, in a light theme a [TopAppBar] will use
+     * [primary] by default for its background color, when in a dark theme it will use [surface].
+     */
+    val isLight: Boolean
 }
 
 /**
  * Creates a complete color definition for the [Material color specification]
- * [https://material.io/design/color/the-color-system.html#color-theme-creation].
+ * [https://material.io/design/color/the-color-system.html#color-theme-creation] using the default
+ * light theme values.
+ *
+ * @see darkColorPalette
  */
-fun ColorPalette(
+fun lightColorPalette(
     primary: Color = Color(0xFF6200EE),
     primaryVariant: Color = Color(0xFF3700B3),
     secondary: Color = Color(0xFF03DAC6),
@@ -117,7 +129,45 @@
     onSecondary,
     onBackground,
     onSurface,
-    onError
+    onError,
+    true
+)
+
+/**
+ * Creates a complete color definition for the [Material color specification]
+ * [https://material.io/design/color/the-color-system.html#color-theme-creation] using the default
+ * dark theme values.
+ *
+ * @see lightColorPalette
+ */
+fun darkColorPalette(
+    primary: Color = Color(0xFFBB86FC),
+    primaryVariant: Color = Color(0xFF3700B3),
+    secondary: Color = Color(0xFF03DAC6),
+    background: Color = Color(0xFF121212),
+    surface: Color = Color(0xFF121212),
+    error: Color = Color(0xFFCF6679),
+    onPrimary: Color = Color.Black,
+    onSecondary: Color = Color.Black,
+    onBackground: Color = Color.White,
+    onSurface: Color = Color.White,
+    onError: Color = Color.Black
+): ColorPalette = ObservableColorPalette(
+    primary,
+    primaryVariant,
+    secondary,
+    // Secondary and secondary variant are the same in dark mode, as contrast should be
+    // higher so there is no need for the variant.
+    secondary,
+    background,
+    surface,
+    error,
+    onPrimary,
+    onSecondary,
+    onBackground,
+    onSurface,
+    onError,
+    false
 )
 
 /**
@@ -146,7 +196,8 @@
     onSecondary: Color,
     onBackground: Color,
     onSurface: Color,
-    onError: Color
+    onError: Color,
+    isLight: Boolean
 ) : ColorPalette {
 
     constructor(colorPalette: ColorPalette) : this(
@@ -161,7 +212,8 @@
         onSecondary = colorPalette.onSecondary,
         onBackground = colorPalette.onBackground,
         onSurface = colorPalette.onSurface,
-        onError = colorPalette.onError
+        onError = colorPalette.onError,
+        isLight = colorPalette.isLight
     )
 
     override var primary by ObservableColor(primary)
@@ -176,6 +228,7 @@
     override var onBackground by ObservableColor(onBackground)
     override var onSurface by ObservableColor(onSurface)
     override var onError by ObservableColor(onError)
+    override var isLight by ObservableBoolean(isLight)
 }
 
 @Model
@@ -187,6 +240,15 @@
     }
 }
 
+@Model
+private class ObservableBoolean(var boolean: Boolean) {
+    operator fun getValue(thisObj: Any?, property: KProperty<*>) = boolean
+
+    operator fun setValue(thisObj: Any?, property: KProperty<*>, next: Boolean) {
+        if (boolean != next) boolean = next
+    }
+}
+
 /**
  * Updates the internal values of the given [ObservableColorPalette] with values from the [other]
  * [ColorPalette].
@@ -204,6 +266,7 @@
     onBackground = other.onBackground
     onSurface = other.onSurface
     onError = other.onError
+    isLight = other.isLight
     return this
 }
 
@@ -215,9 +278,7 @@
 internal fun ProvideColorPalette(colorPalette: ColorPalette, children: @Composable() () -> Unit) {
     val palette = when (colorPalette) {
         is ObservableColorPalette -> {
-            (+memo<ObservableColorPalette> {
-                ObservableColorPalette(colorPalette)
-            }).updateColorsFrom(colorPalette)
+            (+memo { ObservableColorPalette(colorPalette) }).updateColorsFrom(colorPalette)
         }
         else -> colorPalette
     }
@@ -229,4 +290,4 @@
  *
  * To retrieve the current value of this ambient, use [MaterialTheme.colors].
  */
-internal val ColorAmbient = Ambient.of { ColorPalette() }
+internal val ColorAmbient = Ambient.of { lightColorPalette() }
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/FloatingActionButton.kt b/ui/ui-material/src/main/java/androidx/ui/material/FloatingActionButton.kt
index 957ccd2..4ea4cc3 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/FloatingActionButton.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/FloatingActionButton.kt
@@ -42,7 +42,7 @@
 /**
  * A floating action button (FAB) is a [Button] to represents the primary action of a screen.
  *
- * By default it adds the circle shape, the [FabSize] size and the centering for the content.
+ * By default it uses a circle shape and centers its content.
  *
  * @sample androidx.ui.material.samples.FloatingActionButtonCustomContent
  *
@@ -51,7 +51,7 @@
  * @param modifier Modifier to be applied to the button.
  * @param onClick will be called when user clicked on the button. The button will be disabled
  *  when it is null.
- * @param minSize Minimum size of the button. Defaults to [FabSize]
+ * @param minSize Minimum size of the FAB.
  * @param shape Defines the Button's shape as well its shadow. When null is provided it uses
  *  the [Shapes.button] from [ShapeAmbient].
  * @param color The background color
@@ -82,7 +82,7 @@
 /**
  * A floating action button (FAB) is a [Button] to represents the primary action of a screen.
  *
- * It draws the [icon] in the center of the FAB with [FabSize] size.
+ * It draws the [icon] in the center of the FAB.
  *
  * @sample androidx.ui.material.samples.FloatingActionButtonSimple
  *
@@ -165,7 +165,7 @@
     }
 }
 
-val FabSize = 56.dp
-val ExtendedFabHeight = 48.dp
-val ExtendedFabIconPadding = 12.dp
-val ExtendedFabTextPadding = 20.dp
+private val FabSize = 56.dp
+private val ExtendedFabHeight = 48.dp
+private val ExtendedFabIconPadding = 12.dp
+private val ExtendedFabTextPadding = 20.dp
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/MaterialTheme.kt b/ui/ui-material/src/main/java/androidx/ui/material/MaterialTheme.kt
index eeccfeb..0bc689d 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/MaterialTheme.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/MaterialTheme.kt
@@ -41,7 +41,7 @@
  */
 @Composable
 fun MaterialTheme(
-    colors: ColorPalette = ColorPalette(),
+    colors: ColorPalette = lightColorPalette(),
     typography: Typography = Typography(),
     children: @Composable() () -> Unit
 ) {
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/ProgressIndicator.kt b/ui/ui-material/src/main/java/androidx/ui/material/ProgressIndicator.kt
index 65bda9a..d1d6873 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/ProgressIndicator.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/ProgressIndicator.kt
@@ -93,7 +93,8 @@
                 color.copy(alpha = BackgroundOpacity),
                 StrokeCap.butt
             )
-            Transition(definition = LinearIndeterminateTransition, toState = 1) { state ->
+            Transition(definition = LinearIndeterminateTransition, initState = 0, toState = 1) {
+                    state ->
                 val firstLineHead = state[FirstLineHeadProp]
                 val firstLineTail = state[FirstLineTailProp]
                 val secondLineHead = state[SecondLineHeadProp]
@@ -192,7 +193,8 @@
 fun CircularProgressIndicator(color: Color = (+MaterialTheme.colors()).primary) {
     CircularIndicatorContainer {
         val paint = +paint(color, StrokeCap.square)
-        Transition(definition = CircularIndeterminateTransition, toState = 1) { state ->
+        Transition(definition = CircularIndeterminateTransition, initState = 0, toState = 1) {
+                state ->
             val currentRotation = state[IterationProp]
             val baseRotation = state[BaseRotationProp]
 
diff --git a/ui/ui-platform/api/0.1.0-dev03.txt b/ui/ui-platform/api/0.1.0-dev03.txt
index 7430747..fb841f3 100644
--- a/ui/ui-platform/api/0.1.0-dev03.txt
+++ b/ui/ui-platform/api/0.1.0-dev03.txt
@@ -361,6 +361,10 @@
 
 package androidx.ui.core.pointerinput {
 
+  public final class HitPathTrackerKt {
+    ctor public HitPathTrackerKt();
+  }
+
   public final class MotionEventAdapterKt {
     ctor public MotionEventAdapterKt();
   }
diff --git a/ui/ui-platform/api/current.txt b/ui/ui-platform/api/current.txt
index 7430747..fb841f3 100644
--- a/ui/ui-platform/api/current.txt
+++ b/ui/ui-platform/api/current.txt
@@ -361,6 +361,10 @@
 
 package androidx.ui.core.pointerinput {
 
+  public final class HitPathTrackerKt {
+    ctor public HitPathTrackerKt();
+  }
+
   public final class MotionEventAdapterKt {
     ctor public MotionEventAdapterKt();
   }
diff --git a/ui/ui-platform/api/public_plus_experimental_0.1.0-dev03.txt b/ui/ui-platform/api/public_plus_experimental_0.1.0-dev03.txt
index 7430747..fb841f3 100644
--- a/ui/ui-platform/api/public_plus_experimental_0.1.0-dev03.txt
+++ b/ui/ui-platform/api/public_plus_experimental_0.1.0-dev03.txt
@@ -361,6 +361,10 @@
 
 package androidx.ui.core.pointerinput {
 
+  public final class HitPathTrackerKt {
+    ctor public HitPathTrackerKt();
+  }
+
   public final class MotionEventAdapterKt {
     ctor public MotionEventAdapterKt();
   }
diff --git a/ui/ui-platform/api/public_plus_experimental_current.txt b/ui/ui-platform/api/public_plus_experimental_current.txt
index 7430747..fb841f3 100644
--- a/ui/ui-platform/api/public_plus_experimental_current.txt
+++ b/ui/ui-platform/api/public_plus_experimental_current.txt
@@ -361,6 +361,10 @@
 
 package androidx.ui.core.pointerinput {
 
+  public final class HitPathTrackerKt {
+    ctor public HitPathTrackerKt();
+  }
+
   public final class MotionEventAdapterKt {
     ctor public MotionEventAdapterKt();
   }
diff --git a/ui/ui-platform/api/restricted_0.1.0-dev03.txt b/ui/ui-platform/api/restricted_0.1.0-dev03.txt
index 7430747..fb841f3 100644
--- a/ui/ui-platform/api/restricted_0.1.0-dev03.txt
+++ b/ui/ui-platform/api/restricted_0.1.0-dev03.txt
@@ -361,6 +361,10 @@
 
 package androidx.ui.core.pointerinput {
 
+  public final class HitPathTrackerKt {
+    ctor public HitPathTrackerKt();
+  }
+
   public final class MotionEventAdapterKt {
     ctor public MotionEventAdapterKt();
   }
diff --git a/ui/ui-platform/api/restricted_current.txt b/ui/ui-platform/api/restricted_current.txt
index 7430747..fb841f3 100644
--- a/ui/ui-platform/api/restricted_current.txt
+++ b/ui/ui-platform/api/restricted_current.txt
@@ -361,6 +361,10 @@
 
 package androidx.ui.core.pointerinput {
 
+  public final class HitPathTrackerKt {
+    ctor public HitPathTrackerKt();
+  }
+
   public final class MotionEventAdapterKt {
     ctor public MotionEventAdapterKt();
   }
diff --git a/ui/ui-platform/src/main/java/androidx/ui/core/ComponentNodes.kt b/ui/ui-platform/src/main/java/androidx/ui/core/ComponentNodes.kt
index baef999..08db131 100644
--- a/ui/ui-platform/src/main/java/androidx/ui/core/ComponentNodes.kt
+++ b/ui/ui-platform/src/main/java/androidx/ui/core/ComponentNodes.kt
@@ -344,6 +344,8 @@
     override val repaintBoundary: RepaintBoundaryNode? get() = this
 }
 
+// TODO(b/143778512): Why are the properties vars?  Shouldn't they be vals defined in the
+//  constructor such that they both must be provided?
 /**
  * Backing node for handling pointer events.
  */
@@ -353,11 +355,13 @@
      */
     var pointerInputHandler: PointerInputHandler = { event, _, _ -> event }
 
-    // TODO(b/142486858): Should cancelHandler be called when the PointerInputNode is removed
-    //  from the hierarchy?
     /**
-     * Invoked when Android passes an ACTION_CANCEL event to the [AndroidComposeView.onTouchEvent]
-     * method.
+     * Invoked to notify the handler that no more calls to pointerInputHandler will be made, until
+     * at least new pointers exist.  This can occur for a few reasons:
+     * 1. Android dispatches ACTION_CANCEL to [AndroidComposeView.onTouchEvent].
+     * 2. The PointerInputNode has been removed from the compose hierarchy.
+     * 3. The PointerInputNode no longer has any descendant [LayoutNode]s and therefore does not
+     * know what region of the screen it should virtually exist in.
      */
     var cancelHandler: () -> Unit = { }
 }
@@ -851,7 +855,8 @@
     /**
      * The position of the inner layout node content
      */
-    val contentPosition: IntPxPosition get() = innerLayoutNodeWrapper.position
+    var contentPosition: IntPxPosition = IntPxPosition.Origin
+        private set
 
     /**
      * The size of the inner layout node content
@@ -1027,6 +1032,12 @@
         var position = Origin
 
         /**
+         * Calculate and set the content position based on the given offset and any internal
+         * positioning.
+         */
+        abstract fun calculateContentPosition(offset: IntPxPosition)
+
+        /**
          * Assigns a layout size to this [LayoutNodeWrapper] given the assigned innermost size
          * from the call to [MeasureScope.layout]. Assigns and returns [modifiedSize].
          */
@@ -1034,6 +1045,7 @@
     }
 
     private inner class InnerPlaceable : LayoutNodeWrapper(), DensityScope {
+
         override fun measure(constraints: Constraints): Placeable {
             val layoutResult = measureBlocks.measure(measureScope, layoutChildren, constraints)
             handleLayoutResult(layoutResult)
@@ -1060,8 +1072,10 @@
 
         override fun performPlace(position: IntPxPosition) {
             isPlaced = true
-            if (position != this.position) {
-                this.position = position
+            this.position = position
+            val oldContentPosition = contentPosition
+            layoutNodeWrapper.calculateContentPosition(IntPxPosition.Origin)
+            if (oldContentPosition != contentPosition) {
                 owner?.onPositionChange(this@LayoutNode)
             }
             placeChildren()
@@ -1074,7 +1088,13 @@
             return innermostSize
         }
 
-        override fun get(line: AlignmentLine): IntPx? = calculateAlignmentLines()[line]
+        override operator fun get(line: AlignmentLine): IntPx? {
+            return calculateAlignmentLines()[line]
+        }
+
+        override fun calculateContentPosition(offset: IntPxPosition) {
+            contentPosition = position + offset
+        }
     }
 
     private inner class ModifiedLayoutNode(
@@ -1145,15 +1165,20 @@
             private set
 
         override fun performPlace(position: IntPxPosition) {
+            this.position = position
             val placeable = measuredPlaceable ?: error("Placeable not measured")
-            this.position = with(layoutModifier) {
-                measureScope.modifyPosition(position, placeable.size, size)
+            val relativePosition = with(layoutModifier) {
+                measureScope.modifyPosition(placeable.size, size)
             }
-            placeable.place(this.position)
+            placeable.place(relativePosition)
         }
 
-        override fun get(line: AlignmentLine): IntPx? = with(layoutModifier) {
-            measureScope.modifyAlignmentLine(line, wrapped[line])
+        override operator fun get(line: AlignmentLine): IntPx? = with(layoutModifier) {
+            var lineValue = measureScope.modifyAlignmentLine(line, wrapped[line])
+            if (lineValue != null) {
+                lineValue += if (line.horizontal) wrapped.position.y else wrapped.position.x
+            }
+            lineValue
         }
 
         override fun layoutSize(innermostSize: IntPxSize): IntPxSize = with(layoutModifier) {
@@ -1162,6 +1187,10 @@
                 size = it
             }
         }
+
+        override fun calculateContentPosition(offset: IntPxPosition) {
+            wrapped.calculateContentPosition(position + offset)
+        }
     }
 
     internal val coordinates: LayoutCoordinates = LayoutNodeCoordinates(this)
@@ -1259,8 +1288,9 @@
                 layoutChildren.forEach { child ->
                     if (!child.isPlaced) return@forEach
                     child.alignmentLines.entries.forEach { (childLine, linePosition) ->
+                        val offset = child.contentPosition
                         val linePositionInContainer = linePosition +
-                                if (childLine.horizontal) child.y else child.x
+                                    if (childLine.horizontal) offset.y else offset.x
                         // If the line was already provided by a previous child, merge the values.
                         alignmentLines[childLine] = if (childLine in alignmentLines) {
                             childLine.merge(
diff --git a/ui/ui-platform/src/main/java/androidx/ui/core/SemanticsTreeNodeImpl.kt b/ui/ui-platform/src/main/java/androidx/ui/core/SemanticsTreeNodeImpl.kt
index 66344f6..a8f9765 100644
--- a/ui/ui-platform/src/main/java/androidx/ui/core/SemanticsTreeNodeImpl.kt
+++ b/ui/ui-platform/src/main/java/androidx/ui/core/SemanticsTreeNodeImpl.kt
@@ -81,7 +81,7 @@
         )
         parent?.addChild(wrapper)
         nodes.add(wrapper)
-        currentParent = parent
+        currentParent = wrapper
     }
 
     currentNode.visitChildren {
diff --git a/ui/ui-platform/src/main/java/androidx/ui/core/pointerinput/HitPathTracker.kt b/ui/ui-platform/src/main/java/androidx/ui/core/pointerinput/HitPathTracker.kt
index 945fb38..7aecd18 100644
--- a/ui/ui-platform/src/main/java/androidx/ui/core/pointerinput/HitPathTracker.kt
+++ b/ui/ui-platform/src/main/java/androidx/ui/core/pointerinput/HitPathTracker.kt
@@ -18,18 +18,16 @@
 
 import androidx.ui.core.IntPxPosition
 import androidx.ui.core.IntPxSize
-import androidx.ui.core.LayoutNode
 import androidx.ui.core.PointerEventPass
 import androidx.ui.core.PointerInputChange
 import androidx.ui.core.PointerInputNode
 import androidx.ui.core.hasNoLayoutDescendants
 import androidx.ui.core.ipx
-import androidx.ui.core.positionRelativeToRoot
 import androidx.ui.core.isAttached
+import androidx.ui.core.positionRelativeToRoot
 import androidx.ui.core.visitLayoutChildren
-import java.lang.IllegalStateException
-import kotlin.math.min
 import kotlin.math.max
+import kotlin.math.min
 
 /**
  * Organizes pointers and the [PointerInputNode]s that they hit into a hierarchy such that
@@ -148,6 +146,10 @@
         root.refreshPositionInformation(additionalPointerOffset)
     }
 
+    // TODO(b/145305910): removeDetachedPointerInputNodes and
+    //  removePointerInputNodesWithNoLayoutNodeDescendants should not wait to be called during
+    //  dispatching of pointer input events.  Changing PointerInputNodes to be PointerInputModifiers
+    //  will fix this for us.
     /**
      * Convenience method that removes PointerInputNodes that are no longer valid and refreshes the
      * offset information for those that are.
@@ -165,8 +167,7 @@
 // TODO(shepshapard): This really should be private. Currently some tests inspect the node's
 // directly which is unnecessary and bad practice.
 internal class Node(
-    val pointerInputNode: PointerInputNode? = null,
-    val layoutNode: LayoutNode? = null
+    val pointerInputNode: PointerInputNode? = null
 ) {
     val pointerIds: MutableSet<Int> = mutableSetOf()
     val children: MutableSet<Node> = mutableSetOf()
@@ -193,11 +194,13 @@
         }
 
         if (relevantChanges.isEmpty()) {
-            throw IllegalStateException("Currently, HitPathTracker is operating under the " +
-                    "assumption that there should never be a circumstance in which it is tracking" +
-                    " a PointerInputNode where when it receives pointerInputChanges, none are " +
-                    "relevant to that PointerInputNode.  This assumption may not hold true in " +
-                    "the future, but currently it assumes it can abide by this contract.")
+            throw IllegalStateException(
+                "Currently, HitPathTracker is operating under the assumption that there should " +
+                        "never be a circumstance in which it is tracking a PointerInputNode " +
+                        "where when it receives pointerInputChanges, none are relevant to that " +
+                        "PointerInputNode.  This assumption may not hold true in the future, but " +
+                        "currently it assumes it can abide by this contract."
+            )
         }
 
         // For each relevant change:
@@ -253,26 +256,30 @@
         children.clear()
     }
 
-    // TODO(b/142486858): Should cancel events be dispatched to PointerInputNodes that have been
-    //  removed from the tree?
     fun removeDetachedPointerInputNodes() {
-        children.removeAll {
-            it.pointerInputNode != null && !it.pointerInputNode.isAttached()
-        }
-        children.forEach {
-            it.removeDetachedPointerInputNodes()
-        }
+        children.removeAndProcess(
+            removeIf = {
+                it.pointerInputNode != null && !it.pointerInputNode.isAttached()
+            },
+            ifRemoved = {
+                it.dispatchCancel()
+            },
+            ifKept = {
+                it.removeDetachedPointerInputNodes()
+            })
     }
 
-    // TODO(shepshapard): Not sure if this functionality should exist.  The question will be moot
-    //  when/if PointerInputNodes are converted into modifiers.
     fun removePointerInputNodesWithNoLayoutNodeDescendants() {
-        children.removeAll {
-            it.pointerInputNode != null && it.pointerInputNode.hasNoLayoutDescendants()
-        }
-        children.forEach {
-            it.removePointerInputNodesWithNoLayoutNodeDescendants()
-        }
+        children.removeAndProcess(
+            removeIf = {
+                it.pointerInputNode != null && it.pointerInputNode.hasNoLayoutDescendants()
+            },
+            ifRemoved = {
+                it.dispatchCancel()
+            },
+            ifKept = {
+                it.removePointerInputNodesWithNoLayoutNodeDescendants()
+            })
     }
 
     fun removePointerId(pointerId: Int) {
@@ -353,3 +360,21 @@
         }
     }
 }
+
+private fun <T> MutableIterable<T>.removeAndProcess(
+    removeIf: (T) -> Boolean,
+    ifRemoved: (T) -> Unit,
+    ifKept: (T) -> Unit
+) {
+    with(iterator()) {
+        while (hasNext()) {
+            val next = next()
+            if (removeIf(next)) {
+                remove()
+                ifRemoved(next)
+            } else {
+                ifKept(next)
+            }
+        }
+    }
+}
diff --git a/ui/ui-platform/src/main/java/androidx/ui/core/pointerinput/PointerInputEventProcessor.kt b/ui/ui-platform/src/main/java/androidx/ui/core/pointerinput/PointerInputEventProcessor.kt
index 0b04b15..a1ba823 100644
--- a/ui/ui-platform/src/main/java/androidx/ui/core/pointerinput/PointerInputEventProcessor.kt
+++ b/ui/ui-platform/src/main/java/androidx/ui/core/pointerinput/PointerInputEventProcessor.kt
@@ -81,8 +81,6 @@
         }
     }
 
-    // TODO(b/142486858): It seems likely that removed PointerInputNodes should not have their
-    //  cancelHandlers called. Investigate this.
     /**
      * Responds appropriately to Android ACTION_CANCEL events.
      *
diff --git a/ui/ui-platform/src/test/java/androidx/ui/core/pointerinput/HitPathTrackerTest.kt b/ui/ui-platform/src/test/java/androidx/ui/core/pointerinput/HitPathTrackerTest.kt
index b7f97ab..9701856 100644
--- a/ui/ui-platform/src/test/java/androidx/ui/core/pointerinput/HitPathTrackerTest.kt
+++ b/ui/ui-platform/src/test/java/androidx/ui/core/pointerinput/HitPathTrackerTest.kt
@@ -43,6 +43,7 @@
 import com.nhaarman.mockitokotlin2.any
 import com.nhaarman.mockitokotlin2.eq
 import com.nhaarman.mockitokotlin2.inOrder
+import com.nhaarman.mockitokotlin2.never
 import com.nhaarman.mockitokotlin2.spy
 import com.nhaarman.mockitokotlin2.verify
 import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions
@@ -901,33 +902,49 @@
     }
 
     @Test
-    fun removeDetachedPointerInputNodes_complexNothingDetached_nothingRemoved() {
+    fun removeDetachedPointerInputNodes_complexNothingDetached_nothingRemovedNoCancelsCalled() {
 
         // Arrange.
 
-        val pin1 = PointerInputNode()
+        val neverCalled: () -> Unit = spy {}
 
-        val pin2 = PointerInputNode()
-        val pin3 = PointerInputNode().apply {
-            emitInsertAt(0, pin2)
+        val pin1 = PointerInputNode().apply {
+            this.cancelHandler = neverCalled
         }
 
-        val pin4 = PointerInputNode()
+        val pin2 = PointerInputNode().apply {
+            this.cancelHandler = neverCalled
+        }
+        val pin3 = PointerInputNode().apply {
+            emitInsertAt(0, pin2)
+            this.cancelHandler = neverCalled
+        }
+
+        val pin4 = PointerInputNode().apply {
+            this.cancelHandler = neverCalled
+        }
         val pin5 = PointerInputNode().apply {
             emitInsertAt(0, pin4)
+            this.cancelHandler = neverCalled
         }
         val pin6 = PointerInputNode().apply {
             emitInsertAt(0, pin5)
+            this.cancelHandler = neverCalled
         }
 
-        val pin7 = PointerInputNode()
-        val pin8 = PointerInputNode()
+        val pin7 = PointerInputNode().apply {
+            this.cancelHandler = neverCalled
+        }
+        val pin8 = PointerInputNode().apply {
+            this.cancelHandler = neverCalled
+        }
         val layoutNode = LayoutNode().apply {
             emitInsertAt(0, pin7)
             emitInsertAt(1, pin8)
         }
         val pin9 = PointerInputNode().apply {
             emitInsertAt(0, layoutNode)
+            this.cancelHandler = neverCalled
         }
 
         compositionRoot.emitInsertAt(0, pin1)
@@ -978,33 +995,48 @@
             })
         }
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+        verifyNoMoreInteractions(neverCalled)
     }
 
     //  compositionRoot, root -> middle -> leaf
     @Test
-    fun removeDetachedPointerInputNodes_1PathRootDetached_fullPathRemoved() {
-        val leaf = PointerInputNode()
+    fun removeDetachedPointerInputNodes_1PathRootDetached_allRemovedAndCorrectCancels() {
+        val leaf = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle = PointerInputNode().apply {
             emitInsertAt(0, leaf)
+            cancelHandler = spy {}
         }
         val root = PointerInputNode().apply {
             emitInsertAt(0, middle)
+            cancelHandler = spy {}
         }
         hitResult.addHitPath(0, listOf(root, middle, leaf))
 
         hitResult.removeDetachedPointerInputNodes()
 
         assertThat(areEqual(hitResult.root, Node())).isTrue()
+        inOrder(leaf.cancelHandler, middle.cancelHandler, root.cancelHandler) {
+            verify(leaf.cancelHandler).invoke()
+            verify(middle.cancelHandler).invoke()
+            verify(root.cancelHandler).invoke()
+        }
     }
 
     //  compositionRoot -> root, middle -> child
     @Test
-    fun removeDetachedPointerInputNodes_1PathMiddleDetached_itAndAncestorsRemoved() {
-        val child = PointerInputNode()
+    fun removeDetachedPointerInputNodes_1PathMiddleDetached_removesAndCancelsCorrect() {
+        val child = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle = PointerInputNode().apply {
             emitInsertAt(0, child)
+            cancelHandler = spy {}
         }
-        val root = PointerInputNode()
+        val root = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         compositionRoot.add(root)
         hitResult.addHitPath(0, listOf(root, middle, child))
 
@@ -1017,15 +1049,25 @@
         }
 
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+        inOrder(child.cancelHandler, middle.cancelHandler) {
+            verify(child.cancelHandler).invoke()
+            verify(middle.cancelHandler).invoke()
+        }
+        verify(root.cancelHandler, never()).invoke()
     }
 
     //  compositionRoot -> root -> middle, leaf
     @Test
-    fun removeDetachedPointerInputNodes_1PathLeafDetached_justLeafRemoved() {
-        val leaf = PointerInputNode()
-        val middle = PointerInputNode()
+    fun removeDetachedPointerInputNodes_1PathLeafDetached_removesAndCancelsCorrect() {
+        val leaf = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
+        val middle = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val root = PointerInputNode().apply {
             emitInsertAt(0, middle)
+            cancelHandler = spy {}
         }
         compositionRoot.add(root)
         hitResult.addHitPath(0, listOf(root, middle, leaf))
@@ -1042,35 +1084,52 @@
         }
 
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+        verify(leaf.cancelHandler).invoke()
+        verifyNoMoreInteractions(middle.cancelHandler, root.cancelHandler)
     }
 
     //  compositionRoot -> root1 -> middle1 -> leaf1
     //  compositionRoot -> root2 -> middle2 -> leaf2
     //  compositionRoot, root3 -> middle3 -> leaf3
     @Test
-    fun removeDetachedPointerInputNodes_3Roots1Detached_correctRootAndAncestorsRemoved() {
-        val leaf1 = PointerInputNode()
+    fun removeDetachedPointerInputNodes_3Roots1Detached_removesAndCancelsCorrect() {
+
+        val neverCalled: () -> Unit = spy {}
+
+        val leaf1 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
         val middle1 = PointerInputNode().apply {
             emitInsertAt(0, leaf1)
+            cancelHandler = neverCalled
         }
         val root1 = PointerInputNode().apply {
             emitInsertAt(0, middle1)
+            cancelHandler = neverCalled
         }
 
-        val leaf2 = PointerInputNode()
+        val leaf2 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
         val middle2 = PointerInputNode().apply {
             emitInsertAt(0, leaf2)
+            cancelHandler = neverCalled
         }
         val root2 = PointerInputNode().apply {
             emitInsertAt(0, middle2)
+            cancelHandler = neverCalled
         }
 
-        val leaf3 = PointerInputNode()
+        val leaf3 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle3 = PointerInputNode().apply {
             emitInsertAt(0, leaf3)
+            cancelHandler = spy {}
         }
         val root3 = PointerInputNode().apply {
             emitInsertAt(0, middle3)
+            cancelHandler = spy {}
         }
 
         compositionRoot.emitInsertAt(0, root1)
@@ -1104,33 +1163,55 @@
         }
 
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+        inOrder(leaf3.cancelHandler, middle3.cancelHandler, root3.cancelHandler) {
+            verify(leaf3.cancelHandler).invoke()
+            verify(middle3.cancelHandler).invoke()
+            verify(root3.cancelHandler).invoke()
+        }
+        verify(neverCalled, never()).invoke()
     }
 
     //  compositionRoot -> root1, middle1 -> leaf1
     //  compositionRoot -> root2 -> middle2 -> leaf2
     //  compositionRoot -> root3 -> middle3 -> leaf3
     @Test
-    fun removeDetachedPointerInputNodes_3Roots1MiddleDetached_correctMiddleAndAncestorsRemoved() {
-        val leaf1 = PointerInputNode()
+    fun removeDetachedPointerInputNodes_3Roots1MiddleDetached_removesAndCancelsCorrect() {
+
+        val neverCalled: () -> Unit = spy {}
+
+        val leaf1 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle1 = PointerInputNode().apply {
             emitInsertAt(0, leaf1)
+            cancelHandler = spy {}
         }
-        val root1 = PointerInputNode()
+        val root1 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
 
-        val leaf2 = PointerInputNode()
+        val leaf2 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
         val middle2 = PointerInputNode().apply {
             emitInsertAt(0, leaf2)
+            cancelHandler = neverCalled
         }
         val root2 = PointerInputNode().apply {
             emitInsertAt(0, middle2)
+            cancelHandler = neverCalled
         }
 
-        val leaf3 = PointerInputNode()
+        val leaf3 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
         val middle3 = PointerInputNode().apply {
             emitInsertAt(0, leaf3)
+            cancelHandler = neverCalled
         }
         val root3 = PointerInputNode().apply {
             emitInsertAt(0, middle3)
+            cancelHandler = neverCalled
         }
 
         compositionRoot.emitInsertAt(0, root1)
@@ -1168,33 +1249,54 @@
         }
 
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+        inOrder(leaf1.cancelHandler, middle1.cancelHandler) {
+            verify(leaf1.cancelHandler).invoke()
+            verify(middle1.cancelHandler).invoke()
+        }
+        verify(neverCalled, never()).invoke()
     }
 
     //  compositionRoot -> root1 -> middle1 -> leaf1
     //  compositionRoot -> root2 -> middle2, leaf2
     //  compositionRoot -> root3 -> middle3 -> leaf3
     @Test
-    fun removeDetachedPointerInputNodes_3Roots1LeafDetached_correctLeafRemoved() {
-        val leaf1 = PointerInputNode()
+    fun removeDetachedPointerInputNodes_3Roots1LeafDetached_removesAndCancelsCorrect() {
+
+        val neverCalled: () -> Unit = spy {}
+
+        val leaf1 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
         val middle1 = PointerInputNode().apply {
             emitInsertAt(0, leaf1)
+            cancelHandler = neverCalled
         }
         val root1 = PointerInputNode().apply {
             emitInsertAt(0, middle1)
+            cancelHandler = neverCalled
         }
 
-        val leaf2 = PointerInputNode()
-        val middle2 = PointerInputNode()
+        val leaf2 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
+        val middle2 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
         val root2 = PointerInputNode().apply {
             emitInsertAt(0, middle2)
+            cancelHandler = neverCalled
         }
 
-        val leaf3 = PointerInputNode()
+        val leaf3 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
         val middle3 = PointerInputNode().apply {
             emitInsertAt(0, leaf3)
+            cancelHandler = neverCalled
         }
         val root3 = PointerInputNode().apply {
             emitInsertAt(0, middle3)
+            cancelHandler = neverCalled
         }
 
         compositionRoot.emitInsertAt(0, root1)
@@ -1235,35 +1337,52 @@
         }
 
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+        verify(leaf2.cancelHandler).invoke()
+        verify(neverCalled, never()).invoke()
     }
 
     //  compositionRoot, root1 -> middle1 -> leaf1
     //  compositionRoot -> root2 -> middle2 -> leaf2
     //  compositionRoot, root3 -> middle3 -> leaf3
     @Test
-    fun removeDetachedPointerInputNodes_3Roots2Detached_correct2RootsAndAncestorsRemoved() {
-        val leaf1 = PointerInputNode()
+    fun removeDetachedPointerInputNodes_3Roots2Detached_removesAndCancelsCorrect() {
+
+        val neverCalled: () -> Unit = spy {}
+
+        val leaf1 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle1 = PointerInputNode().apply {
             emitInsertAt(0, leaf1)
+            cancelHandler = spy {}
         }
         val root1 = PointerInputNode().apply {
             emitInsertAt(0, middle1)
+            cancelHandler = spy {}
         }
 
-        val leaf2 = PointerInputNode()
+        val leaf2 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
         val middle2 = PointerInputNode().apply {
             emitInsertAt(0, leaf2)
+            cancelHandler = neverCalled
         }
         val root2 = PointerInputNode().apply {
             emitInsertAt(0, middle2)
+            cancelHandler = neverCalled
         }
 
-        val leaf3 = PointerInputNode()
+        val leaf3 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle3 = PointerInputNode().apply {
             emitInsertAt(0, leaf3)
+            cancelHandler = spy {}
         }
         val root3 = PointerInputNode().apply {
             emitInsertAt(0, middle3)
+            cancelHandler = spy {}
         }
 
         compositionRoot.emitInsertAt(0, root2)
@@ -1287,31 +1406,60 @@
         }
 
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+
+        inOrder(leaf1.cancelHandler, middle1.cancelHandler, root1.cancelHandler) {
+            verify(leaf1.cancelHandler).invoke()
+            verify(middle1.cancelHandler).invoke()
+            verify(root1.cancelHandler).invoke()
+        }
+        inOrder(leaf3.cancelHandler, middle3.cancelHandler, root3.cancelHandler) {
+            verify(leaf3.cancelHandler).invoke()
+            verify(middle3.cancelHandler).invoke()
+            verify(root3.cancelHandler).invoke()
+        }
+        verify(neverCalled, never()).invoke()
     }
 
     //  compositionRoot -> root1, middle1 -> leaf1
     //  compositionRoot -> root2, middle2 -> leaf2
     //  compositionRoot -> root3 -> middle3 -> leaf3
     @Test
-    fun removeDetachedPointerInputNodes_3Roots2MiddlesDetached_correct2NodesAndAncestorsRemoved() {
-        val leaf1 = PointerInputNode()
+    fun removeDetachedPointerInputNodes_3Roots2MiddlesDetached_removesAndCancelsCorrect() {
+
+        val neverCalled: () -> Unit = spy {}
+
+        val leaf1 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle1 = PointerInputNode().apply {
             emitInsertAt(0, leaf1)
+            cancelHandler = spy {}
         }
-        val root1 = PointerInputNode()
+        val root1 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
 
-        val leaf2 = PointerInputNode()
+        val leaf2 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle2 = PointerInputNode().apply {
             emitInsertAt(0, leaf2)
+            cancelHandler = spy {}
         }
-        val root2 = PointerInputNode()
+        val root2 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
 
-        val leaf3 = PointerInputNode()
+        val leaf3 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
         val middle3 = PointerInputNode().apply {
             emitInsertAt(0, leaf3)
+            cancelHandler = neverCalled
         }
         val root3 = PointerInputNode().apply {
             emitInsertAt(0, middle3)
+            cancelHandler = neverCalled
         }
 
         compositionRoot.emitInsertAt(0, root1)
@@ -1343,31 +1491,58 @@
         }
 
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+
+        inOrder(leaf1.cancelHandler, middle1.cancelHandler) {
+            verify(leaf1.cancelHandler).invoke()
+            verify(middle1.cancelHandler).invoke()
+        }
+        inOrder(leaf2.cancelHandler, middle2.cancelHandler) {
+            verify(leaf2.cancelHandler).invoke()
+            verify(middle2.cancelHandler).invoke()
+        }
+        verify(neverCalled, never()).invoke()
     }
 
     //  compositionRoot -> root1 -> middle1 -> leaf1
     //  compositionRoot -> root2 -> middle2, leaf2
     //  compositionRoot -> root3 -> middle3, leaf3
     @Test
-    fun removeDetachedPointerInputNodes_3Roots2LeafsDetached_correct2LeafsRemoved() {
-        val leaf1 = PointerInputNode()
+    fun removeDetachedPointerInputNodes_3Roots2LeafsDetached_removesAndCancelsCorrect() {
+
+        val neverCalled: () -> Unit = spy {}
+
+        val leaf1 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
         val middle1 = PointerInputNode().apply {
             emitInsertAt(0, leaf1)
+            cancelHandler = neverCalled
         }
         val root1 = PointerInputNode().apply {
             emitInsertAt(0, middle1)
+            cancelHandler = neverCalled
         }
 
-        val leaf2 = PointerInputNode()
-        val middle2 = PointerInputNode()
+        val leaf2 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
+        val middle2 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
         val root2 = PointerInputNode().apply {
             emitInsertAt(0, middle2)
+            cancelHandler = neverCalled
         }
 
-        val leaf3 = PointerInputNode()
-        val middle3 = PointerInputNode()
+        val leaf3 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
+        val middle3 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
         val root3 = PointerInputNode().apply {
             emitInsertAt(0, middle3)
+            cancelHandler = neverCalled
         }
 
         compositionRoot.emitInsertAt(0, root1)
@@ -1405,35 +1580,50 @@
         }
 
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+        verify(leaf2.cancelHandler).invoke()
+        verify(leaf3.cancelHandler).invoke()
+        verify(neverCalled, never()).invoke()
     }
 
     //  compositionRoot, root1 -> middle1 -> leaf1
     //  compositionRoot, root2 -> middle2 -> leaf2
     //  compositionRoot, root3 -> middle3 -> leaf3
     @Test
-    fun removeDetachedPointerInputNodes_3Roots3Detached_all3RootsAndAncestorsRemoved() {
-        val leaf1 = PointerInputNode()
+    fun removeDetachedPointerInputNodes_3Roots3Detached_allRemovedAndCancelsCorrect() {
+        val leaf1 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle1 = PointerInputNode().apply {
             emitInsertAt(0, leaf1)
+            cancelHandler = spy {}
         }
         val root1 = PointerInputNode().apply {
             emitInsertAt(0, middle1)
+            cancelHandler = spy {}
         }
 
-        val leaf2 = PointerInputNode()
+        val leaf2 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle2 = PointerInputNode().apply {
             emitInsertAt(0, leaf2)
+            cancelHandler = spy {}
         }
         val root2 = PointerInputNode().apply {
             emitInsertAt(0, middle2)
+            cancelHandler = spy {}
         }
 
-        val leaf3 = PointerInputNode()
+        val leaf3 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle3 = PointerInputNode().apply {
             emitInsertAt(0, leaf3)
+            cancelHandler = spy {}
         }
         val root3 = PointerInputNode().apply {
             emitInsertAt(0, middle3)
+            cancelHandler = spy {}
         }
 
         hitResult.addHitPath(3, listOf(root1, middle1, leaf1))
@@ -1445,30 +1635,63 @@
         val expectedRoot = Node()
 
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+        inOrder(leaf1.cancelHandler, middle1.cancelHandler, root1.cancelHandler) {
+            verify(leaf1.cancelHandler).invoke()
+            verify(middle1.cancelHandler).invoke()
+            verify(root1.cancelHandler).invoke()
+        }
+        inOrder(leaf2.cancelHandler, middle2.cancelHandler, root2.cancelHandler) {
+            verify(leaf2.cancelHandler).invoke()
+            verify(middle2.cancelHandler).invoke()
+            verify(root2.cancelHandler).invoke()
+        }
+        inOrder(leaf3.cancelHandler, middle3.cancelHandler, root3.cancelHandler) {
+            verify(leaf3.cancelHandler).invoke()
+            verify(middle3.cancelHandler).invoke()
+            verify(root3.cancelHandler).invoke()
+        }
     }
 
     //  compositionRoot -> root1, middle1 -> leaf1
     //  compositionRoot -> root2, middle2 -> leaf2
     //  compositionRoot -> root3, middle3 -> leaf3
     @Test
-    fun removeDetachedPointerInputNodes_3Roots3MiddlesDetached_all3MiddlesAndAncestorsRemoved() {
-        val leaf1 = PointerInputNode()
+    fun removeDetachedPointerInputNodes_3Roots3MiddlesDetached_removesAndCancelsCorrect() {
+
+        val neverCalled: () -> Unit = spy {}
+
+        val leaf1 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle1 = PointerInputNode().apply {
             emitInsertAt(0, leaf1)
+            cancelHandler = spy {}
         }
-        val root1 = PointerInputNode()
+        val root1 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
 
-        val leaf2 = PointerInputNode()
+        val leaf2 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle2 = PointerInputNode().apply {
             emitInsertAt(0, leaf2)
+            cancelHandler = spy {}
         }
-        val root2 = PointerInputNode()
+        val root2 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
 
-        val leaf3 = PointerInputNode()
+        val leaf3 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle3 = PointerInputNode().apply {
             emitInsertAt(0, leaf3)
+            cancelHandler = spy {}
         }
-        val root3 = PointerInputNode()
+        val root3 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
 
         compositionRoot.emitInsertAt(0, root1)
         compositionRoot.emitInsertAt(1, root2)
@@ -1493,29 +1716,60 @@
         }
 
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+        inOrder(leaf1.cancelHandler, middle1.cancelHandler) {
+            verify(leaf1.cancelHandler).invoke()
+            verify(middle1.cancelHandler).invoke()
+        }
+        inOrder(leaf2.cancelHandler, middle2.cancelHandler) {
+            verify(leaf2.cancelHandler).invoke()
+            verify(middle2.cancelHandler).invoke()
+        }
+        inOrder(leaf3.cancelHandler, middle3.cancelHandler) {
+            verify(leaf3.cancelHandler).invoke()
+            verify(middle3.cancelHandler).invoke()
+        }
+        verify(neverCalled, never()).invoke()
     }
 
     //  compositionRoot -> root1 -> middle1, leaf1
     //  compositionRoot -> root2 -> middle2, leaf2
     //  compositionRoot -> root3 -> middle3, leaf3
     @Test
-    fun removeDetachedPointerInputNodes_3Roots3LeafsDetached_all3LeafsRemoved() {
-        val leaf1 = PointerInputNode()
-        val middle1 = PointerInputNode()
+    fun removeDetachedPointerInputNodes_3Roots3LeafsDetached_removesAndCancelsCorrect() {
+
+        val neverCalled: () -> Unit = spy {}
+
+        val leaf1 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
+        val middle1 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
         val root1 = PointerInputNode().apply {
             emitInsertAt(0, middle1)
+            cancelHandler = neverCalled
         }
 
-        val leaf2 = PointerInputNode()
-        val middle2 = PointerInputNode()
+        val leaf2 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
+        val middle2 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
         val root2 = PointerInputNode().apply {
             emitInsertAt(0, middle2)
+            cancelHandler = neverCalled
         }
 
-        val leaf3 = PointerInputNode()
-        val middle3 = PointerInputNode()
+        val leaf3 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
+        val middle3 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
         val root3 = PointerInputNode().apply {
             emitInsertAt(0, middle3)
+            cancelHandler = neverCalled
         }
 
         compositionRoot.emitInsertAt(0, root1)
@@ -1550,31 +1804,52 @@
         }
 
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+        verify(leaf1.cancelHandler).invoke()
+        verify(leaf2.cancelHandler).invoke()
+        verify(leaf3.cancelHandler).invoke()
+        verify(neverCalled, never()).invoke()
     }
 
     // compositionRoot, root1 -> middle1 -> leaf1
     // compositionRoot -> root2, middle2, leaf2
     // compositionRoot -> root3 -> middle3, leaf3
     @Test
-    fun removeDetachedPointerInputNodes_3RootsStaggeredDetached_correctPathsRemoved() {
-        val leaf1 = PointerInputNode()
+    fun removeDetachedPointerInputNodes_3RootsStaggeredDetached_removesAndCancelsCorrect() {
+
+        val neverCalled: () -> Unit = spy {}
+
+        val leaf1 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle1 = PointerInputNode().apply {
             emitInsertAt(0, leaf1)
+            cancelHandler = spy {}
         }
         val root1 = PointerInputNode().apply {
             emitInsertAt(0, middle1)
+            cancelHandler = spy {}
         }
 
-        val leaf2 = PointerInputNode()
+        val leaf2 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle2 = PointerInputNode().apply {
             emitInsertAt(0, leaf2)
+            cancelHandler = spy {}
         }
-        val root2 = PointerInputNode()
+        val root2 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
 
-        val leaf3 = PointerInputNode()
-        val middle3 = PointerInputNode()
+        val leaf3 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
+        val middle3 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
         val root3 = PointerInputNode().apply {
             emitInsertAt(0, middle3)
+            cancelHandler = neverCalled
         }
 
         compositionRoot.emitInsertAt(0, root2)
@@ -1599,6 +1874,17 @@
         }
 
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+        inOrder(leaf1.cancelHandler, middle1.cancelHandler, root1.cancelHandler) {
+            verify(leaf1.cancelHandler).invoke()
+            verify(middle1.cancelHandler).invoke()
+            verify(root1.cancelHandler).invoke()
+        }
+        inOrder(leaf2.cancelHandler, middle2.cancelHandler) {
+            verify(leaf2.cancelHandler).invoke()
+            verify(middle2.cancelHandler).invoke()
+        }
+        verify(leaf3.cancelHandler).invoke()
+        verify(neverCalled, never()).invoke()
     }
 
     // compositionRoot, root ->
@@ -1606,20 +1892,29 @@
     //   layoutNode -> middle2 -> leaf2
     //   layoutNode -> middle3 -> leaf3
     @Test
-    fun removeDetachedPointerInputNodes_rootWith3MiddlesDetached_allRemoved() {
-        val leaf1 = PointerInputNode()
+    fun removeDetachedPointerInputNodes_rootWith3MiddlesDetached_allRemovedAndCorrectCancels() {
+        val leaf1 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle1 = PointerInputNode().apply {
             emitInsertAt(0, leaf1)
+            cancelHandler = spy {}
         }
 
-        val leaf2 = PointerInputNode()
+        val leaf2 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle2 = PointerInputNode().apply {
             emitInsertAt(0, leaf2)
+            cancelHandler = spy {}
         }
 
-        val leaf3 = PointerInputNode()
+        val leaf3 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle3 = PointerInputNode().apply {
             emitInsertAt(0, leaf3)
+            cancelHandler = spy {}
         }
 
         val layoutNode = LayoutNode().apply {
@@ -1630,6 +1925,7 @@
 
         val root = PointerInputNode().apply {
             emitInsertAt(0, layoutNode)
+            cancelHandler = spy {}
         }
 
         hitResult.addHitPath(3, listOf(root, middle1, leaf1))
@@ -1641,6 +1937,21 @@
         val expectedRoot = Node()
 
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+        inOrder(leaf1.cancelHandler, middle1.cancelHandler, root.cancelHandler) {
+            verify(leaf1.cancelHandler).invoke()
+            verify(middle1.cancelHandler).invoke()
+            verify(root.cancelHandler).invoke()
+        }
+        inOrder(leaf2.cancelHandler, middle2.cancelHandler, root.cancelHandler) {
+            verify(leaf2.cancelHandler).invoke()
+            verify(middle2.cancelHandler).invoke()
+            verify(root.cancelHandler).invoke()
+        }
+        inOrder(leaf3.cancelHandler, middle3.cancelHandler, root.cancelHandler) {
+            verify(leaf3.cancelHandler).invoke()
+            verify(middle3.cancelHandler).invoke()
+            verify(root.cancelHandler).invoke()
+        }
     }
 
     // compositionRoot -> root ->
@@ -1648,20 +1959,32 @@
     //   layoutNode -> middle2 -> leaf2
     //   layoutNode, middle3 -> leaf3
     @Test
-    fun removeDetachedPointerInputNodes_rootWith3Middles1Detached_correctMiddleRemoved() {
-        val leaf1 = PointerInputNode()
+    fun removeDetachedPointerInputNodes_rootWith3Middles1Detached_removesAndCancelsCorrect() {
+
+        val neverCalled: () -> Unit = spy {}
+
+        val leaf1 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
         val middle1 = PointerInputNode().apply {
             emitInsertAt(0, leaf1)
+            cancelHandler = neverCalled
         }
 
-        val leaf2 = PointerInputNode()
+        val leaf2 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
         val middle2 = PointerInputNode().apply {
             emitInsertAt(0, leaf2)
+            cancelHandler = neverCalled
         }
 
-        val leaf3 = PointerInputNode()
+        val leaf3 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle3 = PointerInputNode().apply {
             emitInsertAt(0, leaf3)
+            cancelHandler = spy {}
         }
 
         val layoutNode = LayoutNode().apply {
@@ -1671,6 +1994,7 @@
 
         val root = PointerInputNode().apply {
             emitInsertAt(0, layoutNode)
+            cancelHandler = neverCalled
         }
 
         compositionRoot.emitInsertAt(0, root)
@@ -1702,6 +2026,11 @@
         }
 
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+        inOrder(leaf3.cancelHandler, middle3.cancelHandler) {
+            verify(leaf3.cancelHandler).invoke()
+            verify(middle3.cancelHandler).invoke()
+        }
+        verify(neverCalled, never()).invoke()
     }
 
     // compositionRoot -> root ->
@@ -1709,20 +2038,32 @@
     //   layoutNode, middle2 -> leaf2
     //   layoutNode -> middle3 -> leaf3
     @Test
-    fun removeDetachedPointerInputNodes_rootWith3Middles2Detached_correctMiddlesRemoved() {
-        val leaf1 = PointerInputNode()
+    fun removeDetachedPointerInputNodes_rootWith3Middles2Detached_removesAndCancelsCorrect() {
+
+        val neverCalled: () -> Unit = spy {}
+
+        val leaf1 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle1 = PointerInputNode().apply {
             emitInsertAt(0, leaf1)
+            cancelHandler = spy {}
         }
 
-        val leaf2 = PointerInputNode()
+        val leaf2 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle2 = PointerInputNode().apply {
             emitInsertAt(0, leaf2)
+            cancelHandler = spy {}
         }
 
-        val leaf3 = PointerInputNode()
+        val leaf3 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
         val middle3 = PointerInputNode().apply {
             emitInsertAt(0, leaf3)
+            cancelHandler = neverCalled
         }
 
         val layoutNode = LayoutNode().apply {
@@ -1731,6 +2072,7 @@
 
         val root = PointerInputNode().apply {
             emitInsertAt(0, layoutNode)
+            cancelHandler = neverCalled
         }
 
         compositionRoot.emitInsertAt(0, root)
@@ -1756,6 +2098,15 @@
         }
 
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+        inOrder(leaf1.cancelHandler, middle1.cancelHandler) {
+            verify(leaf1.cancelHandler).invoke()
+            verify(middle1.cancelHandler).invoke()
+        }
+        inOrder(leaf2.cancelHandler, middle2.cancelHandler) {
+            verify(leaf2.cancelHandler).invoke()
+            verify(middle2.cancelHandler).invoke()
+        }
+        verify(neverCalled, never()).invoke()
     }
 
     // compositionRoot -> root ->
@@ -1764,25 +2115,38 @@
     //   layoutNode, middle3 -> leaf3
     @Test
     fun removeDetachedPointerInputNodes_rootWith3MiddlesAllDetached_allMiddlesRemoved() {
-        val leaf1 = PointerInputNode()
+
+        val neverCalled: () -> Unit = spy {}
+
+        val leaf1 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle1 = PointerInputNode().apply {
             emitInsertAt(0, leaf1)
+            cancelHandler = spy {}
         }
 
-        val leaf2 = PointerInputNode()
+        val leaf2 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle2 = PointerInputNode().apply {
             emitInsertAt(0, leaf2)
+            cancelHandler = spy {}
         }
 
-        val leaf3 = PointerInputNode()
+        val leaf3 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val middle3 = PointerInputNode().apply {
             emitInsertAt(0, leaf3)
+            cancelHandler = spy {}
         }
 
         val layoutNode = LayoutNode()
 
         val root = PointerInputNode().apply {
             emitInsertAt(0, layoutNode)
+            cancelHandler = neverCalled
         }
 
         compositionRoot.emitInsertAt(0, root)
@@ -1802,6 +2166,19 @@
         }
 
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+        inOrder(leaf1.cancelHandler, middle1.cancelHandler) {
+            verify(leaf1.cancelHandler).invoke()
+            verify(middle1.cancelHandler).invoke()
+        }
+        inOrder(leaf2.cancelHandler, middle2.cancelHandler) {
+            verify(leaf2.cancelHandler).invoke()
+            verify(middle2.cancelHandler).invoke()
+        }
+        inOrder(leaf3.cancelHandler, middle3.cancelHandler) {
+            verify(leaf3.cancelHandler).invoke()
+            verify(middle3.cancelHandler).invoke()
+        }
+        verify(neverCalled, never()).invoke()
     }
 
     // compositionRoot -> root -> middle ->
@@ -1810,9 +2187,18 @@
     //   layoutNode -> leaf3
     @Test
     fun removeDetachedPointerInputNodes_middleWith3Leafs1Detached_correctLeafRemoved() {
-        val leaf1 = PointerInputNode()
-        val leaf2 = PointerInputNode()
-        val leaf3 = PointerInputNode()
+
+        val neverCalled: () -> Unit = spy {}
+
+        val leaf1 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
+        val leaf2 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
+        val leaf3 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
 
         val layoutNode = LayoutNode().apply {
             emitInsertAt(0, leaf1)
@@ -1821,10 +2207,12 @@
 
         val middle = PointerInputNode().apply {
             emitInsertAt(0, layoutNode)
+            cancelHandler = neverCalled
         }
 
         val root = PointerInputNode().apply {
             emitInsertAt(0, middle)
+            cancelHandler = neverCalled
         }
 
         compositionRoot.emitInsertAt(0, root)
@@ -1855,6 +2243,8 @@
         }
 
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+        verify(leaf2.cancelHandler).invoke()
+        verify(neverCalled, never()).invoke()
     }
 
     // compositionRoot -> root -> middle ->
@@ -1863,9 +2253,18 @@
     //   layoutNode, leaf3
     @Test
     fun removeDetachedPointerInputNodes_middleWith3Leafs2Detached_correctLeafsRemoved() {
-        val leaf1 = PointerInputNode()
-        val leaf2 = PointerInputNode()
-        val leaf3 = PointerInputNode()
+
+        val neverCalled: () -> Unit = spy {}
+
+        val leaf1 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
+        val leaf2 = PointerInputNode().apply {
+            cancelHandler = neverCalled
+        }
+        val leaf3 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
 
         val layoutNode = LayoutNode().apply {
             emitInsertAt(0, leaf2)
@@ -1873,10 +2272,12 @@
 
         val middle = PointerInputNode().apply {
             emitInsertAt(0, layoutNode)
+            cancelHandler = neverCalled
         }
 
         val root = PointerInputNode().apply {
             emitInsertAt(0, middle)
+            cancelHandler = neverCalled
         }
 
         compositionRoot.emitInsertAt(0, root)
@@ -1904,6 +2305,9 @@
         }
 
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+        verify(leaf1.cancelHandler).invoke()
+        verify(leaf3.cancelHandler).invoke()
+        verify(neverCalled, never()).invoke()
     }
 
     // compositionRoot -> root -> middle ->
@@ -1912,18 +2316,29 @@
     //   layoutNode, leaf3
     @Test
     fun removeDetachedPointerInputNodes_middleWith3LeafsAllDetached_allLeafsRemoved() {
-        val leaf1 = PointerInputNode()
-        val leaf2 = PointerInputNode()
-        val leaf3 = PointerInputNode()
+
+        val neverCalled: () -> Unit = spy {}
+
+        val leaf1 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
+        val leaf2 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
+        val leaf3 = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
 
         val layoutNode = LayoutNode()
 
         val middle = PointerInputNode().apply {
             emitInsertAt(0, layoutNode)
+            cancelHandler = neverCalled
         }
 
         val root = PointerInputNode().apply {
             emitInsertAt(0, middle)
+            cancelHandler = neverCalled
         }
 
         compositionRoot.emitInsertAt(0, root)
@@ -1948,6 +2363,10 @@
         }
 
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+        verify(leaf1.cancelHandler).invoke()
+        verify(leaf2.cancelHandler).invoke()
+        verify(leaf3.cancelHandler).invoke()
+        verify(neverCalled, never()).invoke()
     }
 
     @Test
@@ -1962,27 +2381,32 @@
 
     // PointerInputNode
     @Test
-    fun removePointerInputNodesWithNoLayoutNodeDescendants_justPin_pinRemoved() {
-        val pointerInputNode = PointerInputNode()
-        hitResult.addHitPath(0, listOf(pointerInputNode))
-
-        hitResult.removePointerInputNodesWithNoLayoutNodeDescendants()
-
-        assertThat(areEqual(hitResult.root, Node())).isTrue()
-    }
-
-    // PointerInputNode -> DrawNode
-    @Test
-    fun removePointerInputNodesWithNoLayoutNodeDescendants_dnInPin_pinRemoved() {
-        val drawNode = DrawNode()
+    fun removePointerInputNodesWithNoLayoutNodeDescendants_justPin_pinRemovedCancelCalledOnce() {
         val pointerInputNode = PointerInputNode().apply {
-            emitInsertAt(0, drawNode)
+            cancelHandler = spy {}
         }
         hitResult.addHitPath(0, listOf(pointerInputNode))
 
         hitResult.removePointerInputNodesWithNoLayoutNodeDescendants()
 
         assertThat(areEqual(hitResult.root, Node())).isTrue()
+        verify(pointerInputNode.cancelHandler).invoke()
+    }
+
+    // PointerInputNode -> DrawNode
+    @Test
+    fun removePointerInputNodesWithNoLayoutNodeDescendants_dnInPin_pinRemovedCancelCalledOnce() {
+        val drawNode = DrawNode()
+        val pointerInputNode = PointerInputNode().apply {
+            emitInsertAt(0, drawNode)
+            cancelHandler = spy {}
+        }
+        hitResult.addHitPath(0, listOf(pointerInputNode))
+
+        hitResult.removePointerInputNodesWithNoLayoutNodeDescendants()
+
+        assertThat(areEqual(hitResult.root, Node())).isTrue()
+        verify(pointerInputNode.cancelHandler).invoke()
     }
 
     // PointerInputNode -> SemanticsNode
@@ -1991,54 +2415,69 @@
         val semanticsNode = SemanticsComponentNode()
         val pointerInputNode = PointerInputNode().apply {
             emitInsertAt(0, semanticsNode)
+            cancelHandler = spy {}
         }
         hitResult.addHitPath(0, listOf(pointerInputNode))
 
         hitResult.removePointerInputNodesWithNoLayoutNodeDescendants()
 
         assertThat(areEqual(hitResult.root, Node())).isTrue()
+        verify(pointerInputNode.cancelHandler).invoke()
     }
 
     // PointerInputNode A -> PointerInputNode B -> SemanticsNode
     @Test
-    fun removePointerInputNodesWithNoLayoutNodeDescendants_smInPinInPin_pinsRemoved() {
+    fun removePointerInputNodesWithNoLayoutNodeDescendants_smInPinInPin_removesAndCancelsCorrect() {
         val semanticsNode = SemanticsComponentNode()
         val pointerInputNodeB = PointerInputNode().apply {
             emitInsertAt(0, semanticsNode)
+            cancelHandler = spy {}
         }
         val pointerInputNodeA = PointerInputNode().apply {
             emitInsertAt(0, pointerInputNodeB)
+            cancelHandler = spy {}
         }
         hitResult.addHitPath(0, listOf(pointerInputNodeA, pointerInputNodeB))
 
         hitResult.removePointerInputNodesWithNoLayoutNodeDescendants()
 
         assertThat(areEqual(hitResult.root, Node())).isTrue()
+        inOrder(pointerInputNodeB.cancelHandler, pointerInputNodeA.cancelHandler) {
+            verify(pointerInputNodeB.cancelHandler).invoke()
+            verify(pointerInputNodeA.cancelHandler).invoke()
+        }
     }
 
     // PointerInputNode A -> PointerInputNode B -> DrawNode
     @Test
-    fun removePointerInputNodesWithNoLayoutNodeDescendants_dnInPinInPin_pisnRemoved() {
+    fun removePointerInputNodesWithNoLayoutNodeDescendants_dnInPinInPin_removesAndCancelsCorrect() {
         val drawnode = DrawNode()
         val pointerInputNodeB = PointerInputNode().apply {
             emitInsertAt(0, drawnode)
+            cancelHandler = spy {}
         }
         val pointerInputNodeA = PointerInputNode().apply {
             emitInsertAt(0, pointerInputNodeB)
+            cancelHandler = spy {}
         }
         hitResult.addHitPath(0, listOf(pointerInputNodeA, pointerInputNodeB))
 
         hitResult.removePointerInputNodesWithNoLayoutNodeDescendants()
 
         assertThat(areEqual(hitResult.root, Node())).isTrue()
+        inOrder(pointerInputNodeB.cancelHandler, pointerInputNodeA.cancelHandler) {
+            verify(pointerInputNodeB.cancelHandler).invoke()
+            verify(pointerInputNodeA.cancelHandler).invoke()
+        }
     }
 
     // PointerInputNode -> LayoutNode
     @Test
-    fun removePointerInputNodesWithNoLayoutNodeDescendants_pinWithLn_nothingRemoved() {
+    fun removePointerInputNodesWithNoLayoutNodeDescendants_pinWithLn_noRemovesOrCancels() {
         val layoutNode = LayoutNode(0, 0, 100, 100)
         val pointerInputNode = PointerInputNode().apply {
             emitInsertAt(0, layoutNode)
+            cancelHandler = spy {}
         }
         hitResult.addHitPath(0, listOf(pointerInputNode))
 
@@ -2048,17 +2487,23 @@
             children.add(Node(pointerInputNode).apply { pointerIds.add(0) })
         }
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+        verify(pointerInputNode.cancelHandler, never()).invoke()
     }
 
     // PointerInputNode A -> PointerInputNode B -> LayoutNode
     @Test
-    fun removePointerInputNodesWithNoLayoutNodeDescendants_lnInPinInPin_nothingRemoved() {
+    fun removePointerInputNodesWithNoLayoutNodeDescendants_lnInPinInPin_noRemovesOrCancels() {
+
+        val neverCalled: () -> Unit = spy {}
+
         val layoutNode = LayoutNode(0, 0, 100, 100)
         val pointerInputNodeB = PointerInputNode().apply {
             emitInsertAt(0, layoutNode)
+            cancelHandler = neverCalled
         }
         val pointerInputNodeA = PointerInputNode().apply {
             emitInsertAt(0, pointerInputNodeB)
+            cancelHandler = neverCalled
         }
         hitResult.addHitPath(0, listOf(pointerInputNodeA, pointerInputNodeB))
 
@@ -2074,17 +2519,21 @@
         }
 
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+        verify(neverCalled, never()).invoke()
     }
 
     // PointerInputNode A -> LayoutNode -> PointerInputNode B
     @Test
-    fun removePointerInputNodesWithNoLayoutNodeDescendants_PinInLnInPin_childPinRemoved() {
-        val pointerInputNodeB = PointerInputNode()
+    fun removePointerInputNodesWithNoLayoutNodeDescendants_PinInLnInPin_removesAndCancelsCorrect() {
+        val pointerInputNodeB = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val layoutNode = LayoutNode(0, 0, 100, 100).apply {
             emitInsertAt(0, pointerInputNodeB)
         }
         val pointerInputNodeA = PointerInputNode().apply {
             emitInsertAt(0, layoutNode)
+            cancelHandler = spy {}
         }
         hitResult.addHitPath(0, listOf(pointerInputNodeA, pointerInputNodeB))
 
@@ -2097,20 +2546,29 @@
         }
 
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+        verify(pointerInputNodeB.cancelHandler).invoke()
+        verify(pointerInputNodeA.cancelHandler, never()).invoke()
     }
 
     // PointerInputNode A -> PointerInputNode B -> LayoutNode
     // PointerInputNode A -> PointerInputNode C
     @Test
-    fun removePointerInputNodesWithNoLayoutNodeDescendants_2BranchesOneHasLn_otherBranchRemoved() {
+    fun removePointerInputNodesWithNoLayoutNodeDescendants_2BranchOneHasLn_removesCancelsCorrect() {
+
+        val neverCalled: () -> Unit = spy {}
+
         val layoutNode = LayoutNode(0, 0, 100, 100)
         val pointerInputNodeB = PointerInputNode().apply {
             emitInsertAt(0, layoutNode)
+            cancelHandler = neverCalled
         }
-        val pointerInputNodeC = PointerInputNode()
+        val pointerInputNodeC = PointerInputNode().apply {
+            cancelHandler = spy {}
+        }
         val pointerInputNodeA = PointerInputNode().apply {
             emitInsertAt(0, pointerInputNodeB)
             emitInsertAt(0, pointerInputNodeC)
+            cancelHandler = neverCalled
         }
         hitResult.addHitPath(0, listOf(pointerInputNodeA, pointerInputNodeB))
         hitResult.addHitPath(1, listOf(pointerInputNodeA, pointerInputNodeC))
@@ -2128,6 +2586,8 @@
         }
 
         assertThat(areEqual(hitResult.root, expectedRoot)).isTrue()
+        verify(pointerInputNodeC.cancelHandler).invoke()
+        verify(neverCalled, never()).invoke()
     }
 
     // arrange: root(3) -> middle(3) -> leaf(3)
@@ -3392,7 +3852,8 @@
         pointerInputNodeChild.cancelHandler = spy(MyCancelHandler())
         pointerInputNodeMiddle.cancelHandler = spy(MyCancelHandler())
         pointerInputNodeParent.cancelHandler = spy(MyCancelHandler())
-        hitResult.addHitPath(3,
+        hitResult.addHitPath(
+            3,
             listOf(pointerInputNodeParent, pointerInputNodeMiddle, pointerInputNodeChild)
         )
 
@@ -3494,7 +3955,8 @@
         val pointerInputNodeChild = PointerInputNode()
         val pointerInputNodeMiddle = PointerInputNode()
         val pointerInputNodeParent = PointerInputNode()
-        hitResult.addHitPath(3,
+        hitResult.addHitPath(
+            3,
             listOf(pointerInputNodeParent, pointerInputNodeMiddle, pointerInputNodeChild)
         )
 
diff --git a/ui/ui-platform/src/test/java/androidx/ui/core/pointerinput/PointerInputEventProcessorTest.kt b/ui/ui-platform/src/test/java/androidx/ui/core/pointerinput/PointerInputEventProcessorTest.kt
index 5f08b95..a407a57 100644
--- a/ui/ui-platform/src/test/java/androidx/ui/core/pointerinput/PointerInputEventProcessorTest.kt
+++ b/ui/ui-platform/src/test/java/androidx/ui/core/pointerinput/PointerInputEventProcessorTest.kt
@@ -1908,64 +1908,6 @@
     }
 
     @Test
-    fun process_pointerInputNodeRemovedDuringInput_correctPointerInputChangesReceived() {
-
-        // Arrange
-
-        val childLayoutNode = LayoutNode(0, 0, 100, 100)
-        val childPointerInputNode: PointerInputNode = PointerInputNode().apply {
-            emitInsertAt(0, childLayoutNode)
-            pointerInputHandler = spy(MyPointerInputHandler())
-        }
-        val parentLayoutNode: LayoutNode = LayoutNode(0, 0, 100, 100).apply {
-            emitInsertAt(0, childPointerInputNode)
-        }
-        val parentPointerInputNode: PointerInputNode = PointerInputNode().apply {
-            emitInsertAt(0, parentLayoutNode)
-            pointerInputHandler = spy(MyPointerInputHandler())
-        }
-        root.emitInsertAt(0, parentPointerInputNode)
-
-        val offset = PxPosition(50.px, 50.px)
-
-        val down = PointerInputEvent(0, Uptime.Boot + 7.milliseconds, offset, true)
-        val up = PointerInputEvent(0, Uptime.Boot + 11.milliseconds, null, false)
-
-        val expectedDownChange = PointerInputChange(
-            id = 0,
-            current = PointerInputData(Uptime.Boot + 7.milliseconds, offset, true),
-            previous = PointerInputData(null, null, false),
-            consumed = ConsumedData()
-        )
-
-        val expectedUpChange = PointerInputChange(
-            id = 0,
-            current = PointerInputData(Uptime.Boot + 11.milliseconds, null, false),
-            previous = PointerInputData(Uptime.Boot + 7.milliseconds, offset, true),
-            consumed = ConsumedData()
-        )
-
-        // Act
-
-        pointerInputEventProcessor.process(down, IntPxPosition.Origin)
-        parentLayoutNode.emitRemoveAt(0, 1)
-        pointerInputEventProcessor.process(up, IntPxPosition.Origin)
-
-        // Assert
-
-        PointerEventPass.values().forEach {
-            verify(parentPointerInputNode.pointerInputHandler)
-                .invoke(eq(listOf(expectedDownChange)), eq(it), any())
-            verify(childPointerInputNode.pointerInputHandler)
-                .invoke(eq(listOf(expectedDownChange)), eq(it), any())
-            verify(parentPointerInputNode.pointerInputHandler)
-                .invoke(eq(listOf(expectedUpChange)), eq(it), any())
-        }
-        verifyNoMoreInteractions(parentPointerInputNode.pointerInputHandler)
-        verifyNoMoreInteractions(childPointerInputNode.pointerInputHandler)
-    }
-
-    @Test
     fun processCancel_noPointers_doesntCrash() {
         pointerInputEventProcessor.processCancel()
     }
@@ -2459,4 +2401,190 @@
             pointerInputNode.cancelHandler
         )
     }
+
+    @Test
+    fun process_pointerInputNodeRemovedDuringInput_correctPointerInputChangesReceived() {
+
+        // Arrange
+
+        val childLayoutNode = LayoutNode(0, 0, 100, 100)
+        val childPointerInputNode: PointerInputNode = PointerInputNode().apply {
+            emitInsertAt(0, childLayoutNode)
+            pointerInputHandler = spy(MyPointerInputHandler())
+        }
+        val parentLayoutNode: LayoutNode = LayoutNode(0, 0, 100, 100).apply {
+            emitInsertAt(0, childPointerInputNode)
+        }
+        val parentPointerInputNode: PointerInputNode = PointerInputNode().apply {
+            emitInsertAt(0, parentLayoutNode)
+            pointerInputHandler = spy(MyPointerInputHandler())
+        }
+        root.emitInsertAt(0, parentPointerInputNode)
+
+        val offset = PxPosition(50.px, 50.px)
+
+        val down = PointerInputEvent(0, Uptime.Boot + 7.milliseconds, offset, true)
+        val up = PointerInputEvent(0, Uptime.Boot + 11.milliseconds, null, false)
+
+        val expectedDownChange = PointerInputChange(
+            id = 0,
+            current = PointerInputData(Uptime.Boot + 7.milliseconds, offset, true),
+            previous = PointerInputData(null, null, false),
+            consumed = ConsumedData()
+        )
+
+        val expectedUpChange = PointerInputChange(
+            id = 0,
+            current = PointerInputData(Uptime.Boot + 11.milliseconds, null, false),
+            previous = PointerInputData(Uptime.Boot + 7.milliseconds, offset, true),
+            consumed = ConsumedData()
+        )
+
+        // Act
+
+        pointerInputEventProcessor.process(down, IntPxPosition.Origin)
+        parentLayoutNode.emitRemoveAt(0, 1)
+        pointerInputEventProcessor.process(up, IntPxPosition.Origin)
+
+        // Assert
+
+        PointerEventPass.values().forEach {
+            verify(parentPointerInputNode.pointerInputHandler)
+                .invoke(eq(listOf(expectedDownChange)), eq(it), any())
+            verify(childPointerInputNode.pointerInputHandler)
+                .invoke(eq(listOf(expectedDownChange)), eq(it), any())
+            verify(parentPointerInputNode.pointerInputHandler)
+                .invoke(eq(listOf(expectedUpChange)), eq(it), any())
+        }
+        verifyNoMoreInteractions(parentPointerInputNode.pointerInputHandler)
+        verifyNoMoreInteractions(childPointerInputNode.pointerInputHandler)
+    }
+
+    @Test
+    fun process_pointerInputNodeRemovedDuringInput_cancelDispatchedToCorrectPointerInputNode() {
+
+        // Arrange
+
+        val childLayoutNode = LayoutNode(0, 0, 100, 100)
+        val childPointerInputNode: PointerInputNode = PointerInputNode().apply {
+            emitInsertAt(0, childLayoutNode)
+            cancelHandler = spy(MyCancelHandler())
+        }
+        val parentLayoutNode: LayoutNode = LayoutNode(0, 0, 100, 100).apply {
+            emitInsertAt(0, childPointerInputNode)
+        }
+        val parentPointerInputNode: PointerInputNode = PointerInputNode().apply {
+            emitInsertAt(0, parentLayoutNode)
+            cancelHandler = spy(MyCancelHandler())
+        }
+        root.emitInsertAt(0, parentPointerInputNode)
+
+        val down =
+            PointerInputEvent(0, Uptime.Boot + 7.milliseconds, PxPosition(50.px, 50.px), true)
+
+        val up = PointerInputEvent(0, Uptime.Boot + 11.milliseconds, null, false)
+
+        // Act
+
+        pointerInputEventProcessor.process(down, IntPxPosition.Origin)
+        parentLayoutNode.emitRemoveAt(0, 1)
+        pointerInputEventProcessor.process(up, IntPxPosition.Origin)
+
+        // Assert
+        verify(childPointerInputNode.cancelHandler).invoke()
+        verify(parentPointerInputNode.cancelHandler, never()).invoke()
+    }
+
+    @Test
+    fun process_childLayoutNodeRemovedDuringInput_correctPointerInputChangesReceived() {
+
+        // Arrange
+
+        val childLayoutNode = LayoutNode(0, 0, 100, 100)
+        val childPointerInputNode: PointerInputNode = PointerInputNode().apply {
+            emitInsertAt(0, childLayoutNode)
+            pointerInputHandler = spy(MyPointerInputHandler())
+        }
+        val parentLayoutNode: LayoutNode = LayoutNode(0, 0, 100, 100).apply {
+            emitInsertAt(0, childPointerInputNode)
+        }
+        val parentPointerInputNode: PointerInputNode = PointerInputNode().apply {
+            emitInsertAt(0, parentLayoutNode)
+            pointerInputHandler = spy(MyPointerInputHandler())
+        }
+        root.emitInsertAt(0, parentPointerInputNode)
+
+        val offset = PxPosition(50.px, 50.px)
+
+        val down = PointerInputEvent(0, Uptime.Boot + 7.milliseconds, offset, true)
+        val up = PointerInputEvent(0, Uptime.Boot + 11.milliseconds, null, false)
+
+        val expectedDownChange = PointerInputChange(
+            id = 0,
+            current = PointerInputData(Uptime.Boot + 7.milliseconds, offset, true),
+            previous = PointerInputData(null, null, false),
+            consumed = ConsumedData()
+        )
+
+        val expectedUpChange = PointerInputChange(
+            id = 0,
+            current = PointerInputData(Uptime.Boot + 11.milliseconds, null, false),
+            previous = PointerInputData(Uptime.Boot + 7.milliseconds, offset, true),
+            consumed = ConsumedData()
+        )
+
+        // Act
+
+        pointerInputEventProcessor.process(down, IntPxPosition.Origin)
+        childPointerInputNode.emitRemoveAt(0, 1)
+        pointerInputEventProcessor.process(up, IntPxPosition.Origin)
+
+        // Assert
+
+        PointerEventPass.values().forEach {
+            verify(parentPointerInputNode.pointerInputHandler)
+                .invoke(eq(listOf(expectedDownChange)), eq(it), any())
+            verify(childPointerInputNode.pointerInputHandler)
+                .invoke(eq(listOf(expectedDownChange)), eq(it), any())
+            verify(parentPointerInputNode.pointerInputHandler)
+                .invoke(eq(listOf(expectedUpChange)), eq(it), any())
+        }
+        verifyNoMoreInteractions(parentPointerInputNode.pointerInputHandler)
+        verifyNoMoreInteractions(childPointerInputNode.pointerInputHandler)
+    }
+
+    @Test
+    fun process_childLayoutNodeRemovedDuringInput_cancelDispatchedToCorrectPointerInputNode() {
+
+        // Arrange
+
+        val childLayoutNode = LayoutNode(0, 0, 100, 100)
+        val childPointerInputNode: PointerInputNode = PointerInputNode().apply {
+            emitInsertAt(0, childLayoutNode)
+            cancelHandler = spy(MyCancelHandler())
+        }
+        val parentLayoutNode: LayoutNode = LayoutNode(0, 0, 100, 100).apply {
+            emitInsertAt(0, childPointerInputNode)
+        }
+        val parentPointerInputNode: PointerInputNode = PointerInputNode().apply {
+            emitInsertAt(0, parentLayoutNode)
+            cancelHandler = spy(MyCancelHandler())
+        }
+        root.emitInsertAt(0, parentPointerInputNode)
+
+        val down =
+            PointerInputEvent(0, Uptime.Boot + 7.milliseconds, PxPosition(50.px, 50.px), true)
+
+        val up = PointerInputEvent(0, Uptime.Boot + 11.milliseconds, null, false)
+
+        // Act
+
+        pointerInputEventProcessor.process(down, IntPxPosition.Origin)
+        childPointerInputNode.emitRemoveAt(0, 1)
+        pointerInputEventProcessor.process(up, IntPxPosition.Origin)
+
+        // Assert
+        verify(childPointerInputNode.cancelHandler).invoke()
+        verify(parentPointerInputNode.cancelHandler, never()).invoke()
+    }
 }
\ No newline at end of file
diff --git a/ui/ui-test/api/0.1.0-dev03.txt b/ui/ui-test/api/0.1.0-dev03.txt
index 37ae58c..7859d02 100644
--- a/ui/ui-test/api/0.1.0-dev03.txt
+++ b/ui/ui-test/api/0.1.0-dev03.txt
@@ -4,6 +4,7 @@
   public final class ActionsKt {
     ctor public ActionsKt();
     method public static androidx.ui.test.SemanticsNodeInteraction doClick(androidx.ui.test.SemanticsNodeInteraction);
+    method public static androidx.ui.test.SemanticsNodeInteraction doGesture(androidx.ui.test.SemanticsNodeInteraction, kotlin.jvm.functions.Function1<? super androidx.ui.test.GestureScope,kotlin.Unit> block);
     method public static androidx.ui.test.SemanticsNodeInteraction doScrollTo(androidx.ui.test.SemanticsNodeInteraction);
     method public static boolean waitForIdleCompose();
   }
@@ -30,6 +31,12 @@
     method public static void verifyHierarchy(androidx.ui.test.SemanticsNodeInteraction, kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.String> assertionMessage, kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.Boolean> condition);
   }
 
+  public final class BitmapHelpersKt {
+    ctor public BitmapHelpersKt();
+    method public static void assertPixels(android.graphics.Bitmap, androidx.ui.core.IntPxSize? expectedSize = null, kotlin.jvm.functions.Function1<? super androidx.ui.core.IntPxPosition,androidx.ui.graphics.Color> expectedColorProvider);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static android.graphics.Bitmap captureToBitmap(androidx.ui.test.SemanticsNodeInteraction);
+  }
+
   public final class CollectedSizes {
     ctor public CollectedSizes(androidx.ui.core.PxSize size, androidx.ui.core.Density density);
     method public androidx.ui.test.CollectedSizes assertHeightEqualsTo(androidx.ui.core.Dp expectedHeight);
@@ -95,6 +102,7 @@
   }
 
   public interface ComposeTestRule extends org.junit.rules.TestRule {
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public android.graphics.Bitmap captureScreenOnIdle();
     method public androidx.ui.test.ComposeTestCaseSetup forGivenContent(kotlin.jvm.functions.Function0<kotlin.Unit> composable);
     method public androidx.ui.test.ComposeTestCaseSetup forGivenTestCase(androidx.ui.test.ComposeTestCase testCase);
     method public androidx.ui.core.Density getDensity();
@@ -124,6 +132,8 @@
     ctor public FiltersKt();
     method public static boolean getHasClickAction(androidx.ui.core.semantics.SemanticsConfiguration);
     method public static boolean getHasScrollAction(androidx.ui.core.semantics.SemanticsConfiguration);
+    method public static boolean hasSubstring(androidx.ui.core.semantics.SemanticsConfiguration, String substring, boolean ignoreCase = false);
+    method public static boolean hasText(androidx.ui.core.semantics.SemanticsConfiguration, String text, boolean ignoreCase = false);
     method public static boolean isInMutuallyExclusiveGroup(androidx.ui.core.semantics.SemanticsConfiguration);
     method public static boolean isToggleable(androidx.ui.core.semantics.SemanticsConfiguration);
   }
@@ -133,10 +143,25 @@
     method public static androidx.ui.test.SemanticsNodeInteraction find(kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.Boolean> selector);
     method public static java.util.List<androidx.ui.test.SemanticsNodeInteraction> findAll(kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.Boolean> selector);
     method public static java.util.List<androidx.ui.test.SemanticsNodeInteraction> findAllByTag(String testTag);
+    method public static androidx.ui.test.SemanticsNodeInteraction findBySubstring(String text, boolean ignoreCase = false);
     method public static androidx.ui.test.SemanticsNodeInteraction findByTag(String testTag);
     method public static androidx.ui.test.SemanticsNodeInteraction findByText(String text, boolean ignoreCase = false);
   }
 
+  public final class GestureScope {
+  }
+
+  public final class GestureScopeKt {
+    ctor public GestureScopeKt();
+    method public static void sendClick(androidx.ui.test.GestureScope, float x, float y);
+    method public static void sendClick(androidx.ui.test.GestureScope);
+    method public static void sendSwipe(androidx.ui.test.GestureScope, float x0, float y0, float x1, float y1, androidx.ui.core.Duration duration = 200.milliseconds);
+    method public static void sendSwipeDown(androidx.ui.test.GestureScope);
+    method public static void sendSwipeLeft(androidx.ui.test.GestureScope);
+    method public static void sendSwipeRight(androidx.ui.test.GestureScope);
+    method public static void sendSwipeUp(androidx.ui.test.GestureScope);
+  }
+
   public final class GoldenSemanticsKt {
     ctor public GoldenSemanticsKt();
     method public static void assertEquals(androidx.ui.core.semantics.SemanticsConfiguration, androidx.ui.core.semantics.SemanticsConfiguration expected);
@@ -181,6 +206,7 @@
     ctor public AndroidComposeTestRule(boolean disableTransitions, boolean shouldThrowOnRecomposeTimeout);
     ctor public AndroidComposeTestRule();
     method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description? description);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public android.graphics.Bitmap captureScreenOnIdle();
     method public androidx.ui.test.ComposeTestCaseSetup forGivenContent(kotlin.jvm.functions.Function0<kotlin.Unit> composable);
     method public androidx.ui.test.ComposeTestCaseSetup forGivenTestCase(androidx.ui.test.ComposeTestCase testCase);
     method public androidx.test.rule.ActivityTestRule<android.app.Activity> getActivityTestRule();
@@ -198,6 +224,10 @@
     method public void evaluate();
   }
 
+  public final class WindowCaptureKt {
+    ctor public WindowCaptureKt();
+  }
+
 }
 
 package androidx.ui.test.android.fake {
diff --git a/ui/ui-test/api/current.txt b/ui/ui-test/api/current.txt
index 37ae58c..7859d02 100644
--- a/ui/ui-test/api/current.txt
+++ b/ui/ui-test/api/current.txt
@@ -4,6 +4,7 @@
   public final class ActionsKt {
     ctor public ActionsKt();
     method public static androidx.ui.test.SemanticsNodeInteraction doClick(androidx.ui.test.SemanticsNodeInteraction);
+    method public static androidx.ui.test.SemanticsNodeInteraction doGesture(androidx.ui.test.SemanticsNodeInteraction, kotlin.jvm.functions.Function1<? super androidx.ui.test.GestureScope,kotlin.Unit> block);
     method public static androidx.ui.test.SemanticsNodeInteraction doScrollTo(androidx.ui.test.SemanticsNodeInteraction);
     method public static boolean waitForIdleCompose();
   }
@@ -30,6 +31,12 @@
     method public static void verifyHierarchy(androidx.ui.test.SemanticsNodeInteraction, kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.String> assertionMessage, kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.Boolean> condition);
   }
 
+  public final class BitmapHelpersKt {
+    ctor public BitmapHelpersKt();
+    method public static void assertPixels(android.graphics.Bitmap, androidx.ui.core.IntPxSize? expectedSize = null, kotlin.jvm.functions.Function1<? super androidx.ui.core.IntPxPosition,androidx.ui.graphics.Color> expectedColorProvider);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static android.graphics.Bitmap captureToBitmap(androidx.ui.test.SemanticsNodeInteraction);
+  }
+
   public final class CollectedSizes {
     ctor public CollectedSizes(androidx.ui.core.PxSize size, androidx.ui.core.Density density);
     method public androidx.ui.test.CollectedSizes assertHeightEqualsTo(androidx.ui.core.Dp expectedHeight);
@@ -95,6 +102,7 @@
   }
 
   public interface ComposeTestRule extends org.junit.rules.TestRule {
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public android.graphics.Bitmap captureScreenOnIdle();
     method public androidx.ui.test.ComposeTestCaseSetup forGivenContent(kotlin.jvm.functions.Function0<kotlin.Unit> composable);
     method public androidx.ui.test.ComposeTestCaseSetup forGivenTestCase(androidx.ui.test.ComposeTestCase testCase);
     method public androidx.ui.core.Density getDensity();
@@ -124,6 +132,8 @@
     ctor public FiltersKt();
     method public static boolean getHasClickAction(androidx.ui.core.semantics.SemanticsConfiguration);
     method public static boolean getHasScrollAction(androidx.ui.core.semantics.SemanticsConfiguration);
+    method public static boolean hasSubstring(androidx.ui.core.semantics.SemanticsConfiguration, String substring, boolean ignoreCase = false);
+    method public static boolean hasText(androidx.ui.core.semantics.SemanticsConfiguration, String text, boolean ignoreCase = false);
     method public static boolean isInMutuallyExclusiveGroup(androidx.ui.core.semantics.SemanticsConfiguration);
     method public static boolean isToggleable(androidx.ui.core.semantics.SemanticsConfiguration);
   }
@@ -133,10 +143,25 @@
     method public static androidx.ui.test.SemanticsNodeInteraction find(kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.Boolean> selector);
     method public static java.util.List<androidx.ui.test.SemanticsNodeInteraction> findAll(kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.Boolean> selector);
     method public static java.util.List<androidx.ui.test.SemanticsNodeInteraction> findAllByTag(String testTag);
+    method public static androidx.ui.test.SemanticsNodeInteraction findBySubstring(String text, boolean ignoreCase = false);
     method public static androidx.ui.test.SemanticsNodeInteraction findByTag(String testTag);
     method public static androidx.ui.test.SemanticsNodeInteraction findByText(String text, boolean ignoreCase = false);
   }
 
+  public final class GestureScope {
+  }
+
+  public final class GestureScopeKt {
+    ctor public GestureScopeKt();
+    method public static void sendClick(androidx.ui.test.GestureScope, float x, float y);
+    method public static void sendClick(androidx.ui.test.GestureScope);
+    method public static void sendSwipe(androidx.ui.test.GestureScope, float x0, float y0, float x1, float y1, androidx.ui.core.Duration duration = 200.milliseconds);
+    method public static void sendSwipeDown(androidx.ui.test.GestureScope);
+    method public static void sendSwipeLeft(androidx.ui.test.GestureScope);
+    method public static void sendSwipeRight(androidx.ui.test.GestureScope);
+    method public static void sendSwipeUp(androidx.ui.test.GestureScope);
+  }
+
   public final class GoldenSemanticsKt {
     ctor public GoldenSemanticsKt();
     method public static void assertEquals(androidx.ui.core.semantics.SemanticsConfiguration, androidx.ui.core.semantics.SemanticsConfiguration expected);
@@ -181,6 +206,7 @@
     ctor public AndroidComposeTestRule(boolean disableTransitions, boolean shouldThrowOnRecomposeTimeout);
     ctor public AndroidComposeTestRule();
     method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description? description);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public android.graphics.Bitmap captureScreenOnIdle();
     method public androidx.ui.test.ComposeTestCaseSetup forGivenContent(kotlin.jvm.functions.Function0<kotlin.Unit> composable);
     method public androidx.ui.test.ComposeTestCaseSetup forGivenTestCase(androidx.ui.test.ComposeTestCase testCase);
     method public androidx.test.rule.ActivityTestRule<android.app.Activity> getActivityTestRule();
@@ -198,6 +224,10 @@
     method public void evaluate();
   }
 
+  public final class WindowCaptureKt {
+    ctor public WindowCaptureKt();
+  }
+
 }
 
 package androidx.ui.test.android.fake {
diff --git a/ui/ui-test/api/public_plus_experimental_0.1.0-dev03.txt b/ui/ui-test/api/public_plus_experimental_0.1.0-dev03.txt
index 37ae58c..7859d02 100644
--- a/ui/ui-test/api/public_plus_experimental_0.1.0-dev03.txt
+++ b/ui/ui-test/api/public_plus_experimental_0.1.0-dev03.txt
@@ -4,6 +4,7 @@
   public final class ActionsKt {
     ctor public ActionsKt();
     method public static androidx.ui.test.SemanticsNodeInteraction doClick(androidx.ui.test.SemanticsNodeInteraction);
+    method public static androidx.ui.test.SemanticsNodeInteraction doGesture(androidx.ui.test.SemanticsNodeInteraction, kotlin.jvm.functions.Function1<? super androidx.ui.test.GestureScope,kotlin.Unit> block);
     method public static androidx.ui.test.SemanticsNodeInteraction doScrollTo(androidx.ui.test.SemanticsNodeInteraction);
     method public static boolean waitForIdleCompose();
   }
@@ -30,6 +31,12 @@
     method public static void verifyHierarchy(androidx.ui.test.SemanticsNodeInteraction, kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.String> assertionMessage, kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.Boolean> condition);
   }
 
+  public final class BitmapHelpersKt {
+    ctor public BitmapHelpersKt();
+    method public static void assertPixels(android.graphics.Bitmap, androidx.ui.core.IntPxSize? expectedSize = null, kotlin.jvm.functions.Function1<? super androidx.ui.core.IntPxPosition,androidx.ui.graphics.Color> expectedColorProvider);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static android.graphics.Bitmap captureToBitmap(androidx.ui.test.SemanticsNodeInteraction);
+  }
+
   public final class CollectedSizes {
     ctor public CollectedSizes(androidx.ui.core.PxSize size, androidx.ui.core.Density density);
     method public androidx.ui.test.CollectedSizes assertHeightEqualsTo(androidx.ui.core.Dp expectedHeight);
@@ -95,6 +102,7 @@
   }
 
   public interface ComposeTestRule extends org.junit.rules.TestRule {
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public android.graphics.Bitmap captureScreenOnIdle();
     method public androidx.ui.test.ComposeTestCaseSetup forGivenContent(kotlin.jvm.functions.Function0<kotlin.Unit> composable);
     method public androidx.ui.test.ComposeTestCaseSetup forGivenTestCase(androidx.ui.test.ComposeTestCase testCase);
     method public androidx.ui.core.Density getDensity();
@@ -124,6 +132,8 @@
     ctor public FiltersKt();
     method public static boolean getHasClickAction(androidx.ui.core.semantics.SemanticsConfiguration);
     method public static boolean getHasScrollAction(androidx.ui.core.semantics.SemanticsConfiguration);
+    method public static boolean hasSubstring(androidx.ui.core.semantics.SemanticsConfiguration, String substring, boolean ignoreCase = false);
+    method public static boolean hasText(androidx.ui.core.semantics.SemanticsConfiguration, String text, boolean ignoreCase = false);
     method public static boolean isInMutuallyExclusiveGroup(androidx.ui.core.semantics.SemanticsConfiguration);
     method public static boolean isToggleable(androidx.ui.core.semantics.SemanticsConfiguration);
   }
@@ -133,10 +143,25 @@
     method public static androidx.ui.test.SemanticsNodeInteraction find(kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.Boolean> selector);
     method public static java.util.List<androidx.ui.test.SemanticsNodeInteraction> findAll(kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.Boolean> selector);
     method public static java.util.List<androidx.ui.test.SemanticsNodeInteraction> findAllByTag(String testTag);
+    method public static androidx.ui.test.SemanticsNodeInteraction findBySubstring(String text, boolean ignoreCase = false);
     method public static androidx.ui.test.SemanticsNodeInteraction findByTag(String testTag);
     method public static androidx.ui.test.SemanticsNodeInteraction findByText(String text, boolean ignoreCase = false);
   }
 
+  public final class GestureScope {
+  }
+
+  public final class GestureScopeKt {
+    ctor public GestureScopeKt();
+    method public static void sendClick(androidx.ui.test.GestureScope, float x, float y);
+    method public static void sendClick(androidx.ui.test.GestureScope);
+    method public static void sendSwipe(androidx.ui.test.GestureScope, float x0, float y0, float x1, float y1, androidx.ui.core.Duration duration = 200.milliseconds);
+    method public static void sendSwipeDown(androidx.ui.test.GestureScope);
+    method public static void sendSwipeLeft(androidx.ui.test.GestureScope);
+    method public static void sendSwipeRight(androidx.ui.test.GestureScope);
+    method public static void sendSwipeUp(androidx.ui.test.GestureScope);
+  }
+
   public final class GoldenSemanticsKt {
     ctor public GoldenSemanticsKt();
     method public static void assertEquals(androidx.ui.core.semantics.SemanticsConfiguration, androidx.ui.core.semantics.SemanticsConfiguration expected);
@@ -181,6 +206,7 @@
     ctor public AndroidComposeTestRule(boolean disableTransitions, boolean shouldThrowOnRecomposeTimeout);
     ctor public AndroidComposeTestRule();
     method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description? description);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public android.graphics.Bitmap captureScreenOnIdle();
     method public androidx.ui.test.ComposeTestCaseSetup forGivenContent(kotlin.jvm.functions.Function0<kotlin.Unit> composable);
     method public androidx.ui.test.ComposeTestCaseSetup forGivenTestCase(androidx.ui.test.ComposeTestCase testCase);
     method public androidx.test.rule.ActivityTestRule<android.app.Activity> getActivityTestRule();
@@ -198,6 +224,10 @@
     method public void evaluate();
   }
 
+  public final class WindowCaptureKt {
+    ctor public WindowCaptureKt();
+  }
+
 }
 
 package androidx.ui.test.android.fake {
diff --git a/ui/ui-test/api/public_plus_experimental_current.txt b/ui/ui-test/api/public_plus_experimental_current.txt
index 37ae58c..7859d02 100644
--- a/ui/ui-test/api/public_plus_experimental_current.txt
+++ b/ui/ui-test/api/public_plus_experimental_current.txt
@@ -4,6 +4,7 @@
   public final class ActionsKt {
     ctor public ActionsKt();
     method public static androidx.ui.test.SemanticsNodeInteraction doClick(androidx.ui.test.SemanticsNodeInteraction);
+    method public static androidx.ui.test.SemanticsNodeInteraction doGesture(androidx.ui.test.SemanticsNodeInteraction, kotlin.jvm.functions.Function1<? super androidx.ui.test.GestureScope,kotlin.Unit> block);
     method public static androidx.ui.test.SemanticsNodeInteraction doScrollTo(androidx.ui.test.SemanticsNodeInteraction);
     method public static boolean waitForIdleCompose();
   }
@@ -30,6 +31,12 @@
     method public static void verifyHierarchy(androidx.ui.test.SemanticsNodeInteraction, kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.String> assertionMessage, kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.Boolean> condition);
   }
 
+  public final class BitmapHelpersKt {
+    ctor public BitmapHelpersKt();
+    method public static void assertPixels(android.graphics.Bitmap, androidx.ui.core.IntPxSize? expectedSize = null, kotlin.jvm.functions.Function1<? super androidx.ui.core.IntPxPosition,androidx.ui.graphics.Color> expectedColorProvider);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static android.graphics.Bitmap captureToBitmap(androidx.ui.test.SemanticsNodeInteraction);
+  }
+
   public final class CollectedSizes {
     ctor public CollectedSizes(androidx.ui.core.PxSize size, androidx.ui.core.Density density);
     method public androidx.ui.test.CollectedSizes assertHeightEqualsTo(androidx.ui.core.Dp expectedHeight);
@@ -95,6 +102,7 @@
   }
 
   public interface ComposeTestRule extends org.junit.rules.TestRule {
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public android.graphics.Bitmap captureScreenOnIdle();
     method public androidx.ui.test.ComposeTestCaseSetup forGivenContent(kotlin.jvm.functions.Function0<kotlin.Unit> composable);
     method public androidx.ui.test.ComposeTestCaseSetup forGivenTestCase(androidx.ui.test.ComposeTestCase testCase);
     method public androidx.ui.core.Density getDensity();
@@ -124,6 +132,8 @@
     ctor public FiltersKt();
     method public static boolean getHasClickAction(androidx.ui.core.semantics.SemanticsConfiguration);
     method public static boolean getHasScrollAction(androidx.ui.core.semantics.SemanticsConfiguration);
+    method public static boolean hasSubstring(androidx.ui.core.semantics.SemanticsConfiguration, String substring, boolean ignoreCase = false);
+    method public static boolean hasText(androidx.ui.core.semantics.SemanticsConfiguration, String text, boolean ignoreCase = false);
     method public static boolean isInMutuallyExclusiveGroup(androidx.ui.core.semantics.SemanticsConfiguration);
     method public static boolean isToggleable(androidx.ui.core.semantics.SemanticsConfiguration);
   }
@@ -133,10 +143,25 @@
     method public static androidx.ui.test.SemanticsNodeInteraction find(kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.Boolean> selector);
     method public static java.util.List<androidx.ui.test.SemanticsNodeInteraction> findAll(kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.Boolean> selector);
     method public static java.util.List<androidx.ui.test.SemanticsNodeInteraction> findAllByTag(String testTag);
+    method public static androidx.ui.test.SemanticsNodeInteraction findBySubstring(String text, boolean ignoreCase = false);
     method public static androidx.ui.test.SemanticsNodeInteraction findByTag(String testTag);
     method public static androidx.ui.test.SemanticsNodeInteraction findByText(String text, boolean ignoreCase = false);
   }
 
+  public final class GestureScope {
+  }
+
+  public final class GestureScopeKt {
+    ctor public GestureScopeKt();
+    method public static void sendClick(androidx.ui.test.GestureScope, float x, float y);
+    method public static void sendClick(androidx.ui.test.GestureScope);
+    method public static void sendSwipe(androidx.ui.test.GestureScope, float x0, float y0, float x1, float y1, androidx.ui.core.Duration duration = 200.milliseconds);
+    method public static void sendSwipeDown(androidx.ui.test.GestureScope);
+    method public static void sendSwipeLeft(androidx.ui.test.GestureScope);
+    method public static void sendSwipeRight(androidx.ui.test.GestureScope);
+    method public static void sendSwipeUp(androidx.ui.test.GestureScope);
+  }
+
   public final class GoldenSemanticsKt {
     ctor public GoldenSemanticsKt();
     method public static void assertEquals(androidx.ui.core.semantics.SemanticsConfiguration, androidx.ui.core.semantics.SemanticsConfiguration expected);
@@ -181,6 +206,7 @@
     ctor public AndroidComposeTestRule(boolean disableTransitions, boolean shouldThrowOnRecomposeTimeout);
     ctor public AndroidComposeTestRule();
     method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description? description);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public android.graphics.Bitmap captureScreenOnIdle();
     method public androidx.ui.test.ComposeTestCaseSetup forGivenContent(kotlin.jvm.functions.Function0<kotlin.Unit> composable);
     method public androidx.ui.test.ComposeTestCaseSetup forGivenTestCase(androidx.ui.test.ComposeTestCase testCase);
     method public androidx.test.rule.ActivityTestRule<android.app.Activity> getActivityTestRule();
@@ -198,6 +224,10 @@
     method public void evaluate();
   }
 
+  public final class WindowCaptureKt {
+    ctor public WindowCaptureKt();
+  }
+
 }
 
 package androidx.ui.test.android.fake {
diff --git a/ui/ui-test/api/restricted_0.1.0-dev03.txt b/ui/ui-test/api/restricted_0.1.0-dev03.txt
index 37ae58c..7859d02 100644
--- a/ui/ui-test/api/restricted_0.1.0-dev03.txt
+++ b/ui/ui-test/api/restricted_0.1.0-dev03.txt
@@ -4,6 +4,7 @@
   public final class ActionsKt {
     ctor public ActionsKt();
     method public static androidx.ui.test.SemanticsNodeInteraction doClick(androidx.ui.test.SemanticsNodeInteraction);
+    method public static androidx.ui.test.SemanticsNodeInteraction doGesture(androidx.ui.test.SemanticsNodeInteraction, kotlin.jvm.functions.Function1<? super androidx.ui.test.GestureScope,kotlin.Unit> block);
     method public static androidx.ui.test.SemanticsNodeInteraction doScrollTo(androidx.ui.test.SemanticsNodeInteraction);
     method public static boolean waitForIdleCompose();
   }
@@ -30,6 +31,12 @@
     method public static void verifyHierarchy(androidx.ui.test.SemanticsNodeInteraction, kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.String> assertionMessage, kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.Boolean> condition);
   }
 
+  public final class BitmapHelpersKt {
+    ctor public BitmapHelpersKt();
+    method public static void assertPixels(android.graphics.Bitmap, androidx.ui.core.IntPxSize? expectedSize = null, kotlin.jvm.functions.Function1<? super androidx.ui.core.IntPxPosition,androidx.ui.graphics.Color> expectedColorProvider);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static android.graphics.Bitmap captureToBitmap(androidx.ui.test.SemanticsNodeInteraction);
+  }
+
   public final class CollectedSizes {
     ctor public CollectedSizes(androidx.ui.core.PxSize size, androidx.ui.core.Density density);
     method public androidx.ui.test.CollectedSizes assertHeightEqualsTo(androidx.ui.core.Dp expectedHeight);
@@ -95,6 +102,7 @@
   }
 
   public interface ComposeTestRule extends org.junit.rules.TestRule {
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public android.graphics.Bitmap captureScreenOnIdle();
     method public androidx.ui.test.ComposeTestCaseSetup forGivenContent(kotlin.jvm.functions.Function0<kotlin.Unit> composable);
     method public androidx.ui.test.ComposeTestCaseSetup forGivenTestCase(androidx.ui.test.ComposeTestCase testCase);
     method public androidx.ui.core.Density getDensity();
@@ -124,6 +132,8 @@
     ctor public FiltersKt();
     method public static boolean getHasClickAction(androidx.ui.core.semantics.SemanticsConfiguration);
     method public static boolean getHasScrollAction(androidx.ui.core.semantics.SemanticsConfiguration);
+    method public static boolean hasSubstring(androidx.ui.core.semantics.SemanticsConfiguration, String substring, boolean ignoreCase = false);
+    method public static boolean hasText(androidx.ui.core.semantics.SemanticsConfiguration, String text, boolean ignoreCase = false);
     method public static boolean isInMutuallyExclusiveGroup(androidx.ui.core.semantics.SemanticsConfiguration);
     method public static boolean isToggleable(androidx.ui.core.semantics.SemanticsConfiguration);
   }
@@ -133,10 +143,25 @@
     method public static androidx.ui.test.SemanticsNodeInteraction find(kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.Boolean> selector);
     method public static java.util.List<androidx.ui.test.SemanticsNodeInteraction> findAll(kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.Boolean> selector);
     method public static java.util.List<androidx.ui.test.SemanticsNodeInteraction> findAllByTag(String testTag);
+    method public static androidx.ui.test.SemanticsNodeInteraction findBySubstring(String text, boolean ignoreCase = false);
     method public static androidx.ui.test.SemanticsNodeInteraction findByTag(String testTag);
     method public static androidx.ui.test.SemanticsNodeInteraction findByText(String text, boolean ignoreCase = false);
   }
 
+  public final class GestureScope {
+  }
+
+  public final class GestureScopeKt {
+    ctor public GestureScopeKt();
+    method public static void sendClick(androidx.ui.test.GestureScope, float x, float y);
+    method public static void sendClick(androidx.ui.test.GestureScope);
+    method public static void sendSwipe(androidx.ui.test.GestureScope, float x0, float y0, float x1, float y1, androidx.ui.core.Duration duration = 200.milliseconds);
+    method public static void sendSwipeDown(androidx.ui.test.GestureScope);
+    method public static void sendSwipeLeft(androidx.ui.test.GestureScope);
+    method public static void sendSwipeRight(androidx.ui.test.GestureScope);
+    method public static void sendSwipeUp(androidx.ui.test.GestureScope);
+  }
+
   public final class GoldenSemanticsKt {
     ctor public GoldenSemanticsKt();
     method public static void assertEquals(androidx.ui.core.semantics.SemanticsConfiguration, androidx.ui.core.semantics.SemanticsConfiguration expected);
@@ -181,6 +206,7 @@
     ctor public AndroidComposeTestRule(boolean disableTransitions, boolean shouldThrowOnRecomposeTimeout);
     ctor public AndroidComposeTestRule();
     method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description? description);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public android.graphics.Bitmap captureScreenOnIdle();
     method public androidx.ui.test.ComposeTestCaseSetup forGivenContent(kotlin.jvm.functions.Function0<kotlin.Unit> composable);
     method public androidx.ui.test.ComposeTestCaseSetup forGivenTestCase(androidx.ui.test.ComposeTestCase testCase);
     method public androidx.test.rule.ActivityTestRule<android.app.Activity> getActivityTestRule();
@@ -198,6 +224,10 @@
     method public void evaluate();
   }
 
+  public final class WindowCaptureKt {
+    ctor public WindowCaptureKt();
+  }
+
 }
 
 package androidx.ui.test.android.fake {
diff --git a/ui/ui-test/api/restricted_current.txt b/ui/ui-test/api/restricted_current.txt
index 37ae58c..7859d02 100644
--- a/ui/ui-test/api/restricted_current.txt
+++ b/ui/ui-test/api/restricted_current.txt
@@ -4,6 +4,7 @@
   public final class ActionsKt {
     ctor public ActionsKt();
     method public static androidx.ui.test.SemanticsNodeInteraction doClick(androidx.ui.test.SemanticsNodeInteraction);
+    method public static androidx.ui.test.SemanticsNodeInteraction doGesture(androidx.ui.test.SemanticsNodeInteraction, kotlin.jvm.functions.Function1<? super androidx.ui.test.GestureScope,kotlin.Unit> block);
     method public static androidx.ui.test.SemanticsNodeInteraction doScrollTo(androidx.ui.test.SemanticsNodeInteraction);
     method public static boolean waitForIdleCompose();
   }
@@ -30,6 +31,12 @@
     method public static void verifyHierarchy(androidx.ui.test.SemanticsNodeInteraction, kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.String> assertionMessage, kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.Boolean> condition);
   }
 
+  public final class BitmapHelpersKt {
+    ctor public BitmapHelpersKt();
+    method public static void assertPixels(android.graphics.Bitmap, androidx.ui.core.IntPxSize? expectedSize = null, kotlin.jvm.functions.Function1<? super androidx.ui.core.IntPxPosition,androidx.ui.graphics.Color> expectedColorProvider);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static android.graphics.Bitmap captureToBitmap(androidx.ui.test.SemanticsNodeInteraction);
+  }
+
   public final class CollectedSizes {
     ctor public CollectedSizes(androidx.ui.core.PxSize size, androidx.ui.core.Density density);
     method public androidx.ui.test.CollectedSizes assertHeightEqualsTo(androidx.ui.core.Dp expectedHeight);
@@ -95,6 +102,7 @@
   }
 
   public interface ComposeTestRule extends org.junit.rules.TestRule {
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public android.graphics.Bitmap captureScreenOnIdle();
     method public androidx.ui.test.ComposeTestCaseSetup forGivenContent(kotlin.jvm.functions.Function0<kotlin.Unit> composable);
     method public androidx.ui.test.ComposeTestCaseSetup forGivenTestCase(androidx.ui.test.ComposeTestCase testCase);
     method public androidx.ui.core.Density getDensity();
@@ -124,6 +132,8 @@
     ctor public FiltersKt();
     method public static boolean getHasClickAction(androidx.ui.core.semantics.SemanticsConfiguration);
     method public static boolean getHasScrollAction(androidx.ui.core.semantics.SemanticsConfiguration);
+    method public static boolean hasSubstring(androidx.ui.core.semantics.SemanticsConfiguration, String substring, boolean ignoreCase = false);
+    method public static boolean hasText(androidx.ui.core.semantics.SemanticsConfiguration, String text, boolean ignoreCase = false);
     method public static boolean isInMutuallyExclusiveGroup(androidx.ui.core.semantics.SemanticsConfiguration);
     method public static boolean isToggleable(androidx.ui.core.semantics.SemanticsConfiguration);
   }
@@ -133,10 +143,25 @@
     method public static androidx.ui.test.SemanticsNodeInteraction find(kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.Boolean> selector);
     method public static java.util.List<androidx.ui.test.SemanticsNodeInteraction> findAll(kotlin.jvm.functions.Function1<? super androidx.ui.core.semantics.SemanticsConfiguration,java.lang.Boolean> selector);
     method public static java.util.List<androidx.ui.test.SemanticsNodeInteraction> findAllByTag(String testTag);
+    method public static androidx.ui.test.SemanticsNodeInteraction findBySubstring(String text, boolean ignoreCase = false);
     method public static androidx.ui.test.SemanticsNodeInteraction findByTag(String testTag);
     method public static androidx.ui.test.SemanticsNodeInteraction findByText(String text, boolean ignoreCase = false);
   }
 
+  public final class GestureScope {
+  }
+
+  public final class GestureScopeKt {
+    ctor public GestureScopeKt();
+    method public static void sendClick(androidx.ui.test.GestureScope, float x, float y);
+    method public static void sendClick(androidx.ui.test.GestureScope);
+    method public static void sendSwipe(androidx.ui.test.GestureScope, float x0, float y0, float x1, float y1, androidx.ui.core.Duration duration = 200.milliseconds);
+    method public static void sendSwipeDown(androidx.ui.test.GestureScope);
+    method public static void sendSwipeLeft(androidx.ui.test.GestureScope);
+    method public static void sendSwipeRight(androidx.ui.test.GestureScope);
+    method public static void sendSwipeUp(androidx.ui.test.GestureScope);
+  }
+
   public final class GoldenSemanticsKt {
     ctor public GoldenSemanticsKt();
     method public static void assertEquals(androidx.ui.core.semantics.SemanticsConfiguration, androidx.ui.core.semantics.SemanticsConfiguration expected);
@@ -181,6 +206,7 @@
     ctor public AndroidComposeTestRule(boolean disableTransitions, boolean shouldThrowOnRecomposeTimeout);
     ctor public AndroidComposeTestRule();
     method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description? description);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public android.graphics.Bitmap captureScreenOnIdle();
     method public androidx.ui.test.ComposeTestCaseSetup forGivenContent(kotlin.jvm.functions.Function0<kotlin.Unit> composable);
     method public androidx.ui.test.ComposeTestCaseSetup forGivenTestCase(androidx.ui.test.ComposeTestCase testCase);
     method public androidx.test.rule.ActivityTestRule<android.app.Activity> getActivityTestRule();
@@ -198,6 +224,10 @@
     method public void evaluate();
   }
 
+  public final class WindowCaptureKt {
+    ctor public WindowCaptureKt();
+  }
+
 }
 
 package androidx.ui.test.android.fake {
diff --git a/ui/ui-test/build.gradle b/ui/ui-test/build.gradle
index 78872d5..b4ccacaf 100644
--- a/ui/ui-test/build.gradle
+++ b/ui/ui-test/build.gradle
@@ -48,7 +48,7 @@
     testImplementation(TRUTH)
 
     androidTestImplementation(TRUTH)
-
+    androidTestImplementation project(":ui:ui-core")
     androidTestImplementation project(':ui:ui-material')
 }
 
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/BitmapCapturingTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/BitmapCapturingTest.kt
new file mode 100644
index 0000000..44ab5c4
--- /dev/null
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/BitmapCapturingTest.kt
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2019 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.ui.test
+
+import android.os.Build
+import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
+import androidx.ui.core.Alignment
+import androidx.ui.core.IntPxPosition
+import androidx.ui.core.IntPxSize
+import androidx.ui.core.TestTag
+import androidx.ui.core.ipx
+import androidx.ui.core.withDensity
+import androidx.ui.foundation.ColoredRect
+import androidx.ui.foundation.shape.DrawShape
+import androidx.ui.foundation.shape.RectangleShape
+import androidx.ui.graphics.Color
+import androidx.ui.graphics.SolidColor
+import androidx.ui.layout.Column
+import androidx.ui.layout.Container
+import androidx.ui.layout.Row
+import androidx.ui.semantics.Semantics
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@MediumTest
+@RunWith(JUnit4::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+class BitmapCapturingTest {
+
+    @get:Rule
+    val composeTestRule = createComposeRule()
+
+    private val rootTag = "Root"
+    private val tag11 = "Rect11"
+    private val tag12 = "Rect12"
+    private val tag21 = "Rect21"
+    private val tag22 = "Rect22"
+
+    private val color11 = Color.Red
+    private val color12 = Color.Blue
+    private val color21 = Color.Green
+    private val color22 = Color.Yellow
+    private val colorBg = Color.Black
+
+    @Test
+    fun captureIndividualRects_checkSizeAndColors() {
+        composeCheckerboard()
+
+        var calledCount = 0
+        findByTag(tag11)
+            .captureToBitmap()
+            .assertPixels(expectedSize = IntPxSize(100.ipx, 50.ipx)) {
+                calledCount++
+                color11
+            }
+        assertThat(calledCount).isEqualTo(100 * 50)
+
+        findByTag(tag12)
+            .captureToBitmap()
+            .assertPixels(expectedSize = IntPxSize(100.ipx, 50.ipx)) {
+                color12
+            }
+        findByTag(tag21)
+            .captureToBitmap()
+            .assertPixels(expectedSize = IntPxSize(100.ipx, 50.ipx)) {
+                color21
+            }
+        findByTag(tag22)
+            .captureToBitmap()
+            .assertPixels(expectedSize = IntPxSize(100.ipx, 50.ipx)) {
+                color22
+            }
+    }
+
+    @Test
+    fun captureRootContainer_checkSizeAndColors() {
+        composeCheckerboard()
+
+        findByTag(rootTag)
+            .captureToBitmap()
+            .assertPixels(expectedSize = IntPxSize(200.ipx, 100.ipx)) {
+                if (it.y >= 100.ipx || it.x >= 200.ipx) {
+                    throw AssertionError("$it is out of range!")
+                }
+                expectedColorProvider(it)
+            }
+    }
+
+    @Test
+    fun captureWholeWindow_checkSizeAndColors() {
+        composeCheckerboard()
+
+        composeTestRule
+            .captureScreenOnIdle()
+            .assertPixels() {
+                expectedColorProvider(it)
+            }
+    }
+
+    @Test(expected = AssertionError::class)
+    fun assertWrongColor_expectException() {
+        composeCheckerboard()
+
+        findByTag(tag11)
+            .captureToBitmap()
+            .assertPixels(expectedSize = IntPxSize(100.ipx, 50.ipx)) {
+                color22 // Assuming wrong color
+            }
+    }
+
+    @Test(expected = AssertionError::class)
+    fun assertWrongSize_expectException() {
+        composeCheckerboard()
+
+        findByTag(tag11)
+            .captureToBitmap()
+            .assertPixels(expectedSize = IntPxSize(10.ipx, 10.ipx)) {
+                color21
+            }
+    }
+
+    private fun expectedColorProvider(pos: IntPxPosition): Color {
+        if (pos.y < 50.ipx) {
+            if (pos.x < 100.ipx) {
+                return color11
+            } else if (pos.x < 200.ipx) {
+                return color12
+            }
+        } else if (pos.y < 100.ipx) {
+            if (pos.x < 100.ipx) {
+                return color21
+            } else if (pos.x < 200.ipx) {
+                return color22
+            }
+        }
+        return colorBg
+    }
+
+    private fun composeCheckerboard() {
+        withDensity(composeTestRule.density) {
+            composeTestRule.setContent {
+                Container(alignment = Alignment.TopLeft) {
+
+                    DrawShape(RectangleShape, SolidColor(colorBg))
+
+                    TestTag(rootTag) {
+                        Semantics {
+                            Column {
+                                Row {
+                                    TestTag(tag11) {
+                                        Semantics {
+                                            ColoredRect(
+                                                color = color11,
+                                                width = 100.ipx.toDp(),
+                                                height = 50.ipx.toDp()
+                                            )
+                                        }
+                                    }
+                                    TestTag(tag12) {
+                                        Semantics {
+                                            ColoredRect(
+                                                color = color12,
+                                                width = 100.ipx.toDp(),
+                                                height = 50.ipx.toDp()
+                                            )
+                                        }
+                                    }
+                                }
+                                Row {
+                                    TestTag(tag21) {
+                                        Semantics {
+                                            ColoredRect(
+                                                color = color21,
+                                                width = 100.ipx.toDp(),
+                                                height = 50.ipx.toDp()
+                                            )
+                                        }
+                                    }
+                                    TestTag(tag22) {
+                                        Semantics {
+                                            ColoredRect(
+                                                color = color22,
+                                                width = 100.ipx.toDp(),
+                                                height = 50.ipx.toDp()
+                                            )
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/PointerInputRecorder.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/PointerInputRecorder.kt
new file mode 100644
index 0000000..c274abb
--- /dev/null
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/PointerInputRecorder.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2019 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.ui.test
+
+import androidx.ui.core.IntPxSize
+import androidx.ui.core.PointerEventPass
+import androidx.ui.core.PointerInputChange
+import androidx.ui.core.PointerInputData
+import com.google.common.truth.Truth
+
+class PointerInputRecorder {
+
+    data class DataPoint(val id: Int, val data: PointerInputData) {
+        val timestamp get() = data.uptime
+        val position get() = data.position
+        val down get() = data.down
+    }
+
+    private val _events = mutableListOf<DataPoint>()
+    val events get() = _events as List<DataPoint>
+
+    fun onPointerInput(
+        changes: List<PointerInputChange>,
+        pass: PointerEventPass,
+        @Suppress("UNUSED_PARAMETER") bounds: IntPxSize
+    ): List<PointerInputChange> {
+        if (pass == PointerEventPass.InitialDown) {
+            changes.forEach {
+                _events.add(DataPoint(it.id, it.current))
+            }
+        }
+        return changes
+    }
+
+    fun assertTimestampsAreIncreasing() {
+        events.reduce { prev, curr ->
+            Truth.assertThat(curr.timestamp).isAtLeast(prev.timestamp)
+            curr
+        }
+    }
+}
\ No newline at end of file
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/SendSwipeTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/SendSwipeTest.kt
new file mode 100644
index 0000000..f16eb24
--- /dev/null
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/SendSwipeTest.kt
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2019 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.ui.test
+
+import androidx.compose.Composable
+import androidx.test.filters.MediumTest
+import androidx.ui.core.Alignment
+import androidx.ui.core.PointerInputWrapper
+import androidx.ui.core.TestTag
+import androidx.ui.core.dp
+import androidx.ui.foundation.shape.DrawShape
+import androidx.ui.foundation.shape.RectangleShape
+import androidx.ui.graphics.Color
+import androidx.ui.layout.Align
+import androidx.ui.layout.Container
+import androidx.ui.semantics.Semantics
+import com.google.common.collect.Ordering
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@MediumTest
+@RunWith(JUnit4::class)
+class SendSwipeTest {
+
+    private val tag = "widget"
+
+    @get:Rule
+    val composeTestRule = createComposeRule(disableTransitions = true)
+
+    private lateinit var recorder: PointerInputRecorder
+
+    @Before
+    fun setup() {
+        recorder = PointerInputRecorder()
+    }
+
+    @Composable
+    fun Ui(alignment: Alignment) {
+        PointerInputWrapper(pointerInputHandler = recorder::onPointerInput) {
+            Align(alignment = alignment) {
+                TestTag(tag) {
+                    Semantics {
+                        Container(width = 100.dp, height = 100.dp) {
+                            DrawShape(RectangleShape, Color.Yellow)
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    @Test
+    fun swipeUp() {
+        composeTestRule.setContent { Ui(Alignment.TopLeft) }
+        findByTag(tag).doGesture { sendSwipeUp() }
+        recorder.run {
+            assertTimestampsAreIncreasing()
+            assertOnlyLastEventIsUp()
+            assertSwipeIsUp()
+        }
+    }
+
+    @Test
+    fun swipeDown() {
+        composeTestRule.setContent { Ui(Alignment.TopRight) }
+        findByTag(tag).doGesture { sendSwipeDown() }
+        recorder.run {
+            assertTimestampsAreIncreasing()
+            assertOnlyLastEventIsUp()
+            assertSwipeIsDown()
+        }
+    }
+
+    @Test
+    fun swipeLeft() {
+        composeTestRule.setContent { Ui(Alignment.BottomRight) }
+        findByTag(tag).doGesture { sendSwipeLeft() }
+        recorder.run {
+            assertTimestampsAreIncreasing()
+            assertOnlyLastEventIsUp()
+            assertSwipeIsLeft()
+        }
+    }
+
+    @Test
+    fun swipeRight() {
+        composeTestRule.setContent { Ui(Alignment.BottomLeft) }
+        findByTag(tag).doGesture { sendSwipeRight() }
+        recorder.run {
+            assertTimestampsAreIncreasing()
+            assertOnlyLastEventIsUp()
+            assertSwipeIsRight()
+        }
+    }
+}
+
+private fun PointerInputRecorder.assertOnlyLastEventIsUp() {
+    assertThat(events.last().down).isFalse()
+    assertThat(events.filter { !it.down }.size).isEqualTo(1)
+}
+
+private fun PointerInputRecorder.assertSwipeIsUp() {
+    // Must have at least two events to have a direction
+    assertThat(events.size).isAtLeast(2)
+    // Last event must be above first event
+    assertThat(events.last().position!!.y).isLessThan(events.first().position!!.y)
+    // All events in between only move up
+    events.map { it.position!!.x.value }.assertSame(tolerance = 0.001f)
+    events.map { it.position!!.y }.assertDecreasing()
+}
+
+private fun PointerInputRecorder.assertSwipeIsDown() {
+    // Must have at least two events to have a direction
+    assertThat(events.size).isAtLeast(2)
+    // Last event must be below first event
+    assertThat(events.last().position!!.y).isGreaterThan(events.first().position!!.y)
+    // All events in between only move down
+    events.map { it.position!!.x.value }.assertSame(tolerance = 0.001f)
+    events.map { it.position!!.y }.assertIncreasing()
+}
+
+private fun PointerInputRecorder.assertSwipeIsLeft() {
+    // Must have at least two events to have a direction
+    assertThat(events.size).isAtLeast(2)
+    // Last event must be to the left of first event
+    assertThat(events.last().position!!.x).isLessThan(events.first().position!!.x)
+    // All events in between only move to the left
+    events.map { it.position!!.x }.assertDecreasing()
+    events.map { it.position!!.y.value }.assertSame(tolerance = 0.001f)
+}
+
+private fun PointerInputRecorder.assertSwipeIsRight() {
+    // Must have at least two events to have a direction
+    assertThat(events.size).isAtLeast(2)
+    // Last event must be to the right of first event
+    assertThat(events.last().position!!.x).isGreaterThan(events.first().position!!.x)
+    // All events in between only move to the right
+    events.map { it.position!!.x }.assertIncreasing()
+    events.map { it.position!!.y.value }.assertSame(tolerance = 0.001f)
+}
+
+private fun List<Float>.assertSame(tolerance: Float = 0f) {
+    if (size <= 1) {
+        return
+    }
+    val baseValue = first()
+    assertThat(min()).isWithin(tolerance).of(baseValue)
+    assertThat(max()).isWithin(tolerance).of(baseValue)
+}
+
+private fun <E : Comparable<E>> List<E>.assertIncreasing() {
+    assertThat(this).isInOrder(Ordering.natural<E>())
+}
+
+private fun <E : Comparable<E>> List<E>.assertDecreasing() {
+    assertThat(this).isInOrder(Ordering.natural<E>().reverse<E>())
+}
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/Actions.kt b/ui/ui-test/src/main/java/androidx/ui/test/Actions.kt
index 86e74da..109498b 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/Actions.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/Actions.kt
@@ -27,18 +27,17 @@
  * Performs a click action on the given component.
  */
 fun SemanticsNodeInteraction.doClick(): SemanticsNodeInteraction {
-    // TODO(b/129400818): uncomment this after Merge Semantics is merged
-    // assertHasClickAction()
-
-    // TODO(catalintudor): get real coordinates after Semantics API is ready (b/125702443)
-    val globalRect = semanticsTreeNode.globalRect
-        ?: throw AssertionError("Semantic Node has no child layout to perform click on!")
-    val x = globalRect.left + 1f
-    val y = globalRect.top + 1f
-
-    semanticsTreeInteraction.sendClick(x, y)
-
-    return this
+    // TODO(jellefresen): Replace with semantics action when semantics merging is done
+    // The problem we currently have is that the click action might be defined on a different
+    // semantics node than we're interacting with now, even though it is "semantically" the same.
+    // E.g., findByText(buttonText) finds the Text's semantics node, but the click action is
+    // defined on the wrapping Button's semantics node.
+    // Since in general the intended click action can be on a wrapping node or a child node, we
+    // can't just forward to the correct node, as we don't know if we should search up or down the
+    // tree.
+    return doGesture {
+        sendClick()
+    }
 }
 
 /**
@@ -85,4 +84,21 @@
     return this
 }
 
+/**
+ * Executes the gestures specified in the given block.
+ *
+ * Example usage:
+ * findByTag("myWidget")
+ *    .doGesture {
+ *        sendSwipeUp()
+ *    }
+ */
+fun SemanticsNodeInteraction.doGesture(
+    block: GestureScope.() -> Unit
+): SemanticsNodeInteraction {
+    val scope = GestureScope(this)
+    scope.block()
+    return this
+}
+
 fun waitForIdleCompose(): Boolean = semanticsTreeInteractionFactory({ true }).waitForIdleCompose()
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/Assertions.kt b/ui/ui-test/src/main/java/androidx/ui/test/Assertions.kt
index 8460a72..032295a 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/Assertions.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/Assertions.kt
@@ -179,8 +179,8 @@
 }
 
 /**
- * Asserts the component's value equals the given value. This is used by
- * [CircularProgressIndicator] to check progress.
+ * Asserts the component's value equals the given value.
+ *
  * For further details please check [SemanticsConfiguration.accessibilityValue].
  * Throws [AssertionError] if the node's value is not equal to `value`, or if the node has no value
  */
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/BitmapHelpers.kt b/ui/ui-test/src/main/java/androidx/ui/test/BitmapHelpers.kt
new file mode 100644
index 0000000..7c3f390
--- /dev/null
+++ b/ui/ui-test/src/main/java/androidx/ui/test/BitmapHelpers.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2019 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.ui.test
+
+import android.graphics.Bitmap
+import android.os.Build
+import androidx.annotation.RequiresApi
+import androidx.ui.core.IntPxPosition
+import androidx.ui.core.IntPxSize
+import androidx.ui.core.ipx
+import androidx.ui.graphics.Color
+
+/**
+ * Captures the underlying component's surface into bitmap.
+ *
+ * This has currently several limitations. Currently we assume that the component is hosted in
+ * Activity's window. Also if there is another window covering part of the component if won't occur
+ * in the bitmap as this is taken from the component's window surface.
+ */
+@RequiresApi(Build.VERSION_CODES.O)
+fun SemanticsNodeInteraction.captureToBitmap(): Bitmap {
+    return semanticsTreeInteraction.captureNodeToBitmap(semanticsTreeNode)
+}
+
+/**
+ * A helper function to run asserts on [Bitmap].
+ *
+ * @param expectedSize The expected size of the bitmap. Leave null to skip the check.
+ * @param expectedColorProvider Returns the expected color for the provided pixel position.
+ * The returned color is then asserted as the expected one on the given bitmap.
+ *
+ * @throws AssertionError if size or colors don't match.
+ */
+fun Bitmap.assertPixels(
+    expectedSize: IntPxSize? = null,
+    expectedColorProvider: (pos: IntPxPosition) -> Color?
+) {
+    if (expectedSize != null) {
+        if (width != expectedSize.width.value || height != expectedSize.height.value) {
+            throw AssertionError("Bitmap size is wrong! Expected '$expectedSize' but got " +
+                    "'$width x $height'")
+        }
+    }
+
+    val pixels = IntArray(width * height)
+    getPixels(pixels, 0, width, 0, 0, width, height)
+
+    for (x in 0 until width) {
+        for (y in 0 until height) {
+            val pxPos = IntPxPosition(x.ipx, y.ipx)
+            val color = Color(pixels[width * y + x])
+            val expectedClr = expectedColorProvider(pxPos)
+            if (expectedClr != null && expectedClr != color) {
+                throw AssertionError("Comparison failed for $pxPos: expected $expectedClr $ " +
+                        "but received $color")
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/ComposeTestRule.kt b/ui/ui-test/src/main/java/androidx/ui/test/ComposeTestRule.kt
index 0e01792..40ae06c 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/ComposeTestRule.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/ComposeTestRule.kt
@@ -16,7 +16,10 @@
 
 package androidx.ui.test
 
+import android.graphics.Bitmap
+import android.os.Build
 import android.util.DisplayMetrics
+import androidx.annotation.RequiresApi
 import androidx.compose.Composable
 import androidx.ui.core.Density
 import androidx.ui.test.android.AndroidComposeTestRule
@@ -59,6 +62,22 @@
      */
     fun runOnUiThread(action: () -> Unit)
 
+    /**
+     * Takes screenshot of the Activity's window after Compose UI gets idle.
+     *
+     * This function blocks until complete.
+     *
+     * Note that this does not capture the full device screen as it has access only to the test
+     * Activity's window surface. The test Activity is the one that hosts the initial composition
+     * created via [setContent]. If there are windows on top of the Activity's window these won't
+     * be included. It will also not include any other Activities started afterwards.
+     *
+     * You can also use [SemanticsNodeInteraction.captureToBitmap] to capture individual components.
+     * That one does not require any specific Activity.
+     */
+    @RequiresApi(Build.VERSION_CODES.O)
+    fun captureScreenOnIdle(): Bitmap
+
     // TODO(pavlis): Provide better abstraction for host side reusability
     val displayMetrics: DisplayMetrics get
 }
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/Filters.kt b/ui/ui-test/src/main/java/androidx/ui/test/Filters.kt
index a2f1cec..1f839b0 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/Filters.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/Filters.kt
@@ -20,22 +20,52 @@
 import androidx.ui.core.semantics.getOrNull
 import androidx.ui.foundation.semantics.FoundationSemanticsProperties
 import androidx.ui.semantics.SemanticsActions
+import androidx.ui.semantics.SemanticsProperties
 
 /**
- * Verifies that a component is checkable.
+ * Return whether the component is checkable.
  */
 val SemanticsConfiguration.isToggleable: Boolean
     get() = contains(FoundationSemanticsProperties.ToggleableState)
 
+/**
+ * Return whether the component has a semantics click action defined.
+ */
 val SemanticsConfiguration.hasClickAction: Boolean
     get() = SemanticsActions.OnClick in this
 
+/**
+ * Return whether the component has a semantics scrollable action defined.
+ */
 val SemanticsConfiguration.hasScrollAction: Boolean
     get() = SemanticsActions.ScrollTo in this
 
+/**
+ * Returns whether the component's label matches exactly to the given text.
+ *
+ * @param text Text to match.
+ * @param ignoreCase Whether case should be ignored.
+ * @see hasSubstring
+ */
+fun SemanticsConfiguration.hasText(text: String, ignoreCase: Boolean = false): Boolean {
+    return getOrNull(SemanticsProperties.AccessibilityLabel).equals(text, ignoreCase)
+}
+
+/**
+ * Returns whether the component's label contains the given substring.
+ *
+ * @param substring Substring to check.
+ * @param ignoreCase Whether case should be ignored.
+ * @see hasText
+ */
+fun SemanticsConfiguration.hasSubstring(substring: String, ignoreCase: Boolean = false): Boolean {
+    return getOrNull(SemanticsProperties.AccessibilityLabel)?.contains(substring, ignoreCase)
+        ?: false
+}
+
 // TODO(ryanmentley/pavlis): Do we want these convenience functions?
 /**
- * Verifies that a component is in a mutually exclusive group - that is,
+ * Verifies that the component is in a mutually exclusive group - that is,
  * that [FoundationSemanticsProperties.InMutuallyExclusiveGroup] is set to true
  *
  */
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/Finders.kt b/ui/ui-test/src/main/java/androidx/ui/test/Finders.kt
index fdb1cf8..1a746fb 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/Finders.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/Finders.kt
@@ -47,13 +47,26 @@
 }
 
 /**
- * Finds a component by the given text.
+ * Finds a component with label that matches the given text.
  *
  * For usage patterns see [SemanticsNodeInteraction]
+ * @see findBySubstring to search by substring instead of via exact match.
  */
 fun findByText(text: String, ignoreCase: Boolean = false): SemanticsNodeInteraction {
     return find {
-        getOrNull(SemanticsProperties.AccessibilityLabel).equals(text, ignoreCase)
+        hasText(text, ignoreCase)
+    }
+}
+
+/**
+ *  Finds a component with label that contains the given substring.
+ *
+ * For usage patterns see [SemanticsNodeInteraction]
+ * @see findByText to perform exact matches.
+ */
+fun findBySubstring(text: String, ignoreCase: Boolean = false): SemanticsNodeInteraction {
+    return find {
+        hasSubstring(text, ignoreCase)
     }
 }
 
@@ -62,6 +75,7 @@
  * This tries to match exactly one element and throws [AssertionError] if more than one is matched.
  *
  * For usage patterns see [SemanticsNodeInteraction]
+ * @see findAll to work with multiple elements
  */
 fun find(
     selector: SemanticsConfiguration.() -> Boolean
@@ -70,6 +84,13 @@
         .findOne()
 }
 
+/**
+ * Finds all components that match the given condition.
+ *
+ * If you are working with elements that are not supposed to occur multiple times use [find]
+ * instead.
+ * @see find
+ */
 fun findAll(
     selector: SemanticsConfiguration.() -> Boolean
 ): List<SemanticsNodeInteraction> {
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/GestureScope.kt b/ui/ui-test/src/main/java/androidx/ui/test/GestureScope.kt
new file mode 100644
index 0000000..3d5daf2
--- /dev/null
+++ b/ui/ui-test/src/main/java/androidx/ui/test/GestureScope.kt
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2019 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.ui.test
+
+import androidx.ui.core.Duration
+import androidx.ui.core.SemanticsTreeNode
+import androidx.ui.core.milliseconds
+
+/**
+ * An object that has an associated component in which one can inject gestures. The gestures can
+ * be injected by calling methods defined on [GestureScope], such as [sendSwipeUp]. The associated
+ * component is the [SemanticsTreeNode] found by one of the finder methods such as [findByTag].
+ *
+ * Example usage:
+ * findByTag("myWidget")
+ *    .doGesture {
+ *        sendSwipeUp()
+ *    }
+ */
+class GestureScope internal constructor(
+    internal val semanticsNodeInteraction: SemanticsNodeInteraction
+) {
+    internal inline val semanticsTreeNode
+        get() = semanticsNodeInteraction.semanticsTreeNode
+    internal inline val semanticsTreeInteraction
+        get() = semanticsNodeInteraction.semanticsTreeInteraction
+}
+
+/**
+ * The distance of a swipe's start position from the node's edge, in terms of the node's length.
+ * We do not start the swipe exactly on the node's edge, but somewhat more inward, since swiping
+ * from the exact edge may behave in an unexpected way (e.g. may open a navigation drawer).
+ */
+private const val edgeFuzzFactor = 0.083f
+
+/**
+ * Performs a click gesture on the given coordinate on the associated component. The coordinate
+ * ([x], [y]) is in the component's local coordinate system.
+ *
+ * Throws [AssertionError] when the component doesn't have a bounding rectangle set
+ */
+fun GestureScope.sendClick(x: Float, y: Float) {
+    val globalRect = semanticsTreeNode.globalRect
+        ?: throw AssertionError("Semantic Node has no child layout to perform click on!")
+    val xOffset = globalRect.left
+    val yOffset = globalRect.top
+
+    semanticsTreeInteraction.sendInput {
+        it.sendClick(x + xOffset, y + yOffset)
+    }
+}
+
+/**
+ * Performs a click gesture on the associated component. The click is done in the middle of the
+ * component's bounds.
+ *
+ * Throws [AssertionError] when the component doesn't have a bounding rectangle set
+ */
+fun GestureScope.sendClick() {
+    val globalRect = semanticsTreeNode.globalRect
+        ?: throw AssertionError("Semantic Node has no child layout to perform click on!")
+    val x = globalRect.width / 2
+    val y = globalRect.height / 2
+
+    sendClick(x, y)
+}
+
+/**
+ * Performs the swipe gesture on the associated component. The MotionEvents are linearly
+ * interpolated between ([x0], [y0]) and ([x1], [y1]). The coordinates are in the component's local
+ * coordinate system, i.e. (0, 0) is the top left corner of the component. The default duration is
+ * 200 milliseconds.
+ *
+ * Throws [AssertionError] when the component doesn't have a bounding rectangle set
+ */
+fun GestureScope.sendSwipe(
+    x0: Float,
+    y0: Float,
+    x1: Float,
+    y1: Float,
+    duration: Duration = 200.milliseconds
+) {
+    val globalRect = semanticsTreeNode.globalRect
+        ?: throw AssertionError("Semantic Node has no child layout to perform swipe on!")
+    val xOffset = globalRect.left
+    val yOffset = globalRect.top
+
+    semanticsTreeInteraction.sendInput {
+        it.sendSwipe(x0 + xOffset, y0 + yOffset, x1 + xOffset, y1 + yOffset, duration)
+    }
+}
+
+/**
+ * Performs a swipe up gesture on the associated component. The gesture starts slightly above the
+ * bottom of the component and ends at the top.
+ *
+ * Throws [AssertionError] when the component doesn't have a bounding rectangle set
+ */
+fun GestureScope.sendSwipeUp() {
+    val globalRect = semanticsTreeNode.globalRect
+        ?: throw AssertionError("Semantic Node has no child layout to perform swipe on!")
+    val x = globalRect.width / 2
+    val y0 = globalRect.height * (1 - edgeFuzzFactor)
+    val y1 = 0f
+
+    sendSwipe(x, y0, x, y1, 200.milliseconds)
+}
+
+/**
+ * Performs a swipe down gesture on the associated component. The gesture starts slightly below the
+ * top of the component and ends at the bottom.
+ *
+ * Throws [AssertionError] when the component doesn't have a bounding rectangle set
+ */
+fun GestureScope.sendSwipeDown() {
+    val globalRect = semanticsTreeNode.globalRect
+        ?: throw AssertionError("Semantic Node has no child layout to perform swipe on!")
+    val x = globalRect.width / 2
+    val y0 = globalRect.height * edgeFuzzFactor
+    val y1 = globalRect.height
+
+    sendSwipe(x, y0, x, y1, 200.milliseconds)
+}
+
+/**
+ * Performs a swipe left gesture on the associated component. The gesture starts slightly left of
+ * the right side of the component and ends at the left side.
+ *
+ * Throws [AssertionError] when the component doesn't have a bounding rectangle set
+ */
+fun GestureScope.sendSwipeLeft() {
+    val globalRect = semanticsTreeNode.globalRect
+        ?: throw AssertionError("Semantic Node has no child layout to perform swipe on!")
+    val x0 = globalRect.width * (1 - edgeFuzzFactor)
+    val x1 = 0f
+    val y = globalRect.height / 2
+
+    sendSwipe(x0, y, x1, y, 200.milliseconds)
+}
+
+/**
+ * Performs a swipe right gesture on the associated component. The gesture starts slightly right of
+ * the left side of the component and ends at the right side.
+ *
+ * Throws [AssertionError] when the component doesn't have a bounding rectangle set
+ */
+fun GestureScope.sendSwipeRight() {
+    val globalRect = semanticsTreeNode.globalRect
+        ?: throw AssertionError("Semantic Node has no child layout to perform swipe on!")
+    val x0 = globalRect.width * edgeFuzzFactor
+    val x1 = globalRect.width
+    val y = globalRect.height / 2
+
+    sendSwipe(x0, y, x1, y, 200.milliseconds)
+}
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/InputDispatcher.kt b/ui/ui-test/src/main/java/androidx/ui/test/InputDispatcher.kt
new file mode 100644
index 0000000..c8b061a
--- /dev/null
+++ b/ui/ui-test/src/main/java/androidx/ui/test/InputDispatcher.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2019 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.ui.test
+
+import androidx.ui.core.Duration
+
+internal interface InputDispatcher {
+    /**
+     * Sends a click event at coordinate ([x], [y]). There will be 10ms in between the down and
+     * the up event. This method blocks until all input events have been dispatched.
+     */
+    fun sendClick(x: Float, y: Float)
+
+    /**
+     * Sends a swipe gesture from ([x0], [y0]) to ([x1], [y1]) with the given [duration]. This
+     * method blocks until all input events have been dispatched.
+     */
+    fun sendSwipe(x0: Float, y0: Float, x1: Float, y1: Float, duration: Duration)
+}
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/SemanticsTreeInteraction.kt b/ui/ui-test/src/main/java/androidx/ui/test/SemanticsTreeInteraction.kt
index 94a780f..0c72173 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/SemanticsTreeInteraction.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/SemanticsTreeInteraction.kt
@@ -16,6 +16,10 @@
 
 package androidx.ui.test
 
+import android.graphics.Bitmap
+import android.os.Build
+import androidx.annotation.RequiresApi
+import androidx.ui.core.SemanticsTreeNode
 import androidx.ui.core.SemanticsTreeProvider
 import androidx.ui.core.semantics.SemanticsConfiguration
 import androidx.ui.engine.geometry.Rect
@@ -26,21 +30,24 @@
  * extension functions. This class is expected to have Android and host side specific
  * implementations.
  */
-internal abstract class SemanticsTreeInteraction {
+internal interface SemanticsTreeInteraction {
 
-    internal abstract fun findAllMatching(): List<SemanticsNodeInteraction>
+    fun findAllMatching(): List<SemanticsNodeInteraction>
 
-    internal abstract fun findOne(): SemanticsNodeInteraction
+    fun findOne(): SemanticsNodeInteraction
 
-    internal abstract fun performAction(action: (SemanticsTreeProvider) -> Unit)
+    fun performAction(action: (SemanticsTreeProvider) -> Unit)
 
-    internal abstract fun sendClick(x: Float, y: Float)
+    fun sendInput(action: (InputDispatcher) -> Unit)
 
-    internal abstract fun contains(semanticsConfiguration: SemanticsConfiguration): Boolean
+    fun contains(semanticsConfiguration: SemanticsConfiguration): Boolean
 
-    internal abstract fun isInScreenBounds(rectangle: Rect): Boolean
+    fun isInScreenBounds(rectangle: Rect): Boolean
 
-    internal abstract fun waitForIdleCompose(): Boolean
+    fun waitForIdleCompose(): Boolean
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    fun captureNodeToBitmap(node: SemanticsTreeNode): Bitmap
 }
 
 internal var semanticsTreeInteractionFactory: (
@@ -58,4 +65,4 @@
  * just wait for longer timeouts as the tests might still have a value.
  */
 // TODO(pavlis): Turn this on by default for all our Compose tests
-internal var throwOnRecomposeTimeout = false
\ No newline at end of file
+internal var throwOnRecomposeTimeout = false
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidComposeTestRule.kt b/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidComposeTestRule.kt
index 3971e79..39797ca 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidComposeTestRule.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidComposeTestRule.kt
@@ -17,14 +17,20 @@
 package androidx.ui.test.android
 
 import android.app.Activity
+import android.graphics.Bitmap
+import android.os.Build
+import android.os.Handler
+import android.os.Looper
 import android.util.DisplayMetrics
 import android.view.ViewGroup
 import android.view.ViewTreeObserver
+import androidx.annotation.RequiresApi
 import androidx.compose.Composable
 import androidx.test.rule.ActivityTestRule
 import androidx.ui.animation.transitionsEnabled
 import androidx.ui.core.Density
 import androidx.ui.core.setContent
+import androidx.ui.engine.geometry.Rect
 import androidx.ui.test.ComposeTestCase
 import androidx.ui.test.ComposeTestCaseSetup
 import androidx.ui.test.ComposeTestRule
@@ -44,6 +50,8 @@
 
     val activityTestRule = ActivityTestRule<Activity>(Activity::class.java)
 
+    private val handler: Handler = Handler(Looper.getMainLooper())
+
     override val density: Density get() = Density(activityTestRule.activity)
 
     override val displayMetrics: DisplayMetrics get() =
@@ -111,6 +119,21 @@
         )
     }
 
+    @RequiresApi(Build.VERSION_CODES.O)
+    override fun captureScreenOnIdle(): Bitmap {
+        AndroidSemanticsTreeInteraction(throwOnRecomposeTimeOut = true, selector = { true })
+            .waitForIdleCompose()
+        val contentView = activityTestRule.activity.findViewById<ViewGroup>(android.R.id.content)
+
+        val screenRect = Rect.fromLTWH(
+            0f,
+            0f,
+            contentView.width.toFloat(),
+            contentView.height.toFloat()
+        )
+        return captureRegionToBitmap(screenRect, handler, activityTestRule.activity.window)
+    }
+
     inner class AndroidComposeStatement(
         private val base: Statement
     ) : Statement() {
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidInputDispatcher.kt b/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidInputDispatcher.kt
new file mode 100644
index 0000000..d7ab848
--- /dev/null
+++ b/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidInputDispatcher.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2019 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.ui.test.android
+
+import android.os.Handler
+import android.os.Looper
+import android.os.SystemClock
+import android.view.MotionEvent
+import androidx.ui.core.Duration
+import androidx.ui.core.SemanticsTreeProvider
+import androidx.ui.core.inMilliseconds
+import androidx.ui.core.milliseconds
+import androidx.ui.lerp
+import androidx.ui.test.InputDispatcher
+import java.util.concurrent.CountDownLatch
+import kotlin.math.min
+import kotlin.math.roundToInt
+
+internal class AndroidInputDispatcher(
+    private val treeProvider: SemanticsTreeProvider
+) : InputDispatcher {
+    /**
+     * The minimum time between two successive injected MotionEvents. Ideally, the value should
+     * reflect a realistic pointer input sample rate, but that depends on too many factors. Instead,
+     * the value is chosen comfortably below the targeted frame rate (60 fps, equating to a 16ms
+     * period).
+     */
+    private val eventPeriod = 10.milliseconds.inMilliseconds()
+
+    private val handler = Handler(Looper.getMainLooper())
+
+    override fun sendClick(x: Float, y: Float) {
+        val downTime = SystemClock.uptimeMillis()
+        treeProvider.sendMotionEvent(downTime, downTime, MotionEvent.ACTION_DOWN, x, y)
+        treeProvider.sendMotionEvent(downTime, downTime + eventPeriod, MotionEvent.ACTION_UP, x, y)
+    }
+
+    override fun sendSwipe(x0: Float, y0: Float, x1: Float, y1: Float, duration: Duration) {
+        var step = 0
+        val steps = min(1, (duration.inMilliseconds() / eventPeriod.toFloat()).roundToInt())
+        val downTime = SystemClock.uptimeMillis()
+        val upTime = downTime + duration.inMilliseconds()
+
+        treeProvider.sendMotionEvent(downTime, downTime, MotionEvent.ACTION_DOWN, x0, y0)
+        while (step++ < steps) {
+            val progress = step / steps.toFloat()
+            val t = lerp(downTime, upTime, progress)
+            val x = lerp(x0, x1, progress)
+            val y = lerp(y0, y1, progress)
+            treeProvider.sendMotionEvent(downTime, t, MotionEvent.ACTION_MOVE, x, y)
+        }
+        treeProvider.sendMotionEvent(downTime, upTime, MotionEvent.ACTION_UP, x1, y1)
+    }
+
+    /**
+     * Sends an event with the given parameters. Method blocks depending on [waitUntilEventTime].
+     * @param waitUntilEventTime If `true`, blocks until [eventTime]
+     */
+    private fun SemanticsTreeProvider.sendMotionEvent(
+        downTime: Long,
+        eventTime: Long,
+        action: Int,
+        x: Float,
+        y: Float,
+        waitUntilEventTime: Boolean = true
+    ) {
+        if (waitUntilEventTime) {
+            val currTime = SystemClock.uptimeMillis()
+            if (currTime < eventTime) {
+                SystemClock.sleep(eventTime - currTime)
+            }
+        }
+        sendAndRecycleEvent(MotionEvent.obtain(downTime, eventTime, action, x, y, 0))
+    }
+
+    /**
+     * Sends the [event] to the [SemanticsTreeProvider] and [recycles][MotionEvent.recycle] it
+     * regardless of the result. This method blocks until the event is sent.
+     */
+    private fun SemanticsTreeProvider.sendAndRecycleEvent(event: MotionEvent) {
+        val latch = CountDownLatch(1)
+        handler.post {
+            try {
+                sendEvent(event)
+            } finally {
+                event.recycle()
+                latch.countDown()
+            }
+        }
+        latch.await()
+    }
+}
\ No newline at end of file
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidSemanticsTreeInteraction.kt b/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidSemanticsTreeInteraction.kt
index 59feac9..d9a96a2 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidSemanticsTreeInteraction.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidSemanticsTreeInteraction.kt
@@ -20,13 +20,15 @@
 import android.annotation.SuppressLint
 import android.app.Activity
 import android.content.Context
+import android.graphics.Bitmap
+import android.os.Build
 import android.os.Handler
 import android.os.Looper
-import android.os.SystemClock
 import android.view.Choreographer
 import android.view.MotionEvent
 import android.view.View
 import android.view.ViewGroup
+import androidx.annotation.RequiresApi
 import androidx.compose.Recomposer
 import androidx.test.espresso.Espresso
 import androidx.test.espresso.NoMatchingViewException
@@ -38,6 +40,7 @@
 import androidx.ui.core.px
 import androidx.ui.core.semantics.SemanticsConfiguration
 import androidx.ui.engine.geometry.Rect
+import androidx.ui.test.InputDispatcher
 import androidx.ui.test.SemanticsNodeInteraction
 import androidx.ui.test.SemanticsTreeInteraction
 import java.util.concurrent.CountDownLatch
@@ -55,7 +58,7 @@
 internal class AndroidSemanticsTreeInteraction internal constructor(
     private val throwOnRecomposeTimeOut: Boolean,
     private val selector: SemanticsConfiguration.() -> Boolean
-) : SemanticsTreeInteraction() {
+) : SemanticsTreeInteraction {
 
     /**
      * Whether after the latest performed action we waited for any pending changes in composition.
@@ -111,6 +114,11 @@
         hadPendingChangesAfterLastAction = waitForIdleCompose()
     }
 
+    override fun sendInput(action: (InputDispatcher) -> Unit) {
+        action(AndroidInputDispatcher(findActivityAndTreeProvider().treeProvider))
+        hadPendingChangesAfterLastAction = waitForIdleCompose()
+    }
+
     /**
      * Waits for Compose runtime to be idle - meaning it has no pending changes.
      *
@@ -153,25 +161,6 @@
         })
     }
 
-    override fun sendClick(x: Float, y: Float) {
-        performAction { treeProvider ->
-            val downTime = SystemClock.uptimeMillis()
-            val eventDown = MotionEvent.obtain(
-                downTime, downTime,
-                MotionEvent.ACTION_DOWN, x, y, 0
-            )
-            treeProvider.sendEvent(eventDown)
-            eventDown.recycle()
-
-            val eventUp = MotionEvent.obtain(
-                downTime, downTime + 10,
-                MotionEvent.ACTION_UP, x, y, 0
-            )
-            treeProvider.sendEvent(eventUp)
-            eventUp.recycle()
-        }
-    }
-
     override fun contains(semanticsConfiguration: SemanticsConfiguration): Boolean {
         waitForIdleCompose()
 
@@ -191,7 +180,6 @@
             displayMetrics.widthPixels.px,
             displayMetrics.heightPixels.px
         )
-
         val screenRect = Rect.fromLTWH(
             0.px.value,
             0.px.value,
@@ -203,6 +191,37 @@
                 screenRect.contains(rectangle.getBottomRight())
     }
 
+    @RequiresApi(Build.VERSION_CODES.O)
+    override fun captureNodeToBitmap(node: SemanticsTreeNode): Bitmap {
+        val collectedInfo = findActivityAndTreeProvider()
+
+        // TODO: Share this code with contains() somehow?
+        val exists = collectedInfo.treeProvider
+            .getAllSemanticNodes()
+            .any { it.data == node.data }
+        if (!exists) {
+            throw AssertionError("The required node is no longer in the tree!")
+        }
+
+        if (collectedInfo.context !is Activity) {
+            // TODO(pavlis): Espresso might have the windows already somewhere internally ...
+            throw AssertionError("The context assigned to your composable holder view cannot be " +
+                    "cast to Activity. So this function can't access its window to capture the " +
+                    "bitmap.")
+        }
+        val window = collectedInfo.context.window
+
+        // TODO(pavlis): Consider doing assertIsDisplayed here. Will need to move things around.
+
+        // TODO(pavlis): Make sure that the Activity actually hosts the view. As in case of popup
+        // it wouldn't. This will require us rewriting the structure how we collect the nodes.
+
+        // TODO(pavlis): Add support for popups. So if we find composable hosted in popup we can
+        // grab its reference to its window (need to add a hook to popup).
+
+        return captureRegionToBitmap(node.globalRect!!, handler, window)
+    }
+
     private fun findActivityAndTreeProvider(): CollectedInfo {
         val viewForwarder = ViewForwarder()
 
@@ -281,4 +300,4 @@
         val context: Context,
         val treeProvider: SemanticsTreeProvider
     )
-}
\ No newline at end of file
+}
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/android/WindowCapture.kt b/ui/ui-test/src/main/java/androidx/ui/test/android/WindowCapture.kt
new file mode 100644
index 0000000..e8573f0
--- /dev/null
+++ b/ui/ui-test/src/main/java/androidx/ui/test/android/WindowCapture.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2019 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.ui.test.android
+
+import android.graphics.Bitmap
+import android.os.Build
+import android.os.Handler
+import android.view.PixelCopy
+import android.view.Window
+import androidx.annotation.RequiresApi
+import androidx.ui.engine.geometry.Rect
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+import kotlin.math.roundToInt
+
+@RequiresApi(Build.VERSION_CODES.O)
+internal fun captureRegionToBitmap(
+    globalRect: Rect,
+    handler: Handler,
+    window: Window
+): Bitmap {
+    val destBitmap = Bitmap.createBitmap(
+        globalRect.width.roundToInt(),
+        globalRect.height.roundToInt(),
+        Bitmap.Config.ARGB_8888)
+
+    // TODO: This could go to some Android specific extensions.
+    val srcRect = android.graphics.Rect(
+        globalRect.left.roundToInt(),
+        globalRect.top.roundToInt(),
+        globalRect.right.roundToInt(),
+        globalRect.bottom.roundToInt())
+
+    val latch = CountDownLatch(1)
+    var copyResult = 0
+    val onCopyFinished = object : PixelCopy.OnPixelCopyFinishedListener {
+        override fun onPixelCopyFinished(result: Int) {
+            copyResult = result
+            latch.countDown()
+        }
+    }
+
+    PixelCopy.request(window, srcRect, destBitmap, onCopyFinished, handler)
+
+    if (!latch.await(1, TimeUnit.SECONDS)) {
+        throw AssertionError("Failed waiting for PixelCopy!")
+    }
+    if (copyResult != PixelCopy.SUCCESS) {
+        throw AssertionError("PixelCopy failed!")
+    }
+    return destBitmap
+}
diff --git a/ui/ui-test/src/test/java/androidx/ui/test/FindersTests.kt b/ui/ui-test/src/test/java/androidx/ui/test/FindersTests.kt
index c487f67..492e80d 100644
--- a/ui/ui-test/src/test/java/androidx/ui/test/FindersTests.kt
+++ b/ui/ui-test/src/test/java/androidx/ui/test/FindersTests.kt
@@ -20,10 +20,12 @@
 import androidx.ui.core.semantics.SemanticsConfiguration
 import androidx.ui.core.semantics.getOrNull
 import androidx.ui.semantics.SemanticsProperties
+import androidx.ui.semantics.accessibilityLabel
 import androidx.ui.semantics.testTag
 import androidx.ui.test.helpers.FakeSemanticsTreeInteraction
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
 import org.junit.Test
+import java.lang.AssertionError
 
 class FindersTests {
     @Test
@@ -38,7 +40,7 @@
         }
 
         val foundNodes = findAll { getOrNull(SemanticsProperties.TestTag) == "myTestTag" }
-        Truth.assertThat(foundNodes).isEmpty()
+        assertThat(foundNodes).isEmpty()
     }
 
     @Test
@@ -56,7 +58,7 @@
         }
 
         val foundNodes = findAll { getOrNull(SemanticsProperties.TestTag) == "myTestTag" }
-        Truth.assertThat(foundNodes.map { it.semanticsTreeNode }).containsExactly(node1)
+        assertThat(foundNodes.map { it.semanticsTreeNode }).containsExactly(node1)
     }
 
     @Test
@@ -78,10 +80,70 @@
         }
 
         val foundNodes = findAll { getOrNull(SemanticsProperties.TestTag) == "myTestTag" }
-        Truth.assertThat(foundNodes.map { it.semanticsTreeNode }).containsExactly(node1, node2)
+        assertThat(foundNodes.map { it.semanticsTreeNode }).containsExactly(node1, node2)
+    }
+
+    @Test
+    fun findByText_matches() {
+        semanticsTreeInteractionFactory = { selector ->
+            FakeSemanticsTreeInteraction(selector)
+                .withProperties(SemanticsConfiguration().also {
+                    it.accessibilityLabel = "Hello World"
+                })
+        }
+
+        findByText("Hello World")
+    }
+
+    @Test(expected = AssertionError::class)
+    fun findByText_fails() {
+        semanticsTreeInteractionFactory = { selector ->
+            FakeSemanticsTreeInteraction(selector)
+                .withProperties(SemanticsConfiguration().also {
+                    it.accessibilityLabel = "Hello World"
+                })
+        }
+
+        findByText("World")
+    }
+
+    @Test
+    fun findBySubstring_matches() {
+        semanticsTreeInteractionFactory = { selector ->
+            FakeSemanticsTreeInteraction(selector)
+                .withProperties(SemanticsConfiguration().also {
+                    it.accessibilityLabel = "Hello World"
+                })
+        }
+
+        findBySubstring("World")
+    }
+
+    @Test
+    fun findBySubstring_ignoreCase_matches() {
+        semanticsTreeInteractionFactory = { selector ->
+            FakeSemanticsTreeInteraction(selector)
+                .withProperties(SemanticsConfiguration().also {
+                    it.accessibilityLabel = "Hello World"
+                })
+        }
+
+        findBySubstring("world", ignoreCase = true)
+    }
+
+    @Test(expected = AssertionError::class)
+    fun findBySubstring_wrongCase_fails() {
+        semanticsTreeInteractionFactory = { selector ->
+            FakeSemanticsTreeInteraction(selector)
+                .withProperties(SemanticsConfiguration().also {
+                    it.accessibilityLabel = "Hello World"
+                })
+        }
+
+        findBySubstring("world")
     }
 
     private fun newNode(properties: SemanticsConfiguration): SemanticsTreeNode {
-        return SemanticsTreeNodeStub(/* data= */ properties)
+        return SemanticsTreeNodeStub(data = properties)
     }
 }
\ No newline at end of file
diff --git a/ui/ui-test/src/test/java/androidx/ui/test/helpers/FakeSemanticsTreeInteraction.kt b/ui/ui-test/src/test/java/androidx/ui/test/helpers/FakeSemanticsTreeInteraction.kt
index d580c4c..280390c 100644
--- a/ui/ui-test/src/test/java/androidx/ui/test/helpers/FakeSemanticsTreeInteraction.kt
+++ b/ui/ui-test/src/test/java/androidx/ui/test/helpers/FakeSemanticsTreeInteraction.kt
@@ -16,10 +16,12 @@
 
 package androidx.ui.test.helpers
 
+import android.graphics.Bitmap
 import androidx.ui.core.SemanticsTreeNode
 import androidx.ui.core.SemanticsTreeProvider
 import androidx.ui.core.semantics.SemanticsConfiguration
 import androidx.ui.engine.geometry.Rect
+import androidx.ui.test.InputDispatcher
 import androidx.ui.test.SemanticsNodeInteraction
 import androidx.ui.test.SemanticsTreeInteraction
 import androidx.ui.test.SemanticsTreeNodeStub
@@ -27,7 +29,7 @@
 
 internal class FakeSemanticsTreeInteraction internal constructor(
     private val selector: SemanticsConfiguration.() -> Boolean
-) : SemanticsTreeInteraction() {
+) : SemanticsTreeInteraction {
 
     private lateinit var semanticsToUse: List<SemanticsNodeInteraction>
 
@@ -69,7 +71,7 @@
         TODO("replace with host side interaction")
     }
 
-    override fun sendClick(x: Float, y: Float) {
+    override fun sendInput(action: (InputDispatcher) -> Unit) {
         TODO("replace with host side interaction")
     }
 
@@ -86,4 +88,8 @@
     override fun waitForIdleCompose(): Boolean {
         return semanticsTreeInteractionFactory(selector).waitForIdleCompose()
     }
+
+    override fun captureNodeToBitmap(node: SemanticsTreeNode): Bitmap {
+        TODO("not implemented")
+    }
 }
\ No newline at end of file
diff --git a/ui/ui-text/api/0.1.0-dev03.txt b/ui/ui-text/api/0.1.0-dev03.txt
index 36ba5b6..9bc931f 100644
--- a/ui/ui-text/api/0.1.0-dev03.txt
+++ b/ui/ui-text/api/0.1.0-dev03.txt
@@ -220,14 +220,14 @@
   }
 
   public static final class AnnotatedString.Item<T> {
-    ctor public AnnotatedString.Item(T! style, int start, int end);
+    ctor public AnnotatedString.Item(T! item, int start, int end);
     method public T! component1();
     method public int component2();
     method public int component3();
-    method public androidx.ui.text.AnnotatedString.Item<T> copy(T! style, int start, int end);
+    method public androidx.ui.text.AnnotatedString.Item<T> copy(T! item, int start, int end);
     method public int getEnd();
+    method public T! getItem();
     method public int getStart();
-    method public T! getStyle();
   }
 
   public final class AnnotatedStringKt {
diff --git a/ui/ui-text/api/current.txt b/ui/ui-text/api/current.txt
index 36ba5b6..9bc931f 100644
--- a/ui/ui-text/api/current.txt
+++ b/ui/ui-text/api/current.txt
@@ -220,14 +220,14 @@
   }
 
   public static final class AnnotatedString.Item<T> {
-    ctor public AnnotatedString.Item(T! style, int start, int end);
+    ctor public AnnotatedString.Item(T! item, int start, int end);
     method public T! component1();
     method public int component2();
     method public int component3();
-    method public androidx.ui.text.AnnotatedString.Item<T> copy(T! style, int start, int end);
+    method public androidx.ui.text.AnnotatedString.Item<T> copy(T! item, int start, int end);
     method public int getEnd();
+    method public T! getItem();
     method public int getStart();
-    method public T! getStyle();
   }
 
   public final class AnnotatedStringKt {
diff --git a/ui/ui-text/api/public_plus_experimental_0.1.0-dev03.txt b/ui/ui-text/api/public_plus_experimental_0.1.0-dev03.txt
index 36ba5b6..9bc931f 100644
--- a/ui/ui-text/api/public_plus_experimental_0.1.0-dev03.txt
+++ b/ui/ui-text/api/public_plus_experimental_0.1.0-dev03.txt
@@ -220,14 +220,14 @@
   }
 
   public static final class AnnotatedString.Item<T> {
-    ctor public AnnotatedString.Item(T! style, int start, int end);
+    ctor public AnnotatedString.Item(T! item, int start, int end);
     method public T! component1();
     method public int component2();
     method public int component3();
-    method public androidx.ui.text.AnnotatedString.Item<T> copy(T! style, int start, int end);
+    method public androidx.ui.text.AnnotatedString.Item<T> copy(T! item, int start, int end);
     method public int getEnd();
+    method public T! getItem();
     method public int getStart();
-    method public T! getStyle();
   }
 
   public final class AnnotatedStringKt {
diff --git a/ui/ui-text/api/public_plus_experimental_current.txt b/ui/ui-text/api/public_plus_experimental_current.txt
index 36ba5b6..9bc931f 100644
--- a/ui/ui-text/api/public_plus_experimental_current.txt
+++ b/ui/ui-text/api/public_plus_experimental_current.txt
@@ -220,14 +220,14 @@
   }
 
   public static final class AnnotatedString.Item<T> {
-    ctor public AnnotatedString.Item(T! style, int start, int end);
+    ctor public AnnotatedString.Item(T! item, int start, int end);
     method public T! component1();
     method public int component2();
     method public int component3();
-    method public androidx.ui.text.AnnotatedString.Item<T> copy(T! style, int start, int end);
+    method public androidx.ui.text.AnnotatedString.Item<T> copy(T! item, int start, int end);
     method public int getEnd();
+    method public T! getItem();
     method public int getStart();
-    method public T! getStyle();
   }
 
   public final class AnnotatedStringKt {
diff --git a/ui/ui-text/api/restricted_0.1.0-dev03.txt b/ui/ui-text/api/restricted_0.1.0-dev03.txt
index 8e81f5f..b3433b2 100644
--- a/ui/ui-text/api/restricted_0.1.0-dev03.txt
+++ b/ui/ui-text/api/restricted_0.1.0-dev03.txt
@@ -222,14 +222,14 @@
   }
 
   public static final class AnnotatedString.Item<T> {
-    ctor public AnnotatedString.Item(T! style, int start, int end);
+    ctor public AnnotatedString.Item(T! item, int start, int end);
     method public T! component1();
     method public int component2();
     method public int component3();
-    method public androidx.ui.text.AnnotatedString.Item<T> copy(T! style, int start, int end);
+    method public androidx.ui.text.AnnotatedString.Item<T> copy(T! item, int start, int end);
     method public int getEnd();
+    method public T! getItem();
     method public int getStart();
-    method public T! getStyle();
   }
 
   public final class AnnotatedStringKt {
diff --git a/ui/ui-text/api/restricted_current.txt b/ui/ui-text/api/restricted_current.txt
index 8e81f5f..b3433b2 100644
--- a/ui/ui-text/api/restricted_current.txt
+++ b/ui/ui-text/api/restricted_current.txt
@@ -222,14 +222,14 @@
   }
 
   public static final class AnnotatedString.Item<T> {
-    ctor public AnnotatedString.Item(T! style, int start, int end);
+    ctor public AnnotatedString.Item(T! item, int start, int end);
     method public T! component1();
     method public int component2();
     method public int component3();
-    method public androidx.ui.text.AnnotatedString.Item<T> copy(T! style, int start, int end);
+    method public androidx.ui.text.AnnotatedString.Item<T> copy(T! item, int start, int end);
     method public int getEnd();
+    method public T! getItem();
     method public int getStart();
-    method public T! getStyle();
   }
 
   public final class AnnotatedStringKt {
diff --git a/ui/ui-text/src/androidTest/java/androidx/ui/text/MultiParagraphIntegrationTest.kt b/ui/ui-text/src/androidTest/java/androidx/ui/text/MultiParagraphIntegrationTest.kt
index 7cb184f..e12a544 100644
--- a/ui/ui-text/src/androidTest/java/androidx/ui/text/MultiParagraphIntegrationTest.kt
+++ b/ui/ui-text/src/androidTest/java/androidx/ui/text/MultiParagraphIntegrationTest.kt
@@ -1181,17 +1181,17 @@
         val text = AnnotatedString(
             text = "ab",
             paragraphStyles = listOf(
-                AnnotatedString.Item(
-                    style = ParagraphStyle(
+                ParagraphStyleSpan(
+                    item = ParagraphStyle(
                         textDirectionAlgorithm = TextDirectionAlgorithm.ContentOrLtr
                     ),
                     start = 0,
                     end = "a".length
                 ),
-                AnnotatedString.Item(
+                ParagraphStyleSpan(
                     // skip setting [TextDirectionAlgorithm] on purpose, should inherit from the
                     // main [ParagraphStyle]
-                    style = ParagraphStyle(),
+                    item = ParagraphStyle(),
                     start = "a".length,
                     end = "ab".length
                 )
diff --git a/ui/ui-text/src/androidTest/java/androidx/ui/text/ParagraphIntrinsicIntegrationTest.kt b/ui/ui-text/src/androidTest/java/androidx/ui/text/ParagraphIntrinsicIntegrationTest.kt
index 1ddfcf5..50eee9a 100644
--- a/ui/ui-text/src/androidTest/java/androidx/ui/text/ParagraphIntrinsicIntegrationTest.kt
+++ b/ui/ui-text/src/androidTest/java/androidx/ui/text/ParagraphIntrinsicIntegrationTest.kt
@@ -101,8 +101,8 @@
                 text = text,
                 fontSize = fontSize,
                 textStyles = listOf(
-                    AnnotatedString.Item(
-                        style = TextStyle(fontSize = styledFontSize),
+                    TextStyleSpan(
+                        item = TextStyle(fontSize = styledFontSize),
                         start = "a ".length,
                         end = "a bb ".length
                     )
@@ -187,8 +187,8 @@
                 text = text,
                 fontSize = fontSize,
                 textStyles = listOf(
-                    AnnotatedString.Item(
-                        style = TextStyle(fontSize = styledFontSize),
+                    TextStyleSpan(
+                        item = TextStyle(fontSize = styledFontSize),
                         start = "a".length,
                         end = "a bb ".length
                     )
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/AnnotatedString.kt b/ui/ui-text/src/main/java/androidx/ui/text/AnnotatedString.kt
index 4e835e8..88bc1cc 100644
--- a/ui/ui-text/src/main/java/androidx/ui/text/AnnotatedString.kt
+++ b/ui/ui-text/src/main/java/androidx/ui/text/AnnotatedString.kt
@@ -21,13 +21,25 @@
 import java.util.SortedSet
 
 /**
+ * The class changes the character level style of the specified range.
+ * @see AnnotatedString.Builder
+ */
+typealias TextStyleSpan = Item<TextStyle>
+
+/**
+ * The class changes the paragraph level style of the specified range.
+ * @see AnnotatedString.Builder
+ */
+typealias ParagraphStyleSpan = Item<ParagraphStyle>
+
+/**
  * The basic data structure of text with multiple styles. To construct an [AnnotatedString] you
  * can use [Builder].
  */
 data class AnnotatedString(
     val text: String,
-    val textStyles: List<Item<TextStyle>> = listOf(),
-    val paragraphStyles: List<Item<ParagraphStyle>> = listOf()
+    val textStyles: List<TextStyleSpan> = listOf(),
+    val paragraphStyles: List<ParagraphStyleSpan> = listOf()
 ) {
 
     init {
@@ -52,11 +64,11 @@
     /**
      * The information attached on the text such as a TextStyle.
      *
-     * @param style The style being applied on this part of [AnnotatedString]
-     * @param start The start of the range where [style] takes effect. It's inclusive
-     * @param end The end of the range where [style] takes effect. It's exclusive
+     * @param item The object attached to [AnnotatedString]s.
+     * @param start The start of the range where [item] takes effect. It's inclusive
+     * @param end The end of the range where [item] takes effect. It's exclusive
      */
-    data class Item<T>(val style: T, val start: Int, val end: Int) {
+    data class Item<T>(val item: T, val start: Int, val end: Int) {
         init {
             require(start <= end) { "Reversed range is not supported" }
         }
@@ -73,7 +85,7 @@
     class Builder(capacity: Int = 16) {
 
         private data class MutableItem<T>(
-            val style: T,
+            val item: T,
             val start: Int,
             var end: Int = Int.MIN_VALUE
         ) {
@@ -85,7 +97,7 @@
             fun toItem(defaultEnd: Int = Int.MIN_VALUE): Item<T> {
                 val end = if (end == Int.MIN_VALUE) defaultEnd else end
                 check(end != Int.MIN_VALUE) { "Item.end should be set first" }
-                return Item(style = style, start = start, end = end)
+                return Item(item = item, start = start, end = end)
             }
         }
 
@@ -143,10 +155,10 @@
             this.text.append(text.text)
             // offset every style with start and add to the builder
             text.textStyles.forEach {
-                addStyle(it.style, start + it.start, start + it.end)
+                addStyle(it.item, start + it.start, start + it.end)
             }
             text.paragraphStyles.forEach {
-                addStyle(it.style, start + it.start, start + it.end)
+                addStyle(it.item, start + it.start, start + it.end)
             }
         }
 
@@ -158,7 +170,7 @@
          * @param end the exclusive end offset of the range
          */
         fun addStyle(style: TextStyle, start: Int, end: Int) {
-            textStyles.add(MutableItem(style = style, start = start, end = end))
+            textStyles.add(MutableItem(item = style, start = start, end = end))
         }
 
         /**
@@ -170,7 +182,7 @@
          * @param end the exclusive end offset of the range
          */
         fun addStyle(style: ParagraphStyle, start: Int, end: Int) {
-            paragraphStyles.add(MutableItem(style = style, start = start, end = end))
+            paragraphStyles.add(MutableItem(item = style, start = start, end = end))
         }
 
         /**
@@ -182,7 +194,7 @@
          * @param style TextStyle to be applied
          */
         fun pushStyle(style: TextStyle): Int {
-            MutableItem(style = style, start = text.length).also {
+            MutableItem(item = style, start = text.length).also {
                 styleStack.add(it)
                 textStyles.add(it)
             }
@@ -198,7 +210,7 @@
          * @param style ParagraphStyle to be applied
          */
         fun pushStyle(style: ParagraphStyle): Int {
-            MutableItem(style = style, start = text.length).also {
+            MutableItem(item = style, start = text.length).also {
                 styleStack.add(it)
                 paragraphStyles.add(it)
             }
@@ -262,12 +274,12 @@
  */
 internal fun AnnotatedString.normalizedParagraphStyles(
     defaultParagraphStyle: ParagraphStyle
-): List<Item<ParagraphStyle>> {
+): List<ParagraphStyleSpan> {
     val length = text.length
     val paragraphStyles = paragraphStyles
 
     var lastOffset = 0
-    val result = mutableListOf<Item<ParagraphStyle>>()
+    val result = mutableListOf<ParagraphStyleSpan>()
     for ((style, start, end) in paragraphStyles) {
         if (start != lastOffset) {
             result.add(Item(defaultParagraphStyle, lastOffset, start))
@@ -297,7 +309,7 @@
 private fun AnnotatedString.getLocalStyles(
     start: Int,
     end: Int
-): List<Item<TextStyle>> {
+): List<TextStyleSpan> {
     if (start == end) {
         return listOf()
     }
@@ -308,7 +320,7 @@
     return textStyles.filter { it.start < end && it.end > start }
         .map {
             Item(
-                it.style,
+                it.item,
                 it.start.coerceIn(start, end) - start,
                 it.end.coerceIn(start, end) - start
             )
@@ -338,7 +350,7 @@
     defaultParagraphStyle: ParagraphStyle,
     crossinline block: (
         annotatedString: AnnotatedString,
-        paragraphStyle: Item<ParagraphStyle>
+        paragraphStyle: ParagraphStyleSpan
     ) -> T
 ): List<T> {
     return normalizedParagraphStyles(defaultParagraphStyle).map { paragraphStyleItem ->
@@ -456,14 +468,14 @@
         offsetMap.put(end, resultStr.length)
     }
 
-    val newTextStyles = mutableListOf<Item<TextStyle>>()
-    val newParaStyles = mutableListOf<Item<ParagraphStyle>>()
+    val newTextStyles = mutableListOf<TextStyleSpan>()
+    val newParaStyles = mutableListOf<ParagraphStyleSpan>()
 
     for (textStyle in textStyles) {
         // The offset map must have mapping entry from all style start, end position.
         newTextStyles.add(
             Item(
-                textStyle.style,
+                textStyle.item,
                 offsetMap[textStyle.start]!!,
                 offsetMap[textStyle.end]!!
             )
@@ -473,7 +485,7 @@
     for (paraStyle in paragraphStyles) {
         newParaStyles.add(
             Item(
-                paraStyle.style,
+                paraStyle.item,
                 offsetMap[paraStyle.start]!!,
                 offsetMap[paraStyle.end]!!
             )
@@ -577,7 +589,7 @@
         (it.start == start) || !(it.end <= start || it.start >= end)
     }.map {
         Item(
-            style = it.style,
+            item = it.item,
             start = (if (it.start < start) start else it.start) - start,
             end = (if (end < it.end) end else it.end) - start
         )
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/MultiParagraphIntrinsics.kt b/ui/ui-text/src/main/java/androidx/ui/text/MultiParagraphIntrinsics.kt
index 487adde..00faf94 100644
--- a/ui/ui-text/src/main/java/androidx/ui/text/MultiParagraphIntrinsics.kt
+++ b/ui/ui-text/src/main/java/androidx/ui/text/MultiParagraphIntrinsics.kt
@@ -57,7 +57,7 @@
                     intrinsics = ParagraphIntrinsics(
                         text = annotatedString.text,
                         paragraphStyle = resolveTextDirection(
-                            paragraphStyleItem.style,
+                            paragraphStyleItem.item,
                             paragraphStyle
                         ),
                         textStyles = annotatedString.textStyles,
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/platform/AndroidParagraphHelper.kt b/ui/ui-text/src/main/java/androidx/ui/text/platform/AndroidParagraphHelper.kt
index 06b1733..20f4e07 100644
--- a/ui/ui-text/src/main/java/androidx/ui/text/platform/AndroidParagraphHelper.kt
+++ b/ui/ui-text/src/main/java/androidx/ui/text/platform/AndroidParagraphHelper.kt
@@ -205,7 +205,7 @@
     for (textStyle in textStyles) {
         val start = textStyle.start
         val end = textStyle.end
-        val style = textStyle.style
+        val style = textStyle.item
 
         if (start < 0 || start >= text.length || end <= start || end > text.length) continue
 
diff --git a/ui/ui-text/src/test/java/androidx/ui/text/AnnotatedStringBuilderTest.kt b/ui/ui-text/src/test/java/androidx/ui/text/AnnotatedStringBuilderTest.kt
index a48d2c9..e1ff10f 100644
--- a/ui/ui-text/src/test/java/androidx/ui/text/AnnotatedStringBuilderTest.kt
+++ b/ui/ui-text/src/test/java/androidx/ui/text/AnnotatedStringBuilderTest.kt
@@ -148,26 +148,26 @@
 
         val expectedString = "$text$appendedText"
         val expectedTextStyles = listOf(
-            AnnotatedString.Item(
-                style = TextStyle(color),
+            TextStyleSpan(
+                item = TextStyle(color),
                 start = 0,
                 end = text.length
             ),
-            AnnotatedString.Item(
-                style = TextStyle(appendedColor),
+            TextStyleSpan(
+                item = TextStyle(appendedColor),
                 start = text.length,
                 end = expectedString.length
             )
         )
 
         val expectedParagraphStyles = listOf(
-            AnnotatedString.Item(
-                style = ParagraphStyle(lineHeight = lineHeight),
+            ParagraphStyleSpan(
+                item = ParagraphStyle(lineHeight = lineHeight),
                 start = 0,
                 end = text.length
             ),
-            AnnotatedString.Item(
-                style = ParagraphStyle(lineHeight = appendedLineHeight),
+            ParagraphStyleSpan(
+                item = ParagraphStyle(lineHeight = appendedLineHeight),
                 start = text.length,
                 end = expectedString.length
             )
@@ -190,7 +190,7 @@
 
         assertThat(buildResult.text).isEqualTo(text)
         assertThat(buildResult.textStyles).hasSize(1)
-        assertThat(buildResult.textStyles[0].style).isEqualTo(style)
+        assertThat(buildResult.textStyles[0].item).isEqualTo(style)
         assertThat(buildResult.textStyles[0].start).isEqualTo(0)
         assertThat(buildResult.textStyles[0].end).isEqualTo(buildResult.length)
     }
@@ -216,7 +216,7 @@
         assertThat(buildResult.textStyles).hasSize(3)
 
         styles.forEachIndexed { index, textStyle ->
-            assertThat(buildResult.textStyles[index].style).isEqualTo(textStyle)
+            assertThat(buildResult.textStyles[index].item).isEqualTo(textStyle)
             assertThat(buildResult.textStyles[index].end).isEqualTo(buildResult.length)
         }
 
@@ -243,11 +243,11 @@
         assertThat(buildResult.text).isEqualTo("Test me")
         assertThat(buildResult.textStyles).hasSize(2)
 
-        assertThat(buildResult.textStyles[0].style).isEqualTo(textStyle1)
+        assertThat(buildResult.textStyles[0].item).isEqualTo(textStyle1)
         assertThat(buildResult.textStyles[0].start).isEqualTo(0)
         assertThat(buildResult.textStyles[0].end).isEqualTo(buildResult.length)
 
-        assertThat(buildResult.textStyles[1].style).isEqualTo(textStyle2)
+        assertThat(buildResult.textStyles[1].item).isEqualTo(textStyle2)
         assertThat(buildResult.textStyles[1].start).isEqualTo("Test".length)
         assertThat(buildResult.textStyles[1].end).isEqualTo(buildResult.length)
     }
@@ -271,7 +271,7 @@
         assertThat(buildResult.text).isEmpty()
         assertThat(buildResult.textStyles).hasSize(3)
         styles.forEachIndexed { index, textStyle ->
-            assertThat(buildResult.textStyles[index].style).isEqualTo(textStyle)
+            assertThat(buildResult.textStyles[index].item).isEqualTo(textStyle)
             assertThat(buildResult.textStyles[index].start).isEqualTo(buildResult.length)
             assertThat(buildResult.textStyles[index].end).isEqualTo(buildResult.length)
         }
@@ -305,7 +305,7 @@
 
         assertThat(buildResult.textStyles).hasSize(4)
         styles.forEachIndexed { index, textStyle ->
-            assertThat(buildResult.textStyles[index].style).isEqualTo(textStyle)
+            assertThat(buildResult.textStyles[index].item).isEqualTo(textStyle)
         }
     }
 
@@ -338,7 +338,7 @@
 
         assertThat(buildResult.textStyles).hasSize(4)
         styles.forEachIndexed { index, textStyle ->
-            assertThat(buildResult.textStyles[index].style).isEqualTo(textStyle)
+            assertThat(buildResult.textStyles[index].item).isEqualTo(textStyle)
         }
     }
 
@@ -368,11 +368,11 @@
         assertThat(buildResult.textStyles).hasSize(2)
 
         // the order is first applied is in the second
-        assertThat(buildResult.textStyles[0].style).isEqualTo((textStyle1))
+        assertThat(buildResult.textStyles[0].item).isEqualTo((textStyle1))
         assertThat(buildResult.textStyles[0].start).isEqualTo(("Style0".length))
         assertThat(buildResult.textStyles[0].end).isEqualTo(("Style0Style1".length))
 
-        assertThat(buildResult.textStyles[1].style).isEqualTo((textStyle2))
+        assertThat(buildResult.textStyles[1].item).isEqualTo((textStyle2))
         assertThat(buildResult.textStyles[1].start).isEqualTo(("Style0Style1".length))
         assertThat(buildResult.textStyles[1].end).isEqualTo(("Style0Style1Style2".length))
     }
@@ -451,7 +451,7 @@
 
         assertThat(buildResult.paragraphStyles).isEmpty()
         assertThat(buildResult.textStyles).isEqualTo(
-            listOf(AnnotatedString.Item(style, 0, buildResult.length))
+            listOf(TextStyleSpan(style, 0, buildResult.length))
         )
     }
 
@@ -467,7 +467,7 @@
 
         assertThat(buildResult.textStyles).isEmpty()
         assertThat(buildResult.paragraphStyles).isEqualTo(
-            listOf(AnnotatedString.Item(style, 0, buildResult.length))
+            listOf(ParagraphStyleSpan(style, 0, buildResult.length))
         )
     }
 
@@ -506,12 +506,12 @@
 
         val expectedString = "$text1 $text2"
         val expectedTextStyles = listOf(
-            AnnotatedString.Item(textStyle1, 0, text1.length),
-            AnnotatedString.Item(textStyle2, text1.length + 1, expectedString.length)
+            TextStyleSpan(textStyle1, 0, text1.length),
+            TextStyleSpan(textStyle2, text1.length + 1, expectedString.length)
         )
         val expectedParagraphStyles = listOf(
-            AnnotatedString.Item(paragraphStyle1, 0, text1.length),
-            AnnotatedString.Item(paragraphStyle2, text1.length + 1, expectedString.length)
+            ParagraphStyleSpan(paragraphStyle1, 0, text1.length),
+            ParagraphStyleSpan(paragraphStyle2, text1.length + 1, expectedString.length)
         )
 
         assertThat(buildResult.text).isEqualTo(expectedString)
@@ -571,15 +571,15 @@
         return AnnotatedString(
             text = text,
             textStyles = listOf(
-                AnnotatedString.Item(
-                    style = TextStyle(color),
+                TextStyleSpan(
+                    item = TextStyle(color),
                     start = 0,
                     end = text.length
                 )
             ),
             paragraphStyles = listOf(
-                AnnotatedString.Item(
-                    style = ParagraphStyle(lineHeight = lineHeight),
+                ParagraphStyleSpan(
+                    item = ParagraphStyle(lineHeight = lineHeight),
                     start = 0,
                     end = text.length
                 )
diff --git a/ui/ui-text/src/test/java/androidx/ui/text/TextSpanTest.kt b/ui/ui-text/src/test/java/androidx/ui/text/TextSpanTest.kt
index 6d3988a..78d9250 100644
--- a/ui/ui-text/src/test/java/androidx/ui/text/TextSpanTest.kt
+++ b/ui/ui-text/src/test/java/androidx/ui/text/TextSpanTest.kt
@@ -164,7 +164,7 @@
 
         // By default includeRootStyle = true and TextStyle on root node should be converted.
         assertThat(annotatedString.textStyles.size).isEqualTo(1)
-        assertThat(annotatedString.textStyles[0].style).isEqualTo(textStyle)
+        assertThat(annotatedString.textStyles[0].item).isEqualTo(textStyle)
         assertThat(annotatedString.textStyles[0].start).isEqualTo(0)
         assertThat(annotatedString.textStyles[0].end).isEqualTo(text.length)
     }
@@ -202,11 +202,11 @@
         assertThat(annotatedString.text).isEqualTo(text1 + text2)
         assertThat(annotatedString.textStyles.size).isEqualTo(2)
 
-        assertThat(annotatedString.textStyles[0].style).isEqualTo(textStyle1)
+        assertThat(annotatedString.textStyles[0].item).isEqualTo(textStyle1)
         assertThat(annotatedString.textStyles[0].start).isEqualTo(0)
         assertThat(annotatedString.textStyles[0].end).isEqualTo((text1 + text2).length)
 
-        assertThat(annotatedString.textStyles[1].style).isEqualTo(textStyle2)
+        assertThat(annotatedString.textStyles[1].item).isEqualTo(textStyle2)
         assertThat(annotatedString.textStyles[1].start).isEqualTo(text1.length)
         assertThat(annotatedString.textStyles[1].end).isEqualTo((text1 + text2).length)
     }
@@ -258,25 +258,25 @@
         assertThat(annotatedString.text).isEqualTo(text1 + text2 + text3)
         assertThat(annotatedString.textStyles.size).isEqualTo(5)
 
-        assertThat(annotatedString.textStyles[0].style).isEqualTo(textStyleRoot)
+        assertThat(annotatedString.textStyles[0].item).isEqualTo(textStyleRoot)
         assertThat(annotatedString.textStyles[0].start).isEqualTo(0)
         assertThat(annotatedString.textStyles[0].end)
             .isEqualTo((text1 + text2 + text3).length)
 
-        assertThat(annotatedString.textStyles[1].style).isEqualTo(textStyleLeaf1)
+        assertThat(annotatedString.textStyles[1].item).isEqualTo(textStyleLeaf1)
         assertThat(annotatedString.textStyles[1].start).isEqualTo(0)
         assertThat(annotatedString.textStyles[1].end).isEqualTo(text1.length)
 
-        assertThat(annotatedString.textStyles[2].style).isEqualTo(textStyleInner)
+        assertThat(annotatedString.textStyles[2].item).isEqualTo(textStyleInner)
         assertThat(annotatedString.textStyles[2].start).isEqualTo(text1.length)
         assertThat(annotatedString.textStyles[2].end)
             .isEqualTo((text1 + text2 + text3).length)
 
-        assertThat(annotatedString.textStyles[3].style).isEqualTo(textStyleLeaf2)
+        assertThat(annotatedString.textStyles[3].item).isEqualTo(textStyleLeaf2)
         assertThat(annotatedString.textStyles[3].start).isEqualTo(text1.length)
         assertThat(annotatedString.textStyles[3].end).isEqualTo((text1 + text2).length)
 
-        assertThat(annotatedString.textStyles[4].style).isEqualTo(textStyleLeaf3)
+        assertThat(annotatedString.textStyles[4].item).isEqualTo(textStyleLeaf3)
         assertThat(annotatedString.textStyles[4].start).isEqualTo((text1 + text2).length)
         assertThat(annotatedString.textStyles[4].end)
             .isEqualTo((text1 + text2 + text3).length)
diff --git a/versionedparcelable/annotation/build.gradle b/versionedparcelable/annotation/build.gradle
index 1d9c857..ce1c3e1 100644
--- a/versionedparcelable/annotation/build.gradle
+++ b/versionedparcelable/annotation/build.gradle
@@ -19,7 +19,7 @@
 apply plugin: 'java'
 
 dependencies {
-    compile(JAVAPOET)
+    implementation(JAVAPOET)
 }
 
 // The "javadoc" task is unused so we don't want it to appear in the output of `./gradlew tasks`
diff --git a/webkit/integration-tests/testapp/README.md b/webkit/integration-tests/testapp/README.md
index 7e48107..34e18f1 100644
--- a/webkit/integration-tests/testapp/README.md
+++ b/webkit/integration-tests/testapp/README.md
@@ -10,7 +10,7 @@
 cd frameworks/support/
 
 # Optional: you can use Android Studio as your editor
-./studiow -y
+./studiow
 
 # Build the app
 ./gradlew :webkit:integration-tests:testapp:assembleDebug
diff --git a/webkit/integration-tests/testapp/src/main/AndroidManifest.xml b/webkit/integration-tests/testapp/src/main/AndroidManifest.xml
index a31db81..845bc22 100644
--- a/webkit/integration-tests/testapp/src/main/AndroidManifest.xml
+++ b/webkit/integration-tests/testapp/src/main/AndroidManifest.xml
@@ -102,5 +102,11 @@
         <activity
             android:name=".FullscreenActivity"
             android:exported="true" />
+        <activity
+            android:name=".JsJavaInteractionActivity"
+            android:exported="true" />
+        <activity
+            android:name=".WebMessageListenerActivity"
+            android:exported="true" />
     </application>
 </manifest>
diff --git a/webkit/integration-tests/testapp/src/main/assets/www/web_message_listener.html b/webkit/integration-tests/testapp/src/main/assets/www/web_message_listener.html
new file mode 100644
index 0000000..11ed1b0
--- /dev/null
+++ b/webkit/integration-tests/testapp/src/main/assets/www/web_message_listener.html
@@ -0,0 +1,83 @@
+<html>
+<!-- Copyright 2019 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.
+-->
+<head>
+  <script type="text/javascript">
+    let timestamp = 0;
+    replyObject.onmessage = function(event) {
+        document.getElementById("result").innerHTML = event.data;
+    };
+    // Send a message to app, so app could get a JsReplyProxy to reply back to JavaScript.
+    replyObject.postMessage("initialization");
+
+    const channel = new MessageChannel();
+    channel.port2.onmessage = function(event) {
+        document.getElementById("port_result").innerHTML = event.data;
+    };
+    replyWithMessagePortObject.postMessage("send port", [channel.port1]);
+
+    let messageCounter = 0;
+    multipleMessagesObject.addEventListener("message", function(event) {
+        const i = parseInt(event.data);
+        if (i < 4999) {
+            multipleMessagesObject.postMessage((i + 1).toString());
+            if (i % 100 === 0) {
+                const counterInfo = (messageCounter + i)+ " messages sent.";
+                document.getElementById("multiple_messages").innerHTML = counterInfo;
+            }
+        } else {
+            let average = (performance.now() - timestamp) / 5000;
+            let result = "Average time over 5000 messages: " + average.toFixed(2) + "ms.";
+            document.getElementById("multiple_messages").innerHTML = result;
+            messageCounter += i + 1;
+            document.getElementById("multiple_button").disabled = false;
+        }
+    });
+    function startPostMessage(e) {
+        e.preventDefault();
+        document.getElementById("multiple_button").disabled = true;
+        timestamp = performance.now();
+        multipleMessagesObject.postMessage("0");
+    }
+
+    function showToast(e) {
+        e.preventDefault();
+        const message = document.getElementById("toast_message").value;
+        toastObject.postMessage(message);
+    }
+  </script>
+</head>
+<body>
+  <h1>Web content (within WebView)</h1>
+  <div>
+    <span>Message from app: </span>
+    <span id="result" style="color:red">Not received.</span>
+  </div>
+  <div>
+    <span>Message from app (via MessagePort): </span>
+    <span id="port_result" style="color:red">Not received.</span>
+  </div>
+  <div>
+    <input value="toast!" id="toast_message">
+    <button type="button" onclick="showToast(event)">Show Toast</button>
+  </div>
+  <div>
+    <button id="multiple_button" type="button" onclick="startPostMessage(event)">
+      Send 5000 messages
+    </button>
+    <div id="multiple_messages"></div>
+  </div>
+</body>
+</html>
diff --git a/webkit/integration-tests/testapp/src/main/java/com/example/androidx/webkit/JsJavaInteractionActivity.java b/webkit/integration-tests/testapp/src/main/java/com/example/androidx/webkit/JsJavaInteractionActivity.java
new file mode 100644
index 0000000..5f58f3e
--- /dev/null
+++ b/webkit/integration-tests/testapp/src/main/java/com/example/androidx/webkit/JsJavaInteractionActivity.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.androidx.webkit;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+/**
+ * An {@link Activity} to exercise Js Java interaction related functionality.
+ */
+public class JsJavaInteractionActivity extends AppCompatActivity {
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.activity_js_java_interaction);
+        setTitle(R.string.js_java_interaction_activity_title);
+        WebkitHelpers.appendWebViewVersionToTitle(this);
+
+        final Context activityContext = this;
+        MenuListView listView = findViewById(R.id.js_java_interaction_list);
+        MenuListView.MenuItem[] menuItems = new MenuListView.MenuItem[] {
+                new MenuListView.MenuItem(
+                        getResources().getString(R.string.web_message_listener_activity_title),
+                        new Intent(activityContext, WebMessageListenerActivity.class)),
+        };
+        listView.setItems(menuItems);
+    }
+}
diff --git a/webkit/integration-tests/testapp/src/main/java/com/example/androidx/webkit/MainActivity.java b/webkit/integration-tests/testapp/src/main/java/com/example/androidx/webkit/MainActivity.java
index 7c55bc6..f20cc0b 100644
--- a/webkit/integration-tests/testapp/src/main/java/com/example/androidx/webkit/MainActivity.java
+++ b/webkit/integration-tests/testapp/src/main/java/com/example/androidx/webkit/MainActivity.java
@@ -66,6 +66,9 @@
                 new MenuListView.MenuItem(
                         getResources().getString(R.string.fullscreen_activity_title),
                         new Intent(activityContext, FullscreenActivity.class)),
+                new MenuListView.MenuItem(
+                        getResources().getString(R.string.js_java_interaction_activity_title),
+                        new Intent(activityContext, JsJavaInteractionActivity.class)),
         };
         listView.setItems(menuItems);
     }
diff --git a/webkit/integration-tests/testapp/src/main/java/com/example/androidx/webkit/WebMessageListenerActivity.java b/webkit/integration-tests/testapp/src/main/java/com/example/androidx/webkit/WebMessageListenerActivity.java
new file mode 100644
index 0000000..6ebec6e
--- /dev/null
+++ b/webkit/integration-tests/testapp/src/main/java/com/example/androidx/webkit/WebMessageListenerActivity.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.androidx.webkit;
+
+import static androidx.webkit.WebViewAssetLoader.AssetsPathHandler;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.SpannableString;
+import android.text.Spanned;
+import android.text.TextUtils;
+import android.text.style.AbsoluteSizeSpan;
+import android.view.View;
+import android.webkit.WebResourceRequest;
+import android.webkit.WebResourceResponse;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.webkit.JsReplyProxy;
+import androidx.webkit.WebMessageCompat;
+import androidx.webkit.WebMessagePortCompat;
+import androidx.webkit.WebViewAssetLoader;
+import androidx.webkit.WebViewCompat;
+import androidx.webkit.WebViewFeature;
+
+import java.util.Arrays;
+
+/**
+ * An {@link Activity} to exercise WebMessageListener related functionality.
+ */
+@SuppressLint("RestrictedApi")
+public class WebMessageListenerActivity extends AppCompatActivity {
+    private TextView mTextView;
+    private final Uri mExampleUri = new Uri.Builder()
+                                            .scheme("https")
+                                            .authority("example.com")
+                                            .appendPath("androidx_webkit")
+                                            .appendPath("example")
+                                            .appendPath("assets")
+                                            .build();
+    private Button mReplyProxyButton;
+    private Button mPortButton;
+
+    private static class MyWebViewClient extends WebViewClient {
+        private final WebViewAssetLoader mAssetLoader;
+
+        MyWebViewClient(WebViewAssetLoader loader) {
+            mAssetLoader = loader;
+        }
+
+        @Override
+        @RequiresApi(21)
+        public WebResourceResponse shouldInterceptRequest(WebView view,
+                                            WebResourceRequest request) {
+            return mAssetLoader.shouldInterceptRequest(request.getUrl());
+        }
+
+        @Override
+        @SuppressWarnings("deprecation") // use the old one for compatibility with all API levels.
+        public WebResourceResponse shouldInterceptRequest(WebView view, String request) {
+            return mAssetLoader.shouldInterceptRequest(Uri.parse(request));
+        }
+    }
+
+    private static class ReplyMessageListener implements WebViewCompat.WebMessageListener {
+        private final Context mContext;
+        private JsReplyProxy mReplyProxy;
+
+        ReplyMessageListener(Context context, Button button) {
+            mContext = context;
+            button.setOnClickListener((View v) -> {
+                if (mReplyProxy == null) return;
+                mReplyProxy.postMessage("ReplyProxy button clicked.");
+            });
+        }
+
+        @Override
+        public void onPostMessage(WebView view, WebMessageCompat message, Uri sourceOrigin,
+                boolean isMainFrame, JsReplyProxy replyProxy) {
+            if (message.getData().equals("initialization")) {
+                mReplyProxy = replyProxy;
+            }
+        }
+    }
+
+    private static class MessagePortMessageListener implements WebViewCompat.WebMessageListener {
+        private final Context mContext;
+        private WebMessagePortCompat mPort;
+
+        MessagePortMessageListener(Context context, Button button) {
+            mContext = context;
+            button.setOnClickListener((View v) -> {
+                if (mPort == null) return;
+                mPort.postMessage(new WebMessageCompat("Port button clicked."));
+            });
+        }
+
+        @Override
+        public void onPostMessage(WebView view, WebMessageCompat message, Uri sourceOrigin,
+                boolean isMainFrame, JsReplyProxy replyProxy) {
+            if (message.getData().equals("send port")) {
+                mPort = message.getPorts()[0];
+            }
+        }
+    }
+
+    private static class ToastMessageListener implements WebViewCompat.WebMessageListener {
+        private final Context mContext;
+
+        ToastMessageListener(Context context) {
+            mContext = context;
+        }
+
+        @Override
+        public void onPostMessage(WebView view, WebMessageCompat message, Uri sourceOrigin,
+                boolean isMainFrame, JsReplyProxy replyProxy) {
+            Toast.makeText(mContext, "Toast: " + message.getData(), Toast.LENGTH_SHORT).show();
+        }
+    }
+
+    private static class MultipleMessagesListener implements WebViewCompat.WebMessageListener {
+        private final Context mContext;
+        private final TextView mTextView;
+        private int mCounter = 0;
+
+        MultipleMessagesListener(Context context, TextView textView) {
+            mContext = context;
+            mTextView = textView;
+        }
+
+        @Override
+        public void onPostMessage(WebView view, WebMessageCompat message, Uri sourceOrigin,
+                boolean isMainFrame, JsReplyProxy replyProxy) {
+            replyProxy.postMessage(message.getData());
+            mCounter++;
+            if (mCounter % 100 == 0) {
+                mTextView.setText(TextUtils.concat(
+                        createNativeTitle(), "\n", "" + mCounter + " messages received."));
+            }
+        }
+    }
+
+    @SuppressLint("SetJavascriptEnabled")
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_web_message_listener);
+        setTitle(R.string.web_message_listener_activity_title);
+        WebkitHelpers.appendWebViewVersionToTitle(this);
+
+        // Use WebViewAssetLoader to load html page from app's assets.
+        WebViewAssetLoader assetLoader =
+                new WebViewAssetLoader.Builder()
+                        .setDomain("example.com")
+                        .addPathHandler(mExampleUri.getPath() + "/", new AssetsPathHandler(this))
+                        .build();
+
+        mTextView = findViewById(R.id.textview);
+        mTextView.setText(createNativeTitle());
+
+        mReplyProxyButton = findViewById(R.id.button_reply_proxy);
+        mPortButton = findViewById(R.id.button_port);
+
+        WebView webView = findViewById(R.id.webview);
+        webView.setWebViewClient(new MyWebViewClient(assetLoader));
+        webView.getSettings().setJavaScriptEnabled(true);
+
+        // Add WebMessageListeners.
+        if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER)) {
+            WebViewCompat.addWebMessageListener(webView, "replyObject",
+                    Arrays.asList("https://example.com"),
+                    new ReplyMessageListener(this, mReplyProxyButton));
+            WebViewCompat.addWebMessageListener(webView, "replyWithMessagePortObject",
+                    Arrays.asList("https://example.com"),
+                    new MessagePortMessageListener(this, mPortButton));
+            WebViewCompat.addWebMessageListener(webView, "toastObject",
+                    Arrays.asList("https://example.com"), new ToastMessageListener(this));
+            WebViewCompat.addWebMessageListener(webView, "multipleMessagesObject",
+                    Arrays.asList("https://example.com"),
+                    new MultipleMessagesListener(this, mTextView));
+        }
+
+        webView.loadUrl(
+                Uri.withAppendedPath(mExampleUri, "www/web_message_listener.html").toString());
+    }
+
+    private static CharSequence createNativeTitle() {
+        final String title = "Native View";
+        SpannableString ss = new SpannableString(title);
+        ss.setSpan(new AbsoluteSizeSpan(55, true), 0, title.length(),
+                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        return ss;
+    }
+}
diff --git a/webkit/integration-tests/testapp/src/main/res/layout/activity_js_java_interaction.xml b/webkit/integration-tests/testapp/src/main/res/layout/activity_js_java_interaction.xml
new file mode 100644
index 0000000..aecae37
--- /dev/null
+++ b/webkit/integration-tests/testapp/src/main/res/layout/activity_js_java_interaction.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2019 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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/activity_js_java_interaction"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <com.example.androidx.webkit.MenuListView
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/js_java_interaction_list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+
+</LinearLayout>
diff --git a/webkit/integration-tests/testapp/src/main/res/layout/activity_web_message_listener.xml b/webkit/integration-tests/testapp/src/main/res/layout/activity_web_message_listener.xml
new file mode 100644
index 0000000..1c64937
--- /dev/null
+++ b/webkit/integration-tests/testapp/src/main/res/layout/activity_web_message_listener.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2019 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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/activity_web_message_listener"
+    android:orientation="vertical"
+    android:weightSum="3"
+    android:background="#FF0"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <WebView
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/webview"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="2"/>
+    <TextView
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/textview"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"/>
+    <LinearLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:tools="http://schemas.android.com/tools"
+        android:gravity="center"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1">
+        <Button
+            android:id="@+id/button_reply_proxy"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:text="Reply via ReplyProxy" />
+        <Button
+            android:id="@+id/button_port"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignBottom="@+id/button1"
+            android:text="Reply via Port" />
+    </LinearLayout>
+</LinearLayout>
diff --git a/webkit/integration-tests/testapp/src/main/res/values/strings.xml b/webkit/integration-tests/testapp/src/main/res/values/strings.xml
index 7ac3fe6..d955806 100644
--- a/webkit/integration-tests/testapp/src/main/res/values/strings.xml
+++ b/webkit/integration-tests/testapp/src/main/res/values/strings.xml
@@ -70,4 +70,6 @@
     <string name="renderer_terminated_description">WebView renderer was terminated.</string>
     <string name="renderer_unresponsive_description">WebView renderer has become unresponsive.</string>
     <string name="fullscreen_activity_title">Fullscreen web contents Demo</string>
+    <string name="js_java_interaction_activity_title">JavaScript - Java communication</string>
+    <string name="web_message_listener_activity_title">WebMessageListener Demo</string>
 </resources>