1b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets/*
264db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyar * Copyright (C) 2017 The Android Open Source Project
3b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets *
4b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets * Licensed under the Apache License, Version 2.0 (the "License");
5b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets * you may not use this file except in compliance with the License.
6b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets * You may obtain a copy of the License at
7b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets *
8b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets *      http://www.apache.org/licenses/LICENSE-2.0
9b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets *
10b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets * Unless required by applicable law or agreed to in writing, software
11b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets * distributed under the License is distributed on an "AS IS" BASIS,
12b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets * See the License for the specific language governing permissions and
14b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets * limitations under the License.
15b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets */
16b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets
1764db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarpackage android.arch.lifecycle;
18b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets
1927015a7478beac9e231135207e3e705784cee508Sergey Vasilinetsimport static android.arch.lifecycle.Lifecycle.State.RESUMED;
2027015a7478beac9e231135207e3e705784cee508Sergey Vasilinets
211f52c94781fdc0d8aefbaa697bb8b52e18badcd5Sergey Vasilinetsimport android.app.Activity;
22b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinetsimport android.app.Instrumentation;
23b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinetsimport android.app.Instrumentation.ActivityMonitor;
24b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinetsimport android.support.test.InstrumentationRegistry;
25450ed382339544eaf6b7886bc765522fc3446148Yigit Boyarimport android.support.test.rule.ActivityTestRule;
26b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets
278524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinetsimport java.util.concurrent.CountDownLatch;
288524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets
29b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinetspublic class TestUtils {
30b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets
31b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets    private static final long TIMEOUT_MS = 2000;
32b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets
331f52c94781fdc0d8aefbaa697bb8b52e18badcd5Sergey Vasilinets    @SuppressWarnings("unchecked")
34450ed382339544eaf6b7886bc765522fc3446148Yigit Boyar    public static <T extends Activity> T recreateActivity(final T activity, ActivityTestRule rule)
35b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets            throws Throwable {
36b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets        ActivityMonitor monitor = new ActivityMonitor(
371f52c94781fdc0d8aefbaa697bb8b52e18badcd5Sergey Vasilinets                activity.getClass().getCanonicalName(), null, false);
38b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
39b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets        instrumentation.addMonitor(monitor);
401f52c94781fdc0d8aefbaa697bb8b52e18badcd5Sergey Vasilinets        rule.runOnUiThread(activity::recreate);
411f52c94781fdc0d8aefbaa697bb8b52e18badcd5Sergey Vasilinets        T result;
42ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets
43ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets        // this guarantee that we will reinstall monitor between notifications about onDestroy
44ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets        // and onCreate
451f52c94781fdc0d8aefbaa697bb8b52e18badcd5Sergey Vasilinets        //noinspection SynchronizationOnLocalVariableOrMethodParameter
46ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets        synchronized (monitor) {
47ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets            do {
48ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets                // the documetation says "Block until an Activity is created
49ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets                // that matches this monitor." This statement is true, but there are some other
50ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets                // true statements like: "Block until an Activity is destoyed" or
51ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets                // "Block until an Activity is resumed"...
52ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets
53ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets                // this call will release synchronization monitor's monitor
541f52c94781fdc0d8aefbaa697bb8b52e18badcd5Sergey Vasilinets                result = (T) monitor.waitForActivityWithTimeout(TIMEOUT_MS);
55ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets                if (result == null) {
56ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets                    throw new RuntimeException("Timeout. Failed to recreate an activity");
57ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets                }
58ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets            } while (result == activity);
59b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets        }
60b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets        return result;
61b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets    }
628524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets
638524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets    static void waitTillResumed(final LifecycleActivity a, ActivityTestRule<?> activityRule)
648524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets            throws Throwable {
658524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets        final CountDownLatch latch = new CountDownLatch(1);
668524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets        activityRule.runOnUiThread(() -> {
6727015a7478beac9e231135207e3e705784cee508Sergey Vasilinets            Lifecycle.State currentState = a.getLifecycle().getCurrentState();
6827015a7478beac9e231135207e3e705784cee508Sergey Vasilinets            if (currentState == RESUMED) {
698524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets                latch.countDown();
708524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets            }
718524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets            a.getLifecycle().addObserver(new LifecycleObserver() {
72b86bef286718da421268bc52cf4fab7cccb3104cSergey Vasilinets                @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
73e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets                public void onStateChanged(LifecycleOwner provider) {
748524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets                    latch.countDown();
758524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets                    provider.getLifecycle().removeObserver(this);
768524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets                }
778524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets            });
788524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets        });
798524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets        latch.await();
808524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets    }
818524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets
82b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets}
83