1 /* 2 * Copyright 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.app.activity; 18 19 import static android.content.Intent.ACTION_EDIT; 20 import static android.content.Intent.ACTION_VIEW; 21 22 import static org.junit.Assert.assertNull; 23 import static org.junit.Assert.assertTrue; 24 25 import android.app.Activity; 26 import android.app.ActivityThread; 27 import android.app.IApplicationThread; 28 import android.app.servertransaction.ActivityRelaunchItem; 29 import android.app.servertransaction.ClientTransaction; 30 import android.app.servertransaction.ClientTransactionItem; 31 import android.app.servertransaction.ResumeActivityItem; 32 import android.app.servertransaction.StopActivityItem; 33 import android.content.Intent; 34 import android.os.IBinder; 35 import android.support.test.InstrumentationRegistry; 36 import android.support.test.filters.MediumTest; 37 import android.support.test.rule.ActivityTestRule; 38 import android.support.test.runner.AndroidJUnit4; 39 import android.util.MergedConfiguration; 40 41 import org.junit.Test; 42 import org.junit.runner.RunWith; 43 44 /** 45 * Test for verifying {@link android.app.ActivityThread} class. 46 * Build/Install/Run: 47 * atest FrameworksCoreTests:android.app.activity.ActivityThreadTest 48 */ 49 @RunWith(AndroidJUnit4.class) 50 @MediumTest 51 public class ActivityThreadTest { 52 53 private final ActivityTestRule mActivityTestRule = 54 new ActivityTestRule(TestActivity.class, true /* initialTouchMode */, 55 false /* launchActivity */); 56 57 @Test testDoubleRelaunch()58 public void testDoubleRelaunch() throws Exception { 59 final Activity activity = mActivityTestRule.launchActivity(new Intent()); 60 final IApplicationThread appThread = activity.getActivityThread().getApplicationThread(); 61 62 appThread.scheduleTransaction(newRelaunchResumeTransaction(activity)); 63 appThread.scheduleTransaction(newRelaunchResumeTransaction(activity)); 64 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); 65 } 66 67 @Test testResumeAfterRelaunch()68 public void testResumeAfterRelaunch() throws Exception { 69 final Activity activity = mActivityTestRule.launchActivity(new Intent()); 70 final IApplicationThread appThread = activity.getActivityThread().getApplicationThread(); 71 72 appThread.scheduleTransaction(newRelaunchResumeTransaction(activity)); 73 appThread.scheduleTransaction(newResumeTransaction(activity)); 74 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); 75 } 76 77 @Test testSleepAndStop()78 public void testSleepAndStop() throws Exception { 79 final Activity activity = mActivityTestRule.launchActivity(new Intent()); 80 final IApplicationThread appThread = activity.getActivityThread().getApplicationThread(); 81 82 appThread.scheduleSleeping(activity.getActivityToken(), true /* sleeping */); 83 appThread.scheduleTransaction(newStopTransaction(activity)); 84 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); 85 } 86 87 /** Verify that repeated resume requests to activity will be ignored. */ 88 @Test testRepeatedResume()89 public void testRepeatedResume() throws Exception { 90 final Activity activity = mActivityTestRule.launchActivity(new Intent()); 91 final ActivityThread activityThread = activity.getActivityThread(); 92 InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { 93 activityThread.executeTransaction(newResumeTransaction(activity)); 94 assertNull(activityThread.performResumeActivity(activity.getActivityToken(), 95 true /* finalStateRequest */, "test")); 96 97 assertNull(activityThread.performResumeActivity(activity.getActivityToken(), 98 false /* finalStateRequest */, "test")); 99 }); 100 } 101 102 /** Verify that custom intent set via Activity#setIntent() is preserved on relaunch. */ 103 @Test testCustomIntentPreservedOnRelaunch()104 public void testCustomIntentPreservedOnRelaunch() throws Exception { 105 final Intent initIntent = new Intent(); 106 initIntent.setAction(ACTION_VIEW); 107 final Activity activity = mActivityTestRule.launchActivity(initIntent); 108 IBinder token = activity.getActivityToken(); 109 110 final ActivityThread activityThread = activity.getActivityThread(); 111 InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { 112 // Recreate and check that intent is still the same. 113 activity.recreate(); 114 115 final Activity newActivity = activityThread.getActivity(token); 116 assertTrue("Original intent must be preserved after recreate", 117 initIntent.filterEquals(newActivity.getIntent())); 118 119 // Set custom intent, recreate and check if it is preserved. 120 final Intent customIntent = new Intent(); 121 customIntent.setAction(ACTION_EDIT); 122 newActivity.setIntent(customIntent); 123 124 activity.recreate(); 125 126 final Activity lastActivity = activityThread.getActivity(token); 127 assertTrue("Custom intent must be preserved after recreate", 128 customIntent.filterEquals(lastActivity.getIntent())); 129 }); 130 } 131 newRelaunchResumeTransaction(Activity activity)132 private static ClientTransaction newRelaunchResumeTransaction(Activity activity) { 133 final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(null, 134 null, 0, new MergedConfiguration(), false /* preserveWindow */); 135 final ResumeActivityItem resumeStateRequest = 136 ResumeActivityItem.obtain(true /* isForward */); 137 138 final ClientTransaction transaction = newTransaction(activity); 139 transaction.addCallback(callbackItem); 140 transaction.setLifecycleStateRequest(resumeStateRequest); 141 142 return transaction; 143 } 144 newResumeTransaction(Activity activity)145 private static ClientTransaction newResumeTransaction(Activity activity) { 146 final ResumeActivityItem resumeStateRequest = 147 ResumeActivityItem.obtain(true /* isForward */); 148 149 final ClientTransaction transaction = newTransaction(activity); 150 transaction.setLifecycleStateRequest(resumeStateRequest); 151 152 return transaction; 153 } 154 newStopTransaction(Activity activity)155 private static ClientTransaction newStopTransaction(Activity activity) { 156 final StopActivityItem stopStateRequest = 157 StopActivityItem.obtain(false /* showWindow */, 0 /* configChanges */); 158 159 final ClientTransaction transaction = newTransaction(activity); 160 transaction.setLifecycleStateRequest(stopStateRequest); 161 162 return transaction; 163 } 164 newTransaction(Activity activity)165 private static ClientTransaction newTransaction(Activity activity) { 166 final IApplicationThread appThread = activity.getActivityThread().getApplicationThread(); 167 return ClientTransaction.obtain(appThread, activity.getActivityToken()); 168 } 169 170 // Test activity 171 public static class TestActivity extends Activity { 172 } 173 } 174