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.systemui.keyguard; 18 19 import static org.mockito.Matchers.any; 20 import static org.mockito.Matchers.anyInt; 21 import static org.mockito.Matchers.argThat; 22 import static org.mockito.Mockito.doReturn; 23 import static org.mockito.Mockito.eq; 24 import static org.mockito.Mockito.never; 25 import static org.mockito.Mockito.verify; 26 27 import android.app.Activity; 28 import android.app.ActivityManager; 29 import android.app.ActivityOptions; 30 import android.app.IActivityTaskManager; 31 import android.app.IApplicationThread; 32 import android.app.ProfilerInfo; 33 import android.content.ComponentName; 34 import android.content.Context; 35 import android.content.Intent; 36 import android.os.Bundle; 37 import android.os.IBinder; 38 import android.os.UserHandle; 39 40 import androidx.test.filters.SmallTest; 41 import androidx.test.runner.AndroidJUnit4; 42 43 import com.android.systemui.SysuiTestCase; 44 import com.android.systemui.shared.system.ActivityManagerWrapper; 45 import com.android.systemui.shared.system.TaskStackChangeListener; 46 47 import org.junit.Before; 48 import org.junit.Test; 49 import org.junit.runner.RunWith; 50 import org.mockito.ArgumentCaptor; 51 import org.mockito.ArgumentMatcher; 52 import org.mockito.Mock; 53 import org.mockito.MockitoAnnotations; 54 55 /** 56 * runtest systemui -c com.android.systemui.keyguard.WorkLockActivityControllerTest 57 */ 58 @SmallTest 59 @RunWith(AndroidJUnit4.class) 60 public class WorkLockActivityControllerTest extends SysuiTestCase { 61 private static final int USER_ID = 333; 62 private static final int TASK_ID = 444; 63 64 private @Mock Context mContext; 65 private @Mock ActivityManagerWrapper mActivityManager; 66 private @Mock IActivityTaskManager mIActivityTaskManager; 67 68 private WorkLockActivityController mController; 69 private TaskStackChangeListener mTaskStackListener; 70 71 @Before setUp()72 public void setUp() throws Exception { 73 MockitoAnnotations.initMocks(this); 74 75 // Set a package name to use for checking ComponentName well-formedness in tests. 76 doReturn("com.example.test").when(mContext).getPackageName(); 77 78 // Construct controller. Save the TaskStackListener for injecting events. 79 final ArgumentCaptor<TaskStackChangeListener> listenerCaptor = 80 ArgumentCaptor.forClass(TaskStackChangeListener.class); 81 mController = new WorkLockActivityController(mContext, mActivityManager, 82 mIActivityTaskManager); 83 84 verify(mActivityManager).registerTaskStackListener(listenerCaptor.capture()); 85 mTaskStackListener = listenerCaptor.getValue(); 86 } 87 88 @Test testOverlayStartedWhenLocked()89 public void testOverlayStartedWhenLocked() throws Exception { 90 // When starting an activity succeeds, 91 setActivityStartCode(TASK_ID, true /*taskOverlay*/, ActivityManager.START_SUCCESS); 92 93 // And the controller receives a message saying the profile is locked, 94 mTaskStackListener.onTaskProfileLocked(TASK_ID, USER_ID); 95 96 // The overlay should start and the task the activity started in should not be removed. 97 verifyStartActivity(TASK_ID, true /*taskOverlay*/); 98 verify(mIActivityTaskManager, never()).removeTask(anyInt() /*taskId*/); 99 } 100 101 @Test testRemoveTaskOnFailureToStartOverlay()102 public void testRemoveTaskOnFailureToStartOverlay() throws Exception { 103 // When starting an activity fails, 104 setActivityStartCode(TASK_ID, true /*taskOverlay*/, ActivityManager.START_CLASS_NOT_FOUND); 105 106 // And the controller receives a message saying the profile is locked, 107 mTaskStackListener.onTaskProfileLocked(TASK_ID, USER_ID); 108 109 // The task the activity started in should be removed to prevent the locked task from 110 // being shown. 111 verifyStartActivity(TASK_ID, true /*taskOverlay*/); 112 verify(mIActivityTaskManager).removeTask(TASK_ID); 113 } 114 115 // End of tests, start of helpers 116 // ------------------------------ 117 setActivityStartCode(int taskId, boolean taskOverlay, int code)118 private void setActivityStartCode(int taskId, boolean taskOverlay, int code) throws Exception { 119 doReturn(code).when(mIActivityTaskManager).startActivityAsUser( 120 eq((IApplicationThread) null), 121 eq((String) null), 122 eq((String) null), 123 any(Intent.class), 124 eq((String) null), 125 eq((IBinder) null), 126 eq((String) null), 127 anyInt(), 128 anyInt(), 129 eq((ProfilerInfo) null), 130 argThat(hasOptions(taskId, taskOverlay)), 131 eq(UserHandle.USER_CURRENT)); 132 } 133 verifyStartActivity(int taskId, boolean taskOverlay)134 private void verifyStartActivity(int taskId, boolean taskOverlay) throws Exception { 135 verify(mIActivityTaskManager).startActivityAsUser( 136 eq((IApplicationThread) null), 137 eq((String) null), 138 eq((String) null), 139 any(Intent.class), 140 eq((String) null), 141 eq((IBinder) null), 142 eq((String) null), 143 anyInt(), 144 anyInt(), 145 eq((ProfilerInfo) null), 146 argThat(hasOptions(taskId, taskOverlay)), 147 eq(UserHandle.USER_CURRENT)); 148 } 149 hasComponent(final Context context, final Class<? extends Activity> activityClass)150 private static ArgumentMatcher<Intent> hasComponent(final Context context, 151 final Class<? extends Activity> activityClass) { 152 return new ArgumentMatcher<Intent>() { 153 @Override 154 public boolean matches(Intent intent) { 155 return new ComponentName(context, activityClass).equals(intent.getComponent()); 156 } 157 }; 158 } 159 160 private static ArgumentMatcher<Bundle> hasOptions(final int taskId, final boolean overlay) { 161 return new ArgumentMatcher<Bundle>() { 162 @Override 163 public boolean matches(Bundle item) { 164 final ActivityOptions options = ActivityOptions.fromBundle(item); 165 return (options.getLaunchTaskId() == taskId) 166 && (options.getTaskOverlay() == overlay); 167 } 168 }; 169 } 170 } 171