ActivityTestsBase.java revision af691c0be7bbfea63e880dd717c51a38a0bc874a
1/* 2 * Copyright (C) 2017 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 17package com.android.server.am; 18 19import static org.mockito.Mockito.mock; 20 21import android.content.ComponentName; 22import android.content.Context; 23import android.content.Intent; 24import android.content.pm.ActivityInfo; 25import android.content.pm.ApplicationInfo; 26import android.content.res.Configuration; 27import android.graphics.Rect; 28import android.os.Handler; 29import android.os.Looper; 30import android.support.test.InstrumentationRegistry; 31import com.android.server.AttributeCache; 32import com.android.server.wm.AppWindowContainerController; 33import com.android.server.wm.StackWindowController; 34 35import com.android.server.wm.WindowManagerService; 36import com.android.server.wm.WindowTestUtils; 37import org.junit.Before; 38import org.mockito.MockitoAnnotations; 39 40/** 41 * A base class to handle common operations in activity related unit tests. 42 */ 43public class ActivityTestsBase { 44 private final Context mContext = InstrumentationRegistry.getContext(); 45 private static boolean sLooperPrepared; 46 private Handler mHandler; 47 48 // Grabbing an instance of {@link WindowManagerService} creates it if not present so this must 49 // be called at before any tests. 50 private final WindowManagerService mWms = WindowTestUtils.getWindowManagerService(mContext); 51 52 @Before 53 public void setUp() throws Exception { 54 MockitoAnnotations.initMocks(this); 55 56 if (!sLooperPrepared) { 57 sLooperPrepared = true; 58 Looper.prepare(); 59 } 60 } 61 62 protected ActivityManagerService createActivityManagerService() { 63 return new TestActivityManagerService(mContext); 64 } 65 66 protected static TestActivityStack createActivityStack(ActivityManagerService service, 67 int stackId, int displayId, boolean onTop) { 68 if (service.mStackSupervisor instanceof TestActivityStackSupervisor) { 69 final TestActivityStack stack = ((TestActivityStackSupervisor) service.mStackSupervisor) 70 .createTestStack(stackId, onTop); 71 return stack; 72 } 73 74 return null; 75 } 76 77 protected static ActivityRecord createActivity(ActivityManagerService service, 78 ComponentName component, TaskRecord task) { 79 Intent intent = new Intent(); 80 intent.setComponent(component); 81 final ActivityInfo aInfo = new ActivityInfo(); 82 aInfo.applicationInfo = new ApplicationInfo(); 83 aInfo.applicationInfo.packageName = component.getPackageName(); 84 AttributeCache.init(service.mContext); 85 final ActivityRecord activity = new ActivityRecord(service, null /* caller */, 86 0 /* launchedFromPid */, 0, null, intent, null, 87 aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */, 88 0 /* reqCode */, false /*componentSpecified*/, false /* rootVoiceInteraction */, 89 service.mStackSupervisor, null /* container */, null /* options */, 90 null /* sourceRecord */); 91 activity.mWindowContainerController = mock(AppWindowContainerController.class); 92 93 if (task != null) { 94 task.addActivityToTop(activity); 95 } 96 97 return activity; 98 } 99 100 protected static TaskRecord createTask(ActivityManagerService service, 101 ComponentName component, ActivityStack stack) { 102 final ActivityInfo aInfo = new ActivityInfo(); 103 aInfo.applicationInfo = new ApplicationInfo(); 104 aInfo.applicationInfo.packageName = component.getPackageName(); 105 106 Intent intent = new Intent(); 107 intent.setComponent(component); 108 109 final TaskRecord task = new TaskRecord(service, 0, aInfo, intent /*intent*/, 110 null /*_taskDescription*/, null /*thumbnailInfo*/); 111 stack.addTask(task, true, "creating test task"); 112 task.setStack(stack); 113 task.createWindowContainer(true, true); 114 115 return task; 116 } 117 118 /** 119 * An {@link ActivityManagerService} subclass which provides a test 120 * {@link ActivityStackSupervisor}. 121 */ 122 protected static class TestActivityManagerService extends ActivityManagerService { 123 public TestActivityManagerService(Context context) { 124 super(context); 125 } 126 127 @Override 128 protected ActivityStackSupervisor createStackSupervisor() { 129 return new TestActivityStackSupervisor(this, new Handler().getLooper()); 130 } 131 } 132 133 /** 134 * An {@link ActivityStackSupervisor} which stubs out certain methods that depend on 135 * setup not available in the test environment. Also specifies an injector for 136 */ 137 protected static class TestActivityStackSupervisor extends ActivityStackSupervisor { 138 public TestActivityStackSupervisor(ActivityManagerService service, Looper looper) { 139 super(service, looper); 140 } 141 142 // Invoked during {@link ActivityStack} creation. 143 @Override 144 void updateUIDsPresentOnDisplay() { 145 } 146 147 public TestActivityStack createTestStack(int stackId, boolean onTop) { 148 final ActivityDisplay display = new ActivityDisplay(); 149 final TestActivityContainer container = 150 new TestActivityContainer(stackId, display, onTop); 151 return container.getStack(); 152 } 153 154 private class TestActivityContainer extends ActivityContainer { 155 private TestActivityStack mStack; 156 TestActivityContainer(int stackId, ActivityDisplay activityDisplay, boolean onTop) { 157 super(stackId, activityDisplay, onTop); 158 } 159 160 @Override 161 protected void createStack(int stackId, boolean onTop) { 162 mStack = new TestActivityStack(this, null /*recentTasks*/, onTop); 163 } 164 165 public TestActivityStack getStack() { 166 return mStack; 167 } 168 } 169 } 170 171 /** 172 * Override of {@link ActivityStack} that tracks test metrics, such as the number of times a 173 * method is called. Note that its functionality depends on the implementations of the 174 * construction arguments. 175 */ 176 protected static class TestActivityStack<T extends StackWindowController> 177 extends ActivityStack<T> { 178 private int mOnActivityRemovedFromStackCount = 0; 179 private T mContainerController; 180 TestActivityStack(ActivityStackSupervisor.ActivityContainer activityContainer, 181 RecentTasks recentTasks, boolean onTop) { 182 super(activityContainer, recentTasks, onTop); 183 } 184 185 @Override 186 void onActivityRemovedFromStack(ActivityRecord r) { 187 mOnActivityRemovedFromStackCount++; 188 super.onActivityRemovedFromStack(r); 189 } 190 191 // Returns the number of times {@link #onActivityRemovedFromStack} has been called 192 public int onActivityRemovedFromStackInvocationCount() { 193 return mOnActivityRemovedFromStackCount; 194 } 195 196 @Override 197 protected T createStackWindowController(int displayId, boolean onTop, 198 Rect outBounds) { 199 mContainerController = (T) WindowTestUtils.createMockStackWindowContainerController(); 200 return mContainerController; 201 } 202 203 @Override 204 T getWindowContainerController() { 205 return mContainerController; 206 } 207 } 208 209 protected static class ActivityStackBuilder { 210 private boolean mOnTop = true; 211 private int mStackId = 0; 212 private int mDisplayId = 1; 213 214 private final ActivityManagerService mService; 215 216 public ActivityStackBuilder(ActivityManagerService ams) { 217 mService = ams; 218 } 219 220 public ActivityStackBuilder setOnTop(boolean onTop) { 221 mOnTop = onTop; 222 return this; 223 } 224 225 public ActivityStackBuilder setStackId(int id) { 226 mStackId = id; 227 return this; 228 } 229 230 public ActivityStackBuilder setDisplayId(int id) { 231 mDisplayId = id; 232 return this; 233 } 234 235 public TestActivityStack build() { 236 return createActivityStack(mService, mStackId, mDisplayId, mOnTop); 237 } 238 } 239} 240