Java8 interface for LifecycleObserver

Test: LifecycleObserversTest
bug: 65296790
Change-Id: I127a172f3c9e2aeaecff9415a9f8b4a3b233aba7
diff --git a/app-toolkit/settings.gradle b/app-toolkit/settings.gradle
index 31fc0e1..aa0db94 100644
--- a/app-toolkit/settings.gradle
+++ b/app-toolkit/settings.gradle
@@ -57,6 +57,9 @@
 include ':lifecycle:common'
 project(':lifecycle:common').projectDir = new File(supportRoot, "lifecycle/common")
 
+include ':lifecycle:common-java8'
+project(':lifecycle:common-java8').projectDir = new File(supportRoot, "lifecycle/common-java8")
+
 include ':lifecycle:compiler'
 project(':lifecycle:compiler').projectDir = new File(supportRoot, "lifecycle/compiler")
 
diff --git a/buildSrc/src/main/groovy/android/support/SupportJavaLibraryPlugin.groovy b/buildSrc/src/main/groovy/android/support/SupportJavaLibraryPlugin.groovy
index 443df5a..ae0d55c 100644
--- a/buildSrc/src/main/groovy/android/support/SupportJavaLibraryPlugin.groovy
+++ b/buildSrc/src/main/groovy/android/support/SupportJavaLibraryPlugin.groovy
@@ -33,10 +33,13 @@
         SupportLibraryMavenUploader.apply(project, supportLibraryExtension);
 
         project.apply(ImmutableMap.of("plugin", "java"));
-
-        project.compileJava {
-            sourceCompatibility = JavaVersion.VERSION_1_7
-            targetCompatibility = JavaVersion.VERSION_1_7
+        project.afterEvaluate {
+            project.compileJava {
+                def version = supportLibraryExtension.java8Library ?
+                    JavaVersion.VERSION_1_8 : JavaVersion.VERSION_1_7
+                sourceCompatibility = version
+                targetCompatibility = version
+            }
         }
     }
 }
\ No newline at end of file
diff --git a/buildSrc/src/main/groovy/android/support/SupportLibraryExtension.groovy b/buildSrc/src/main/groovy/android/support/SupportLibraryExtension.groovy
index 2aacf60..93afb9a 100644
--- a/buildSrc/src/main/groovy/android/support/SupportLibraryExtension.groovy
+++ b/buildSrc/src/main/groovy/android/support/SupportLibraryExtension.groovy
@@ -33,6 +33,7 @@
     String inceptionYear;
     String url = SUPPORT_URL;
     Collection<License> licenses = [];
+    boolean java8Library = false;
     boolean publish = false;
 
     SupportLibraryExtension(Project project) {
diff --git a/lifecycle/common-java8/build.gradle b/lifecycle/common-java8/build.gradle
new file mode 100644
index 0000000..fccc813
--- /dev/null
+++ b/lifecycle/common-java8/build.gradle
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+import android.support.LibraryVersions;
+import android.support.SupportLibraryExtension;
+
+apply plugin: android.support.SupportJavaLibraryPlugin
+
+dependencies {
+    testCompile libs.junit
+    testCompile libs.mockito_core
+    compile project(":lifecycle:common")
+    compile libs.support.annotations
+}
+
+createAndroidCheckstyle(project)
+
+version = LibraryVersions.LIFECYCLES_EXT.toString()
+supportLibrary {
+    name 'Android Lifecycle-Common for Java 8 Language'
+    publish true
+    inceptionYear '2017'
+    description "Android Lifecycle-Common for Java 8 Language"
+    url SupportLibraryExtension.ARCHITECTURE_URL
+    java8Library true
+}
diff --git a/lifecycle/common-java8/src/main/java/android/arch/lifecycle/DefaultLifecycleObserver.java b/lifecycle/common-java8/src/main/java/android/arch/lifecycle/DefaultLifecycleObserver.java
new file mode 100644
index 0000000..77a7dfd
--- /dev/null
+++ b/lifecycle/common-java8/src/main/java/android/arch/lifecycle/DefaultLifecycleObserver.java
@@ -0,0 +1,98 @@
+/*
+ * 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;
+
+/**
+ * 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(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(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(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(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(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(LifecycleOwner owner) {
+    }
+}
+
diff --git a/lifecycle/common/src/main/java/android/arch/lifecycle/FullLifecycleObserver.java b/lifecycle/common/src/main/java/android/arch/lifecycle/FullLifecycleObserver.java
new file mode 100644
index 0000000..f179274
--- /dev/null
+++ b/lifecycle/common/src/main/java/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/lifecycle/common/src/main/java/android/arch/lifecycle/FullLifecycleObserverAdapter.java b/lifecycle/common/src/main/java/android/arch/lifecycle/FullLifecycleObserverAdapter.java
new file mode 100644
index 0000000..0a91a66
--- /dev/null
+++ b/lifecycle/common/src/main/java/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/lifecycle/common/src/main/java/android/arch/lifecycle/Lifecycle.java b/lifecycle/common/src/main/java/android/arch/lifecycle/Lifecycle.java
index fcbd50a..02db5ff 100644
--- a/lifecycle/common/src/main/java/android/arch/lifecycle/Lifecycle.java
+++ b/lifecycle/common/src/main/java/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/lifecycle/common/src/main/java/android/arch/lifecycle/Lifecycling.java b/lifecycle/common/src/main/java/android/arch/lifecycle/Lifecycling.java
index 3a5c0b9..0dfa2e1 100644
--- a/lifecycle/common/src/main/java/android/arch/lifecycle/Lifecycling.java
+++ b/lifecycle/common/src/main/java/android/arch/lifecycle/Lifecycling.java
@@ -47,6 +47,10 @@
 
     @NonNull
     static GenericLifecycleObserver getCallback(Object object) {
+        if (object instanceof FullLifecycleObserver) {
+            return new FullLifecycleObserverAdapter((FullLifecycleObserver) object);
+        }
+
         if (object instanceof GenericLifecycleObserver) {
             return (GenericLifecycleObserver) object;
         }
diff --git a/lifecycle/common/src/test/java/android/arch/lifecycle/FullLifecycleObserverTest.java b/lifecycle/common/src/test/java/android/arch/lifecycle/FullLifecycleObserverTest.java
new file mode 100644
index 0000000..def6755
--- /dev/null
+++ b/lifecycle/common/src/test/java/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);
+    }
+}