1 /* 2 * Copyright (C) 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 com.android.server.wm; 18 19 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; 20 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; 21 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE; 22 23 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 24 25 import static org.junit.Assert.assertEquals; 26 import static org.junit.Assert.assertNotEquals; 27 import static org.junit.Assert.assertNotNull; 28 import static org.junit.Assert.assertNull; 29 import static org.junit.Assert.assertTrue; 30 31 import android.app.Activity; 32 import android.app.ActivityManager.RunningTaskInfo; 33 import android.app.ActivityOptions; 34 import android.app.Instrumentation; 35 import android.app.Instrumentation.ActivityMonitor; 36 import android.app.PictureInPictureParams; 37 import android.content.ComponentName; 38 import android.content.Context; 39 import android.content.Intent; 40 import android.os.Binder; 41 import android.os.Bundle; 42 import android.os.IBinder; 43 import android.platform.test.annotations.Presubmit; 44 import android.util.Rational; 45 import android.view.SurfaceControl; 46 import android.window.TaskOrganizer; 47 48 import androidx.test.filters.MediumTest; 49 50 import org.junit.Test; 51 52 import java.util.concurrent.CountDownLatch; 53 import java.util.concurrent.TimeUnit; 54 55 /** 56 * Build/Install/Run: 57 * atest WmTests:ActivityOptionsTest 58 */ 59 @MediumTest 60 @Presubmit 61 public class ActivityOptionsTest { 62 63 @Test testMerge_NoClobber()64 public void testMerge_NoClobber() { 65 // Construct some options with set values 66 ActivityOptions opts = ActivityOptions.makeBasic(); 67 opts.setLaunchDisplayId(Integer.MAX_VALUE); 68 opts.setLaunchActivityType(ACTIVITY_TYPE_STANDARD); 69 opts.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN); 70 opts.setAvoidMoveToFront(); 71 opts.setLaunchTaskId(Integer.MAX_VALUE); 72 opts.setLockTaskEnabled(true); 73 opts.setRotationAnimationHint(ROTATION_ANIMATION_ROTATE); 74 opts.setTaskAlwaysOnTop(true); 75 opts.setTaskOverlay(true, true); 76 Bundle optsBundle = opts.toBundle(); 77 78 // Try and merge the constructed options with a new set of options 79 optsBundle.putAll(ActivityOptions.makeBasic().toBundle()); 80 81 // Ensure the set values are not clobbered 82 ActivityOptions restoredOpts = ActivityOptions.fromBundle(optsBundle); 83 assertEquals(Integer.MAX_VALUE, restoredOpts.getLaunchDisplayId()); 84 assertEquals(ACTIVITY_TYPE_STANDARD, restoredOpts.getLaunchActivityType()); 85 assertEquals(WINDOWING_MODE_FULLSCREEN, restoredOpts.getLaunchWindowingMode()); 86 assertTrue(restoredOpts.getAvoidMoveToFront()); 87 assertEquals(Integer.MAX_VALUE, restoredOpts.getLaunchTaskId()); 88 assertTrue(restoredOpts.getLockTaskMode()); 89 assertEquals(ROTATION_ANIMATION_ROTATE, restoredOpts.getRotationAnimationHint()); 90 assertTrue(restoredOpts.getTaskAlwaysOnTop()); 91 assertTrue(restoredOpts.getTaskOverlay()); 92 assertTrue(restoredOpts.canTaskOverlayResume()); 93 } 94 95 @Test testMakeLaunchIntoPip()96 public void testMakeLaunchIntoPip() { 97 // Construct some params with set values 98 PictureInPictureParams params = new PictureInPictureParams.Builder() 99 .setAspectRatio(new Rational(1, 1)) 100 .build(); 101 // Construct ActivityOptions via makeLaunchIntoPip 102 ActivityOptions opts = ActivityOptions.makeLaunchIntoPip(params); 103 104 // Verify the params in ActivityOptions has the right flag being turned on 105 assertNotNull(opts.getLaunchIntoPipParams()); 106 assertTrue(opts.isLaunchIntoPip()); 107 } 108 109 @Test testTransferLaunchCookie()110 public void testTransferLaunchCookie() { 111 final Binder cookie = new Binder(); 112 final ActivityOptions options = ActivityOptions.makeBasic(); 113 options.setLaunchCookie(cookie); 114 final Instrumentation instrumentation = getInstrumentation(); 115 final Context context = instrumentation.getContext(); 116 final ComponentName trampoline = new ComponentName(context, TrampolineActivity.class); 117 final ComponentName main = new ComponentName(context, MainActivity.class); 118 final Intent intent = new Intent().setComponent(trampoline) 119 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 120 final ActivityMonitor monitor = new ActivityMonitor(main.getClassName(), 121 null /* result */, false /* block */); 122 instrumentation.addMonitor(monitor); 123 final CountDownLatch mainLatch = new CountDownLatch(1); 124 final IBinder[] appearedCookies = new IBinder[2]; 125 final TaskOrganizer organizer = new TaskOrganizer() { 126 @Override 127 public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { 128 try (SurfaceControl.Transaction t = new SurfaceControl.Transaction()) { 129 t.show(leash).apply(); 130 } 131 int cookieIndex = -1; 132 if (trampoline.equals(taskInfo.baseActivity)) { 133 cookieIndex = 0; 134 } else if (main.equals(taskInfo.baseActivity)) { 135 cookieIndex = 1; 136 } 137 if (cookieIndex >= 0) { 138 appearedCookies[cookieIndex] = taskInfo.launchCookies.isEmpty() 139 ? null : taskInfo.launchCookies.get(0); 140 if (cookieIndex == 1) { 141 mainLatch.countDown(); 142 } 143 } 144 } 145 }; 146 Activity mainActivity = null; 147 try { 148 organizer.registerOrganizer(); 149 context.startActivity(intent, options.toBundle()); 150 try { 151 mainLatch.await(10, TimeUnit.SECONDS); 152 } catch (InterruptedException ignored) { 153 } 154 mainActivity = monitor.getLastActivity(); 155 156 assertNotNull(mainActivity); 157 assertNotEquals(TrampolineActivity.sTaskId, mainActivity.getTaskId()); 158 assertNull("Trampoline task must not have cookie", appearedCookies[0]); 159 assertEquals("Main task must get the same cookie", cookie, appearedCookies[1]); 160 } finally { 161 organizer.unregisterOrganizer(); 162 instrumentation.removeMonitor(monitor); 163 if (mainActivity != null) { 164 mainActivity.finish(); 165 } 166 } 167 } 168 169 public static class TrampolineActivity extends Activity { 170 static int sTaskId; 171 172 @Override onCreate(Bundle savedInstanceState)173 protected void onCreate(Bundle savedInstanceState) { 174 super.onCreate(savedInstanceState); 175 sTaskId = getTaskId(); 176 startActivity(new Intent(this, MainActivity.class) 177 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); 178 finish(); 179 } 180 } 181 182 public static class MainActivity extends Activity { 183 } 184 } 185