Home | History | Annotate | Download | only in am
      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 
     17 package com.android.server.am;
     18 
     19 import static org.mockito.Mockito.mock;
     20 import static org.mockito.Mockito.doReturn;
     21 import static org.mockito.Mockito.any;
     22 import static org.mockito.Mockito.doAnswer;
     23 
     24 import org.mockito.invocation.InvocationOnMock;
     25 
     26 import android.app.ActivityManager;
     27 import android.content.ComponentName;
     28 import android.content.Context;
     29 import android.content.Intent;
     30 import android.content.pm.ActivityInfo;
     31 import android.content.pm.ApplicationInfo;
     32 import android.content.res.Configuration;
     33 import android.graphics.Rect;
     34 import android.os.HandlerThread;
     35 import android.os.Looper;
     36 import android.support.test.InstrumentationRegistry;
     37 import com.android.server.AttributeCache;
     38 import com.android.server.wm.AppWindowContainerController;
     39 import com.android.server.wm.StackWindowController;
     40 
     41 import com.android.server.wm.TaskWindowContainerController;
     42 import com.android.server.wm.WindowManagerService;
     43 import com.android.server.wm.WindowTestUtils;
     44 import org.junit.After;
     45 import org.junit.Before;
     46 import org.mockito.MockitoAnnotations;
     47 
     48 /**
     49  * A base class to handle common operations in activity related unit tests.
     50  */
     51 public class ActivityTestsBase {
     52     private final Context mContext = InstrumentationRegistry.getContext();
     53     private HandlerThread mHandlerThread;
     54 
     55     // Grabbing an instance of {@link WindowManagerService} creates it if not present so this must
     56     // be called at before any tests.
     57     private final WindowManagerService mWms = WindowTestUtils.getWindowManagerService(mContext);
     58 
     59     @Before
     60     public void setUp() throws Exception {
     61         MockitoAnnotations.initMocks(this);
     62         mHandlerThread = new HandlerThread("ActivityTestsBaseThread");
     63         mHandlerThread.start();
     64     }
     65 
     66     @After
     67     public void tearDown() {
     68         mHandlerThread.quitSafely();
     69     }
     70 
     71     protected ActivityManagerService createActivityManagerService() {
     72         final ActivityManagerService service = new TestActivityManagerService(mContext);
     73         service.mWindowManager = WindowTestUtils.getMockWindowManagerService();
     74         return service;
     75     }
     76 
     77     protected static ActivityStack createActivityStack(ActivityManagerService service,
     78             int stackId, int displayId, boolean onTop) {
     79         if (service.mStackSupervisor instanceof TestActivityStackSupervisor) {
     80             return ((TestActivityStackSupervisor) service.mStackSupervisor)
     81                     .createTestStack(service, stackId, onTop);
     82         }
     83 
     84         return null;
     85     }
     86 
     87     protected static ActivityRecord createActivity(ActivityManagerService service,
     88             ComponentName component, TaskRecord task) {
     89         Intent intent = new Intent();
     90         intent.setComponent(component);
     91         final ActivityInfo aInfo = new ActivityInfo();
     92         aInfo.applicationInfo = new ApplicationInfo();
     93         aInfo.applicationInfo.packageName = component.getPackageName();
     94         AttributeCache.init(service.mContext);
     95         final ActivityRecord activity = new ActivityRecord(service, null /* caller */,
     96                 0 /* launchedFromPid */, 0, null, intent, null,
     97                 aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */,
     98                 0 /* reqCode */, false /*componentSpecified*/, false /* rootVoiceInteraction */,
     99                 service.mStackSupervisor, null /* container */, null /* options */,
    100                 null /* sourceRecord */);
    101         activity.mWindowContainerController = mock(AppWindowContainerController.class);
    102 
    103         if (task != null) {
    104             task.addActivityToTop(activity);
    105         }
    106 
    107         return activity;
    108     }
    109 
    110     protected static TaskRecord createTask(ActivityManagerService service,
    111             ComponentName component, int stackId) {
    112         final ActivityInfo aInfo = new ActivityInfo();
    113         aInfo.applicationInfo = new ApplicationInfo();
    114         aInfo.applicationInfo.packageName = component.getPackageName();
    115 
    116         Intent intent = new Intent();
    117         intent.setComponent(component);
    118 
    119         final TaskRecord task = new TaskRecord(service, 0, aInfo, intent /*intent*/,
    120                 null /*_taskDescription*/, new ActivityManager.TaskThumbnailInfo());
    121         final ActivityStack stack = service.mStackSupervisor.getStack(stackId,
    122                 true /*createStaticStackIfNeeded*/, true /*onTop*/);
    123         stack.addTask(task, true, "creating test task");
    124         task.setStack(stack);
    125         task.setWindowContainerController(mock(TaskWindowContainerController.class));
    126 
    127         return task;
    128     }
    129 
    130 
    131     /**
    132      * An {@link ActivityManagerService} subclass which provides a test
    133      * {@link ActivityStackSupervisor}.
    134      */
    135     protected static class TestActivityManagerService extends ActivityManagerService {
    136         public TestActivityManagerService(Context context) {
    137             super(context);
    138             mSupportsMultiWindow = true;
    139             mSupportsMultiDisplay = true;
    140             mWindowManager = WindowTestUtils.getWindowManagerService(context);
    141         }
    142 
    143         @Override
    144         protected ActivityStackSupervisor createStackSupervisor() {
    145             return new TestActivityStackSupervisor(this, mHandlerThread.getLooper());
    146         }
    147     }
    148 
    149     /**
    150      * An {@link ActivityStackSupervisor} which stubs out certain methods that depend on
    151      * setup not available in the test environment. Also specifies an injector for
    152      */
    153     protected static class TestActivityStackSupervisor extends ActivityStackSupervisor {
    154         private final ActivityDisplay mDisplay;
    155 
    156         public TestActivityStackSupervisor(ActivityManagerService service, Looper looper) {
    157             super(service, looper);
    158             mWindowManager = prepareMockWindowManager();
    159             mDisplay = new ActivityDisplay();
    160         }
    161 
    162         // No home stack is set.
    163         @Override
    164         void moveHomeStackToFront(String reason) {
    165         }
    166 
    167         @Override
    168         boolean moveHomeStackTaskToTop(String reason) {
    169             return true;
    170         }
    171 
    172         // Invoked during {@link ActivityStack} creation.
    173         @Override
    174         void updateUIDsPresentOnDisplay() {
    175         }
    176 
    177         // Just return the current front task.
    178         @Override
    179         ActivityStack getNextFocusableStackLocked(ActivityStack currentFocus) {
    180             return mFocusedStack;
    181         }
    182 
    183         // Called when moving activity to pinned stack.
    184         @Override
    185         void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
    186                 boolean preserveWindows) {
    187         }
    188 
    189         public <T extends ActivityStack> T createTestStack(ActivityManagerService service,
    190                 int stackId, boolean onTop) {
    191             final TestActivityContainer container =
    192                     new TestActivityContainer(service, stackId, mDisplay, onTop);
    193             mActivityContainers.put(stackId, container);
    194             return (T) container.getStack();
    195         }
    196 
    197         @Override
    198         protected <T extends ActivityStack> T getStack(int stackId,
    199                 boolean createStaticStackIfNeeded, boolean createOnTop) {
    200             final T stack = super.getStack(stackId, createStaticStackIfNeeded, createOnTop);
    201 
    202             if (stack != null || !createStaticStackIfNeeded) {
    203                 return stack;
    204             }
    205 
    206             return createTestStack(mService, stackId, createOnTop);
    207         }
    208 
    209         private class TestActivityContainer extends ActivityContainer {
    210             private final ActivityManagerService mService;
    211 
    212             private boolean mOnTop;
    213             private int mStackId;
    214             private ActivityStack mStack;
    215 
    216             TestActivityContainer(ActivityManagerService service, int stackId,
    217                     ActivityDisplay activityDisplay, boolean onTop) {
    218                 super(stackId, activityDisplay, onTop);
    219                 mService = service;
    220             }
    221 
    222             @Override
    223             protected void createStack(int stackId, boolean onTop) {
    224                 // normally stack creation is done here. However we need to do it on demand since
    225                 // we cannot set {@link mService} by the time the super constructor calling this
    226                 // method is invoked.
    227                 mOnTop = onTop;
    228                 mStackId = stackId;
    229             }
    230 
    231             public ActivityStack getStack() {
    232                 if (mStack == null) {
    233                     final RecentTasks recents =
    234                             new RecentTasks(mService, mService.mStackSupervisor);
    235                     if (mStackId == ActivityManager.StackId.PINNED_STACK_ID) {
    236                         mStack = new PinnedActivityStack(this, recents, mOnTop) {
    237                             @Override
    238                             Rect getDefaultPictureInPictureBounds(float aspectRatio) {
    239                                 return new Rect(50, 50, 100, 100);
    240                             }
    241                         };
    242                     } else {
    243                         mStack = new TestActivityStack(this, recents, mOnTop);
    244                     }
    245                 }
    246 
    247                 return mStack;
    248             }
    249         }
    250     }
    251 
    252     private static WindowManagerService prepareMockWindowManager() {
    253         final WindowManagerService service = mock(WindowManagerService.class);
    254 
    255         doAnswer((InvocationOnMock invocationOnMock) -> {
    256             final Runnable runnable = invocationOnMock.<Runnable>getArgument(0);
    257             if (runnable != null) {
    258                 runnable.run();
    259             }
    260             return null;
    261         }).when(service).inSurfaceTransaction(any());
    262 
    263         return service;
    264     }
    265 
    266     protected interface ActivityStackReporter {
    267         int onActivityRemovedFromStackInvocationCount();
    268     }
    269 
    270     /**
    271      * Override of {@link ActivityStack} that tracks test metrics, such as the number of times a
    272      * method is called. Note that its functionality depends on the implementations of the
    273      * construction arguments.
    274      */
    275     protected static class TestActivityStack<T extends StackWindowController>
    276             extends ActivityStack<T> implements ActivityStackReporter {
    277         private int mOnActivityRemovedFromStackCount = 0;
    278         private T mContainerController;
    279         TestActivityStack(ActivityStackSupervisor.ActivityContainer activityContainer,
    280                 RecentTasks recentTasks, boolean onTop) {
    281             super(activityContainer, recentTasks, onTop);
    282         }
    283 
    284         @Override
    285         void onActivityRemovedFromStack(ActivityRecord r) {
    286             mOnActivityRemovedFromStackCount++;
    287             super.onActivityRemovedFromStack(r);
    288         }
    289 
    290         // Returns the number of times {@link #onActivityRemovedFromStack} has been called
    291         @Override
    292         public int onActivityRemovedFromStackInvocationCount() {
    293             return mOnActivityRemovedFromStackCount;
    294         }
    295 
    296         @Override
    297         protected T createStackWindowController(int displayId, boolean onTop,
    298                 Rect outBounds) {
    299             mContainerController = (T) WindowTestUtils.createMockStackWindowContainerController();
    300             return mContainerController;
    301         }
    302 
    303         @Override
    304         T getWindowContainerController() {
    305             return mContainerController;
    306         }
    307     }
    308 
    309 
    310     protected static class ActivityStackBuilder {
    311         private boolean mOnTop = true;
    312         private int mStackId = 0;
    313         private int mDisplayId = 1;
    314 
    315         private final ActivityManagerService mService;
    316 
    317         public ActivityStackBuilder(ActivityManagerService ams) {
    318             mService = ams;
    319         }
    320 
    321         public ActivityStackBuilder setOnTop(boolean onTop) {
    322             mOnTop = onTop;
    323             return this;
    324         }
    325 
    326         public ActivityStackBuilder setStackId(int id) {
    327             mStackId = id;
    328             return this;
    329         }
    330 
    331         public ActivityStackBuilder setDisplayId(int id) {
    332             mDisplayId = id;
    333             return this;
    334         }
    335 
    336         public ActivityStack build() {
    337             return createActivityStack(mService, mStackId, mDisplayId, mOnTop);
    338         }
    339     }
    340 }
    341