Convert LifecycleRegistry to Kotlin

Part of the kotlinification process of Lifecycle library.

RelNote: "`LifecycleRegistry` is now in Kotlin"
Test: ./gradlew checkApi
Bug: 240298691
Change-Id: I9593df2393b1399302ade4acc011128fce3277b2
diff --git a/lifecycle/lifecycle-runtime/api/current.txt b/lifecycle/lifecycle-runtime/api/current.txt
index 5bbe95f..c7da237 100644
--- a/lifecycle/lifecycle-runtime/api/current.txt
+++ b/lifecycle/lifecycle-runtime/api/current.txt
@@ -2,15 +2,22 @@
 package androidx.lifecycle {
 
   public class LifecycleRegistry extends androidx.lifecycle.Lifecycle {
-    ctor public LifecycleRegistry(androidx.lifecycle.LifecycleOwner);
-    method public void addObserver(androidx.lifecycle.LifecycleObserver);
-    method @VisibleForTesting public static androidx.lifecycle.LifecycleRegistry createUnsafe(androidx.lifecycle.LifecycleOwner);
+    ctor public LifecycleRegistry(androidx.lifecycle.LifecycleOwner provider);
+    method public void addObserver(androidx.lifecycle.LifecycleObserver observer);
+    method @VisibleForTesting public static final androidx.lifecycle.LifecycleRegistry createUnsafe(androidx.lifecycle.LifecycleOwner owner);
     method public androidx.lifecycle.Lifecycle.State getCurrentState();
     method public int getObserverCount();
-    method public void handleLifecycleEvent(androidx.lifecycle.Lifecycle.Event);
-    method @Deprecated @MainThread public void markState(androidx.lifecycle.Lifecycle.State);
-    method public void removeObserver(androidx.lifecycle.LifecycleObserver);
-    method @MainThread public void setCurrentState(androidx.lifecycle.Lifecycle.State);
+    method public void handleLifecycleEvent(androidx.lifecycle.Lifecycle.Event event);
+    method @Deprecated @MainThread public void markState(androidx.lifecycle.Lifecycle.State state);
+    method public void removeObserver(androidx.lifecycle.LifecycleObserver observer);
+    method public void setCurrentState(androidx.lifecycle.Lifecycle.State);
+    property public androidx.lifecycle.Lifecycle.State currentState;
+    property public int observerCount;
+    field public static final androidx.lifecycle.LifecycleRegistry.Companion Companion;
+  }
+
+  public static final class LifecycleRegistry.Companion {
+    method @VisibleForTesting public androidx.lifecycle.LifecycleRegistry createUnsafe(androidx.lifecycle.LifecycleOwner owner);
   }
 
   @Deprecated public interface LifecycleRegistryOwner extends androidx.lifecycle.LifecycleOwner {
diff --git a/lifecycle/lifecycle-runtime/api/public_plus_experimental_current.txt b/lifecycle/lifecycle-runtime/api/public_plus_experimental_current.txt
index 5bbe95f..c7da237 100644
--- a/lifecycle/lifecycle-runtime/api/public_plus_experimental_current.txt
+++ b/lifecycle/lifecycle-runtime/api/public_plus_experimental_current.txt
@@ -2,15 +2,22 @@
 package androidx.lifecycle {
 
   public class LifecycleRegistry extends androidx.lifecycle.Lifecycle {
-    ctor public LifecycleRegistry(androidx.lifecycle.LifecycleOwner);
-    method public void addObserver(androidx.lifecycle.LifecycleObserver);
-    method @VisibleForTesting public static androidx.lifecycle.LifecycleRegistry createUnsafe(androidx.lifecycle.LifecycleOwner);
+    ctor public LifecycleRegistry(androidx.lifecycle.LifecycleOwner provider);
+    method public void addObserver(androidx.lifecycle.LifecycleObserver observer);
+    method @VisibleForTesting public static final androidx.lifecycle.LifecycleRegistry createUnsafe(androidx.lifecycle.LifecycleOwner owner);
     method public androidx.lifecycle.Lifecycle.State getCurrentState();
     method public int getObserverCount();
-    method public void handleLifecycleEvent(androidx.lifecycle.Lifecycle.Event);
-    method @Deprecated @MainThread public void markState(androidx.lifecycle.Lifecycle.State);
-    method public void removeObserver(androidx.lifecycle.LifecycleObserver);
-    method @MainThread public void setCurrentState(androidx.lifecycle.Lifecycle.State);
+    method public void handleLifecycleEvent(androidx.lifecycle.Lifecycle.Event event);
+    method @Deprecated @MainThread public void markState(androidx.lifecycle.Lifecycle.State state);
+    method public void removeObserver(androidx.lifecycle.LifecycleObserver observer);
+    method public void setCurrentState(androidx.lifecycle.Lifecycle.State);
+    property public androidx.lifecycle.Lifecycle.State currentState;
+    property public int observerCount;
+    field public static final androidx.lifecycle.LifecycleRegistry.Companion Companion;
+  }
+
+  public static final class LifecycleRegistry.Companion {
+    method @VisibleForTesting public androidx.lifecycle.LifecycleRegistry createUnsafe(androidx.lifecycle.LifecycleOwner owner);
   }
 
   @Deprecated public interface LifecycleRegistryOwner extends androidx.lifecycle.LifecycleOwner {
diff --git a/lifecycle/lifecycle-runtime/api/restricted_current.txt b/lifecycle/lifecycle-runtime/api/restricted_current.txt
index 74af488..4602a21 100644
--- a/lifecycle/lifecycle-runtime/api/restricted_current.txt
+++ b/lifecycle/lifecycle-runtime/api/restricted_current.txt
@@ -2,15 +2,22 @@
 package androidx.lifecycle {
 
   public class LifecycleRegistry extends androidx.lifecycle.Lifecycle {
-    ctor public LifecycleRegistry(androidx.lifecycle.LifecycleOwner);
-    method public void addObserver(androidx.lifecycle.LifecycleObserver);
-    method @VisibleForTesting public static androidx.lifecycle.LifecycleRegistry createUnsafe(androidx.lifecycle.LifecycleOwner);
+    ctor public LifecycleRegistry(androidx.lifecycle.LifecycleOwner provider);
+    method public void addObserver(androidx.lifecycle.LifecycleObserver observer);
+    method @VisibleForTesting public static final androidx.lifecycle.LifecycleRegistry createUnsafe(androidx.lifecycle.LifecycleOwner owner);
     method public androidx.lifecycle.Lifecycle.State getCurrentState();
     method public int getObserverCount();
-    method public void handleLifecycleEvent(androidx.lifecycle.Lifecycle.Event);
-    method @Deprecated @MainThread public void markState(androidx.lifecycle.Lifecycle.State);
-    method public void removeObserver(androidx.lifecycle.LifecycleObserver);
-    method @MainThread public void setCurrentState(androidx.lifecycle.Lifecycle.State);
+    method public void handleLifecycleEvent(androidx.lifecycle.Lifecycle.Event event);
+    method @Deprecated @MainThread public void markState(androidx.lifecycle.Lifecycle.State state);
+    method public void removeObserver(androidx.lifecycle.LifecycleObserver observer);
+    method public void setCurrentState(androidx.lifecycle.Lifecycle.State);
+    property public androidx.lifecycle.Lifecycle.State currentState;
+    property public int observerCount;
+    field public static final androidx.lifecycle.LifecycleRegistry.Companion Companion;
+  }
+
+  public static final class LifecycleRegistry.Companion {
+    method @VisibleForTesting public androidx.lifecycle.LifecycleRegistry createUnsafe(androidx.lifecycle.LifecycleOwner owner);
   }
 
   @Deprecated public interface LifecycleRegistryOwner extends androidx.lifecycle.LifecycleOwner {
diff --git a/lifecycle/lifecycle-runtime/build.gradle b/lifecycle/lifecycle-runtime/build.gradle
index bd48528..dc3c2eb 100644
--- a/lifecycle/lifecycle-runtime/build.gradle
+++ b/lifecycle/lifecycle-runtime/build.gradle
@@ -3,6 +3,7 @@
 plugins {
     id("AndroidXPlugin")
     id("com.android.library")
+    id("org.jetbrains.kotlin.android")
 }
 
 android {
@@ -13,6 +14,7 @@
 }
 
 dependencies {
+    api(libs.kotlinStdlib)
     api(project(":lifecycle:lifecycle-common"))
 
     api("androidx.arch.core:core-common:2.1.0")
diff --git a/lifecycle/lifecycle-runtime/src/main/java/androidx/lifecycle/LifecycleRegistry.kt b/lifecycle/lifecycle-runtime/src/main/java/androidx/lifecycle/LifecycleRegistry.kt
index 5279d4c..a0d64db 100644
--- a/lifecycle/lifecycle-runtime/src/main/java/androidx/lifecycle/LifecycleRegistry.kt
+++ b/lifecycle/lifecycle-runtime/src/main/java/androidx/lifecycle/LifecycleRegistry.kt
@@ -13,34 +13,25 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package androidx.lifecycle
 
-package androidx.lifecycle;
-
-import static androidx.lifecycle.Lifecycle.State.DESTROYED;
-import static androidx.lifecycle.Lifecycle.State.INITIALIZED;
-
-import android.annotation.SuppressLint;
-
-import androidx.annotation.MainThread;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-import androidx.arch.core.executor.ArchTaskExecutor;
-import androidx.arch.core.internal.FastSafeIterableMap;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.Map;
+import android.annotation.SuppressLint
+import androidx.annotation.MainThread
+import androidx.annotation.VisibleForTesting
+import androidx.arch.core.executor.ArchTaskExecutor
+import androidx.arch.core.internal.FastSafeIterableMap
+import java.lang.ref.WeakReference
 
 /**
- * An implementation of {@link Lifecycle} that can handle multiple observers.
- * <p>
+ * An implementation of [Lifecycle] that can handle multiple observers.
+ *
  * It is used by Fragments and Support Library Activities. You can also directly use it if you have
  * a custom LifecycleOwner.
  */
-public class LifecycleRegistry extends Lifecycle {
-
+open class LifecycleRegistry private constructor(
+    provider: LifecycleOwner,
+    private val enforceMainThread: Boolean
+) : Lifecycle() {
     /**
      * Custom list that keeps observers and can handle removals / additions during traversal.
      *
@@ -48,12 +39,13 @@
      * if addition_order(observer1) < addition_order(observer2), then
      * state(observer1) >= state(observer2),
      */
-    private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap =
-            new FastSafeIterableMap<>();
+    private var observerMap = FastSafeIterableMap<LifecycleObserver, ObserverWithState>()
+
     /**
      * Current state
      */
-    private State mState;
+    private var state: State = State.INITIALIZED
+
     /**
      * The provider that owns this Lifecycle.
      * Only WeakReference on LifecycleOwner is kept, so if somebody leaks Lifecycle, they won't leak
@@ -61,12 +53,10 @@
      * because it keeps strong references on all other listeners, so you'll leak all of them as
      * well.
      */
-    private final WeakReference<LifecycleOwner> mLifecycleOwner;
-
-    private int mAddingObserverCounter = 0;
-
-    private boolean mHandlingEvent = false;
-    private boolean mNewEventOccurred = false;
+    private val lifecycleOwner: WeakReference<LifecycleOwner>
+    private var addingObserverCounter = 0
+    private var handlingEvent = false
+    private var newEventOccurred = false
 
     // we have to keep it for cases:
     // void onStart() {
@@ -74,40 +64,22 @@
     //     mRegistry.add(newObserver);
     // }
     // newObserver should be brought only to CREATED state during the execution of
-    // this onStart method. our invariant with mObserverMap doesn't help, because parent observer
+    // this onStart method. our invariant with observerMap doesn't help, because parent observer
     // is no longer in the map.
-    private ArrayList<State> mParentStates = new ArrayList<>();
-    private final boolean mEnforceMainThread;
+    private var parentStates = ArrayList<State>()
 
     /**
      * Creates a new LifecycleRegistry for the given provider.
-     * <p>
+     *
      * You should usually create this inside your LifecycleOwner class's constructor and hold
      * onto the same instance.
      *
      * @param provider The owner LifecycleOwner
      */
-    public LifecycleRegistry(@NonNull LifecycleOwner provider) {
-        this(provider, true);
-    }
+    constructor(provider: LifecycleOwner) : this(provider, true)
 
-    private LifecycleRegistry(@NonNull LifecycleOwner provider, boolean enforceMainThread) {
-        mLifecycleOwner = new WeakReference<>(provider);
-        mState = INITIALIZED;
-        mEnforceMainThread = enforceMainThread;
-    }
-
-    /**
-     * Moves the Lifecycle to the given state and dispatches necessary events to the observers.
-     *
-     * @param state new state
-     * @deprecated Use {@link #setCurrentState(State)}.
-     */
-    @Deprecated
-    @MainThread
-    public void markState(@NonNull State state) {
-        enforceMainThreadIfNeeded("markState");
-        setCurrentState(state);
+    init {
+        lifecycleOwner = WeakReference(provider)
     }
 
     /**
@@ -116,114 +88,129 @@
      * @param state new state
      */
     @MainThread
-    public void setCurrentState(@NonNull State state) {
-        enforceMainThreadIfNeeded("setCurrentState");
-        moveToState(state);
+    @Deprecated("Override [currentState].")
+    open fun markState(state: State) {
+        enforceMainThreadIfNeeded("markState")
+        currentState = state
     }
 
+    override var currentState: State
+        get() = state
+        /**
+         * Moves the Lifecycle to the given state and dispatches necessary events to the observers.
+         *
+         * @param state new state
+         */
+        set(state) {
+            enforceMainThreadIfNeeded("setCurrentState")
+            moveToState(state)
+        }
+
     /**
      * Sets the current state and notifies the observers.
-     * <p>
-     * Note that if the {@code currentState} is the same state as the last call to this method,
+     *
+     * Note that if the `currentState` is the same state as the last call to this method,
      * calling this method has no effect.
      *
      * @param event The event that was received
      */
-    public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
-        enforceMainThreadIfNeeded("handleLifecycleEvent");
-        moveToState(event.getTargetState());
+    open fun handleLifecycleEvent(event: Event) {
+        enforceMainThreadIfNeeded("handleLifecycleEvent")
+        moveToState(event.targetState)
     }
 
-    private void moveToState(State next) {
-        if (mState == next) {
-            return;
+    private fun moveToState(next: State) {
+        if (state == next) {
+            return
         }
-        if (mState == INITIALIZED && next == DESTROYED) {
-            throw new IllegalStateException(
-                    "no event down from " + mState + " in component " + mLifecycleOwner.get());
+        check(!(state == State.INITIALIZED && next == State.DESTROYED)) {
+            "no event down from $state in component ${lifecycleOwner.get()}"
         }
-        mState = next;
-        if (mHandlingEvent || mAddingObserverCounter != 0) {
-            mNewEventOccurred = true;
+        state = next
+        if (handlingEvent || addingObserverCounter != 0) {
+            newEventOccurred = true
             // we will figure out what to do on upper level.
-            return;
+            return
         }
-        mHandlingEvent = true;
-        sync();
-        mHandlingEvent = false;
-        if (mState == DESTROYED) {
-            mObserverMap = new FastSafeIterableMap<>();
+        handlingEvent = true
+        sync()
+        handlingEvent = false
+        if (state == State.DESTROYED) {
+            observerMap = FastSafeIterableMap()
         }
     }
 
-    private boolean isSynced() {
-        if (mObserverMap.size() == 0) {
-            return true;
-        }
-        State eldestObserverState = mObserverMap.eldest().getValue().mState;
-        State newestObserverState = mObserverMap.newest().getValue().mState;
-        return eldestObserverState == newestObserverState && mState == newestObserverState;
-    }
-
-    private State calculateTargetState(LifecycleObserver observer) {
-        Map.Entry<LifecycleObserver, ObserverWithState> previous = mObserverMap.ceil(observer);
-
-        State siblingState = previous != null ? previous.getValue().mState : null;
-        State parentState = !mParentStates.isEmpty() ? mParentStates.get(mParentStates.size() - 1)
-                : null;
-        return min(min(mState, siblingState), parentState);
-    }
-
-    @Override
-    public void addObserver(@NonNull LifecycleObserver observer) {
-        enforceMainThreadIfNeeded("addObserver");
-        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
-        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
-        ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
-
-        if (previous != null) {
-            return;
-        }
-        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
-        if (lifecycleOwner == null) {
-            // it is null we should be destroyed. Fallback quickly
-            return;
-        }
-
-        boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
-        State targetState = calculateTargetState(observer);
-        mAddingObserverCounter++;
-        while ((statefulObserver.mState.compareTo(targetState) < 0
-                && mObserverMap.contains(observer))) {
-            pushParentState(statefulObserver.mState);
-            final Event event = Event.upFrom(statefulObserver.mState);
-            if (event == null) {
-                throw new IllegalStateException("no event up from " + statefulObserver.mState);
+    private val isSynced: Boolean
+        get() {
+            if (observerMap.size() == 0) {
+                return true
             }
-            statefulObserver.dispatchEvent(lifecycleOwner, event);
-            popParentState();
-            // mState / subling may have been changed recalculate
-            targetState = calculateTargetState(observer);
+            val eldestObserverState = observerMap.eldest()!!.value.state
+            val newestObserverState = observerMap.newest()!!.value.state
+            return eldestObserverState == newestObserverState && state == newestObserverState
         }
 
+    private fun calculateTargetState(observer: LifecycleObserver): State {
+        val map = observerMap.ceil(observer)
+        val siblingState = map?.value?.state
+        val parentState =
+            if (parentStates.isNotEmpty()) parentStates[parentStates.size - 1] else null
+        return min(min(state, siblingState), parentState)
+    }
+
+    /**
+     * Adds a LifecycleObserver that will be notified when the LifecycleOwner changes
+     * state.
+     *
+     * The given observer will be brought to the current state of the LifecycleOwner.
+     * For example, if the LifecycleOwner is in [Lifecycle.State.STARTED] state, the given observer
+     * will receive [Lifecycle.Event.ON_CREATE], [Lifecycle.Event.ON_START] events.
+     *
+     * @param observer The observer to notify.
+     *
+     * @throws IllegalStateException if no event up from observer's initial state
+     */
+    override fun addObserver(observer: LifecycleObserver) {
+        enforceMainThreadIfNeeded("addObserver")
+        val initialState = if (state == State.DESTROYED) State.DESTROYED else State.INITIALIZED
+        val statefulObserver = ObserverWithState(observer, initialState)
+        val previous = observerMap.putIfAbsent(observer, statefulObserver)
+        if (previous != null) {
+            return
+        }
+        val lifecycleOwner = lifecycleOwner.get()
+            ?: // it is null we should be destroyed. Fallback quickly
+            return
+        val isReentrance = addingObserverCounter != 0 || handlingEvent
+        var targetState = calculateTargetState(observer)
+        addingObserverCounter++
+        while (statefulObserver.state < targetState && observerMap.contains(observer)
+        ) {
+            pushParentState(statefulObserver.state)
+            val event = Event.upFrom(statefulObserver.state)
+                ?: throw IllegalStateException("no event up from ${statefulObserver.state}")
+            statefulObserver.dispatchEvent(lifecycleOwner, event)
+            popParentState()
+            // mState / subling may have been changed recalculate
+            targetState = calculateTargetState(observer)
+        }
         if (!isReentrance) {
             // we do sync only on the top level.
-            sync();
+            sync()
         }
-        mAddingObserverCounter--;
+        addingObserverCounter--
     }
 
-    private void popParentState() {
-        mParentStates.remove(mParentStates.size() - 1);
+    private fun popParentState() {
+        parentStates.removeAt(parentStates.size - 1)
     }
 
-    private void pushParentState(State state) {
-        mParentStates.add(state);
+    private fun pushParentState(state: State) {
+        parentStates.add(state)
     }
 
-    @Override
-    public void removeObserver(@NonNull LifecycleObserver observer) {
-        enforceMainThreadIfNeeded("removeObserver");
+    override fun removeObserver(observer: LifecycleObserver) {
+        enforceMainThreadIfNeeded("removeObserver")
         // we consciously decided not to send destruction events here in opposition to addObserver.
         // Our reasons for that:
         // 1. These events haven't yet happened at all. In contrast to events in addObservers, that
@@ -236,7 +223,7 @@
         // lost an internet and as a result you removed this observer. If you get destruction
         // events in removeObserver, you should have a special case in your onStop method that
         // checks if your web connection died and you shouldn't try to report anything to a server.
-        mObserverMap.remove(observer);
+        observerMap.remove(observer)
     }
 
     /**
@@ -244,122 +231,109 @@
      *
      * @return The number of observers.
      */
-    @SuppressWarnings("WeakerAccess")
-    public int getObserverCount() {
-        enforceMainThreadIfNeeded("getObserverCount");
-        return mObserverMap.size();
-    }
+    open val observerCount: Int
+        get() {
+            enforceMainThreadIfNeeded("getObserverCount")
+            return observerMap.size()
+        }
 
-    @NonNull
-    @Override
-    public State getCurrentState() {
-        return mState;
-    }
-
-    private void forwardPass(LifecycleOwner lifecycleOwner) {
-        Iterator<Map.Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =
-                mObserverMap.iteratorWithAdditions();
-        while (ascendingIterator.hasNext() && !mNewEventOccurred) {
-            Map.Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next();
-            ObserverWithState observer = entry.getValue();
-            while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred
-                    && mObserverMap.contains(entry.getKey()))) {
-                pushParentState(observer.mState);
-                final Event event = Event.upFrom(observer.mState);
-                if (event == null) {
-                    throw new IllegalStateException("no event up from " + observer.mState);
-                }
-                observer.dispatchEvent(lifecycleOwner, event);
-                popParentState();
+    private fun forwardPass(lifecycleOwner: LifecycleOwner) {
+        @Suppress()
+        val ascendingIterator: Iterator<Map.Entry<LifecycleObserver, ObserverWithState>> =
+            observerMap.iteratorWithAdditions()
+        while (ascendingIterator.hasNext() && !newEventOccurred) {
+            val (key, observer) = ascendingIterator.next()
+            while (observer.state < state && !newEventOccurred && observerMap.contains(key)
+            ) {
+                pushParentState(observer.state)
+                val event = Event.upFrom(observer.state)
+                    ?: throw IllegalStateException("no event up from ${observer.state}")
+                observer.dispatchEvent(lifecycleOwner, event)
+                popParentState()
             }
         }
     }
 
-    private void backwardPass(LifecycleOwner lifecycleOwner) {
-        Iterator<Map.Entry<LifecycleObserver, ObserverWithState>> descendingIterator =
-                mObserverMap.descendingIterator();
-        while (descendingIterator.hasNext() && !mNewEventOccurred) {
-            Map.Entry<LifecycleObserver, ObserverWithState> entry = descendingIterator.next();
-            ObserverWithState observer = entry.getValue();
-            while ((observer.mState.compareTo(mState) > 0 && !mNewEventOccurred
-                    && mObserverMap.contains(entry.getKey()))) {
-                Event event = Event.downFrom(observer.mState);
-                if (event == null) {
-                    throw new IllegalStateException("no event down from " + observer.mState);
-                }
-                pushParentState(event.getTargetState());
-                observer.dispatchEvent(lifecycleOwner, event);
-                popParentState();
+    private fun backwardPass(lifecycleOwner: LifecycleOwner) {
+        val descendingIterator = observerMap.descendingIterator()
+        while (descendingIterator.hasNext() && !newEventOccurred) {
+            val (key, observer) = descendingIterator.next()
+            while (observer.state > state && !newEventOccurred && observerMap.contains(key)
+            ) {
+                val event = Event.downFrom(observer.state)
+                    ?: throw IllegalStateException("no event down from ${observer.state}")
+                pushParentState(event.targetState)
+                observer.dispatchEvent(lifecycleOwner, event)
+                popParentState()
             }
         }
     }
 
     // happens only on the top of stack (never in reentrance),
     // so it doesn't have to take in account parents
-    private void sync() {
-        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
-        if (lifecycleOwner == null) {
-            throw new IllegalStateException("LifecycleOwner of this LifecycleRegistry is already"
-                    + "garbage collected. It is too late to change lifecycle state.");
-        }
-        while (!isSynced()) {
-            mNewEventOccurred = false;
-            // no need to check eldest for nullability, because isSynced does it for us.
-            if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
-                backwardPass(lifecycleOwner);
+    private fun sync() {
+        val lifecycleOwner = lifecycleOwner.get()
+            ?: throw IllegalStateException(
+                "LifecycleOwner of this LifecycleRegistry is already " +
+                    "garbage collected. It is too late to change lifecycle state."
+            )
+        while (!isSynced) {
+            newEventOccurred = false
+            if (state < observerMap.eldest()!!.value.state) {
+                backwardPass(lifecycleOwner)
             }
-            Map.Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
-            if (!mNewEventOccurred && newest != null
-                    && mState.compareTo(newest.getValue().mState) > 0) {
-                forwardPass(lifecycleOwner);
+            val newest = observerMap.newest()
+            if (!newEventOccurred && newest != null && state > newest.value.state) {
+                forwardPass(lifecycleOwner)
             }
         }
-        mNewEventOccurred = false;
+        newEventOccurred = false
     }
 
     @SuppressLint("RestrictedApi")
-    private void enforceMainThreadIfNeeded(String methodName) {
-        if (mEnforceMainThread) {
-            if (!ArchTaskExecutor.getInstance().isMainThread()) {
-                throw new IllegalStateException("Method " + methodName + " must be called on the "
-                        + "main thread");
+    private fun enforceMainThreadIfNeeded(methodName: String) {
+        if (enforceMainThread) {
+            check(ArchTaskExecutor.getInstance().isMainThread) {
+                ("Method $methodName must be called on the main thread")
             }
         }
     }
 
-    /**
-     * Creates a new LifecycleRegistry for the given provider, that doesn't check
-     * that its methods are called on the threads other than main.
-     * <p>
-     * LifecycleRegistry is not synchronized: if multiple threads access this {@code
-     * LifecycleRegistry}, it must be synchronized externally.
-     * <p>
-     * Another possible use-case for this method is JVM testing, when main thread is not present.
-     */
-    @VisibleForTesting
-    @NonNull
-    public static LifecycleRegistry createUnsafe(@NonNull LifecycleOwner owner) {
-        return new LifecycleRegistry(owner, false);
-    }
+    internal class ObserverWithState(observer: LifecycleObserver?, initialState: State) {
+        var state: State
+        var lifecycleObserver: LifecycleEventObserver
 
-    static State min(@NonNull State state1, @Nullable State state2) {
-        return state2 != null && state2.compareTo(state1) < 0 ? state2 : state1;
-    }
-
-    static class ObserverWithState {
-        State mState;
-        LifecycleEventObserver mLifecycleObserver;
-
-        ObserverWithState(LifecycleObserver observer, State initialState) {
-            mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
-            mState = initialState;
+        init {
+            lifecycleObserver = Lifecycling.lifecycleEventObserver(observer)
+            state = initialState
         }
 
-        void dispatchEvent(LifecycleOwner owner, Event event) {
-            State newState = event.getTargetState();
-            mState = min(mState, newState);
-            mLifecycleObserver.onStateChanged(owner, event);
-            mState = newState;
+        fun dispatchEvent(owner: LifecycleOwner?, event: Event) {
+            val newState = event.targetState
+            state = min(state, newState)
+            lifecycleObserver.onStateChanged(owner!!, event)
+            state = newState
         }
     }
-}
+
+    companion object {
+        /**
+         * Creates a new LifecycleRegistry for the given provider, that doesn't check
+         * that its methods are called on the threads other than main.
+         *
+         * LifecycleRegistry is not synchronized: if multiple threads access this `LifecycleRegistry`, it must be synchronized externally.
+         *
+         * Another possible use-case for this method is JVM testing, when main thread is not present.
+         */
+        @JvmStatic
+        @VisibleForTesting
+        fun createUnsafe(owner: LifecycleOwner): LifecycleRegistry {
+            return LifecycleRegistry(owner, false)
+        }
+
+        @JvmStatic
+        internal fun min(state1: State, state2: State?): State {
+            return if ((state2 != null) && (state2 < state1)) state2 else state1
+        }
+    }
+}
\ No newline at end of file