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