Merge "CreatePassword Play Auth Module Flow" into androidx-main
diff --git a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoFilter.kt b/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoFilter.kt
index e883852..8081212 100644
--- a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoFilter.kt
+++ b/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoFilter.kt
@@ -16,24 +16,20 @@
 
 package androidx.compose.integration.demos
 
-import androidx.compose.foundation.ExperimentalFoundationApi
-import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.wrapContentSize
-import androidx.compose.foundation.rememberScrollState
-import androidx.compose.foundation.text.BasicTextField
-import androidx.compose.foundation.verticalScroll
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
 import androidx.compose.integration.demos.common.Demo
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Close
 import androidx.compose.material3.ExperimentalMaterial3Api
 import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
-import androidx.compose.material3.LocalContentColor
-import androidx.compose.material3.LocalTextStyle
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
+import androidx.compose.material3.TextField
 import androidx.compose.material3.TopAppBar
 import androidx.compose.material3.TopAppBarScrollBehavior
 import androidx.compose.runtime.Composable
@@ -44,7 +40,6 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.focus.FocusRequester
 import androidx.compose.ui.focus.focusRequester
-import androidx.compose.ui.graphics.SolidColor
 import androidx.compose.ui.text.SpanStyle
 import androidx.compose.ui.text.buildAnnotatedString
 import androidx.compose.ui.text.withStyle
@@ -58,9 +53,8 @@
     val filteredDemos = launchableDemos
         .filter { it.title.contains(filterText, ignoreCase = true) }
         .sortedBy { it.title }
-    // TODO: migrate to LazyColumn after b/175671850
-    Column(Modifier.verticalScroll(rememberScrollState())) {
-        filteredDemos.forEach { demo ->
+    LazyColumn {
+        items(filteredDemos) { demo ->
             FilteredDemoListItem(
                 demo,
                 filterText = filterText,
@@ -99,23 +93,20 @@
 }
 
 /**
- * [BasicTextField] that edits the current [filterText], providing [onFilter] when edited.
+ * [TextField] that edits the current [filterText], providing [onFilter] when edited.
  */
 @Composable
-@OptIn(ExperimentalFoundationApi::class)
+@OptIn(ExperimentalMaterial3Api::class)
 private fun FilterField(
     filterText: String,
     onFilter: (String) -> Unit,
     modifier: Modifier = Modifier
 ) {
     val focusRequester = remember { FocusRequester() }
-    // TODO: replace with Material text field when available
-    BasicTextField(
+    TextField(
         modifier = modifier.focusRequester(focusRequester),
         value = filterText,
-        onValueChange = onFilter,
-        textStyle = LocalTextStyle.current,
-        cursorBrush = SolidColor(LocalContentColor.current)
+        onValueChange = onFilter
     )
     DisposableEffect(focusRequester) {
         focusRequester.requestFocus()
diff --git a/heifwriter/heifwriter/src/androidTest/java/androidx/heifwriter/HeifWriterTest.java b/heifwriter/heifwriter/src/androidTest/java/androidx/heifwriter/HeifWriterTest.java
index af40a5a..b8e3752 100644
--- a/heifwriter/heifwriter/src/androidTest/java/androidx/heifwriter/HeifWriterTest.java
+++ b/heifwriter/heifwriter/src/androidTest/java/androidx/heifwriter/HeifWriterTest.java
@@ -53,6 +53,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -157,6 +158,7 @@
         }
     }
 
+    @Ignore // b/239415930
     @Test
     @LargeTest
     public void testInputBuffer_NoGrid_NoHandler() throws Throwable {
@@ -166,6 +168,7 @@
         doTestForVariousNumberImages(builder);
     }
 
+    @Ignore // b/239415930
     @Test
     @LargeTest
     public void testInputBuffer_Grid_NoHandler() throws Throwable {
@@ -175,6 +178,7 @@
         doTestForVariousNumberImages(builder);
     }
 
+    @Ignore // b/239415930
     @Test
     @LargeTest
     public void testInputBuffer_NoGrid_Handler() throws Throwable {
@@ -184,6 +188,7 @@
         doTestForVariousNumberImages(builder);
     }
 
+    @Ignore // b/239415930
     @Test
     @LargeTest
     public void testInputBuffer_Grid_Handler() throws Throwable {
diff --git a/lifecycle/lifecycle-common/api/restricted_current.txt b/lifecycle/lifecycle-common/api/restricted_current.txt
index 29da8af..045594a 100644
--- a/lifecycle/lifecycle-common/api/restricted_current.txt
+++ b/lifecycle/lifecycle-common/api/restricted_current.txt
@@ -79,7 +79,7 @@
 
   @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class MethodCallsLogger {
     ctor public MethodCallsLogger();
-    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public boolean approveCall(String, int);
+    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public boolean approveCall(String name, int type);
   }
 
   @Deprecated @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) public @interface OnLifecycleEvent {
diff --git a/lifecycle/lifecycle-common/src/main/java/androidx/lifecycle/MethodCallsLogger.java b/lifecycle/lifecycle-common/src/main/java/androidx/lifecycle/MethodCallsLogger.java
deleted file mode 100644
index d72a3ac..0000000
--- a/lifecycle/lifecycle-common/src/main/java/androidx/lifecycle/MethodCallsLogger.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2017 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.lifecycle;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RestrictTo;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @hide
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
-public class MethodCallsLogger {
-    private Map<String, Integer> mCalledMethods = new HashMap<>();
-
-    /**
-     * @hide
-     */
-    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
-    public boolean approveCall(@NonNull String name, int type) {
-        Integer nullableMask = mCalledMethods.get(name);
-        int mask = nullableMask != null ? nullableMask : 0;
-        boolean wasCalled = (mask & type) != 0;
-        mCalledMethods.put(name, mask | type);
-        return !wasCalled;
-    }
-}
diff --git a/lifecycle/lifecycle-common/src/main/java/androidx/lifecycle/MethodCallsLogger.kt b/lifecycle/lifecycle-common/src/main/java/androidx/lifecycle/MethodCallsLogger.kt
new file mode 100644
index 0000000..c14c15e
--- /dev/null
+++ b/lifecycle/lifecycle-common/src/main/java/androidx/lifecycle/MethodCallsLogger.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 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.lifecycle
+
+import androidx.annotation.RestrictTo
+
+/**
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+public open class MethodCallsLogger() {
+    private val calledMethods: MutableMap<String, Int> = HashMap()
+
+    /**
+     * @hide
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+    public open fun approveCall(name: String, type: Int): Boolean {
+        val nullableMask = calledMethods[name]
+        val mask = nullableMask ?: 0
+        val wasCalled = mask and type != 0
+        calledMethods[name] = mask or type
+        return !wasCalled
+    }
+}
\ No newline at end of file
diff --git a/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyScrollTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyScrollTest.kt
index b14edf9..4441259 100644
--- a/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyScrollTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyScrollTest.kt
@@ -38,6 +38,7 @@
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.withContext
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 
@@ -250,6 +251,7 @@
         assertThat(state.canScrollBackward).isFalse()
     }
 
+    @Ignore // b/259588804
     @Test
     fun canScrollBackward() = runBlocking {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
diff --git a/work/work-runtime/api/current.ignore b/work/work-runtime/api/current.ignore
new file mode 100644
index 0000000..33b7b2f
--- /dev/null
+++ b/work/work-runtime/api/current.ignore
@@ -0,0 +1,3 @@
+// Baseline format: 1.0
+ChangedType: androidx.work.WorkInfo#getTags():
+    Method androidx.work.WorkInfo.getTags has changed return type from java.util.Set<java.lang.String!> to java.util.Set<java.lang.String>
diff --git a/work/work-runtime/api/current.txt b/work/work-runtime/api/current.txt
index 446ee00..370e634 100644
--- a/work/work-runtime/api/current.txt
+++ b/work/work-runtime/api/current.txt
@@ -320,13 +320,23 @@
     method public java.util.UUID getId();
     method public androidx.work.Data getOutputData();
     method public androidx.work.Data getProgress();
-    method @IntRange(from=0) public int getRunAttemptCount();
+    method @IntRange(from=0L) public int getRunAttemptCount();
     method public androidx.work.WorkInfo.State getState();
-    method public java.util.Set<java.lang.String!> getTags();
+    method public java.util.Set<java.lang.String> getTags();
+    property public final int generation;
+    property public final java.util.UUID id;
+    property public final androidx.work.Data outputData;
+    property public final androidx.work.Data progress;
+    property @IntRange(from=0L) public final int runAttemptCount;
+    property public final androidx.work.WorkInfo.State state;
+    property public final java.util.Set<java.lang.String> tags;
   }
 
   public enum WorkInfo.State {
-    method public boolean isFinished();
+    method public final boolean isFinished();
+    method public static androidx.work.WorkInfo.State valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.work.WorkInfo.State[] values();
+    property public final boolean isFinished;
     enum_constant public static final androidx.work.WorkInfo.State BLOCKED;
     enum_constant public static final androidx.work.WorkInfo.State CANCELLED;
     enum_constant public static final androidx.work.WorkInfo.State ENQUEUED;
diff --git a/work/work-runtime/api/public_plus_experimental_current.txt b/work/work-runtime/api/public_plus_experimental_current.txt
index 446ee00..370e634 100644
--- a/work/work-runtime/api/public_plus_experimental_current.txt
+++ b/work/work-runtime/api/public_plus_experimental_current.txt
@@ -320,13 +320,23 @@
     method public java.util.UUID getId();
     method public androidx.work.Data getOutputData();
     method public androidx.work.Data getProgress();
-    method @IntRange(from=0) public int getRunAttemptCount();
+    method @IntRange(from=0L) public int getRunAttemptCount();
     method public androidx.work.WorkInfo.State getState();
-    method public java.util.Set<java.lang.String!> getTags();
+    method public java.util.Set<java.lang.String> getTags();
+    property public final int generation;
+    property public final java.util.UUID id;
+    property public final androidx.work.Data outputData;
+    property public final androidx.work.Data progress;
+    property @IntRange(from=0L) public final int runAttemptCount;
+    property public final androidx.work.WorkInfo.State state;
+    property public final java.util.Set<java.lang.String> tags;
   }
 
   public enum WorkInfo.State {
-    method public boolean isFinished();
+    method public final boolean isFinished();
+    method public static androidx.work.WorkInfo.State valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.work.WorkInfo.State[] values();
+    property public final boolean isFinished;
     enum_constant public static final androidx.work.WorkInfo.State BLOCKED;
     enum_constant public static final androidx.work.WorkInfo.State CANCELLED;
     enum_constant public static final androidx.work.WorkInfo.State ENQUEUED;
diff --git a/work/work-runtime/api/restricted_current.ignore b/work/work-runtime/api/restricted_current.ignore
new file mode 100644
index 0000000..33b7b2f
--- /dev/null
+++ b/work/work-runtime/api/restricted_current.ignore
@@ -0,0 +1,3 @@
+// Baseline format: 1.0
+ChangedType: androidx.work.WorkInfo#getTags():
+    Method androidx.work.WorkInfo.getTags has changed return type from java.util.Set<java.lang.String!> to java.util.Set<java.lang.String>
diff --git a/work/work-runtime/api/restricted_current.txt b/work/work-runtime/api/restricted_current.txt
index 446ee00..370e634 100644
--- a/work/work-runtime/api/restricted_current.txt
+++ b/work/work-runtime/api/restricted_current.txt
@@ -320,13 +320,23 @@
     method public java.util.UUID getId();
     method public androidx.work.Data getOutputData();
     method public androidx.work.Data getProgress();
-    method @IntRange(from=0) public int getRunAttemptCount();
+    method @IntRange(from=0L) public int getRunAttemptCount();
     method public androidx.work.WorkInfo.State getState();
-    method public java.util.Set<java.lang.String!> getTags();
+    method public java.util.Set<java.lang.String> getTags();
+    property public final int generation;
+    property public final java.util.UUID id;
+    property public final androidx.work.Data outputData;
+    property public final androidx.work.Data progress;
+    property @IntRange(from=0L) public final int runAttemptCount;
+    property public final androidx.work.WorkInfo.State state;
+    property public final java.util.Set<java.lang.String> tags;
   }
 
   public enum WorkInfo.State {
-    method public boolean isFinished();
+    method public final boolean isFinished();
+    method public static androidx.work.WorkInfo.State valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.work.WorkInfo.State[] values();
+    property public final boolean isFinished;
     enum_constant public static final androidx.work.WorkInfo.State BLOCKED;
     enum_constant public static final androidx.work.WorkInfo.State CANCELLED;
     enum_constant public static final androidx.work.WorkInfo.State ENQUEUED;
diff --git a/work/work-runtime/src/main/java/androidx/work/WorkInfo.java b/work/work-runtime/src/main/java/androidx/work/WorkInfo.java
deleted file mode 100644
index 7560af3..0000000
--- a/work/work-runtime/src/main/java/androidx/work/WorkInfo.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright 2018 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.work;
-
-import androidx.annotation.IntRange;
-import androidx.annotation.NonNull;
-import androidx.annotation.RestrictTo;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
-
-/**
- * Information about a particular {@link WorkRequest} containing the id of the WorkRequest, its
- * current {@link State}, output, tags, and run attempt count.  Note that output is only available
- * for the terminal states ({@link State#SUCCEEDED} and {@link State#FAILED}).
- */
-
-public final class WorkInfo {
-
-    private @NonNull UUID mId;
-    private @NonNull State mState;
-    private @NonNull Data mOutputData;
-    private @NonNull Set<String> mTags;
-    private @NonNull Data mProgress;
-    private int mRunAttemptCount;
-
-    private final int mGeneration;
-    /**
-     * @hide
-     */
-    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-    public WorkInfo(
-            @NonNull UUID id,
-            @NonNull State state,
-            @NonNull Data outputData,
-            @NonNull List<String> tags,
-            @NonNull Data progress,
-            int runAttemptCount,
-            int generation) {
-        mId = id;
-        mState = state;
-        mOutputData = outputData;
-        mTags = new HashSet<>(tags);
-        mProgress = progress;
-        mRunAttemptCount = runAttemptCount;
-        mGeneration = generation;
-    }
-
-    /**
-     * Gets the identifier of the {@link WorkRequest}.
-     *
-     * @return The identifier of a {@link WorkRequest}
-     */
-    public @NonNull UUID getId() {
-        return mId;
-    }
-
-    /**
-     * Gets the current {@link State} of the {@link WorkRequest}.
-     *
-     * @return The current {@link State} of the {@link WorkRequest}
-     */
-    public @NonNull State getState() {
-        return mState;
-    }
-
-    /**
-     * Gets the output {@link Data} for the {@link WorkRequest}.  If the WorkRequest is unfinished,
-     * this is always {@link Data#EMPTY}.
-     *
-     * @return The output {@link Data} of the {@link WorkRequest}
-     */
-    public @NonNull Data getOutputData() {
-        return mOutputData;
-    }
-
-    /**
-     * Gets the {@link Set} of tags associated with the {@link WorkRequest}.
-     *
-     * @return The {@link Set} of tags associated with the {@link WorkRequest}
-     */
-    public @NonNull Set<String> getTags() {
-        return mTags;
-    }
-
-    /**
-     * Gets the progress {@link Data} associated with the {@link WorkRequest}.
-     *
-     * @return The progress {@link Data} associated with the {@link WorkRequest}
-     */
-    public @NonNull Data getProgress() {
-        return mProgress;
-    }
-
-    /**
-     * Gets the run attempt count of the {@link WorkRequest}.  Note that for
-     * {@link PeriodicWorkRequest}s, the run attempt count gets reset between successful runs.
-     *
-     * @return The run attempt count of the {@link WorkRequest}.
-     */
-    @IntRange(from = 0)
-    public int getRunAttemptCount() {
-        return mRunAttemptCount;
-    }
-
-    /**
-     * Gets the latest generation of this Worker.
-     * <p>
-     * A work has multiple generations, if it was updated via
-     * {@link WorkManager#updateWork(WorkRequest)} or
-     * {@link WorkManager#enqueueUniquePeriodicWork(String,
-     * ExistingPeriodicWorkPolicy, PeriodicWorkRequest)} using
-     * {@link ExistingPeriodicWorkPolicy#UPDATE}.
-     * <p>
-     * If this worker is currently running, it can possibly be of an older generation rather than
-     * returned by this function if an update has happened during an execution of this worker.
-     *
-     * @return a generation of this work.
-     */
-    public int getGeneration() {
-        return mGeneration;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        WorkInfo workInfo = (WorkInfo) o;
-
-        if (mRunAttemptCount != workInfo.mRunAttemptCount) return false;
-        if (mGeneration != workInfo.mGeneration) return false;
-        if (!mId.equals(workInfo.mId)) return false;
-        if (mState != workInfo.mState) return false;
-        if (!mOutputData.equals(workInfo.mOutputData)) return false;
-        if (!mTags.equals(workInfo.mTags)) return false;
-        return mProgress.equals(workInfo.mProgress);
-    }
-
-    @Override
-    public int hashCode() {
-        int result = mId.hashCode();
-        result = 31 * result + mState.hashCode();
-        result = 31 * result + mOutputData.hashCode();
-        result = 31 * result + mTags.hashCode();
-        result = 31 * result + mProgress.hashCode();
-        result = 31 * result + mRunAttemptCount;
-        result = 31 * result + mGeneration;
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return "WorkInfo{"
-                +   "mId='" + mId + '\''
-                +   ", mState=" + mState
-                +   ", mOutputData=" + mOutputData
-                +   ", mTags=" + mTags
-                +   ", mProgress=" + mProgress
-                + '}';
-    }
-
-    /**
-     * The current lifecycle state of a {@link WorkRequest}.
-     */
-    public enum State {
-
-        /**
-         * Used to indicate that the {@link WorkRequest} is enqueued and eligible to run when its
-         * {@link Constraints} are met and resources are available.
-         */
-        ENQUEUED,
-
-        /**
-         * Used to indicate that the {@link WorkRequest} is currently being executed.
-         */
-        RUNNING,
-
-        /**
-         * Used to indicate that the {@link WorkRequest} has completed in a successful state.  Note
-         * that {@link PeriodicWorkRequest}s will never enter this state (they will simply go back
-         * to {@link #ENQUEUED} and be eligible to run again).
-         */
-        SUCCEEDED,
-
-        /**
-         * Used to indicate that the {@link WorkRequest} has completed in a failure state.  All
-         * dependent work will also be marked as {@code #FAILED} and will never run.
-         */
-        FAILED,
-
-        /**
-         * Used to indicate that the {@link WorkRequest} is currently blocked because its
-         * prerequisites haven't finished successfully.
-         */
-        BLOCKED,
-
-        /**
-         * Used to indicate that the {@link WorkRequest} has been cancelled and will not execute.
-         * All dependent work will also be marked as {@code #CANCELLED} and will not run.
-         */
-        CANCELLED;
-
-        /**
-         * Returns {@code true} if this State is considered finished.
-         *
-         * @return {@code true} for {@link #SUCCEEDED}, {@link #FAILED}, and * {@link #CANCELLED}
-         *         states
-         */
-        public boolean isFinished() {
-            return (this == SUCCEEDED || this == FAILED || this == CANCELLED);
-        }
-    }
-}
diff --git a/work/work-runtime/src/main/java/androidx/work/WorkInfo.kt b/work/work-runtime/src/main/java/androidx/work/WorkInfo.kt
new file mode 100644
index 0000000..5d4ab92
--- /dev/null
+++ b/work/work-runtime/src/main/java/androidx/work/WorkInfo.kt
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2018 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.work
+
+import androidx.annotation.IntRange
+import androidx.annotation.RestrictTo
+import androidx.work.WorkInfo.State
+import java.util.UUID
+
+/**
+ * Information about a particular [WorkRequest] containing the id of the WorkRequest, its
+ * current [State], output, tags, and run attempt count.  Note that output is only available
+ * for the terminal states ([State.SUCCEEDED] and [State.FAILED]).
+ */
+class WorkInfo @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) constructor(
+    /**
+     * The identifier of the [WorkRequest].
+     */
+    val id: UUID,
+    /**
+     * The current [State] of the [WorkRequest].
+     */
+    val state: State,
+    /**
+     * The output [Data] for the [WorkRequest]. If the WorkRequest is unfinished,
+     * this is always [Data.EMPTY].
+     */
+    val outputData: Data,
+
+    tags: List<String>,
+    /**
+     * The progress [Data] associated with the [WorkRequest].
+     */
+    val progress: Data,
+
+    /**
+     * The run attempt count of the [WorkRequest].  Note that for
+     * [PeriodicWorkRequest]s, the run attempt count gets reset between successful runs.
+     */
+    @get:IntRange(from = 0)
+    val runAttemptCount: Int,
+
+    /**
+     * The latest generation of this Worker.
+     *
+     *
+     * A work has multiple generations, if it was updated via
+     * [WorkManager.updateWork] or
+     * [WorkManager.enqueueUniquePeriodicWork] using
+     * [ExistingPeriodicWorkPolicy.UPDATE].
+     *
+     *
+     * If this worker is currently running, it can possibly be of an older generation rather than
+     * returned by this function if an update has happened during an execution of this worker.
+     */
+    val generation: Int
+) {
+    /**
+     * The [Set] of tags associated with the [WorkRequest].
+     */
+    val tags: Set<String> = HashSet(tags)
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other == null || javaClass != other.javaClass) return false
+        val workInfo = other as WorkInfo
+        if (runAttemptCount != workInfo.runAttemptCount) return false
+        if (generation != workInfo.generation) return false
+        if (id != workInfo.id) return false
+        if (state != workInfo.state) return false
+        if (outputData != workInfo.outputData) return false
+        return if (tags != workInfo.tags) false else progress == workInfo.progress
+    }
+
+    override fun hashCode(): Int {
+        var result = id.hashCode()
+        result = 31 * result + state.hashCode()
+        result = 31 * result + outputData.hashCode()
+        result = 31 * result + tags.hashCode()
+        result = 31 * result + progress.hashCode()
+        result = 31 * result + runAttemptCount
+        result = 31 * result + generation
+        return result
+    }
+
+    override fun toString(): String {
+        return ("WorkInfo{mId='$id', mState=$state, " +
+            "mOutputData=$outputData, mTags=$tags, mProgress=$progress}")
+    }
+
+    /**
+     * The current lifecycle state of a [WorkRequest].
+     */
+    enum class State {
+        /**
+         * Used to indicate that the [WorkRequest] is enqueued and eligible to run when its
+         * [Constraints] are met and resources are available.
+         */
+        ENQUEUED,
+
+        /**
+         * Used to indicate that the [WorkRequest] is currently being executed.
+         */
+        RUNNING,
+
+        /**
+         * Used to indicate that the [WorkRequest] has completed in a successful state.  Note
+         * that [PeriodicWorkRequest]s will never enter this state (they will simply go back
+         * to [.ENQUEUED] and be eligible to run again).
+         */
+        SUCCEEDED,
+
+        /**
+         * Used to indicate that the [WorkRequest] has completed in a failure state.  All
+         * dependent work will also be marked as `#FAILED` and will never run.
+         */
+        FAILED,
+
+        /**
+         * Used to indicate that the [WorkRequest] is currently blocked because its
+         * prerequisites haven't finished successfully.
+         */
+        BLOCKED,
+
+        /**
+         * Used to indicate that the [WorkRequest] has been cancelled and will not execute.
+         * All dependent work will also be marked as `#CANCELLED` and will not run.
+         */
+        CANCELLED;
+
+        /**
+         * Returns `true` if this State is considered finished:
+         * [.SUCCEEDED], [.FAILED], and * [.CANCELLED]
+         */
+        val isFinished: Boolean
+            get() = this == SUCCEEDED || this == FAILED || this == CANCELLED
+    }
+}
\ No newline at end of file