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