blob: 7270672f36f916fde888160100dfbf8e35b7c244 [file] [log] [blame]
/*
* Copyright (C) 2015 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.app.cts;
import android.app.FragmentManager;
import android.app.stubs.FragmentTestActivity;
import android.app.stubs.FragmentTestActivity.OnTransitionListener;
import android.app.stubs.FragmentTestActivity.TestFragment;
import android.app.stubs.R;
import android.os.Debug;
import android.os.SystemClock;
import android.test.ActivityInstrumentationTestCase2;
import android.view.View;
public class FragmentTransitionTest extends
ActivityInstrumentationTestCase2<FragmentTestActivity> {
private TestFragment mStartFragment;
private TestFragment mMidFragment;
private TestFragment mEndFragment;
private FragmentTestActivity mActivity;
public FragmentTransitionTest() {
super(FragmentTestActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
mStartFragment = null;
mMidFragment = null;
mEndFragment = null;
mActivity = getActivity();
}
public void testFragmentTransition() throws Throwable {
runTestOnUiThread(new Runnable() {
@Override
public void run() {
mStartFragment = new TestFragment(R.layout.fragment_start);
mActivity.getFragmentManager().beginTransaction()
.replace(R.id.content, mStartFragment)
.commit();
mActivity.getFragmentManager().executePendingTransactions();
}
});
waitForEnd(mStartFragment, TestFragment.ENTER);
assertTrue(mStartFragment.wasEndCalled(TestFragment.ENTER));
mStartFragment.clearNotifications();
runTestOnUiThread(new Runnable() {
@Override
public void run() {
final View sharedElement = mActivity.findViewById(R.id.hello);
assertEquals("source", sharedElement.getTransitionName());
mEndFragment = new TestFragment(R.layout.fragment_end);
mActivity.getFragmentManager().beginTransaction()
.replace(R.id.content, mEndFragment)
.addSharedElement(sharedElement, "destination")
.addToBackStack(null)
.commit();
mActivity.getFragmentManager().executePendingTransactions();
}
});
waitForEnd(mEndFragment, TestFragment.ENTER);
assertTrue(mEndFragment.wasEndCalled(TestFragment.ENTER));
assertTrue(mStartFragment.wasEndCalled(TestFragment.EXIT));
assertTrue(mEndFragment.wasEndCalled(TestFragment.SHARED_ELEMENT_ENTER));
runTestOnUiThread(new Runnable() {
@Override
public void run() {
final View textView = mActivity.findViewById(R.id.hello);
assertEquals("destination", textView.getTransitionName());
mActivity.getFragmentManager().popBackStack();
mActivity.getFragmentManager().executePendingTransactions();
}
});
waitForEnd(mStartFragment, TestFragment.REENTER);
assertTrue(mStartFragment.wasEndCalled(TestFragment.REENTER));
assertTrue(mEndFragment.wasEndCalled(TestFragment.RETURN));
}
public void testFirstOutLastInTransition() throws Throwable {
runTestOnUiThread(new Runnable() {
@Override
public void run() {
mStartFragment = new TestFragment(R.layout.fragment_start);
mActivity.getFragmentManager().beginTransaction()
.replace(R.id.content, mStartFragment)
.commit();
mActivity.getFragmentManager().executePendingTransactions();
}
});
waitForEnd(mStartFragment, TestFragment.ENTER);
assertTrue(mStartFragment.wasEndCalled(TestFragment.ENTER));
mStartFragment.clearNotifications();
runTestOnUiThread(new Runnable() {
@Override
public void run() {
mMidFragment = new TestFragment(R.layout.checkbox_layout);
mEndFragment = new TestFragment(R.layout.fragment_end);
mActivity.getFragmentManager().beginTransaction()
.replace(R.id.content, mMidFragment)
.replace(R.id.content, mEndFragment)
.addToBackStack(null)
.commit();
mActivity.getFragmentManager().executePendingTransactions();
}
});
waitForEnd(mEndFragment, TestFragment.ENTER);
assertTrue(mEndFragment.wasEndCalled(TestFragment.ENTER));
assertFalse(mEndFragment.wasEndCalled(TestFragment.EXIT));
assertFalse(mEndFragment.wasEndCalled(TestFragment.RETURN));
assertFalse(mEndFragment.wasEndCalled(TestFragment.REENTER));
assertTrue(mStartFragment.wasEndCalled(TestFragment.EXIT));
assertFalse(mStartFragment.wasEndCalled(TestFragment.ENTER));
assertFalse(mStartFragment.wasEndCalled(TestFragment.RETURN));
assertFalse(mStartFragment.wasEndCalled(TestFragment.REENTER));
assertFalse(mMidFragment.wasStartCalled(TestFragment.ENTER));
assertFalse(mMidFragment.wasStartCalled(TestFragment.EXIT));
assertFalse(mMidFragment.wasStartCalled(TestFragment.REENTER));
assertFalse(mMidFragment.wasStartCalled(TestFragment.RETURN));
mStartFragment.clearNotifications();
mEndFragment.clearNotifications();
runTestOnUiThread(new Runnable() {
@Override
public void run() {
mActivity.getFragmentManager().popBackStack();
mActivity.getFragmentManager().executePendingTransactions();
}
});
waitForEnd(mEndFragment, TestFragment.RETURN);
assertTrue(mEndFragment.wasEndCalled(TestFragment.RETURN));
assertFalse(mMidFragment.wasStartCalled(TestFragment.ENTER));
assertFalse(mMidFragment.wasStartCalled(TestFragment.EXIT));
assertFalse(mMidFragment.wasStartCalled(TestFragment.REENTER));
assertFalse(mMidFragment.wasStartCalled(TestFragment.RETURN));
assertTrue(mStartFragment.wasStartCalled(TestFragment.REENTER));
assertFalse(mStartFragment.wasStartCalled(TestFragment.ENTER));
assertFalse(mStartFragment.wasStartCalled(TestFragment.EXIT));
assertFalse(mStartFragment.wasStartCalled(TestFragment.RETURN));
}
public void testPopTwo() throws Throwable {
runTestOnUiThread(new Runnable() {
@Override
public void run() {
mStartFragment = new TestFragment(R.layout.fragment_start);
mActivity.getFragmentManager().beginTransaction()
.replace(R.id.content, mStartFragment)
.commit();
mActivity.getFragmentManager().executePendingTransactions();
}
});
waitForEnd(mStartFragment, TestFragment.ENTER);
assertTrue(mStartFragment.wasEndCalled(TestFragment.ENTER));
mStartFragment.clearNotifications();
runTestOnUiThread(new Runnable() {
@Override
public void run() {
mMidFragment = new TestFragment(R.layout.checkbox_layout);
mActivity.getFragmentManager().beginTransaction()
.replace(R.id.content, mMidFragment)
.addToBackStack(null)
.commit();
mActivity.getFragmentManager().executePendingTransactions();
}
});
waitForEnd(mMidFragment, TestFragment.ENTER);
runTestOnUiThread(new Runnable() {
@Override
public void run() {
mEndFragment = new TestFragment(R.layout.fragment_end);
mActivity.getFragmentManager().beginTransaction()
.replace(R.id.content, mEndFragment)
.addToBackStack(null)
.commit();
mActivity.getFragmentManager().executePendingTransactions();
}
});
waitForEnd(mEndFragment, TestFragment.ENTER);
assertTrue(mEndFragment.wasEndCalled(TestFragment.ENTER));
assertFalse(mEndFragment.wasEndCalled(TestFragment.EXIT));
assertFalse(mEndFragment.wasEndCalled(TestFragment.RETURN));
assertFalse(mEndFragment.wasEndCalled(TestFragment.REENTER));
assertTrue(mStartFragment.wasEndCalled(TestFragment.EXIT));
assertFalse(mStartFragment.wasEndCalled(TestFragment.ENTER));
assertFalse(mStartFragment.wasEndCalled(TestFragment.RETURN));
assertFalse(mStartFragment.wasEndCalled(TestFragment.REENTER));
assertTrue(mMidFragment.wasStartCalled(TestFragment.ENTER));
assertTrue(mMidFragment.wasStartCalled(TestFragment.EXIT));
assertFalse(mMidFragment.wasStartCalled(TestFragment.REENTER));
assertFalse(mMidFragment.wasStartCalled(TestFragment.RETURN));
mStartFragment.clearNotifications();
mMidFragment.clearNotifications();
mEndFragment.clearNotifications();
runTestOnUiThread(new Runnable() {
@Override
public void run() {
FragmentManager fm = mActivity.getFragmentManager();
int id = fm.getBackStackEntryAt(0).getId();
fm.popBackStack(id, FragmentManager.POP_BACK_STACK_INCLUSIVE);
fm.executePendingTransactions();
}
});
waitForEnd(mEndFragment, TestFragment.RETURN);
assertTrue(mEndFragment.wasEndCalled(TestFragment.RETURN));
assertFalse(mMidFragment.wasStartCalled(TestFragment.ENTER));
assertFalse(mMidFragment.wasStartCalled(TestFragment.EXIT));
assertFalse(mMidFragment.wasStartCalled(TestFragment.REENTER));
assertFalse(mMidFragment.wasStartCalled(TestFragment.RETURN));
assertTrue(mStartFragment.wasStartCalled(TestFragment.REENTER));
assertFalse(mStartFragment.wasStartCalled(TestFragment.ENTER));
assertFalse(mStartFragment.wasStartCalled(TestFragment.EXIT));
assertFalse(mStartFragment.wasStartCalled(TestFragment.RETURN));
}
public void testNullTransition() throws Throwable {
runTestOnUiThread(new Runnable() {
@Override
public void run() {
mStartFragment = new TestFragment(R.layout.fragment_start);
mStartFragment.clearTransitions();
mActivity.getFragmentManager().beginTransaction()
.replace(R.id.content, mStartFragment)
.commit();
mActivity.getFragmentManager().executePendingTransactions();
}
});
waitForStart(mStartFragment, TestFragment.ENTER);
// No transitions
assertFalse(mStartFragment.wasStartCalled(TestFragment.ENTER));
runTestOnUiThread(new Runnable() {
@Override
public void run() {
mMidFragment = new TestFragment(R.layout.checkbox_layout);
mEndFragment = new TestFragment(R.layout.fragment_end);
mEndFragment.clearTransitions();
mActivity.getFragmentManager().beginTransaction()
.replace(R.id.content, mMidFragment)
.replace(R.id.content, mEndFragment)
.addToBackStack(null)
.commit();
mActivity.getFragmentManager().executePendingTransactions();
}
});
waitForStart(mEndFragment, TestFragment.ENTER);
assertFalse(mEndFragment.wasEndCalled(TestFragment.ENTER));
assertFalse(mEndFragment.wasEndCalled(TestFragment.EXIT));
assertFalse(mEndFragment.wasEndCalled(TestFragment.RETURN));
assertFalse(mEndFragment.wasEndCalled(TestFragment.REENTER));
assertFalse(mStartFragment.wasEndCalled(TestFragment.EXIT));
assertFalse(mStartFragment.wasEndCalled(TestFragment.ENTER));
assertFalse(mStartFragment.wasEndCalled(TestFragment.RETURN));
assertFalse(mStartFragment.wasEndCalled(TestFragment.REENTER));
assertFalse(mMidFragment.wasStartCalled(TestFragment.ENTER));
assertFalse(mMidFragment.wasStartCalled(TestFragment.EXIT));
assertFalse(mMidFragment.wasStartCalled(TestFragment.REENTER));
assertFalse(mMidFragment.wasStartCalled(TestFragment.RETURN));
runTestOnUiThread(new Runnable() {
@Override
public void run() {
mActivity.getFragmentManager().popBackStack();
mActivity.getFragmentManager().executePendingTransactions();
}
});
waitForStart(mEndFragment, TestFragment.RETURN);
assertFalse(mEndFragment.wasEndCalled(TestFragment.RETURN));
assertFalse(mMidFragment.wasStartCalled(TestFragment.ENTER));
assertFalse(mMidFragment.wasStartCalled(TestFragment.EXIT));
assertFalse(mMidFragment.wasStartCalled(TestFragment.REENTER));
assertFalse(mMidFragment.wasStartCalled(TestFragment.RETURN));
assertFalse(mStartFragment.wasStartCalled(TestFragment.REENTER));
assertFalse(mStartFragment.wasStartCalled(TestFragment.ENTER));
assertFalse(mStartFragment.wasStartCalled(TestFragment.EXIT));
assertFalse(mStartFragment.wasStartCalled(TestFragment.RETURN));
}
public void testRemoveAdded() throws Throwable {
runTestOnUiThread(new Runnable() {
@Override
public void run() {
mStartFragment = new TestFragment(R.layout.fragment_start);
mActivity.getFragmentManager().beginTransaction()
.replace(R.id.content, mStartFragment)
.commit();
mActivity.getFragmentManager().executePendingTransactions();
}
});
waitForEnd(mStartFragment, TestFragment.ENTER);
assertTrue(mStartFragment.wasEndCalled(TestFragment.ENTER));
mStartFragment.clearNotifications();
runTestOnUiThread(new Runnable() {
@Override
public void run() {
mEndFragment = new TestFragment(R.layout.fragment_end);
mActivity.getFragmentManager().beginTransaction()
.replace(R.id.content, mEndFragment)
.replace(R.id.content, mStartFragment)
.replace(R.id.content, mEndFragment)
.addToBackStack(null)
.commit();
mActivity.getFragmentManager().executePendingTransactions();
}
});
waitForEnd(mEndFragment, TestFragment.ENTER);
assertTrue(mEndFragment.wasEndCalled(TestFragment.ENTER));
assertTrue(mStartFragment.wasEndCalled(TestFragment.EXIT));
runTestOnUiThread(new Runnable() {
@Override
public void run() {
mActivity.getFragmentManager().popBackStack();
mActivity.getFragmentManager().executePendingTransactions();
}
});
waitForEnd(mStartFragment, TestFragment.REENTER);
assertTrue(mStartFragment.wasEndCalled(TestFragment.REENTER));
assertTrue(mEndFragment.wasEndCalled(TestFragment.RETURN));
}
public void testAddRemoved() throws Throwable {
runTestOnUiThread(new Runnable() {
@Override
public void run() {
mStartFragment = new TestFragment(R.layout.fragment_start);
mActivity.getFragmentManager().beginTransaction()
.replace(R.id.content, mStartFragment)
.commit();
mActivity.getFragmentManager().executePendingTransactions();
}
});
waitForEnd(mStartFragment, TestFragment.ENTER);
assertTrue(mStartFragment.wasEndCalled(TestFragment.ENTER));
mStartFragment.clearNotifications();
runTestOnUiThread(new Runnable() {
@Override
public void run() {
mEndFragment = new TestFragment(R.layout.fragment_end);
mActivity.getFragmentManager().beginTransaction()
.replace(R.id.content, mEndFragment)
.replace(R.id.content, mStartFragment)
.addToBackStack(null)
.commit();
mActivity.getFragmentManager().executePendingTransactions();
}
});
waitForStart(mStartFragment, TestFragment.ENTER);
assertFalse(mStartFragment.wasStartCalled(TestFragment.ENTER));
assertFalse(mStartFragment.wasStartCalled(TestFragment.EXIT));
assertFalse(mEndFragment.wasStartCalled(TestFragment.ENTER));
assertFalse(mEndFragment.wasStartCalled(TestFragment.EXIT));
runTestOnUiThread(new Runnable() {
@Override
public void run() {
mActivity.getFragmentManager().popBackStack();
mActivity.getFragmentManager().executePendingTransactions();
}
});
waitForStart(mStartFragment, TestFragment.REENTER);
assertFalse(mStartFragment.wasStartCalled(TestFragment.REENTER));
assertFalse(mStartFragment.wasStartCalled(TestFragment.RETURN));
assertFalse(mEndFragment.wasStartCalled(TestFragment.REENTER));
assertFalse(mEndFragment.wasStartCalled(TestFragment.RETURN));
}
private boolean waitForStart(TestFragment fragment, int key) throws InterruptedException {
final boolean started;
WaitForTransition listener = new WaitForTransition(key, true);
fragment.setOnTransitionListener(listener);
final long endTime = SystemClock.uptimeMillis() + 100;
synchronized (listener) {
long waitTime;
while ((waitTime = endTime - SystemClock.uptimeMillis()) > 0 &&
!listener.isDone()) {
listener.wait(waitTime);
}
started = listener.isDone();
}
fragment.setOnTransitionListener(null);
getInstrumentation().waitForIdleSync();
return started;
}
private boolean waitForEnd(TestFragment fragment, int key) throws InterruptedException {
if (!waitForStart(fragment, key)) {
return false;
}
final boolean ended;
WaitForTransition listener = new WaitForTransition(key, false);
fragment.setOnTransitionListener(listener);
final long endTime = SystemClock.uptimeMillis() + 400;
synchronized (listener) {
long waitTime;
while ((waitTime = endTime - SystemClock.uptimeMillis()) > 0 &&
!listener.isDone()) {
listener.wait(waitTime);
}
ended = listener.isDone();
}
fragment.setOnTransitionListener(null);
getInstrumentation().waitForIdleSync();
return ended;
}
private static class WaitForTransition implements OnTransitionListener {
final int key;
final boolean isStart;
boolean isDone;
public WaitForTransition(int key, boolean isStart) {
this.key = key;
this.isStart = isStart;
}
protected boolean isComplete(TestFragment fragment) {
if (isStart) {
return fragment.wasStartCalled(key);
} else {
return fragment.wasEndCalled(key);
}
}
public synchronized boolean isDone() {
return isDone;
}
@Override
public synchronized void onTransition(TestFragment fragment) {
isDone = isComplete(fragment);
if (isDone) {
notifyAll();
}
}
}
}