Import Android SDK Platform P [4386628]

/google/data/ro/projects/android/fetch_artifact \
    --bid 4386628 \
    --target sdk_phone_armv7-win_sdk \
    sdk-repo-linux-sources-4386628.zip

AndroidVersion.ApiLevel has been modified to appear as 28

Change-Id: I9b8400ac92116cae4f033d173f7a5682b26ccba9
diff --git a/android/arch/lifecycle/ClassesInfoCache.java b/android/arch/lifecycle/ClassesInfoCache.java
new file mode 100644
index 0000000..f077dae
--- /dev/null
+++ b/android/arch/lifecycle/ClassesInfoCache.java
@@ -0,0 +1,237 @@
+/*
+ * 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 android.arch.lifecycle;
+
+import android.support.annotation.Nullable;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Reflection is expensive, so we cache information about methods
+ * for {@link ReflectiveGenericLifecycleObserver}, so it can call them,
+ * and for {@link Lifecycling} to determine which observer adapter to use.
+ */
+class ClassesInfoCache {
+
+    static ClassesInfoCache sInstance = new ClassesInfoCache();
+
+    private static final int CALL_TYPE_NO_ARG = 0;
+    private static final int CALL_TYPE_PROVIDER = 1;
+    private static final int CALL_TYPE_PROVIDER_WITH_EVENT = 2;
+
+    private final Map<Class, CallbackInfo> mCallbackMap = new HashMap<>();
+    private final Map<Class, Boolean> mHasLifecycleMethods = new HashMap<>();
+
+    boolean hasLifecycleMethods(Class klass) {
+        if (mHasLifecycleMethods.containsKey(klass)) {
+            return mHasLifecycleMethods.get(klass);
+        }
+
+        Method[] methods = klass.getDeclaredMethods();
+        for (Method method : methods) {
+            OnLifecycleEvent annotation = method.getAnnotation(OnLifecycleEvent.class);
+            if (annotation != null) {
+                // Optimization for reflection, we know that this method is called
+                // when there is no generated adapter. But there are methods with @OnLifecycleEvent
+                // so we know that will use ReflectiveGenericLifecycleObserver,
+                // so we createInfo in advance.
+                // CreateInfo always initialize mHasLifecycleMethods for a class, so we don't do it
+                // here.
+                createInfo(klass, methods);
+                return true;
+            }
+        }
+        mHasLifecycleMethods.put(klass, false);
+        return false;
+    }
+
+    CallbackInfo getInfo(Class klass) {
+        CallbackInfo existing = mCallbackMap.get(klass);
+        if (existing != null) {
+            return existing;
+        }
+        existing = createInfo(klass, null);
+        return existing;
+    }
+
+    private void verifyAndPutHandler(Map<MethodReference, Lifecycle.Event> handlers,
+            MethodReference newHandler, Lifecycle.Event newEvent, Class klass) {
+        Lifecycle.Event event = handlers.get(newHandler);
+        if (event != null && newEvent != event) {
+            Method method = newHandler.mMethod;
+            throw new IllegalArgumentException(
+                    "Method " + method.getName() + " in " + klass.getName()
+                            + " already declared with different @OnLifecycleEvent value: previous"
+                            + " value " + event + ", new value " + newEvent);
+        }
+        if (event == null) {
+            handlers.put(newHandler, newEvent);
+        }
+    }
+
+    private CallbackInfo createInfo(Class klass, @Nullable Method[] declaredMethods) {
+        Class superclass = klass.getSuperclass();
+        Map<MethodReference, Lifecycle.Event> handlerToEvent = new HashMap<>();
+        if (superclass != null) {
+            CallbackInfo superInfo = getInfo(superclass);
+            if (superInfo != null) {
+                handlerToEvent.putAll(superInfo.mHandlerToEvent);
+            }
+        }
+
+        Class[] interfaces = klass.getInterfaces();
+        for (Class intrfc : interfaces) {
+            for (Map.Entry<MethodReference, Lifecycle.Event> entry : getInfo(
+                    intrfc).mHandlerToEvent.entrySet()) {
+                verifyAndPutHandler(handlerToEvent, entry.getKey(), entry.getValue(), klass);
+            }
+        }
+
+        Method[] methods = declaredMethods != null ? declaredMethods : klass.getDeclaredMethods();
+        boolean hasLifecycleMethods = false;
+        for (Method method : methods) {
+            OnLifecycleEvent annotation = method.getAnnotation(OnLifecycleEvent.class);
+            if (annotation == null) {
+                continue;
+            }
+            hasLifecycleMethods = true;
+            Class<?>[] params = method.getParameterTypes();
+            int callType = CALL_TYPE_NO_ARG;
+            if (params.length > 0) {
+                callType = CALL_TYPE_PROVIDER;
+                if (!params[0].isAssignableFrom(LifecycleOwner.class)) {
+                    throw new IllegalArgumentException(
+                            "invalid parameter type. Must be one and instanceof LifecycleOwner");
+                }
+            }
+            Lifecycle.Event event = annotation.value();
+
+            if (params.length > 1) {
+                callType = CALL_TYPE_PROVIDER_WITH_EVENT;
+                if (!params[1].isAssignableFrom(Lifecycle.Event.class)) {
+                    throw new IllegalArgumentException(
+                            "invalid parameter type. second arg must be an event");
+                }
+                if (event != Lifecycle.Event.ON_ANY) {
+                    throw new IllegalArgumentException(
+                            "Second arg is supported only for ON_ANY value");
+                }
+            }
+            if (params.length > 2) {
+                throw new IllegalArgumentException("cannot have more than 2 params");
+            }
+            MethodReference methodReference = new MethodReference(callType, method);
+            verifyAndPutHandler(handlerToEvent, methodReference, event, klass);
+        }
+        CallbackInfo info = new CallbackInfo(handlerToEvent);
+        mCallbackMap.put(klass, info);
+        mHasLifecycleMethods.put(klass, hasLifecycleMethods);
+        return info;
+    }
+
+    @SuppressWarnings("WeakerAccess")
+    static class CallbackInfo {
+        final Map<Lifecycle.Event, List<MethodReference>> mEventToHandlers;
+        final Map<MethodReference, Lifecycle.Event> mHandlerToEvent;
+
+        CallbackInfo(Map<MethodReference, Lifecycle.Event> handlerToEvent) {
+            mHandlerToEvent = handlerToEvent;
+            mEventToHandlers = new HashMap<>();
+            for (Map.Entry<MethodReference, Lifecycle.Event> entry : handlerToEvent.entrySet()) {
+                Lifecycle.Event event = entry.getValue();
+                List<MethodReference> methodReferences = mEventToHandlers.get(event);
+                if (methodReferences == null) {
+                    methodReferences = new ArrayList<>();
+                    mEventToHandlers.put(event, methodReferences);
+                }
+                methodReferences.add(entry.getKey());
+            }
+        }
+
+        @SuppressWarnings("ConstantConditions")
+        void invokeCallbacks(LifecycleOwner source, Lifecycle.Event event, Object target) {
+            invokeMethodsForEvent(mEventToHandlers.get(event), source, event, target);
+            invokeMethodsForEvent(mEventToHandlers.get(Lifecycle.Event.ON_ANY), source, event,
+                    target);
+        }
+
+        private static void invokeMethodsForEvent(List<MethodReference> handlers,
+                LifecycleOwner source, Lifecycle.Event event, Object mWrapped) {
+            if (handlers != null) {
+                for (int i = handlers.size() - 1; i >= 0; i--) {
+                    handlers.get(i).invokeCallback(source, event, mWrapped);
+                }
+            }
+        }
+    }
+
+    @SuppressWarnings("WeakerAccess")
+    static class MethodReference {
+        final int mCallType;
+        final Method mMethod;
+
+        MethodReference(int callType, Method method) {
+            mCallType = callType;
+            mMethod = method;
+            mMethod.setAccessible(true);
+        }
+
+        void invokeCallback(LifecycleOwner source, Lifecycle.Event event, Object target) {
+            //noinspection TryWithIdenticalCatches
+            try {
+                switch (mCallType) {
+                    case CALL_TYPE_NO_ARG:
+                        mMethod.invoke(target);
+                        break;
+                    case CALL_TYPE_PROVIDER:
+                        mMethod.invoke(target, source);
+                        break;
+                    case CALL_TYPE_PROVIDER_WITH_EVENT:
+                        mMethod.invoke(target, source, event);
+                        break;
+                }
+            } catch (InvocationTargetException e) {
+                throw new RuntimeException("Failed to call observer method", e.getCause());
+            } catch (IllegalAccessException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+
+            MethodReference that = (MethodReference) o;
+            return mCallType == that.mCallType && mMethod.getName().equals(that.mMethod.getName());
+        }
+
+        @Override
+        public int hashCode() {
+            return 31 * mCallType + mMethod.getName().hashCode();
+        }
+    }
+}
diff --git a/android/arch/lifecycle/CompositeGeneratedAdaptersObserver.java b/android/arch/lifecycle/CompositeGeneratedAdaptersObserver.java
new file mode 100644
index 0000000..e8cbe7c
--- /dev/null
+++ b/android/arch/lifecycle/CompositeGeneratedAdaptersObserver.java
@@ -0,0 +1,44 @@
+/*
+ * 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 android.arch.lifecycle;
+
+
+import android.support.annotation.RestrictTo;
+
+/**
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+public class CompositeGeneratedAdaptersObserver implements GenericLifecycleObserver {
+
+    private final GeneratedAdapter[] mGeneratedAdapters;
+
+    CompositeGeneratedAdaptersObserver(GeneratedAdapter[] generatedAdapters) {
+        mGeneratedAdapters = generatedAdapters;
+    }
+
+    @Override
+    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
+        MethodCallsLogger logger = new MethodCallsLogger();
+        for (GeneratedAdapter mGenerated: mGeneratedAdapters) {
+            mGenerated.callMethods(source, event, false, logger);
+        }
+        for (GeneratedAdapter mGenerated: mGeneratedAdapters) {
+            mGenerated.callMethods(source, event, true, logger);
+        }
+    }
+}
diff --git a/android/arch/lifecycle/ComputableLiveData.java b/android/arch/lifecycle/ComputableLiveData.java
index fe18243..f135244 100644
--- a/android/arch/lifecycle/ComputableLiveData.java
+++ b/android/arch/lifecycle/ComputableLiveData.java
@@ -1,136 +1,9 @@
-/*
- * 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.
- */
-
+//ComputableLiveData interface for tests
 package android.arch.lifecycle;
-
-import android.arch.core.executor.AppToolkitTaskExecutor;
-import android.support.annotation.MainThread;
-import android.support.annotation.NonNull;
-import android.support.annotation.RestrictTo;
-import android.support.annotation.VisibleForTesting;
-import android.support.annotation.WorkerThread;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * A LiveData class that can be invalidated & computed on demand.
- * <p>
- * This is an internal class for now, might be public if we see the necessity.
- *
- * @param <T> The type of the live data
- * @hide internal
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+import android.arch.lifecycle.LiveData;
 public abstract class ComputableLiveData<T> {
-
-    private final LiveData<T> mLiveData;
-
-    private AtomicBoolean mInvalid = new AtomicBoolean(true);
-    private AtomicBoolean mComputing = new AtomicBoolean(false);
-
-    /**
-     * Creates a computable live data which is computed when there are active observers.
-     * <p>
-     * It can also be invalidated via {@link #invalidate()} which will result in a call to
-     * {@link #compute()} if there are active observers (or when they start observing)
-     */
-    @SuppressWarnings("WeakerAccess")
-    public ComputableLiveData() {
-        mLiveData = new LiveData<T>() {
-            @Override
-            protected void onActive() {
-                // TODO if we make this class public, we should accept an executor
-                AppToolkitTaskExecutor.getInstance().executeOnDiskIO(mRefreshRunnable);
-            }
-        };
-    }
-
-    /**
-     * Returns the LiveData managed by this class.
-     *
-     * @return A LiveData that is controlled by ComputableLiveData.
-     */
-    @SuppressWarnings("WeakerAccess")
-    @NonNull
-    public LiveData<T> getLiveData() {
-        return mLiveData;
-    }
-
-    @VisibleForTesting
-    final Runnable mRefreshRunnable = new Runnable() {
-        @WorkerThread
-        @Override
-        public void run() {
-            boolean computed;
-            do {
-                computed = false;
-                // compute can happen only in 1 thread but no reason to lock others.
-                if (mComputing.compareAndSet(false, true)) {
-                    // as long as it is invalid, keep computing.
-                    try {
-                        T value = null;
-                        while (mInvalid.compareAndSet(true, false)) {
-                            computed = true;
-                            value = compute();
-                        }
-                        if (computed) {
-                            mLiveData.postValue(value);
-                        }
-                    } finally {
-                        // release compute lock
-                        mComputing.set(false);
-                    }
-                }
-                // check invalid after releasing compute lock to avoid the following scenario.
-                // Thread A runs compute()
-                // Thread A checks invalid, it is false
-                // Main thread sets invalid to true
-                // Thread B runs, fails to acquire compute lock and skips
-                // Thread A releases compute lock
-                // We've left invalid in set state. The check below recovers.
-            } while (computed && mInvalid.get());
-        }
-    };
-
-    // invalidation check always happens on the main thread
-    @VisibleForTesting
-    final Runnable mInvalidationRunnable = new Runnable() {
-        @MainThread
-        @Override
-        public void run() {
-            boolean isActive = mLiveData.hasActiveObservers();
-            if (mInvalid.compareAndSet(false, true)) {
-                if (isActive) {
-                    // TODO if we make this class public, we should accept an executor.
-                    AppToolkitTaskExecutor.getInstance().executeOnDiskIO(mRefreshRunnable);
-                }
-            }
-        }
-    };
-
-    /**
-     * Invalidates the LiveData.
-     * <p>
-     * When there are active observers, this will trigger a call to {@link #compute()}.
-     */
-    public void invalidate() {
-        AppToolkitTaskExecutor.getInstance().executeOnMainThread(mInvalidationRunnable);
-    }
-
-    @SuppressWarnings("WeakerAccess")
-    @WorkerThread
-    protected abstract T compute();
+    public ComputableLiveData(){}
+    abstract protected T compute();
+    public LiveData<T> getLiveData() {return null;}
+    public void invalidate() {}
 }
diff --git a/android/arch/lifecycle/ComputableLiveDataTest.java b/android/arch/lifecycle/ComputableLiveDataTest.java
index 0a3fbed..eb89d8d 100644
--- a/android/arch/lifecycle/ComputableLiveDataTest.java
+++ b/android/arch/lifecycle/ComputableLiveDataTest.java
@@ -27,7 +27,7 @@
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.arch.core.executor.TaskExecutor;
 import android.arch.core.executor.TaskExecutorWithFakeMainThread;
 import android.arch.lifecycle.util.InstantTaskExecutor;
@@ -58,12 +58,12 @@
     @Before
     public void swapExecutorDelegate() {
         mTaskExecutor = spy(new InstantTaskExecutor());
-        AppToolkitTaskExecutor.getInstance().setDelegate(mTaskExecutor);
+        ArchTaskExecutor.getInstance().setDelegate(mTaskExecutor);
     }
 
     @After
     public void removeExecutorDelegate() {
-        AppToolkitTaskExecutor.getInstance().setDelegate(null);
+        ArchTaskExecutor.getInstance().setDelegate(null);
     }
 
     @Test
@@ -76,7 +76,7 @@
     @Test
     public void noConcurrentCompute() throws InterruptedException {
         TaskExecutorWithFakeMainThread executor = new TaskExecutorWithFakeMainThread(2);
-        AppToolkitTaskExecutor.getInstance().setDelegate(executor);
+        ArchTaskExecutor.getInstance().setDelegate(executor);
         try {
             // # of compute calls
             final Semaphore computeCounter = new Semaphore(0);
@@ -121,7 +121,7 @@
             // assert no other results arrive
             verify(observer, never()).onChanged(anyInt());
         } finally {
-            AppToolkitTaskExecutor.getInstance().setDelegate(null);
+            ArchTaskExecutor.getInstance().setDelegate(null);
         }
     }
 
diff --git a/android/arch/lifecycle/DefaultLifecycleObserver.java b/android/arch/lifecycle/DefaultLifecycleObserver.java
new file mode 100644
index 0000000..b6f468c
--- /dev/null
+++ b/android/arch/lifecycle/DefaultLifecycleObserver.java
@@ -0,0 +1,100 @@
+/*
+ * 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 android.arch.lifecycle;
+
+import android.support.annotation.NonNull;
+
+/**
+ * Callback interface for listening to {@link LifecycleOwner} state changes.
+ * <p>
+ * If you use Java 8 language, <b>always</b> prefer it over annotations.
+ */
+@SuppressWarnings("unused")
+public interface DefaultLifecycleObserver extends FullLifecycleObserver {
+
+    /**
+     * Notifies that {@code ON_CREATE} event occurred.
+     * <p>
+     * This method will be called after the {@link LifecycleOwner}'s {@code onCreate}
+     * method returns.
+     *
+     * @param owner the component, whose state was changed
+     */
+    @Override
+    default void onCreate(@NonNull LifecycleOwner owner) {
+    }
+
+    /**
+     * Notifies that {@code ON_START} event occurred.
+     * <p>
+     * This method will be called after the {@link LifecycleOwner}'s {@code onStart} method returns.
+     *
+     * @param owner the component, whose state was changed
+     */
+    @Override
+    default void onStart(@NonNull LifecycleOwner owner) {
+    }
+
+    /**
+     * Notifies that {@code ON_RESUME} event occurred.
+     * <p>
+     * This method will be called after the {@link LifecycleOwner}'s {@code onResume}
+     * method returns.
+     *
+     * @param owner the component, whose state was changed
+     */
+    @Override
+    default void onResume(@NonNull LifecycleOwner owner) {
+    }
+
+    /**
+     * Notifies that {@code ON_PAUSE} event occurred.
+     * <p>
+     * This method will be called before the {@link LifecycleOwner}'s {@code onPause} method
+     * is called.
+     *
+     * @param owner the component, whose state was changed
+     */
+    @Override
+    default void onPause(@NonNull LifecycleOwner owner) {
+    }
+
+    /**
+     * Notifies that {@code ON_STOP} event occurred.
+     * <p>
+     * This method will be called before the {@link LifecycleOwner}'s {@code onStop} method
+     * is called.
+     *
+     * @param owner the component, whose state was changed
+     */
+    @Override
+    default void onStop(@NonNull LifecycleOwner owner) {
+    }
+
+    /**
+     * Notifies that {@code ON_DESTROY} event occurred.
+     * <p>
+     * This method will be called before the {@link LifecycleOwner}'s {@code onStop} method
+     * is called.
+     *
+     * @param owner the component, whose state was changed
+     */
+    @Override
+    default void onDestroy(@NonNull LifecycleOwner owner) {
+    }
+}
+
diff --git a/android/arch/lifecycle/FragmentInBackStackLifecycleTest.java b/android/arch/lifecycle/FragmentInBackStackLifecycleTest.java
index 3397f5f..f48f788 100644
--- a/android/arch/lifecycle/FragmentInBackStackLifecycleTest.java
+++ b/android/arch/lifecycle/FragmentInBackStackLifecycleTest.java
@@ -37,6 +37,7 @@
 import android.support.test.filters.SmallTest;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
+import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentActivity;
 import android.support.v4.app.FragmentManager;
 
@@ -58,20 +59,20 @@
         final ArrayList<Event> collectedEvents = new ArrayList<>();
         LifecycleObserver collectingObserver = new LifecycleObserver() {
             @OnLifecycleEvent(Event.ON_ANY)
-            void onAny(LifecycleOwner owner, Event event) {
+            void onAny(@SuppressWarnings("unused") LifecycleOwner owner, Event event) {
                 collectedEvents.add(event);
             }
         };
         final FragmentActivity activity = activityTestRule.getActivity();
         activityTestRule.runOnUiThread(() -> {
             FragmentManager fm = activity.getSupportFragmentManager();
-            LifecycleFragment fragment = new LifecycleFragment();
+            Fragment fragment = new Fragment();
             fm.beginTransaction().add(R.id.fragment_container, fragment, "tag").addToBackStack(null)
                     .commit();
             fm.executePendingTransactions();
 
             fragment.getLifecycle().addObserver(collectingObserver);
-            LifecycleFragment fragment2 = new LifecycleFragment();
+            Fragment fragment2 = new Fragment();
             fm.beginTransaction().replace(R.id.fragment_container, fragment2).addToBackStack(null)
                     .commit();
             fm.executePendingTransactions();
@@ -82,12 +83,13 @@
         EmptyActivity newActivity = recreateActivity(activityTestRule.getActivity(),
                 activityTestRule);
 
+        //noinspection ArraysAsListWithZeroOrOneArgument
         assertThat(collectedEvents, is(asList(ON_DESTROY)));
         collectedEvents.clear();
         EmptyActivity lastActivity = recreateActivity(newActivity, activityTestRule);
         activityTestRule.runOnUiThread(() -> {
             FragmentManager fm = lastActivity.getSupportFragmentManager();
-            LifecycleFragment fragment = (LifecycleFragment) fm.findFragmentByTag("tag");
+            Fragment fragment = fm.findFragmentByTag("tag");
             fragment.getLifecycle().addObserver(collectingObserver);
             assertThat(collectedEvents, iterableWithSize(0));
             fm.popBackStackImmediate();
diff --git a/android/arch/lifecycle/FragmentOperationsLifecycleTest.java b/android/arch/lifecycle/FragmentOperationsLifecycleTest.java
index be062cb..3e61277 100644
--- a/android/arch/lifecycle/FragmentOperationsLifecycleTest.java
+++ b/android/arch/lifecycle/FragmentOperationsLifecycleTest.java
@@ -34,6 +34,7 @@
 import android.support.test.filters.MediumTest;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
+import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentManager;
 
 import org.junit.Rule;
@@ -55,7 +56,7 @@
     @UiThreadTest
     public void addRemoveFragment() {
         EmptyActivity activity = mActivityTestRule.getActivity();
-        LifecycleFragment fragment = new LifecycleFragment();
+        Fragment fragment = new Fragment();
         FragmentManager fm = activity.getSupportFragmentManager();
         fm.beginTransaction().add(fragment, "tag").commitNow();
         CollectingObserver observer = observeAndCollectIn(fragment);
@@ -70,7 +71,7 @@
     @UiThreadTest
     public void fragmentInBackstack() {
         EmptyActivity activity = mActivityTestRule.getActivity();
-        LifecycleFragment fragment1 = new LifecycleFragment();
+        Fragment fragment1 = new Fragment();
         FragmentManager fm = activity.getSupportFragmentManager();
         fm.beginTransaction().add(R.id.fragment_container, fragment1, "tag").addToBackStack(null)
                 .commit();
@@ -78,7 +79,7 @@
         CollectingObserver observer1 = observeAndCollectIn(fragment1);
         assertThat(observer1.getEventsAndReset(), is(asList(ON_CREATE, ON_START, ON_RESUME)));
 
-        LifecycleFragment fragment2 = new LifecycleFragment();
+        Fragment fragment2 = new Fragment();
         fm.beginTransaction().replace(R.id.fragment_container, fragment2).addToBackStack(null)
                 .commit();
         fm.executePendingTransactions();
@@ -95,7 +96,7 @@
         assertThat(observer1.getEventsAndReset(), is(asList(ON_PAUSE, ON_STOP, ON_DESTROY)));
     }
 
-    private static CollectingObserver observeAndCollectIn(LifecycleFragment fragment) {
+    private static CollectingObserver observeAndCollectIn(Fragment fragment) {
         CollectingObserver observer = new CollectingObserver();
         fragment.getLifecycle().addObserver(observer);
         return observer;
diff --git a/android/arch/lifecycle/FullLifecycleObserver.java b/android/arch/lifecycle/FullLifecycleObserver.java
new file mode 100644
index 0000000..f179274
--- /dev/null
+++ b/android/arch/lifecycle/FullLifecycleObserver.java
@@ -0,0 +1,32 @@
+/*
+ * 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 android.arch.lifecycle;
+
+interface FullLifecycleObserver extends LifecycleObserver {
+
+    void onCreate(LifecycleOwner owner);
+
+    void onStart(LifecycleOwner owner);
+
+    void onResume(LifecycleOwner owner);
+
+    void onPause(LifecycleOwner owner);
+
+    void onStop(LifecycleOwner owner);
+
+    void onDestroy(LifecycleOwner owner);
+}
diff --git a/android/arch/lifecycle/FullLifecycleObserverAdapter.java b/android/arch/lifecycle/FullLifecycleObserverAdapter.java
new file mode 100644
index 0000000..0a91a66
--- /dev/null
+++ b/android/arch/lifecycle/FullLifecycleObserverAdapter.java
@@ -0,0 +1,52 @@
+/*
+ * 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 android.arch.lifecycle;
+
+class FullLifecycleObserverAdapter implements GenericLifecycleObserver {
+
+    private final FullLifecycleObserver mObserver;
+
+    FullLifecycleObserverAdapter(FullLifecycleObserver observer) {
+        mObserver = observer;
+    }
+
+    @Override
+    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
+        switch (event) {
+            case ON_CREATE:
+                mObserver.onCreate(source);
+                break;
+            case ON_START:
+                mObserver.onStart(source);
+                break;
+            case ON_RESUME:
+                mObserver.onResume(source);
+                break;
+            case ON_PAUSE:
+                mObserver.onPause(source);
+                break;
+            case ON_STOP:
+                mObserver.onStop(source);
+                break;
+            case ON_DESTROY:
+                mObserver.onDestroy(source);
+                break;
+            case ON_ANY:
+                throw new IllegalArgumentException("ON_ANY must not been send by anybody");
+        }
+    }
+}
diff --git a/android/arch/lifecycle/FullLifecycleObserverTest.java b/android/arch/lifecycle/FullLifecycleObserverTest.java
new file mode 100644
index 0000000..def6755
--- /dev/null
+++ b/android/arch/lifecycle/FullLifecycleObserverTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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 android.arch.lifecycle;
+
+import static android.arch.lifecycle.Lifecycle.Event.ON_CREATE;
+import static android.arch.lifecycle.Lifecycle.Event.ON_DESTROY;
+import static android.arch.lifecycle.Lifecycle.Event.ON_PAUSE;
+import static android.arch.lifecycle.Lifecycle.Event.ON_RESUME;
+import static android.arch.lifecycle.Lifecycle.Event.ON_START;
+import static android.arch.lifecycle.Lifecycle.Event.ON_STOP;
+import static android.arch.lifecycle.Lifecycle.State.CREATED;
+import static android.arch.lifecycle.Lifecycle.State.INITIALIZED;
+import static android.arch.lifecycle.Lifecycle.State.RESUMED;
+import static android.arch.lifecycle.Lifecycle.State.STARTED;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.InOrder;
+import org.mockito.Mockito;
+
+@RunWith(JUnit4.class)
+public class FullLifecycleObserverTest {
+    private LifecycleOwner mOwner;
+    private Lifecycle mLifecycle;
+
+    @Before
+    public void initMocks() {
+        mOwner = mock(LifecycleOwner.class);
+        mLifecycle = mock(Lifecycle.class);
+        when(mOwner.getLifecycle()).thenReturn(mLifecycle);
+    }
+
+    @Test
+    public void eachEvent() {
+        FullLifecycleObserver obj = mock(FullLifecycleObserver.class);
+        FullLifecycleObserverAdapter observer = new FullLifecycleObserverAdapter(obj);
+        when(mLifecycle.getCurrentState()).thenReturn(CREATED);
+
+        observer.onStateChanged(mOwner, ON_CREATE);
+        InOrder inOrder = Mockito.inOrder(obj);
+        inOrder.verify(obj).onCreate(mOwner);
+        reset(obj);
+
+        when(mLifecycle.getCurrentState()).thenReturn(STARTED);
+        observer.onStateChanged(mOwner, ON_START);
+        inOrder.verify(obj).onStart(mOwner);
+        reset(obj);
+
+        when(mLifecycle.getCurrentState()).thenReturn(RESUMED);
+        observer.onStateChanged(mOwner, ON_RESUME);
+        inOrder.verify(obj).onResume(mOwner);
+        reset(obj);
+
+        when(mLifecycle.getCurrentState()).thenReturn(STARTED);
+        observer.onStateChanged(mOwner, ON_PAUSE);
+        inOrder.verify(obj).onPause(mOwner);
+        reset(obj);
+
+        when(mLifecycle.getCurrentState()).thenReturn(CREATED);
+        observer.onStateChanged(mOwner, ON_STOP);
+        inOrder.verify(obj).onStop(mOwner);
+        reset(obj);
+
+        when(mLifecycle.getCurrentState()).thenReturn(INITIALIZED);
+        observer.onStateChanged(mOwner, ON_DESTROY);
+        inOrder.verify(obj).onDestroy(mOwner);
+        reset(obj);
+    }
+}
diff --git a/android/arch/lifecycle/GeneratedAdapter.java b/android/arch/lifecycle/GeneratedAdapter.java
new file mode 100644
index 0000000..a8862da
--- /dev/null
+++ b/android/arch/lifecycle/GeneratedAdapter.java
@@ -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 android.arch.lifecycle;
+
+import android.support.annotation.RestrictTo;
+
+/**
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+public interface GeneratedAdapter {
+
+    /**
+     * Called when a state transition event happens.
+     *
+     * @param source The source of the event
+     * @param event The event
+     * @param onAny approveCall onAny handlers
+     * @param logger if passed, used to track called methods and prevent calling the same method
+     *              twice
+     */
+    void callMethods(LifecycleOwner source, Lifecycle.Event event, boolean onAny,
+            MethodCallsLogger logger);
+}
diff --git a/android/arch/lifecycle/GeneratedAdaptersTest.java b/android/arch/lifecycle/GeneratedAdaptersTest.java
new file mode 100644
index 0000000..2abb511
--- /dev/null
+++ b/android/arch/lifecycle/GeneratedAdaptersTest.java
@@ -0,0 +1,212 @@
+/*
+ * 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 android.arch.lifecycle;
+
+import static android.arch.lifecycle.Lifecycle.Event.ON_ANY;
+import static android.arch.lifecycle.Lifecycle.Event.ON_RESUME;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.singletonList;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public class GeneratedAdaptersTest {
+
+    private LifecycleOwner mOwner;
+    @SuppressWarnings("FieldCanBeLocal")
+    private Lifecycle mLifecycle;
+
+    @Before
+    public void initMocks() {
+        mOwner = mock(LifecycleOwner.class);
+        mLifecycle = mock(Lifecycle.class);
+        when(mOwner.getLifecycle()).thenReturn(mLifecycle);
+    }
+
+    static class SimpleObserver implements LifecycleObserver {
+        List<String> mLog;
+
+        SimpleObserver(List<String> log) {
+            mLog = log;
+        }
+
+        @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
+        void onCreate() {
+            mLog.add("onCreate");
+        }
+    }
+
+    @Test
+    public void testSimpleSingleGeneratedAdapter() {
+        List<String>  actual = new ArrayList<>();
+        GenericLifecycleObserver callback = Lifecycling.getCallback(new SimpleObserver(actual));
+        callback.onStateChanged(mOwner, Lifecycle.Event.ON_CREATE);
+        assertThat(callback, instanceOf(SingleGeneratedAdapterObserver.class));
+        assertThat(actual, is(singletonList("onCreate")));
+    }
+
+    static class TestObserver implements LifecycleObserver {
+        List<String> mLog;
+
+        TestObserver(List<String> log) {
+            mLog = log;
+        }
+
+        @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
+        void onCreate() {
+            mLog.add("onCreate");
+        }
+
+        @OnLifecycleEvent(ON_ANY)
+        void onAny() {
+            mLog.add("onAny");
+        }
+    }
+
+    @Test
+    public void testOnAny() {
+        List<String>  actual = new ArrayList<>();
+        GenericLifecycleObserver callback = Lifecycling.getCallback(new TestObserver(actual));
+        callback.onStateChanged(mOwner, Lifecycle.Event.ON_CREATE);
+        assertThat(callback, instanceOf(SingleGeneratedAdapterObserver.class));
+        assertThat(actual, is(asList("onCreate", "onAny")));
+    }
+
+    interface OnPauses extends LifecycleObserver {
+        @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
+        void onPause();
+
+        @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
+        void onPause(LifecycleOwner owner);
+    }
+
+    interface OnPauseResume extends LifecycleObserver {
+        @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
+        void onPause();
+
+        @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
+        void onResume();
+    }
+
+    class Impl1 implements OnPauses, OnPauseResume {
+
+        List<String> mLog;
+
+        Impl1(List<String> log) {
+            mLog = log;
+        }
+
+        @Override
+        public void onPause() {
+            mLog.add("onPause_0");
+        }
+
+        @Override
+        public void onResume() {
+            mLog.add("onResume");
+        }
+
+        @Override
+        public void onPause(LifecycleOwner owner) {
+            mLog.add("onPause_1");
+        }
+    }
+
+    @Test
+    public void testClashingInterfaces() {
+        List<String>  actual = new ArrayList<>();
+        GenericLifecycleObserver callback = Lifecycling.getCallback(new Impl1(actual));
+        callback.onStateChanged(mOwner, Lifecycle.Event.ON_PAUSE);
+        assertThat(callback, instanceOf(CompositeGeneratedAdaptersObserver.class));
+        assertThat(actual, is(asList("onPause_0", "onPause_1")));
+        actual.clear();
+        callback.onStateChanged(mOwner, Lifecycle.Event.ON_RESUME);
+        assertThat(actual, is(singletonList("onResume")));
+    }
+
+    class Base implements LifecycleObserver {
+
+        List<String> mLog;
+
+        Base(List<String> log) {
+            mLog = log;
+        }
+
+        @OnLifecycleEvent(ON_ANY)
+        void onAny() {
+            mLog.add("onAny_0");
+        }
+
+        @OnLifecycleEvent(ON_ANY)
+        void onAny(LifecycleOwner owner) {
+            mLog.add("onAny_1");
+        }
+
+        @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
+        void onResume() {
+            mLog.add("onResume");
+        }
+    }
+
+    interface OnAny extends LifecycleObserver {
+        @OnLifecycleEvent(ON_ANY)
+        void onAny();
+
+        @OnLifecycleEvent(ON_ANY)
+        void onAny(LifecycleOwner owner, Lifecycle.Event event);
+    }
+
+    class Derived extends Base implements OnAny {
+        Derived(List<String> log) {
+            super(log);
+        }
+
+        @Override
+        public void onAny() {
+            super.onAny();
+        }
+
+        @Override
+        public void onAny(LifecycleOwner owner, Lifecycle.Event event) {
+            mLog.add("onAny_2");
+            assertThat(event, is(ON_RESUME));
+        }
+    }
+
+    @Test
+    public void testClashingClassAndInterface() {
+        List<String>  actual = new ArrayList<>();
+        GenericLifecycleObserver callback = Lifecycling.getCallback(new Derived(actual));
+        callback.onStateChanged(mOwner, Lifecycle.Event.ON_RESUME);
+        assertThat(callback, instanceOf(CompositeGeneratedAdaptersObserver.class));
+        assertThat(actual, is(asList("onResume", "onAny_0", "onAny_1", "onAny_2")));
+    }
+
+}
diff --git a/android/arch/lifecycle/Lifecycle.java b/android/arch/lifecycle/Lifecycle.java
index fcbd50a..02db5ff 100644
--- a/android/arch/lifecycle/Lifecycle.java
+++ b/android/arch/lifecycle/Lifecycle.java
@@ -34,7 +34,21 @@
  * before {@link android.app.Activity#onStop onStop} is called.
  * This gives you certain guarantees on which state the owner is in.
  * <p>
- * Lifecycle events are observed using annotations.
+ * If you use <b>Java 8 Language</b>, then observe events with {@link DefaultLifecycleObserver}.
+ * To include it you should add {@code "android.arch.lifecycle:common-java8:<version>"} to your
+ * build.gradle file.
+ * <pre>
+ * class TestObserver implements DefaultLifecycleObserver {
+ *     {@literal @}Override
+ *     public void onCreate(LifecycleOwner owner) {
+ *         // your code
+ *     }
+ * }
+ * </pre>
+ * If you use <b>Java 7 Language</b>, Lifecycle events are observed using annotations.
+ * Once Java 8 Language becomes mainstream on Android, annotations will be deprecated, so between
+ * {@link DefaultLifecycleObserver} and annotations,
+ * you must always prefer {@code DefaultLifecycleObserver}.
  * <pre>
  * class TestObserver implements LifecycleObserver {
  *   {@literal @}OnLifecycleEvent(ON_STOP)
@@ -42,16 +56,6 @@
  * }
  * </pre>
  * <p>
- * Multiple methods can observe the same event.
- * <pre>
- * class TestObserver implements LifecycleObserver {
- *   {@literal @}OnLifecycleEvent(ON_STOP)
- *   void onStoppedFirst() {}
- *   {@literal @}OnLifecycleEvent(ON_STOP)
- *   void onStoppedSecond() {}
- * }
- * </pre>
- * <p>
  * Observer methods can receive zero or one argument.
  * If used, the first argument must be of type {@link LifecycleOwner}.
  * Methods annotated with {@link Event#ON_ANY} can receive the second argument, which must be
diff --git a/android/arch/lifecycle/Lifecycling.java b/android/arch/lifecycle/Lifecycling.java
index 3a5c0b9..7d6b37f 100644
--- a/android/arch/lifecycle/Lifecycling.java
+++ b/android/arch/lifecycle/Lifecycling.java
@@ -22,52 +22,61 @@
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
  * Internal class to handle lifecycle conversion etc.
+ *
  * @hide
  */
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-class Lifecycling {
-    private static Constructor<? extends GenericLifecycleObserver> sREFLECTIVE;
+public class Lifecycling {
 
-    static {
-        try {
-            sREFLECTIVE = ReflectiveGenericLifecycleObserver.class
-                    .getDeclaredConstructor(Object.class);
-        } catch (NoSuchMethodException ignored) {
+    private static final int REFLECTIVE_CALLBACK = 1;
+    private static final int GENERATED_CALLBACK = 2;
 
-        }
-    }
-
-    private static Map<Class, Constructor<? extends GenericLifecycleObserver>> sCallbackCache =
+    private static Map<Class, Integer> sCallbackCache = new HashMap<>();
+    private static Map<Class, List<Constructor<? extends GeneratedAdapter>>> sClassToAdapters =
             new HashMap<>();
 
     @NonNull
     static GenericLifecycleObserver getCallback(Object object) {
+        if (object instanceof FullLifecycleObserver) {
+            return new FullLifecycleObserverAdapter((FullLifecycleObserver) object);
+        }
+
         if (object instanceof GenericLifecycleObserver) {
             return (GenericLifecycleObserver) object;
         }
+
+        final Class<?> klass = object.getClass();
+        int type = getObserverConstructorType(klass);
+        if (type == GENERATED_CALLBACK) {
+            List<Constructor<? extends GeneratedAdapter>> constructors =
+                    sClassToAdapters.get(klass);
+            if (constructors.size() == 1) {
+                GeneratedAdapter generatedAdapter = createGeneratedAdapter(
+                        constructors.get(0), object);
+                return new SingleGeneratedAdapterObserver(generatedAdapter);
+            }
+            GeneratedAdapter[] adapters = new GeneratedAdapter[constructors.size()];
+            for (int i = 0; i < constructors.size(); i++) {
+                adapters[i] = createGeneratedAdapter(constructors.get(i), object);
+            }
+            return new CompositeGeneratedAdaptersObserver(adapters);
+        }
+        return new ReflectiveGenericLifecycleObserver(object);
+    }
+
+    private static GeneratedAdapter createGeneratedAdapter(
+            Constructor<? extends GeneratedAdapter> constructor, Object object) {
         //noinspection TryWithIdenticalCatches
         try {
-            final Class<?> klass = object.getClass();
-            Constructor<? extends GenericLifecycleObserver> cachedConstructor = sCallbackCache.get(
-                    klass);
-            if (cachedConstructor != null) {
-                return cachedConstructor.newInstance(object);
-            }
-            cachedConstructor = getGeneratedAdapterConstructor(klass);
-            if (cachedConstructor != null) {
-                if (!cachedConstructor.isAccessible()) {
-                    cachedConstructor.setAccessible(true);
-                }
-            } else {
-                cachedConstructor = sREFLECTIVE;
-            }
-            sCallbackCache.put(klass, cachedConstructor);
-            return cachedConstructor.newInstance(object);
+            return constructor.newInstance(object);
         } catch (IllegalAccessException e) {
             throw new RuntimeException(e);
         } catch (InstantiationException e) {
@@ -78,37 +87,95 @@
     }
 
     @Nullable
-    private static Constructor<? extends GenericLifecycleObserver> getGeneratedAdapterConstructor(
-            Class<?> klass) {
-        Package aPackage = klass.getPackage();
-        final String fullPackage = aPackage != null ? aPackage.getName() : "";
-
-        String name = klass.getCanonicalName();
-        // anonymous class bug:35073837
-        if (name == null) {
-            return null;
-        }
-        final String adapterName = getAdapterName(fullPackage.isEmpty() ? name :
-                name.substring(fullPackage.length() + 1));
+    private static Constructor<? extends GeneratedAdapter> generatedConstructor(Class<?> klass) {
         try {
-            @SuppressWarnings("unchecked")
-            final Class<? extends GenericLifecycleObserver> aClass =
-                    (Class<? extends GenericLifecycleObserver>) Class.forName(
+            Package aPackage = klass.getPackage();
+            String name = klass.getCanonicalName();
+            final String fullPackage = aPackage != null ? aPackage.getName() : "";
+            final String adapterName = getAdapterName(fullPackage.isEmpty() ? name :
+                    name.substring(fullPackage.length() + 1));
+
+            @SuppressWarnings("unchecked") final Class<? extends GeneratedAdapter> aClass =
+                    (Class<? extends GeneratedAdapter>) Class.forName(
                             fullPackage.isEmpty() ? adapterName : fullPackage + "." + adapterName);
-            return aClass.getDeclaredConstructor(klass);
-        } catch (ClassNotFoundException e) {
-            final Class<?> superclass = klass.getSuperclass();
-            if (superclass != null) {
-                return getGeneratedAdapterConstructor(superclass);
+            Constructor<? extends GeneratedAdapter> constructor =
+                    aClass.getDeclaredConstructor(klass);
+            if (!constructor.isAccessible()) {
+                constructor.setAccessible(true);
             }
+            return constructor;
+        } catch (ClassNotFoundException e) {
+            return null;
         } catch (NoSuchMethodException e) {
             // this should not happen
             throw new RuntimeException(e);
         }
-        return null;
     }
 
-    static String getAdapterName(String className) {
+    private static int getObserverConstructorType(Class<?> klass) {
+        if (sCallbackCache.containsKey(klass)) {
+            return sCallbackCache.get(klass);
+        }
+        int type = resolveObserverCallbackType(klass);
+        sCallbackCache.put(klass, type);
+        return type;
+    }
+
+    private static int resolveObserverCallbackType(Class<?> klass) {
+        // anonymous class bug:35073837
+        if (klass.getCanonicalName() == null) {
+            return REFLECTIVE_CALLBACK;
+        }
+
+        Constructor<? extends GeneratedAdapter> constructor = generatedConstructor(klass);
+        if (constructor != null) {
+            sClassToAdapters.put(klass, Collections
+                    .<Constructor<? extends GeneratedAdapter>>singletonList(constructor));
+            return GENERATED_CALLBACK;
+        }
+
+        boolean hasLifecycleMethods = ClassesInfoCache.sInstance.hasLifecycleMethods(klass);
+        if (hasLifecycleMethods) {
+            return REFLECTIVE_CALLBACK;
+        }
+
+        Class<?> superclass = klass.getSuperclass();
+        List<Constructor<? extends GeneratedAdapter>> adapterConstructors = null;
+        if (isLifecycleParent(superclass)) {
+            if (getObserverConstructorType(superclass) == REFLECTIVE_CALLBACK) {
+                return REFLECTIVE_CALLBACK;
+            }
+            adapterConstructors = new ArrayList<>(sClassToAdapters.get(superclass));
+        }
+
+        for (Class<?> intrface : klass.getInterfaces()) {
+            if (!isLifecycleParent(intrface)) {
+                continue;
+            }
+            if (getObserverConstructorType(intrface) == REFLECTIVE_CALLBACK) {
+                return REFLECTIVE_CALLBACK;
+            }
+            if (adapterConstructors == null) {
+                adapterConstructors = new ArrayList<>();
+            }
+            adapterConstructors.addAll(sClassToAdapters.get(intrface));
+        }
+        if (adapterConstructors != null) {
+            sClassToAdapters.put(klass, adapterConstructors);
+            return GENERATED_CALLBACK;
+        }
+
+        return REFLECTIVE_CALLBACK;
+    }
+
+    private static boolean isLifecycleParent(Class<?> klass) {
+        return klass != null && LifecycleObserver.class.isAssignableFrom(klass);
+    }
+
+    /**
+     * Create a name for an adapter class.
+     */
+    public static String getAdapterName(String className) {
         return className.replace(".", "_") + "_LifecycleAdapter";
     }
 }
diff --git a/android/arch/lifecycle/LifecyclingTest.java b/android/arch/lifecycle/LifecyclingTest.java
new file mode 100644
index 0000000..70ce84c
--- /dev/null
+++ b/android/arch/lifecycle/LifecyclingTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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 android.arch.lifecycle;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import android.arch.lifecycle.observers.DerivedSequence1;
+import android.arch.lifecycle.observers.DerivedSequence2;
+import android.arch.lifecycle.observers.DerivedWithNewMethods;
+import android.arch.lifecycle.observers.DerivedWithNoNewMethods;
+import android.arch.lifecycle.observers.DerivedWithOverridenMethodsWithLfAnnotation;
+import android.arch.lifecycle.observers.InterfaceImpl1;
+import android.arch.lifecycle.observers.InterfaceImpl2;
+import android.arch.lifecycle.observers.InterfaceImpl3;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class LifecyclingTest {
+
+    @Test
+    public void testDerivedWithNewLfMethodsNoGeneratedAdapter() {
+        GenericLifecycleObserver callback = Lifecycling.getCallback(new DerivedWithNewMethods());
+        assertThat(callback, instanceOf(ReflectiveGenericLifecycleObserver.class));
+    }
+
+    @Test
+    public void testDerivedWithNoNewLfMethodsNoGeneratedAdapter() {
+        GenericLifecycleObserver callback = Lifecycling.getCallback(new DerivedWithNoNewMethods());
+        assertThat(callback, instanceOf(SingleGeneratedAdapterObserver.class));
+    }
+
+    @Test
+    public void testDerivedWithOverridenMethodsNoGeneratedAdapter() {
+        GenericLifecycleObserver callback = Lifecycling.getCallback(
+                new DerivedWithOverridenMethodsWithLfAnnotation());
+        // that is not effective but...
+        assertThat(callback, instanceOf(ReflectiveGenericLifecycleObserver.class));
+    }
+
+    @Test
+    public void testInterfaceImpl1NoGeneratedAdapter() {
+        GenericLifecycleObserver callback = Lifecycling.getCallback(new InterfaceImpl1());
+        assertThat(callback, instanceOf(SingleGeneratedAdapterObserver.class));
+    }
+
+    @Test
+    public void testInterfaceImpl2NoGeneratedAdapter() {
+        GenericLifecycleObserver callback = Lifecycling.getCallback(new InterfaceImpl2());
+        assertThat(callback, instanceOf(CompositeGeneratedAdaptersObserver.class));
+    }
+
+    @Test
+    public void testInterfaceImpl3NoGeneratedAdapter() {
+        GenericLifecycleObserver callback = Lifecycling.getCallback(new InterfaceImpl3());
+        assertThat(callback, instanceOf(CompositeGeneratedAdaptersObserver.class));
+    }
+
+    @Test
+    public void testDerivedSequence() {
+        GenericLifecycleObserver callback2 = Lifecycling.getCallback(new DerivedSequence2());
+        assertThat(callback2, instanceOf(ReflectiveGenericLifecycleObserver.class));
+        GenericLifecycleObserver callback1 = Lifecycling.getCallback(new DerivedSequence1());
+        assertThat(callback1, instanceOf(SingleGeneratedAdapterObserver.class));
+    }
+}
diff --git a/android/arch/lifecycle/LiveData.java b/android/arch/lifecycle/LiveData.java
index 99d859c..3aea6ac 100644
--- a/android/arch/lifecycle/LiveData.java
+++ b/android/arch/lifecycle/LiveData.java
@@ -1,411 +1,4 @@
-/*
- * 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.
- */
-
+//LiveData interface for tests
 package android.arch.lifecycle;
-
-import static android.arch.lifecycle.Lifecycle.State.DESTROYED;
-import static android.arch.lifecycle.Lifecycle.State.STARTED;
-
-import android.arch.core.executor.AppToolkitTaskExecutor;
-import android.arch.core.internal.SafeIterableMap;
-import android.arch.lifecycle.Lifecycle.State;
-import android.support.annotation.MainThread;
-import android.support.annotation.Nullable;
-
-import java.util.Iterator;
-import java.util.Map;
-
-/**
- * LiveData is a data holder class that can be observed within a given lifecycle.
- * This means that an {@link Observer} can be added in a pair with a {@link LifecycleOwner}, and
- * this observer will be notified about modifications of the wrapped data only if the paired
- * LifecycleOwner is in active state. LifecycleOwner is considered as active, if its state is
- * {@link Lifecycle.State#STARTED} or {@link Lifecycle.State#RESUMED}. An observer added via
- * {@link #observeForever(Observer)} is considered as always active and thus will be always notified
- * about modifications. For those observers, you should manually call
- * {@link #removeObserver(Observer)}.
- *
- * <p> An observer added with a Lifecycle will be automatically removed if the corresponding
- * Lifecycle moves to {@link Lifecycle.State#DESTROYED} state. This is especially useful for
- * activities and fragments where they can safely observe LiveData and not worry about leaks:
- * they will be instantly unsubscribed when they are destroyed.
- *
- * <p>
- * In addition, LiveData has {@link LiveData#onActive()} and {@link LiveData#onInactive()} methods
- * to get notified when number of active {@link Observer}s change between 0 and 1.
- * This allows LiveData to release any heavy resources when it does not have any Observers that
- * are actively observing.
- * <p>
- * This class is designed to hold individual data fields of {@link ViewModel},
- * but can also be used for sharing data between different modules in your application
- * in a decoupled fashion.
- *
- * @param <T> The type of data hold by this instance
- * @see ViewModel
- */
-@SuppressWarnings({"WeakerAccess", "unused"})
-// TODO: Thread checks are too strict right now, we may consider automatically moving them to main
-// thread.
-public abstract class LiveData<T> {
-    private final Object mDataLock = new Object();
-    static final int START_VERSION = -1;
-    private static final Object NOT_SET = new Object();
-
-    private static final LifecycleOwner ALWAYS_ON = new LifecycleOwner() {
-
-        private LifecycleRegistry mRegistry = init();
-
-        private LifecycleRegistry init() {
-            LifecycleRegistry registry = new LifecycleRegistry(this);
-            registry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
-            registry.handleLifecycleEvent(Lifecycle.Event.ON_START);
-            registry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
-            return registry;
-        }
-
-        @Override
-        public Lifecycle getLifecycle() {
-            return mRegistry;
-        }
-    };
-
-    private SafeIterableMap<Observer<T>, LifecycleBoundObserver> mObservers =
-            new SafeIterableMap<>();
-
-    // how many observers are in active state
-    private int mActiveCount = 0;
-    private volatile Object mData = NOT_SET;
-    // when setData is called, we set the pending data and actual data swap happens on the main
-    // thread
-    private volatile Object mPendingData = NOT_SET;
-    private int mVersion = START_VERSION;
-
-    private boolean mDispatchingValue;
-    @SuppressWarnings("FieldCanBeLocal")
-    private boolean mDispatchInvalidated;
-    private final Runnable mPostValueRunnable = new Runnable() {
-        @Override
-        public void run() {
-            Object newValue;
-            synchronized (mDataLock) {
-                newValue = mPendingData;
-                mPendingData = NOT_SET;
-            }
-            //noinspection unchecked
-            setValue((T) newValue);
-        }
-    };
-
-    private void considerNotify(LifecycleBoundObserver observer) {
-        if (!observer.active) {
-            return;
-        }
-        // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
-        //
-        // we still first check observer.active to keep it as the entrance for events. So even if
-        // the observer moved to an active state, if we've not received that event, we better not
-        // notify for a more predictable notification order.
-        if (!isActiveState(observer.owner.getLifecycle().getCurrentState())) {
-            return;
-        }
-        if (observer.lastVersion >= mVersion) {
-            return;
-        }
-        observer.lastVersion = mVersion;
-        //noinspection unchecked
-        observer.observer.onChanged((T) mData);
-    }
-
-    private void dispatchingValue(@Nullable LifecycleBoundObserver initiator) {
-        if (mDispatchingValue) {
-            mDispatchInvalidated = true;
-            return;
-        }
-        mDispatchingValue = true;
-        do {
-            mDispatchInvalidated = false;
-            if (initiator != null) {
-                considerNotify(initiator);
-                initiator = null;
-            } else {
-                for (Iterator<Map.Entry<Observer<T>, LifecycleBoundObserver>> iterator =
-                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
-                    considerNotify(iterator.next().getValue());
-                    if (mDispatchInvalidated) {
-                        break;
-                    }
-                }
-            }
-        } while (mDispatchInvalidated);
-        mDispatchingValue = false;
-    }
-
-    /**
-     * Adds the given observer to the observers list within the lifespan of the given
-     * owner. The events are dispatched on the main thread. If LiveData already has data
-     * set, it will be delivered to the observer.
-     * <p>
-     * The observer will only receive events if the owner is in {@link Lifecycle.State#STARTED}
-     * or {@link Lifecycle.State#RESUMED} state (active).
-     * <p>
-     * If the owner moves to the {@link Lifecycle.State#DESTROYED} state, the observer will
-     * automatically be removed.
-     * <p>
-     * When data changes while the {@code owner} is not active, it will not receive any updates.
-     * If it becomes active again, it will receive the last available data automatically.
-     * <p>
-     * LiveData keeps a strong reference to the observer and the owner as long as the
-     * given LifecycleOwner is not destroyed. When it is destroyed, LiveData removes references to
-     * the observer &amp; the owner.
-     * <p>
-     * If the given owner is already in {@link Lifecycle.State#DESTROYED} state, LiveData
-     * ignores the call.
-     * <p>
-     * If the given owner, observer tuple is already in the list, the call is ignored.
-     * If the observer is already in the list with another owner, LiveData throws an
-     * {@link IllegalArgumentException}.
-     *
-     * @param owner    The LifecycleOwner which controls the observer
-     * @param observer The observer that will receive the events
-     */
-    @MainThread
-    public void observe(LifecycleOwner owner, Observer<T> observer) {
-        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
-            // ignore
-            return;
-        }
-        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
-        LifecycleBoundObserver existing = mObservers.putIfAbsent(observer, wrapper);
-        if (existing != null && existing.owner != wrapper.owner) {
-            throw new IllegalArgumentException("Cannot add the same observer"
-                    + " with different lifecycles");
-        }
-        if (existing != null) {
-            return;
-        }
-        owner.getLifecycle().addObserver(wrapper);
-        wrapper.activeStateChanged(isActiveState(owner.getLifecycle().getCurrentState()));
-    }
-
-    /**
-     * Adds the given observer to the observers list. This call is similar to
-     * {@link LiveData#observe(LifecycleOwner, Observer)} with a LifecycleOwner, which
-     * is always active. This means that the given observer will receive all events and will never
-     * be automatically removed. You should manually call {@link #removeObserver(Observer)} to stop
-     * observing this LiveData.
-     * While LiveData has one of such observers, it will be considered
-     * as active.
-     * <p>
-     * If the observer was already added with an owner to this LiveData, LiveData throws an
-     * {@link IllegalArgumentException}.
-     *
-     * @param observer The observer that will receive the events
-     */
-    @MainThread
-    public void observeForever(Observer<T> observer) {
-        observe(ALWAYS_ON, observer);
-    }
-
-    /**
-     * Removes the given observer from the observers list.
-     *
-     * @param observer The Observer to receive events.
-     */
-    @MainThread
-    public void removeObserver(final Observer<T> observer) {
-        assertMainThread("removeObserver");
-        LifecycleBoundObserver removed = mObservers.remove(observer);
-        if (removed == null) {
-            return;
-        }
-        removed.owner.getLifecycle().removeObserver(removed);
-        removed.activeStateChanged(false);
-    }
-
-    /**
-     * Removes all observers that are tied to the given {@link LifecycleOwner}.
-     *
-     * @param owner The {@code LifecycleOwner} scope for the observers to be removed.
-     */
-    @MainThread
-    public void removeObservers(final LifecycleOwner owner) {
-        assertMainThread("removeObservers");
-        for (Map.Entry<Observer<T>, LifecycleBoundObserver> entry : mObservers) {
-            if (entry.getValue().owner == owner) {
-                removeObserver(entry.getKey());
-            }
-        }
-    }
-
-    /**
-     * Posts a task to a main thread to set the given value. So if you have a following code
-     * executed in the main thread:
-     * <pre class="prettyprint">
-     * liveData.postValue("a");
-     * liveData.setValue("b");
-     * </pre>
-     * The value "b" would be set at first and later the main thread would override it with
-     * the value "a".
-     * <p>
-     * If you called this method multiple times before a main thread executed a posted task, only
-     * the last value would be dispatched.
-     *
-     * @param value The new value
-     */
-    protected void postValue(T value) {
-        boolean postTask;
-        synchronized (mDataLock) {
-            postTask = mPendingData == NOT_SET;
-            mPendingData = value;
-        }
-        if (!postTask) {
-            return;
-        }
-        AppToolkitTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
-    }
-
-    /**
-     * Sets the value. If there are active observers, the value will be dispatched to them.
-     * <p>
-     * This method must be called from the main thread. If you need set a value from a background
-     * thread, you can use {@link #postValue(Object)}
-     *
-     * @param value The new value
-     */
-    @MainThread
-    protected void setValue(T value) {
-        assertMainThread("setValue");
-        mVersion++;
-        mData = value;
-        dispatchingValue(null);
-    }
-
-    /**
-     * Returns the current value.
-     * Note that calling this method on a background thread does not guarantee that the latest
-     * value set will be received.
-     *
-     * @return the current value
-     */
-    @Nullable
-    public T getValue() {
-        Object data = mData;
-        if (data != NOT_SET) {
-            //noinspection unchecked
-            return (T) data;
-        }
-        return null;
-    }
-
-    int getVersion() {
-        return mVersion;
-    }
-
-    /**
-     * Called when the number of active observers change to 1 from 0.
-     * <p>
-     * This callback can be used to know that this LiveData is being used thus should be kept
-     * up to date.
-     */
-    protected void onActive() {
-
-    }
-
-    /**
-     * Called when the number of active observers change from 1 to 0.
-     * <p>
-     * This does not mean that there are no observers left, there may still be observers but their
-     * lifecycle states aren't {@link Lifecycle.State#STARTED} or {@link Lifecycle.State#RESUMED}
-     * (like an Activity in the back stack).
-     * <p>
-     * You can check if there are observers via {@link #hasObservers()}.
-     */
-    protected void onInactive() {
-
-    }
-
-    /**
-     * Returns true if this LiveData has observers.
-     *
-     * @return true if this LiveData has observers
-     */
-    public boolean hasObservers() {
-        return mObservers.size() > 0;
-    }
-
-    /**
-     * Returns true if this LiveData has active observers.
-     *
-     * @return true if this LiveData has active observers
-     */
-    public boolean hasActiveObservers() {
-        return mActiveCount > 0;
-    }
-
-    class LifecycleBoundObserver implements LifecycleObserver {
-        public final LifecycleOwner owner;
-        public final Observer<T> observer;
-        public boolean active;
-        public int lastVersion = START_VERSION;
-
-        LifecycleBoundObserver(LifecycleOwner owner, Observer<T> observer) {
-            this.owner = owner;
-            this.observer = observer;
-        }
-
-        @SuppressWarnings("unused")
-        @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
-        void onStateChange() {
-            if (owner.getLifecycle().getCurrentState() == DESTROYED) {
-                removeObserver(observer);
-                return;
-            }
-            // immediately set active state, so we'd never dispatch anything to inactive
-            // owner
-            activeStateChanged(isActiveState(owner.getLifecycle().getCurrentState()));
-
-        }
-
-        void activeStateChanged(boolean newActive) {
-            if (newActive == active) {
-                return;
-            }
-            active = newActive;
-            boolean wasInactive = LiveData.this.mActiveCount == 0;
-            LiveData.this.mActiveCount += active ? 1 : -1;
-            if (wasInactive && active) {
-                onActive();
-            }
-            if (LiveData.this.mActiveCount == 0 && !active) {
-                onInactive();
-            }
-            if (active) {
-                dispatchingValue(this);
-            }
-        }
-    }
-
-    static boolean isActiveState(State state) {
-        return state.isAtLeast(STARTED);
-    }
-
-    private void assertMainThread(String methodName) {
-        if (!AppToolkitTaskExecutor.getInstance().isMainThread()) {
-            throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
-                    + " thread");
-        }
-    }
+public class LiveData<T> {
 }
diff --git a/android/arch/lifecycle/LiveDataReactiveStreams.java b/android/arch/lifecycle/LiveDataReactiveStreams.java
index 0be0149..2b25bc9 100644
--- a/android/arch/lifecycle/LiveDataReactiveStreams.java
+++ b/android/arch/lifecycle/LiveDataReactiveStreams.java
@@ -16,7 +16,8 @@
 
 package android.arch.lifecycle;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
+import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 
 import org.reactivestreams.Publisher;
@@ -85,7 +86,7 @@
                         if (n < 0 || mCanceled) {
                             return;
                         }
-                        AppToolkitTaskExecutor.getInstance().executeOnMainThread(new Runnable() {
+                        ArchTaskExecutor.getInstance().executeOnMainThread(new Runnable() {
                             @Override
                             public void run() {
                                 if (mCanceled) {
@@ -110,7 +111,7 @@
                         if (mCanceled) {
                             return;
                         }
-                        AppToolkitTaskExecutor.getInstance().executeOnMainThread(new Runnable() {
+                        ArchTaskExecutor.getInstance().executeOnMainThread(new Runnable() {
                             @Override
                             public void run() {
                                 if (mCanceled) {
@@ -133,40 +134,101 @@
 
     /**
      * Creates an Observable {@link LiveData} stream from a ReactiveStreams publisher.
+     *
+     * <p>
+     * When the LiveData becomes active, it subscribes to the emissions from the Publisher.
+     *
+     * <p>
+     * When the LiveData becomes inactive, the subscription is cleared.
+     * LiveData holds the last value emitted by the Publisher when the LiveData was active.
+     * <p>
+     * Therefore, in the case of a hot RxJava Observable, when a new LiveData {@link Observer} is
+     * added, it will automatically notify with the last value held in LiveData,
+     * which might not be the last value emitted by the Publisher.
+     *
+     * @param <T> The type of data hold by this instance.
      */
     public static <T> LiveData<T> fromPublisher(final Publisher<T> publisher) {
-        MutableLiveData<T> liveData = new MutableLiveData<>();
-        // Since we don't have a way to directly observe cancels, weakly hold the live data.
-        final WeakReference<MutableLiveData<T>> liveDataRef = new WeakReference<>(liveData);
-
-        publisher.subscribe(new Subscriber<T>() {
-            @Override
-            public void onSubscribe(Subscription s) {
-                // Don't worry about backpressure. If the stream is too noisy then backpressure can
-                // be handled upstream.
-                s.request(Long.MAX_VALUE);
-            }
-
-            @Override
-            public void onNext(final T t) {
-                final LiveData<T> liveData = liveDataRef.get();
-                if (liveData != null) {
-                    liveData.postValue(t);
-                }
-            }
-
-            @Override
-            public void onError(Throwable t) {
-                // Errors should be handled upstream, so propagate as a crash.
-                throw new RuntimeException(t);
-            }
-
-            @Override
-            public void onComplete() {
-            }
-        });
-
-        return liveData;
+        return new PublisherLiveData<>(publisher);
     }
 
+    /**
+     * Defines a {@link LiveData} object that wraps a {@link Publisher}.
+     *
+     * <p>
+     * When the LiveData becomes active, it subscribes to the emissions from the Publisher.
+     *
+     * <p>
+     * When the LiveData becomes inactive, the subscription is cleared.
+     * LiveData holds the last value emitted by the Publisher when the LiveData was active.
+     * <p>
+     * Therefore, in the case of a hot RxJava Observable, when a new LiveData {@link Observer} is
+     * added, it will automatically notify with the last value held in LiveData,
+     * which might not be the last value emitted by the Publisher.
+     *
+     * @param <T> The type of data hold by this instance.
+     */
+    private static class PublisherLiveData<T> extends LiveData<T> {
+        private WeakReference<Subscription> mSubscriptionRef;
+        private final Publisher mPublisher;
+        private final Object mLock = new Object();
+
+        PublisherLiveData(@NonNull final Publisher publisher) {
+            mPublisher = publisher;
+        }
+
+        @Override
+        protected void onActive() {
+            super.onActive();
+
+            mPublisher.subscribe(new Subscriber<T>() {
+                @Override
+                public void onSubscribe(Subscription s) {
+                    // Don't worry about backpressure. If the stream is too noisy then
+                    // backpressure can be handled upstream.
+                    synchronized (mLock) {
+                        s.request(Long.MAX_VALUE);
+                        mSubscriptionRef = new WeakReference<>(s);
+                    }
+                }
+
+                @Override
+                public void onNext(final T t) {
+                    postValue(t);
+                }
+
+                @Override
+                public void onError(Throwable t) {
+                    synchronized (mLock) {
+                        mSubscriptionRef = null;
+                    }
+                    // Errors should be handled upstream, so propagate as a crash.
+                    throw new RuntimeException(t);
+                }
+
+                @Override
+                public void onComplete() {
+                    synchronized (mLock) {
+                        mSubscriptionRef = null;
+                    }
+                }
+            });
+
+        }
+
+        @Override
+        protected void onInactive() {
+            super.onInactive();
+            synchronized (mLock) {
+                WeakReference<Subscription> subscriptionRef = mSubscriptionRef;
+                if (subscriptionRef != null) {
+                    Subscription subscription = subscriptionRef.get();
+                    if (subscription != null) {
+                        subscription.cancel();
+                    }
+                    mSubscriptionRef = null;
+                }
+            }
+        }
+    }
 }
diff --git a/android/arch/lifecycle/LiveDataReactiveStreamsTest.java b/android/arch/lifecycle/LiveDataReactiveStreamsTest.java
index 87fba27..7278847 100644
--- a/android/arch/lifecycle/LiveDataReactiveStreamsTest.java
+++ b/android/arch/lifecycle/LiveDataReactiveStreamsTest.java
@@ -16,12 +16,10 @@
 
 package android.arch.lifecycle;
 
-import static android.arch.lifecycle.Lifecycle.State.RESUMED;
-
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.arch.core.executor.TaskExecutor;
 import android.support.annotation.Nullable;
 import android.support.test.filters.SmallTest;
@@ -47,28 +45,7 @@
 
 @SmallTest
 public class LiveDataReactiveStreamsTest {
-    private static final Lifecycle sLifecycle = new Lifecycle() {
-        @Override
-        public void addObserver(LifecycleObserver observer) {
-        }
-
-        @Override
-        public void removeObserver(LifecycleObserver observer) {
-        }
-
-        @Override
-        public State getCurrentState() {
-            return RESUMED;
-        }
-    };
-    private static final LifecycleOwner S_LIFECYCLE_OWNER = new LifecycleOwner() {
-
-        @Override
-        public Lifecycle getLifecycle() {
-            return sLifecycle;
-        }
-
-    };
+    private LifecycleOwner mLifecycleOwner;
 
     private final List<String> mLiveDataOutput = new ArrayList<>();
     private final Observer<String> mObserver = new Observer<String>() {
@@ -85,8 +62,19 @@
 
     @Before
     public void init() {
+        mLifecycleOwner = new LifecycleOwner() {
+            LifecycleRegistry mRegistry = new LifecycleRegistry(this);
+            {
+                mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
+            }
+
+            @Override
+            public Lifecycle getLifecycle() {
+                return mRegistry;
+            }
+        };
         mTestThread = Thread.currentThread();
-        AppToolkitTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
+        ArchTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
 
             @Override
             public void executeOnDiskIO(Runnable runnable) {
@@ -109,7 +97,7 @@
 
     @After
     public void removeExecutorDelegate() {
-        AppToolkitTaskExecutor.getInstance().setDelegate(null);
+        ArchTaskExecutor.getInstance().setDelegate(null);
     }
 
     @Test
@@ -117,7 +105,7 @@
         PublishProcessor<String> processor = PublishProcessor.create();
         LiveData<String> liveData = LiveDataReactiveStreams.fromPublisher(processor);
 
-        liveData.observe(S_LIFECYCLE_OWNER, mObserver);
+        liveData.observe(mLifecycleOwner, mObserver);
 
         processor.onNext("foo");
         processor.onNext("bar");
@@ -132,13 +120,13 @@
         PublishProcessor<String> processor = PublishProcessor.create();
         LiveData<String> liveData = LiveDataReactiveStreams.fromPublisher(processor);
 
-        liveData.observe(S_LIFECYCLE_OWNER, mObserver);
+        liveData.observe(mLifecycleOwner, mObserver);
 
         processor.onNext("foo");
         processor.onNext("bar");
 
         // The second mObserver should only get the newest value and any later values.
-        liveData.observe(S_LIFECYCLE_OWNER, new Observer<String>() {
+        liveData.observe(mLifecycleOwner, new Observer<String>() {
             @Override
             public void onChanged(@Nullable String s) {
                 output2.add(s);
@@ -152,12 +140,44 @@
     }
 
     @Test
+    public void convertsFromPublisherAfterInactive() {
+        PublishProcessor<String> processor = PublishProcessor.create();
+        LiveData<String> liveData = LiveDataReactiveStreams.fromPublisher(processor);
+
+        liveData.observe(mLifecycleOwner, mObserver);
+        processor.onNext("foo");
+        liveData.removeObserver(mObserver);
+        processor.onNext("bar");
+
+        liveData.observe(mLifecycleOwner, mObserver);
+        processor.onNext("baz");
+
+        assertThat(mLiveDataOutput, is(Arrays.asList("foo", "foo", "baz")));
+    }
+
+    @Test
+    public void convertsFromPublisherManagesSubcriptions() {
+        PublishProcessor<String> processor = PublishProcessor.create();
+        LiveData<String> liveData = LiveDataReactiveStreams.fromPublisher(processor);
+
+        assertThat(processor.hasSubscribers(), is(false));
+        liveData.observe(mLifecycleOwner, mObserver);
+
+        // once the live data is active, there's a subscriber
+        assertThat(processor.hasSubscribers(), is(true));
+
+        liveData.removeObserver(mObserver);
+        // once the live data is inactive, the subscriber is removed
+        assertThat(processor.hasSubscribers(), is(false));
+    }
+
+    @Test
     public void convertsFromAsyncPublisher() {
         Flowable<String> input = Flowable.just("foo")
                 .concatWith(Flowable.just("bar", "baz").observeOn(sBackgroundScheduler));
         LiveData<String> liveData = LiveDataReactiveStreams.fromPublisher(input);
 
-        liveData.observe(S_LIFECYCLE_OWNER, mObserver);
+        liveData.observe(mLifecycleOwner, mObserver);
 
         assertThat(mLiveDataOutput, is(Collections.singletonList("foo")));
         sBackgroundScheduler.triggerActions();
@@ -170,7 +190,7 @@
         liveData.setValue("foo");
         assertThat(liveData.getValue(), is("foo"));
 
-        Flowable.fromPublisher(LiveDataReactiveStreams.toPublisher(S_LIFECYCLE_OWNER, liveData))
+        Flowable.fromPublisher(LiveDataReactiveStreams.toPublisher(mLifecycleOwner, liveData))
                 .subscribe(mOutputProcessor);
 
         liveData.setValue("bar");
@@ -188,7 +208,7 @@
         assertThat(liveData.getValue(), is("foo"));
 
         Disposable disposable = Flowable
-                .fromPublisher(LiveDataReactiveStreams.toPublisher(S_LIFECYCLE_OWNER, liveData))
+                .fromPublisher(LiveDataReactiveStreams.toPublisher(mLifecycleOwner, liveData))
                 .subscribe(new Consumer<String>() {
                     @Override
                     public void accept(String s) throws Exception {
@@ -216,7 +236,7 @@
 
         final AsyncSubject<Subscription> subscriptionSubject = AsyncSubject.create();
 
-        Flowable.fromPublisher(LiveDataReactiveStreams.toPublisher(S_LIFECYCLE_OWNER, liveData))
+        Flowable.fromPublisher(LiveDataReactiveStreams.toPublisher(mLifecycleOwner, liveData))
                 .subscribe(new Subscriber<String>() {
                     @Override
                     public void onSubscribe(Subscription s) {
@@ -275,7 +295,7 @@
     public void convertsToPublisherWithAsyncData() {
         MutableLiveData<String> liveData = new MutableLiveData<>();
 
-        Flowable.fromPublisher(LiveDataReactiveStreams.toPublisher(S_LIFECYCLE_OWNER, liveData))
+        Flowable.fromPublisher(LiveDataReactiveStreams.toPublisher(mLifecycleOwner, liveData))
                 .observeOn(sBackgroundScheduler)
                 .subscribe(mOutputProcessor);
 
diff --git a/android/arch/lifecycle/LiveDataTest.java b/android/arch/lifecycle/LiveDataTest.java
index ed2a35d..9f0b425 100644
--- a/android/arch/lifecycle/LiveDataTest.java
+++ b/android/arch/lifecycle/LiveDataTest.java
@@ -36,16 +36,20 @@
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.arch.lifecycle.util.InstantTaskExecutor;
 import android.support.annotation.Nullable;
 
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.InOrder;
 import org.mockito.Mockito;
 
 @SuppressWarnings({"unchecked"})
+@RunWith(JUnit4.class)
 public class LiveDataTest {
     private PublicLiveData<String> mLiveData;
     private LifecycleOwner mOwner;
@@ -66,12 +70,12 @@
 
     @Before
     public void swapExecutorDelegate() {
-        AppToolkitTaskExecutor.getInstance().setDelegate(new InstantTaskExecutor());
+        ArchTaskExecutor.getInstance().setDelegate(new InstantTaskExecutor());
     }
 
     @After
     public void removeExecutorDelegate() {
-        AppToolkitTaskExecutor.getInstance().setDelegate(null);
+        ArchTaskExecutor.getInstance().setDelegate(null);
     }
 
     @Test
@@ -418,6 +422,40 @@
         verify(mActiveObserversChanged, never()).onCall(anyBoolean());
     }
 
+    @Test
+    public void testRemoveDuringAddition() {
+        mRegistry.handleLifecycleEvent(ON_START);
+        mLiveData.setValue("bla");
+        mLiveData.observeForever(new Observer<String>() {
+            @Override
+            public void onChanged(@Nullable String s) {
+                mLiveData.removeObserver(this);
+            }
+        });
+        assertThat(mLiveData.hasActiveObservers(), is(false));
+        InOrder inOrder = Mockito.inOrder(mActiveObserversChanged);
+        inOrder.verify(mActiveObserversChanged).onCall(true);
+        inOrder.verify(mActiveObserversChanged).onCall(false);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testRemoveDuringBringingUpToState() {
+        mLiveData.setValue("bla");
+        mLiveData.observeForever(new Observer<String>() {
+            @Override
+            public void onChanged(@Nullable String s) {
+                mLiveData.removeObserver(this);
+            }
+        });
+        mRegistry.handleLifecycleEvent(ON_RESUME);
+        assertThat(mLiveData.hasActiveObservers(), is(false));
+        InOrder inOrder = Mockito.inOrder(mActiveObserversChanged);
+        inOrder.verify(mActiveObserversChanged).onCall(true);
+        inOrder.verify(mActiveObserversChanged).onCall(false);
+        inOrder.verifyNoMoreInteractions();
+    }
+
     @SuppressWarnings("WeakerAccess")
     static class PublicLiveData<T> extends LiveData<T> {
         // cannot spy due to internal calls
diff --git a/android/arch/lifecycle/MediatorLiveDataTest.java b/android/arch/lifecycle/MediatorLiveDataTest.java
index 3de3eee..e2eadbe 100644
--- a/android/arch/lifecycle/MediatorLiveDataTest.java
+++ b/android/arch/lifecycle/MediatorLiveDataTest.java
@@ -25,7 +25,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.arch.lifecycle.util.InstantTaskExecutor;
 import android.support.annotation.Nullable;
 
@@ -69,7 +69,7 @@
 
     @Before
     public void swapExecutorDelegate() {
-        AppToolkitTaskExecutor.getInstance().setDelegate(new InstantTaskExecutor());
+        ArchTaskExecutor.getInstance().setDelegate(new InstantTaskExecutor());
     }
 
     @Test
diff --git a/android/arch/lifecycle/MethodCallsLogger.java b/android/arch/lifecycle/MethodCallsLogger.java
new file mode 100644
index 0000000..031e43e
--- /dev/null
+++ b/android/arch/lifecycle/MethodCallsLogger.java
@@ -0,0 +1,42 @@
+/*
+ * 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 android.arch.lifecycle;
+
+import android.support.annotation.RestrictTo;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+public class MethodCallsLogger {
+    private Map<String, Integer> mCalledMethods = new HashMap<>();
+
+    /**
+     * @hide
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public boolean approveCall(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/android/arch/lifecycle/ProcessOwnerTest.java b/android/arch/lifecycle/ProcessOwnerTest.java
index e80e11c..37bdcdb 100644
--- a/android/arch/lifecycle/ProcessOwnerTest.java
+++ b/android/arch/lifecycle/ProcessOwnerTest.java
@@ -37,6 +37,7 @@
 import android.support.test.filters.SmallTest;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
+import android.support.v4.app.FragmentActivity;
 
 import org.junit.After;
 import org.junit.Rule;
@@ -78,7 +79,7 @@
 
     @Test
     public void testNavigation() throws Throwable {
-        LifecycleActivity firstActivity = setupObserverOnResume();
+        FragmentActivity firstActivity = setupObserverOnResume();
         Instrumentation.ActivityMonitor monitor = new Instrumentation.ActivityMonitor(
                 NavigationTestActivitySecond.class.getCanonicalName(), null, false);
         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
@@ -88,15 +89,15 @@
         firstActivity.finish();
         firstActivity.startActivity(intent);
 
-        LifecycleActivity secondActivity = (LifecycleActivity) monitor.waitForActivity();
+        FragmentActivity secondActivity = (FragmentActivity) monitor.waitForActivity();
         assertThat("Failed to navigate", secondActivity, notNullValue());
         checkProcessObserverSilent(secondActivity);
     }
 
     @Test
     public void testRecreation() throws Throwable {
-        LifecycleActivity activity = setupObserverOnResume();
-        LifecycleActivity recreated = TestUtils.recreateActivity(activity, activityTestRule);
+        FragmentActivity activity = setupObserverOnResume();
+        FragmentActivity recreated = TestUtils.recreateActivity(activity, activityTestRule);
         assertThat("Failed to recreate", recreated, notNullValue());
         checkProcessObserverSilent(recreated);
     }
@@ -112,14 +113,15 @@
 
         NavigationTestActivityFirst activity = activityTestRule.getActivity();
         activity.startActivity(new Intent(activity, NavigationDialogActivity.class));
-        LifecycleActivity dialogActivity = (LifecycleActivity) monitor.waitForActivity();
+        FragmentActivity dialogActivity = (FragmentActivity) monitor.waitForActivity();
         checkProcessObserverSilent(dialogActivity);
 
         List<Event> events = Collections.synchronizedList(new ArrayList<>());
 
         LifecycleObserver collectingObserver = new LifecycleObserver() {
             @OnLifecycleEvent(Event.ON_ANY)
-            public void onStateChanged(LifecycleOwner provider, Event event) {
+            public void onStateChanged(@SuppressWarnings("unused") LifecycleOwner provider,
+                    Event event) {
                 events.add(event);
             }
         };
@@ -138,8 +140,8 @@
         dialogActivity.finish();
     }
 
-    private LifecycleActivity setupObserverOnResume() throws Throwable {
-        LifecycleActivity firstActivity = activityTestRule.getActivity();
+    private FragmentActivity setupObserverOnResume() throws Throwable {
+        FragmentActivity firstActivity = activityTestRule.getActivity();
         waitTillResumed(firstActivity, activityTestRule);
         addProcessObserver(mObserver);
         mObserver.mChangedState = false;
@@ -156,7 +158,7 @@
                 ProcessLifecycleOwner.get().getLifecycle().removeObserver(observer));
     }
 
-    private void checkProcessObserverSilent(LifecycleActivity activity) throws Throwable {
+    private void checkProcessObserverSilent(FragmentActivity activity) throws Throwable {
         waitTillResumed(activity, activityTestRule);
         assertThat(mObserver.mChangedState, is(false));
         activityTestRule.runOnUiThread(() ->
diff --git a/android/arch/lifecycle/ReflectiveGenericLifecycleObserver.java b/android/arch/lifecycle/ReflectiveGenericLifecycleObserver.java
index 44815e6..f010ed8 100644
--- a/android/arch/lifecycle/ReflectiveGenericLifecycleObserver.java
+++ b/android/arch/lifecycle/ReflectiveGenericLifecycleObserver.java
@@ -16,204 +16,23 @@
 
 package android.arch.lifecycle;
 
+import android.arch.lifecycle.ClassesInfoCache.CallbackInfo;
 import android.arch.lifecycle.Lifecycle.Event;
 
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
 /**
  * An internal implementation of {@link GenericLifecycleObserver} that relies on reflection.
  */
 class ReflectiveGenericLifecycleObserver implements GenericLifecycleObserver {
     private final Object mWrapped;
     private final CallbackInfo mInfo;
-    @SuppressWarnings("WeakerAccess")
-    static final Map<Class, CallbackInfo> sInfoCache = new HashMap<>();
 
     ReflectiveGenericLifecycleObserver(Object wrapped) {
         mWrapped = wrapped;
-        mInfo = getInfo(mWrapped.getClass());
+        mInfo = ClassesInfoCache.sInstance.getInfo(mWrapped.getClass());
     }
 
     @Override
     public void onStateChanged(LifecycleOwner source, Event event) {
-        invokeCallbacks(mInfo, source, event);
+        mInfo.invokeCallbacks(source, event, mWrapped);
     }
-
-    private void invokeMethodsForEvent(List<MethodReference> handlers, LifecycleOwner source,
-            Event event) {
-        if (handlers != null) {
-            for (int i = handlers.size() - 1; i >= 0; i--) {
-                MethodReference reference = handlers.get(i);
-                invokeCallback(reference, source, event);
-            }
-        }
-    }
-
-    @SuppressWarnings("ConstantConditions")
-    private void invokeCallbacks(CallbackInfo info, LifecycleOwner source, Event event) {
-        invokeMethodsForEvent(info.mEventToHandlers.get(event), source, event);
-        invokeMethodsForEvent(info.mEventToHandlers.get(Event.ON_ANY), source, event);
-    }
-
-    private void invokeCallback(MethodReference reference, LifecycleOwner source, Event event) {
-        //noinspection TryWithIdenticalCatches
-        try {
-            switch (reference.mCallType) {
-                case CALL_TYPE_NO_ARG:
-                    reference.mMethod.invoke(mWrapped);
-                    break;
-                case CALL_TYPE_PROVIDER:
-                    reference.mMethod.invoke(mWrapped, source);
-                    break;
-                case CALL_TYPE_PROVIDER_WITH_EVENT:
-                    reference.mMethod.invoke(mWrapped, source, event);
-                    break;
-            }
-        } catch (InvocationTargetException e) {
-            throw new RuntimeException("Failed to call observer method", e.getCause());
-        } catch (IllegalAccessException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    private static CallbackInfo getInfo(Class klass) {
-        CallbackInfo existing = sInfoCache.get(klass);
-        if (existing != null) {
-            return existing;
-        }
-        existing = createInfo(klass);
-        return existing;
-    }
-
-    private static void verifyAndPutHandler(Map<MethodReference, Event> handlers,
-            MethodReference newHandler, Event newEvent, Class klass) {
-        Event event = handlers.get(newHandler);
-        if (event != null && newEvent != event) {
-            Method method = newHandler.mMethod;
-            throw new IllegalArgumentException(
-                    "Method " + method.getName() + " in " + klass.getName()
-                            + " already declared with different @OnLifecycleEvent value: previous"
-                            + " value " + event + ", new value " + newEvent);
-        }
-        if (event == null) {
-            handlers.put(newHandler, newEvent);
-        }
-    }
-
-    private static CallbackInfo createInfo(Class klass) {
-        Class superclass = klass.getSuperclass();
-        Map<MethodReference, Event> handlerToEvent = new HashMap<>();
-        if (superclass != null) {
-            CallbackInfo superInfo = getInfo(superclass);
-            if (superInfo != null) {
-                handlerToEvent.putAll(superInfo.mHandlerToEvent);
-            }
-        }
-
-        Method[] methods = klass.getDeclaredMethods();
-
-        Class[] interfaces = klass.getInterfaces();
-        for (Class intrfc : interfaces) {
-            for (Entry<MethodReference, Event> entry : getInfo(intrfc).mHandlerToEvent.entrySet()) {
-                verifyAndPutHandler(handlerToEvent, entry.getKey(), entry.getValue(), klass);
-            }
-        }
-
-        for (Method method : methods) {
-            OnLifecycleEvent annotation = method.getAnnotation(OnLifecycleEvent.class);
-            if (annotation == null) {
-                continue;
-            }
-            Class<?>[] params = method.getParameterTypes();
-            int callType = CALL_TYPE_NO_ARG;
-            if (params.length > 0) {
-                callType = CALL_TYPE_PROVIDER;
-                if (!params[0].isAssignableFrom(LifecycleOwner.class)) {
-                    throw new IllegalArgumentException(
-                            "invalid parameter type. Must be one and instanceof LifecycleOwner");
-                }
-            }
-            Event event = annotation.value();
-
-            if (params.length > 1) {
-                callType = CALL_TYPE_PROVIDER_WITH_EVENT;
-                if (!params[1].isAssignableFrom(Event.class)) {
-                    throw new IllegalArgumentException(
-                            "invalid parameter type. second arg must be an event");
-                }
-                if (event != Event.ON_ANY) {
-                    throw new IllegalArgumentException(
-                            "Second arg is supported only for ON_ANY value");
-                }
-            }
-            if (params.length > 2) {
-                throw new IllegalArgumentException("cannot have more than 2 params");
-            }
-            MethodReference methodReference = new MethodReference(callType, method);
-            verifyAndPutHandler(handlerToEvent, methodReference, event, klass);
-        }
-        CallbackInfo info = new CallbackInfo(handlerToEvent);
-        sInfoCache.put(klass, info);
-        return info;
-    }
-
-    @SuppressWarnings("WeakerAccess")
-    static class CallbackInfo {
-        final Map<Event, List<MethodReference>> mEventToHandlers;
-        final Map<MethodReference, Event> mHandlerToEvent;
-
-        CallbackInfo(Map<MethodReference, Event> handlerToEvent) {
-            mHandlerToEvent = handlerToEvent;
-            mEventToHandlers = new HashMap<>();
-            for (Entry<MethodReference, Event> entry : handlerToEvent.entrySet()) {
-                Event event = entry.getValue();
-                List<MethodReference> methodReferences = mEventToHandlers.get(event);
-                if (methodReferences == null) {
-                    methodReferences = new ArrayList<>();
-                    mEventToHandlers.put(event, methodReferences);
-                }
-                methodReferences.add(entry.getKey());
-            }
-        }
-    }
-
-    @SuppressWarnings("WeakerAccess")
-    static class MethodReference {
-        final int mCallType;
-        final Method mMethod;
-
-        MethodReference(int callType, Method method) {
-            mCallType = callType;
-            mMethod = method;
-            mMethod.setAccessible(true);
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) {
-                return true;
-            }
-            if (o == null || getClass() != o.getClass()) {
-                return false;
-            }
-
-            MethodReference that = (MethodReference) o;
-            return mCallType == that.mCallType && mMethod.getName().equals(that.mMethod.getName());
-        }
-
-        @Override
-        public int hashCode() {
-            return 31 * mCallType + mMethod.getName().hashCode();
-        }
-    }
-
-    private static final int CALL_TYPE_NO_ARG = 0;
-    private static final int CALL_TYPE_PROVIDER = 1;
-    private static final int CALL_TYPE_PROVIDER_WITH_EVENT = 2;
 }
diff --git a/android/arch/lifecycle/SingleGeneratedAdapterObserver.java b/android/arch/lifecycle/SingleGeneratedAdapterObserver.java
new file mode 100644
index 0000000..d176a3a
--- /dev/null
+++ b/android/arch/lifecycle/SingleGeneratedAdapterObserver.java
@@ -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 android.arch.lifecycle;
+
+import android.support.annotation.RestrictTo;
+
+/**
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+public class SingleGeneratedAdapterObserver implements GenericLifecycleObserver {
+
+    private final GeneratedAdapter mGeneratedAdapter;
+
+    SingleGeneratedAdapterObserver(GeneratedAdapter generatedAdapter) {
+        mGeneratedAdapter = generatedAdapter;
+    }
+
+    @Override
+    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
+        mGeneratedAdapter.callMethods(source, event, false, null);
+        mGeneratedAdapter.callMethods(source, event, true, null);
+    }
+}
diff --git a/android/arch/lifecycle/TestUtils.java b/android/arch/lifecycle/TestUtils.java
index c5a520f..f0214bf 100644
--- a/android/arch/lifecycle/TestUtils.java
+++ b/android/arch/lifecycle/TestUtils.java
@@ -23,15 +23,16 @@
 import android.app.Instrumentation.ActivityMonitor;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.rule.ActivityTestRule;
+import android.support.v4.app.FragmentActivity;
 
 import java.util.concurrent.CountDownLatch;
 
-public class TestUtils {
+class TestUtils {
 
     private static final long TIMEOUT_MS = 2000;
 
     @SuppressWarnings("unchecked")
-    public static <T extends Activity> T recreateActivity(final T activity, ActivityTestRule rule)
+    static <T extends Activity> T recreateActivity(final T activity, ActivityTestRule rule)
             throws Throwable {
         ActivityMonitor monitor = new ActivityMonitor(
                 activity.getClass().getCanonicalName(), null, false);
@@ -60,7 +61,7 @@
         return result;
     }
 
-    static void waitTillResumed(final LifecycleActivity a, ActivityTestRule<?> activityRule)
+    static void waitTillResumed(final FragmentActivity a, ActivityTestRule<?> activityRule)
             throws Throwable {
         final CountDownLatch latch = new CountDownLatch(1);
         activityRule.runOnUiThread(() -> {
diff --git a/android/arch/lifecycle/Transformations.java b/android/arch/lifecycle/Transformations.java
index c316563..9ce9cbb 100644
--- a/android/arch/lifecycle/Transformations.java
+++ b/android/arch/lifecycle/Transformations.java
@@ -22,6 +22,12 @@
 
 /**
  * Transformations for a {@link LiveData} class.
+ * <p>
+ * You can use transformation methods to carry information across the observer's lifecycle. The
+ * transformations aren't calculated unless an observer is observing the returned LiveData object.
+ * <p>
+ * Because the transformations are calculated lazily, lifecycle-related behavior is implicitly
+ * passed down without requiring additional explicit calls or dependencies.
  */
 @SuppressWarnings("WeakerAccess")
 public class Transformations {
@@ -34,6 +40,18 @@
      * LiveData and returns LiveData, which emits resulting values.
      * <p>
      * The given function {@code func} will be executed on the main thread.
+     * <p>
+     * Suppose that you have a LiveData, named {@code userLiveData}, that contains user data and you
+     * need to display the user name, created by concatenating the first and the last
+     * name of the user. You can define a function that handles the name creation, that will be
+     * applied to every value emitted by {@code useLiveData}.
+     *
+     * <pre>
+     * LiveData<User> userLiveData = ...;
+     * LiveData<String> userName = Transformations.map(userLiveData, user -> {
+     *      return user.firstName + " " + user.lastName
+     * });
+     * </pre>
      *
      * @param source a {@code LiveData} to listen to
      * @param func   a function to apply
@@ -63,9 +81,39 @@
      * <p>
      * If the given function returns null, then {@code swLiveData} is not "backed" by any other
      * LiveData.
+     *
      * <p>
      * The given function {@code func} will be executed on the main thread.
      *
+     * <p>
+     * Consider the case where you have a LiveData containing a user id. Every time there's a new
+     * user id emitted, you want to trigger a request to get the user object corresponding to that
+     * id, from a repository that also returns a LiveData.
+     * <p>
+     * The {@code userIdLiveData} is the trigger and the LiveData returned by the {@code
+     * repository.getUserById} is the "backing" LiveData.
+     * <p>
+     * In a scenario where the repository contains User(1, "Jane") and User(2, "John"), when the
+     * userIdLiveData value is set to "1", the {@code switchMap} will call {@code getUser(1)},
+     * that will return a LiveData containing the value User(1, "Jane"). So now, the userLiveData
+     * will emit User(1, "Jane"). When the user in the repository gets updated to User(1, "Sarah"),
+     * the {@code userLiveData} gets automatically notified and will emit User(1, "Sarah").
+     * <p>
+     * When the {@code setUserId} method is called with userId = "2", the value of the {@code
+     * userIdLiveData} changes and automatically triggers a request for getting the user with id
+     * "2" from the repository. So, the {@code userLiveData} emits User(2, "John"). The LiveData
+     * returned by {@code repository.getUserById(1)} is removed as a source.
+     *
+     * <pre>
+     * MutableLiveData<String> userIdLiveData = ...;
+     * LiveData<User> userLiveData = Transformations.switchMap(userIdLiveData, id ->
+     *     repository.getUserById(id));
+     *
+     * void setUserId(String userId) {
+     *      this.userIdLiveData.setValue(userId);
+     * }
+     * </pre>
+     *
      * @param trigger a {@code LiveData} to listen to
      * @param func    a function which creates "backing" LiveData
      * @param <X>     a type of {@code source} LiveData
diff --git a/android/arch/lifecycle/TransformationsTest.java b/android/arch/lifecycle/TransformationsTest.java
index e92ecca..940a3e8 100644
--- a/android/arch/lifecycle/TransformationsTest.java
+++ b/android/arch/lifecycle/TransformationsTest.java
@@ -25,7 +25,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.arch.core.util.Function;
 import android.arch.lifecycle.util.InstantTaskExecutor;
 
@@ -42,7 +42,7 @@
 
     @Before
     public void swapExecutorDelegate() {
-        AppToolkitTaskExecutor.getInstance().setDelegate(new InstantTaskExecutor());
+        ArchTaskExecutor.getInstance().setDelegate(new InstantTaskExecutor());
     }
 
     @Before
diff --git a/android/arch/lifecycle/ViewModelProviderTest.java b/android/arch/lifecycle/ViewModelProviderTest.java
index 61760fc..8877357 100644
--- a/android/arch/lifecycle/ViewModelProviderTest.java
+++ b/android/arch/lifecycle/ViewModelProviderTest.java
@@ -21,6 +21,8 @@
 import static org.hamcrest.MatcherAssert.assertThat;
 
 import android.arch.lifecycle.ViewModelProvider.NewInstanceFactory;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
 
 import org.junit.Assert;
 import org.junit.Before;
@@ -82,6 +84,18 @@
         assertThat(viewModel, is(provider.get(ViewModel1.class)));
     }
 
+    @Test(expected = IllegalStateException.class)
+    public void testNotAttachedActivity() {
+        // This is similar to call ViewModelProviders.of in Activity's constructor
+        ViewModelProviders.of(new FragmentActivity());
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testNotAttachedFragment() {
+        // This is similar to call ViewModelProviders.of in Activity's constructor
+        ViewModelProviders.of(new Fragment());
+    }
+
     public static class ViewModel1 extends ViewModel {
         boolean mCleared;
 
diff --git a/android/arch/lifecycle/ViewModelProviders.java b/android/arch/lifecycle/ViewModelProviders.java
index f64365b..746162a 100644
--- a/android/arch/lifecycle/ViewModelProviders.java
+++ b/android/arch/lifecycle/ViewModelProviders.java
@@ -17,6 +17,7 @@
 package android.arch.lifecycle;
 
 import android.annotation.SuppressLint;
+import android.app.Activity;
 import android.app.Application;
 import android.arch.lifecycle.ViewModelProvider.Factory;
 import android.support.annotation.MainThread;
@@ -40,6 +41,23 @@
         }
     }
 
+    private static Application checkApplication(Activity activity) {
+        Application application = activity.getApplication();
+        if (application == null) {
+            throw new IllegalStateException("Your activity/fragment is not yet attached to "
+                    + "Application. You can't request ViewModel before onCreate call.");
+        }
+        return application;
+    }
+
+    private static Activity checkActivity(Fragment fragment) {
+        Activity activity = fragment.getActivity();
+        if (activity == null) {
+            throw new IllegalStateException("Can't create ViewModelProvider for detached fragment");
+        }
+        return activity;
+    }
+
     /**
      * Creates a {@link ViewModelProvider}, which retains ViewModels while a scope of given
      * {@code fragment} is alive. More detailed explanation is in {@link ViewModel}.
@@ -51,12 +69,7 @@
      */
     @MainThread
     public static ViewModelProvider of(@NonNull Fragment fragment) {
-        FragmentActivity activity = fragment.getActivity();
-        if (activity == null) {
-            throw new IllegalArgumentException(
-                    "Can't create ViewModelProvider for detached fragment");
-        }
-        initializeFactoryIfNeeded(activity.getApplication());
+        initializeFactoryIfNeeded(checkApplication(checkActivity(fragment)));
         return new ViewModelProvider(ViewModelStores.of(fragment), sDefaultFactory);
     }
 
@@ -71,7 +84,7 @@
      */
     @MainThread
     public static ViewModelProvider of(@NonNull FragmentActivity activity) {
-        initializeFactoryIfNeeded(activity.getApplication());
+        initializeFactoryIfNeeded(checkApplication(activity));
         return new ViewModelProvider(ViewModelStores.of(activity), sDefaultFactory);
     }
 
@@ -87,6 +100,7 @@
      */
     @MainThread
     public static ViewModelProvider of(@NonNull Fragment fragment, @NonNull Factory factory) {
+        checkApplication(checkActivity(fragment));
         return new ViewModelProvider(ViewModelStores.of(fragment), factory);
     }
 
@@ -103,6 +117,7 @@
     @MainThread
     public static ViewModelProvider of(@NonNull FragmentActivity activity,
             @NonNull Factory factory) {
+        checkApplication(activity);
         return new ViewModelProvider(ViewModelStores.of(activity), factory);
     }
 
diff --git a/android/arch/lifecycle/ViewModelTest.java b/android/arch/lifecycle/ViewModelTest.java
index 98ce027..03ebdf3 100644
--- a/android/arch/lifecycle/ViewModelTest.java
+++ b/android/arch/lifecycle/ViewModelTest.java
@@ -32,6 +32,7 @@
 import android.support.test.filters.MediumTest;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
+import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentActivity;
 import android.support.v4.app.FragmentManager;
 
@@ -120,7 +121,7 @@
             void onResume() {
                 try {
                     final FragmentManager manager = activity.getSupportFragmentManager();
-                    LifecycleFragment fragment = new LifecycleFragment();
+                    Fragment fragment = new Fragment();
                     manager.beginTransaction().add(fragment, "temp").commitNow();
                     ViewModel1 vm = ViewModelProviders.of(fragment).get(ViewModel1.class);
                     assertThat(vm.mCleared, is(false));
diff --git a/android/arch/lifecycle/activity/EmptyActivity.java b/android/arch/lifecycle/activity/EmptyActivity.java
index 017fff4..c32c898 100644
--- a/android/arch/lifecycle/activity/EmptyActivity.java
+++ b/android/arch/lifecycle/activity/EmptyActivity.java
@@ -16,13 +16,12 @@
 
 package android.arch.lifecycle.activity;
 
+import android.arch.lifecycle.extensions.test.R;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
+import android.support.v4.app.FragmentActivity;
 
-import android.arch.lifecycle.LifecycleActivity;
-import android.arch.lifecycle.extensions.test.R;
-
-public class EmptyActivity extends LifecycleActivity {
+public class EmptyActivity extends FragmentActivity {
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
diff --git a/android/arch/lifecycle/activity/FragmentLifecycleActivity.java b/android/arch/lifecycle/activity/FragmentLifecycleActivity.java
index f4485e8..2eb1cc2 100644
--- a/android/arch/lifecycle/activity/FragmentLifecycleActivity.java
+++ b/android/arch/lifecycle/activity/FragmentLifecycleActivity.java
@@ -17,7 +17,6 @@
 package android.arch.lifecycle.activity;
 
 import android.arch.lifecycle.Lifecycle;
-import android.arch.lifecycle.LifecycleFragment;
 import android.arch.lifecycle.LifecycleObserver;
 import android.arch.lifecycle.LifecycleOwner;
 import android.arch.lifecycle.OnLifecycleEvent;
@@ -26,6 +25,7 @@
 import android.content.Intent;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
 import android.support.v7.app.AppCompatActivity;
 
 import java.util.ArrayList;
@@ -70,9 +70,9 @@
         mLoggedEvents.clear();
     }
 
-    public static class MainFragment extends LifecycleFragment {
+    public static class MainFragment extends Fragment {
         @Nullable
-        LifecycleFragment mNestedFragment;
+        Fragment mNestedFragment;
 
         @Override
         public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -85,7 +85,7 @@
         }
     }
 
-    public static class NestedFragment extends LifecycleFragment {
+    public static class NestedFragment extends Fragment {
     }
 
     public static Intent intentFor(Context context, boolean nested) {
@@ -98,7 +98,8 @@
         mObservedOwner = provider;
         provider.getLifecycle().addObserver(new LifecycleObserver() {
             @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
-            public void anyEvent(LifecycleOwner owner, Lifecycle.Event event) {
+            public void anyEvent(@SuppressWarnings("unused") LifecycleOwner owner,
+                    Lifecycle.Event event) {
                 mLoggedEvents.add(event);
             }
         });
diff --git a/android/arch/lifecycle/observers/Base.java b/android/arch/lifecycle/observers/Base.java
new file mode 100644
index 0000000..08919d4
--- /dev/null
+++ b/android/arch/lifecycle/observers/Base.java
@@ -0,0 +1,28 @@
+/*
+ * 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 android.arch.lifecycle.observers;
+
+import android.arch.lifecycle.Lifecycle;
+import android.arch.lifecycle.LifecycleObserver;
+import android.arch.lifecycle.OnLifecycleEvent;
+
+public class Base implements LifecycleObserver {
+
+    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
+    public void onCreate() {
+    }
+}
diff --git a/android/arch/lifecycle/observers/Base_LifecycleAdapter.java b/android/arch/lifecycle/observers/Base_LifecycleAdapter.java
new file mode 100644
index 0000000..4218b96
--- /dev/null
+++ b/android/arch/lifecycle/observers/Base_LifecycleAdapter.java
@@ -0,0 +1,34 @@
+/*
+ * 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 android.arch.lifecycle.observers;
+
+import android.arch.lifecycle.GeneratedAdapter;
+import android.arch.lifecycle.Lifecycle;
+import android.arch.lifecycle.LifecycleOwner;
+import android.arch.lifecycle.MethodCallsLogger;
+
+public class Base_LifecycleAdapter implements GeneratedAdapter {
+
+    public Base_LifecycleAdapter(Base base) {
+    }
+
+    @Override
+    public void callMethods(LifecycleOwner source, Lifecycle.Event event, boolean onAny,
+            MethodCallsLogger logger) {
+
+    }
+}
diff --git a/android/arch/lifecycle/observers/DerivedSequence1.java b/android/arch/lifecycle/observers/DerivedSequence1.java
new file mode 100644
index 0000000..9db37f1
--- /dev/null
+++ b/android/arch/lifecycle/observers/DerivedSequence1.java
@@ -0,0 +1,23 @@
+/*
+ * 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 android.arch.lifecycle.observers;
+
+public class DerivedSequence1 extends Base {
+
+    public void something() {
+    }
+}
diff --git a/android/arch/lifecycle/observers/DerivedSequence2.java b/android/arch/lifecycle/observers/DerivedSequence2.java
new file mode 100644
index 0000000..f2ef943
--- /dev/null
+++ b/android/arch/lifecycle/observers/DerivedSequence2.java
@@ -0,0 +1,28 @@
+/*
+ * 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 android.arch.lifecycle.observers;
+
+import android.arch.lifecycle.Lifecycle;
+import android.arch.lifecycle.OnLifecycleEvent;
+
+public class DerivedSequence2 extends DerivedSequence1 {
+
+    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
+    void onStop() {
+
+    }
+}
diff --git a/android/arch/lifecycle/observers/DerivedWithNewMethods.java b/android/arch/lifecycle/observers/DerivedWithNewMethods.java
new file mode 100644
index 0000000..b1eaef0
--- /dev/null
+++ b/android/arch/lifecycle/observers/DerivedWithNewMethods.java
@@ -0,0 +1,28 @@
+/*
+ * 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 android.arch.lifecycle.observers;
+
+import android.arch.lifecycle.Lifecycle;
+import android.arch.lifecycle.OnLifecycleEvent;
+
+public class DerivedWithNewMethods extends Base {
+
+    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
+    void onStop() {
+
+    }
+}
diff --git a/android/arch/lifecycle/observers/DerivedWithNoNewMethods.java b/android/arch/lifecycle/observers/DerivedWithNoNewMethods.java
new file mode 100644
index 0000000..cb1afb8
--- /dev/null
+++ b/android/arch/lifecycle/observers/DerivedWithNoNewMethods.java
@@ -0,0 +1,20 @@
+/*
+ * 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 android.arch.lifecycle.observers;
+
+public class DerivedWithNoNewMethods extends Base {
+}
diff --git a/android/arch/lifecycle/observers/DerivedWithOverridenMethodsWithLfAnnotation.java b/android/arch/lifecycle/observers/DerivedWithOverridenMethodsWithLfAnnotation.java
new file mode 100644
index 0000000..40c7c9a
--- /dev/null
+++ b/android/arch/lifecycle/observers/DerivedWithOverridenMethodsWithLfAnnotation.java
@@ -0,0 +1,29 @@
+/*
+ * 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 android.arch.lifecycle.observers;
+
+import android.arch.lifecycle.Lifecycle;
+import android.arch.lifecycle.OnLifecycleEvent;
+
+public class DerivedWithOverridenMethodsWithLfAnnotation extends Base {
+
+    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
+    @Override
+    public void onCreate() {
+        super.onCreate();
+    }
+}
diff --git a/android/arch/lifecycle/observers/Interface1.java b/android/arch/lifecycle/observers/Interface1.java
new file mode 100644
index 0000000..e193de9
--- /dev/null
+++ b/android/arch/lifecycle/observers/Interface1.java
@@ -0,0 +1,27 @@
+/*
+ * 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 android.arch.lifecycle.observers;
+
+import android.arch.lifecycle.Lifecycle;
+import android.arch.lifecycle.LifecycleObserver;
+import android.arch.lifecycle.OnLifecycleEvent;
+
+public interface Interface1 extends LifecycleObserver {
+
+    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
+    void onCreate();
+}
diff --git a/android/arch/lifecycle/observers/Interface1_LifecycleAdapter.java b/android/arch/lifecycle/observers/Interface1_LifecycleAdapter.java
new file mode 100644
index 0000000..c597b1c
--- /dev/null
+++ b/android/arch/lifecycle/observers/Interface1_LifecycleAdapter.java
@@ -0,0 +1,34 @@
+/*
+ * 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 android.arch.lifecycle.observers;
+
+import android.arch.lifecycle.GeneratedAdapter;
+import android.arch.lifecycle.Lifecycle;
+import android.arch.lifecycle.LifecycleOwner;
+import android.arch.lifecycle.MethodCallsLogger;
+
+public class Interface1_LifecycleAdapter implements GeneratedAdapter {
+
+    public Interface1_LifecycleAdapter(Interface1 base) {
+    }
+
+    @Override
+    public void callMethods(LifecycleOwner source, Lifecycle.Event event, boolean onAny,
+            MethodCallsLogger logger) {
+
+    }
+}
diff --git a/android/arch/lifecycle/observers/Interface2.java b/android/arch/lifecycle/observers/Interface2.java
new file mode 100644
index 0000000..1056fcb
--- /dev/null
+++ b/android/arch/lifecycle/observers/Interface2.java
@@ -0,0 +1,30 @@
+/*
+ * 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 android.arch.lifecycle.observers;
+
+import android.arch.lifecycle.Lifecycle;
+import android.arch.lifecycle.LifecycleObserver;
+import android.arch.lifecycle.OnLifecycleEvent;
+
+public interface Interface2 extends LifecycleObserver {
+
+    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
+    void onCreate();
+
+    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
+    void onDestroy();
+}
diff --git a/android/arch/lifecycle/observers/Interface2_LifecycleAdapter.java b/android/arch/lifecycle/observers/Interface2_LifecycleAdapter.java
new file mode 100644
index 0000000..b05b41a
--- /dev/null
+++ b/android/arch/lifecycle/observers/Interface2_LifecycleAdapter.java
@@ -0,0 +1,34 @@
+/*
+ * 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 android.arch.lifecycle.observers;
+
+import android.arch.lifecycle.GeneratedAdapter;
+import android.arch.lifecycle.Lifecycle;
+import android.arch.lifecycle.LifecycleOwner;
+import android.arch.lifecycle.MethodCallsLogger;
+
+public class Interface2_LifecycleAdapter implements GeneratedAdapter {
+
+    public Interface2_LifecycleAdapter(Interface2 base) {
+    }
+
+    @Override
+    public void callMethods(LifecycleOwner source, Lifecycle.Event event, boolean onAny,
+            MethodCallsLogger logger) {
+
+    }
+}
diff --git a/android/arch/lifecycle/observers/InterfaceImpl1.java b/android/arch/lifecycle/observers/InterfaceImpl1.java
new file mode 100644
index 0000000..2f03393
--- /dev/null
+++ b/android/arch/lifecycle/observers/InterfaceImpl1.java
@@ -0,0 +1,23 @@
+/*
+ * 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 android.arch.lifecycle.observers;
+
+public class InterfaceImpl1 implements Interface1 {
+    @Override
+    public void onCreate() {
+    }
+}
diff --git a/android/arch/lifecycle/observers/InterfaceImpl2.java b/android/arch/lifecycle/observers/InterfaceImpl2.java
new file mode 100644
index 0000000..eef8ce4
--- /dev/null
+++ b/android/arch/lifecycle/observers/InterfaceImpl2.java
@@ -0,0 +1,28 @@
+/*
+ * 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 android.arch.lifecycle.observers;
+
+public class InterfaceImpl2 implements Interface1, Interface2 {
+    @Override
+    public void onCreate() {
+    }
+
+    @Override
+    public void onDestroy() {
+
+    }
+}
diff --git a/android/arch/lifecycle/observers/InterfaceImpl3.java b/android/arch/lifecycle/observers/InterfaceImpl3.java
new file mode 100644
index 0000000..8f31808
--- /dev/null
+++ b/android/arch/lifecycle/observers/InterfaceImpl3.java
@@ -0,0 +1,23 @@
+/*
+ * 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 android.arch.lifecycle.observers;
+
+public class InterfaceImpl3 extends Base implements Interface1 {
+    @Override
+    public void onCreate() {
+    }
+}
diff --git a/android/arch/lifecycle/testapp/FullLifecycleTestActivity.java b/android/arch/lifecycle/testapp/FullLifecycleTestActivity.java
index 5972b16..5f33c28 100644
--- a/android/arch/lifecycle/testapp/FullLifecycleTestActivity.java
+++ b/android/arch/lifecycle/testapp/FullLifecycleTestActivity.java
@@ -19,8 +19,8 @@
 import static android.arch.lifecycle.testapp.TestEvent.ACTIVITY_CALLBACK;
 
 import android.arch.lifecycle.Lifecycle;
-import android.arch.lifecycle.LifecycleActivity;
 import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
 import android.util.Pair;
 
 import java.util.ArrayList;
@@ -31,7 +31,7 @@
 /**
  * Activity for testing full lifecycle
  */
-public class FullLifecycleTestActivity extends LifecycleActivity implements CollectingActivity {
+public class FullLifecycleTestActivity extends FragmentActivity implements CollectingActivity {
 
     private List<Pair<TestEvent, Lifecycle.Event>> mCollectedEvents = new ArrayList<>();
     private TestObserver mTestObserver = new TestObserver(mCollectedEvents);
diff --git a/android/arch/lifecycle/testapp/LifecycleTestActivity.java b/android/arch/lifecycle/testapp/LifecycleTestActivity.java
index 093ec7f..cf07aee 100644
--- a/android/arch/lifecycle/testapp/LifecycleTestActivity.java
+++ b/android/arch/lifecycle/testapp/LifecycleTestActivity.java
@@ -16,13 +16,13 @@
 
 package android.arch.lifecycle.testapp;
 
-import android.arch.lifecycle.LifecycleActivity;
 import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
 
 /**
  * Activity for testing events by themselves
  */
-public class LifecycleTestActivity extends LifecycleActivity {
+public class LifecycleTestActivity extends FragmentActivity {
 
     /**
      * identifies that
diff --git a/android/arch/lifecycle/testapp/NavigationDialogActivity.java b/android/arch/lifecycle/testapp/NavigationDialogActivity.java
index 709bd8d..0ae9403 100644
--- a/android/arch/lifecycle/testapp/NavigationDialogActivity.java
+++ b/android/arch/lifecycle/testapp/NavigationDialogActivity.java
@@ -16,10 +16,10 @@
 
 package android.arch.lifecycle.testapp;
 
-import android.arch.lifecycle.LifecycleActivity;
+import android.support.v4.app.FragmentActivity;
 
 /**
  *  an activity with Dialog theme.
  */
-public class NavigationDialogActivity extends LifecycleActivity {
+public class NavigationDialogActivity extends FragmentActivity {
 }
diff --git a/android/arch/lifecycle/testapp/NavigationTestActivityFirst.java b/android/arch/lifecycle/testapp/NavigationTestActivityFirst.java
index f1847c9..69fd478 100644
--- a/android/arch/lifecycle/testapp/NavigationTestActivityFirst.java
+++ b/android/arch/lifecycle/testapp/NavigationTestActivityFirst.java
@@ -16,10 +16,10 @@
 
 package android.arch.lifecycle.testapp;
 
-import android.arch.lifecycle.LifecycleActivity;
+import android.support.v4.app.FragmentActivity;
 
 /**
  * Activity for ProcessOwnerTest
  */
-public class NavigationTestActivityFirst extends LifecycleActivity {
+public class NavigationTestActivityFirst extends FragmentActivity {
 }
diff --git a/android/arch/lifecycle/testapp/NavigationTestActivitySecond.java b/android/arch/lifecycle/testapp/NavigationTestActivitySecond.java
index 221e927..0f9a4c9 100644
--- a/android/arch/lifecycle/testapp/NavigationTestActivitySecond.java
+++ b/android/arch/lifecycle/testapp/NavigationTestActivitySecond.java
@@ -16,10 +16,10 @@
 
 package android.arch.lifecycle.testapp;
 
-import android.arch.lifecycle.LifecycleActivity;
+import android.support.v4.app.FragmentActivity;
 
 /**
  * Activity for ProcessOwnerTest
  */
-public class NavigationTestActivitySecond extends LifecycleActivity {
+public class NavigationTestActivitySecond extends FragmentActivity {
 }
diff --git a/android/arch/lifecycle/testapp/SimpleAppLifecycleTestActivity.java b/android/arch/lifecycle/testapp/SimpleAppLifecycleTestActivity.java
index 6d61c5e..77bd99f 100644
--- a/android/arch/lifecycle/testapp/SimpleAppLifecycleTestActivity.java
+++ b/android/arch/lifecycle/testapp/SimpleAppLifecycleTestActivity.java
@@ -17,12 +17,12 @@
 package android.arch.lifecycle.testapp;
 
 import android.arch.lifecycle.Lifecycle;
-import android.arch.lifecycle.LifecycleActivity;
 import android.arch.lifecycle.LifecycleObserver;
 import android.arch.lifecycle.LifecycleOwner;
 import android.arch.lifecycle.OnLifecycleEvent;
 import android.arch.lifecycle.ProcessLifecycleOwner;
 import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
 import android.util.Pair;
 
 import java.util.ArrayList;
@@ -33,7 +33,7 @@
 /**
  * Activity for SimpleAppFullLifecycleTest
  */
-public class SimpleAppLifecycleTestActivity extends LifecycleActivity {
+public class SimpleAppLifecycleTestActivity extends FragmentActivity {
 
     public enum TestEventType {
         PROCESS_EVENT,
diff --git a/android/arch/lifecycle/viewmodeltest/ViewModelActivity.java b/android/arch/lifecycle/viewmodeltest/ViewModelActivity.java
index 5ef9f16..1f9f100 100644
--- a/android/arch/lifecycle/viewmodeltest/ViewModelActivity.java
+++ b/android/arch/lifecycle/viewmodeltest/ViewModelActivity.java
@@ -16,15 +16,14 @@
 
 package android.arch.lifecycle.viewmodeltest;
 
+import android.arch.lifecycle.ViewModelProviders;
 import android.arch.lifecycle.extensions.test.R;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
 
-import android.arch.lifecycle.LifecycleActivity;
-import android.arch.lifecycle.LifecycleFragment;
-import android.arch.lifecycle.ViewModelProviders;
-
-public class ViewModelActivity extends LifecycleActivity {
+public class ViewModelActivity extends FragmentActivity {
     public static final String KEY_FRAGMENT_MODEL = "fragment-model";
     public static final String KEY_ACTIVITY_MODEL = "activity-model";
     public static final String FRAGMENT_TAG_1 = "f1";
@@ -47,7 +46,7 @@
         defaultActivityModel = ViewModelProviders.of(this).get(TestViewModel.class);
     }
 
-    public static class ViewModelFragment extends LifecycleFragment {
+    public static class ViewModelFragment extends Fragment {
         public TestViewModel fragmentModel;
         public TestViewModel activityModel;
         public TestViewModel defaultActivityModel;