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