Merge "CTS: Activity Transition: onSharedElementsArrived tests." into mnc-dev
diff --git a/tests/tests/app.usage/AndroidManifest.xml b/tests/tests/app.usage/AndroidManifest.xml
index 3bd795a..54fde71 100644
--- a/tests/tests/app.usage/AndroidManifest.xml
+++ b/tests/tests/app.usage/AndroidManifest.xml
@@ -32,6 +32,7 @@
<activity android:name=".Activities$ActivityTwo" />
<activity android:name=".Activities$ActivityThree" />
<activity android:name=".Activities$ActivityFour" />
+ <activity android:name=".ActivityTransitionActivity" />
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/app.usage/res/layout/end.xml b/tests/tests/app.usage/res/layout/end.xml
new file mode 100644
index 0000000..2847249
--- /dev/null
+++ b/tests/tests/app.usage/res/layout/end.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+ <View android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:background="#F00"
+ android:id="@+id/redSquare"/>
+ <TextView android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:transitionName="target"
+ android:text="@string/hello"/>
+ <View android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:background="#0F0"
+ android:id="@+id/greenSquare"/>
+</LinearLayout>
diff --git a/tests/tests/app.usage/res/layout/start.xml b/tests/tests/app.usage/res/layout/start.xml
new file mode 100644
index 0000000..793e9b5
--- /dev/null
+++ b/tests/tests/app.usage/res/layout/start.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+ <View android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:background="#0F0"
+ android:id="@+id/greenSquare"/>
+ <View android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:background="#F00"
+ android:id="@+id/redSquare"/>
+ <TextView android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:transitionName="source"
+ android:id="@+id/hello"
+ android:text="@string/hello"/>
+</LinearLayout>
diff --git a/tests/tests/app.usage/res/values/strings.xml b/tests/tests/app.usage/res/values/strings.xml
new file mode 100644
index 0000000..8ca6f73
--- /dev/null
+++ b/tests/tests/app.usage/res/values/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+ <string name="hello">Hello</string>
+</resources>
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/ActivityTransitionActivity.java b/tests/tests/app.usage/src/android/app/usage/cts/ActivityTransitionActivity.java
new file mode 100644
index 0000000..10ac4ea
--- /dev/null
+++ b/tests/tests/app.usage/src/android/app/usage/cts/ActivityTransitionActivity.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2014 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.usage.cts;
+
+import android.app.Activity;
+import android.app.SharedElementCallback;
+import android.app.usage.cts.R;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.ResultReceiver;
+import android.os.SystemClock;
+import android.transition.ChangeBounds;
+import android.transition.Explode;
+import android.transition.Fade;
+import android.transition.Transition;
+import android.transition.Transition.TransitionListener;
+import android.view.View;
+
+import java.util.List;
+
+/**
+ * A simple activity containing the start state for an Activity Transition
+ */
+public class ActivityTransitionActivity extends Activity {
+ private static final long DURATION = 50;
+ private static final long SHARED_ELEMENT_READY_DELAY = 50;
+ public static final String LAYOUT_ID = "layoutId";
+ public static final String TEST = "test";
+ public static final String RESULT_RECEIVER = "resultReceiver";
+
+ public static final int NO_TEST = 0;
+ public static final int TEST_ARRIVE = 1;
+
+ public static final String ARRIVE_COUNT = "numArrived";
+ public static final String ARRIVE_ENTER_START_VISIBILITY = "arriveEnterStartVisibility";
+ public static final String ARRIVE_ENTER_DELAY_VISIBILITY = "arriveEnterDelayVisibility";
+ public static final String ARRIVE_ENTER_TIME_READY = "arriveEnterTimeReady";
+ public static final String ARRIVE_ENTER_TIME = "arriveEnterTime";
+ public static final String ARRIVE_RETURN_TIME_READY = "arriveReturnTimeReady";
+ public static final String ARRIVE_RETURN_TIME = "arriveReturnTime";
+
+ private int mLayoutId;
+ private int mTest;
+ private ResultReceiver mResultReceiver;
+ private int mNumSharedElementsArrivedCalled = 0;
+ private boolean mEntering = true;
+
+ public int resultCode = 0;
+ public Bundle result = new Bundle();
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ getWindow().setSharedElementEnterTransition(new ChangeBounds().setDuration(DURATION));
+ getWindow().setSharedElementReturnTransition(new ChangeBounds().setDuration(DURATION));
+ getWindow().setEnterTransition(new Explode().setDuration(DURATION));
+ getWindow().setReturnTransition(new Explode().setDuration(DURATION));
+ getWindow().setExitTransition(new Fade().setDuration(DURATION));
+ mLayoutId = 0;
+ if (icicle != null) {
+ mLayoutId = icicle.getInt(LAYOUT_ID);
+ mTest = icicle.getInt(TEST);
+ mResultReceiver = icicle.getParcelable(RESULT_RECEIVER);
+ }
+
+ if (mLayoutId == 0) {
+ Intent intent = getIntent();
+ mLayoutId = intent.getIntExtra(LAYOUT_ID, R.layout.start);
+ mTest = intent.getIntExtra(TEST, 0);
+ mResultReceiver = intent.getParcelableExtra(RESULT_RECEIVER);
+ }
+
+ setContentView(mLayoutId);
+
+ startTest();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ outState.putInt(LAYOUT_ID, mLayoutId);
+ outState.putInt(TEST, mTest);
+ outState.putParcelable(RESULT_RECEIVER, mResultReceiver);
+ }
+
+ private void startTest() {
+ if (mTest == TEST_ARRIVE) {
+ setEnterSharedElementCallback(new SharedElementCallback() {
+ @Override
+ public void onSharedElementsArrived(List<String> sharedElementNames,
+ final List<View> sharedElements,
+ final OnSharedElementsReadyListener listener) {
+ mNumSharedElementsArrivedCalled++;
+ result.putInt(ARRIVE_COUNT, mNumSharedElementsArrivedCalled);
+ if (mEntering) {
+ result.putInt(ARRIVE_ENTER_START_VISIBILITY, sharedElements.get(0).getVisibility());
+ result.putLong(ARRIVE_ENTER_TIME, SystemClock.uptimeMillis());
+ } else {
+ result.putLong(ARRIVE_RETURN_TIME, SystemClock.uptimeMillis());
+ }
+
+ getWindow().getDecorView().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if (mEntering) {
+ result.putInt(ARRIVE_ENTER_DELAY_VISIBILITY,
+ sharedElements.get(0).getVisibility());
+ result.putLong(ARRIVE_ENTER_TIME_READY, SystemClock.uptimeMillis());
+ } else {
+ result.putLong(ARRIVE_RETURN_TIME_READY,
+ SystemClock.uptimeMillis());
+ mResultReceiver.send(RESULT_OK, result);
+ }
+ listener.onSharedElementsReady();
+ }
+ }, SHARED_ELEMENT_READY_DELAY);
+ }
+ });
+ getWindow().getEnterTransition().addListener(new TransitionListener() {
+ @Override
+ public void onTransitionStart(Transition transition) {
+ }
+
+ @Override
+ public void onTransitionEnd(Transition transition) {
+ mEntering = false;
+ setResult(RESULT_OK);
+ getWindow().getDecorView().post(new Runnable() {
+ @Override
+ public void run() {
+ finishAfterTransition();
+ }
+ });
+ }
+
+ @Override
+ public void onTransitionCancel(Transition transition) {
+ }
+
+ @Override
+ public void onTransitionPause(Transition transition) {
+ }
+
+ @Override
+ public void onTransitionResume(Transition transition) {
+ }
+ });
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ synchronized (this) {
+ super.onActivityResult(requestCode, resultCode, data);
+ this.resultCode = resultCode;
+ this.notifyAll();
+ }
+ }
+}
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/ActivityTransitionTest.java b/tests/tests/app.usage/src/android/app/usage/cts/ActivityTransitionTest.java
new file mode 100644
index 0000000..ef126fe
--- /dev/null
+++ b/tests/tests/app.usage/src/android/app/usage/cts/ActivityTransitionTest.java
@@ -0,0 +1,147 @@
+/*
+ * 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.usage.cts;
+
+import android.app.ActivityOptions;
+import android.app.SharedElementCallback;
+import android.app.usage.cts.R;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.ResultReceiver;
+import android.os.SystemClock;
+import android.test.ActivityInstrumentationTestCase2;
+import android.view.View;
+
+import java.util.List;
+
+public class ActivityTransitionTest extends
+ ActivityInstrumentationTestCase2<ActivityTransitionActivity> {
+ protected ActivityTransitionActivity mActivity;
+
+ private int mNumArrivedCalls;
+ private PassInfo mReceiver;
+ private long mExitTime;
+ private long mExitTimeReady;
+ private long mReenterTime;
+ private long mReenterTimeReady;
+
+ public ActivityTransitionTest() {
+ super(ActivityTransitionActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ setActivityInitialTouchMode(false);
+ mActivity = getActivity();
+ mNumArrivedCalls = 0;
+ }
+
+ public void testOnSharedElementsArrived() throws Throwable {
+ getInstrumentation().waitForIdleSync();
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mReceiver = new PassInfo(new Handler());
+ mActivity.setExitSharedElementCallback(new SharedElementCallback() {
+ @Override
+ public void onSharedElementsArrived(List<String> sharedElementNames,
+ List<View> sharedElements,
+ final OnSharedElementsReadyListener listener) {
+ mNumArrivedCalls++;
+ final boolean isExiting = mExitTimeReady == 0;
+ if (isExiting) {
+ mExitTime = SystemClock.uptimeMillis();
+ } else {
+ mReenterTime = SystemClock.uptimeMillis();
+ }
+ mActivity.getWindow().getDecorView().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if (isExiting) {
+ mExitTimeReady = SystemClock.uptimeMillis();
+ } else {
+ mReenterTimeReady = SystemClock.uptimeMillis();
+ }
+ listener.onSharedElementsReady();
+ }
+ }, 60);
+ }
+ });
+
+ Bundle options = ActivityOptions.makeSceneTransitionAnimation(mActivity,
+ mActivity.findViewById(R.id.hello), "target").toBundle();
+ Intent intent = new Intent(mActivity, ActivityTransitionActivity.class);
+ intent.putExtra(ActivityTransitionActivity.TEST,
+ ActivityTransitionActivity.TEST_ARRIVE);
+ intent.putExtra(ActivityTransitionActivity.LAYOUT_ID, R.layout.end);
+ intent.putExtra(ActivityTransitionActivity.RESULT_RECEIVER, mReceiver);
+ mActivity.startActivityForResult(intent, 0, options);
+ }
+ });
+
+ long endTime = SystemClock.uptimeMillis() + 1500;
+ synchronized (mActivity) {
+ while (mActivity.resultCode == 0) {
+ long waitTime = endTime - SystemClock.uptimeMillis();
+ if (waitTime <= 0) {
+ fail("Activity didn't finish!");
+ }
+ mActivity.wait(waitTime);
+ }
+ }
+ assertNotNull(mReceiver.resultData);
+ assertEquals(2, mReceiver.resultData.getInt(
+ ActivityTransitionActivity.ARRIVE_COUNT, -1));
+ assertEquals(2, mNumArrivedCalls);
+ assertNotSame(View.VISIBLE, mReceiver.resultData.getInt(
+ ActivityTransitionActivity.ARRIVE_ENTER_START_VISIBILITY));
+ assertNotSame(View.VISIBLE, mReceiver.resultData.getInt(
+ ActivityTransitionActivity.ARRIVE_ENTER_DELAY_VISIBILITY));
+ long enterTimeReady = mReceiver.resultData.getLong(
+ ActivityTransitionActivity.ARRIVE_ENTER_TIME_READY);
+ long returnTimeReady = mReceiver.resultData.getLong(
+ ActivityTransitionActivity.ARRIVE_RETURN_TIME_READY);
+ long enterTime = mReceiver.resultData.getLong(
+ ActivityTransitionActivity.ARRIVE_ENTER_TIME);
+ long returnTime = mReceiver.resultData.getLong(
+ ActivityTransitionActivity.ARRIVE_RETURN_TIME);
+
+ assertTrue(mExitTime < mExitTimeReady);
+ assertTrue(mExitTimeReady <= enterTime);
+ assertTrue(enterTime < enterTimeReady);
+ assertTrue(enterTimeReady <= returnTime);
+ assertTrue(returnTime < returnTimeReady);
+ assertTrue(returnTimeReady <= mReenterTime);
+ assertTrue(mReenterTime < mReenterTimeReady);
+ }
+
+ public static class PassInfo extends ResultReceiver {
+ public int resultCode;
+ public Bundle resultData;
+
+ public PassInfo(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ this.resultCode = resultCode;
+ this.resultData = resultData;
+ }
+ }
+}