1 /* 2 * Copyright (C) 2024 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.wm.shell.desktopmode.minimize 18 19 import android.app.ActivityManager 20 import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM 21 import android.os.Binder 22 import android.os.IBinder 23 import android.testing.AndroidTestingRunner 24 import android.view.SurfaceControl.Transaction 25 import android.view.WindowManager.TRANSIT_TO_BACK 26 import android.view.WindowManager.TRANSIT_TO_FRONT 27 import android.window.IRemoteTransition 28 import android.window.RemoteTransition 29 import androidx.test.filters.SmallTest 30 import com.android.wm.shell.RootTaskDisplayAreaOrganizer 31 import com.android.wm.shell.TestRunningTaskInfoBuilder 32 import com.android.wm.shell.TestShellExecutor 33 import com.android.wm.shell.transition.TransitionInfoBuilder 34 import com.android.wm.shell.transition.Transitions 35 import com.google.common.truth.Truth.assertThat 36 import org.junit.Before 37 import org.junit.Test 38 import org.junit.runner.RunWith 39 import org.mockito.ArgumentMatchers.any 40 import org.mockito.ArgumentMatchers.anyInt 41 import org.mockito.Mockito.mock 42 import org.mockito.Mockito.times 43 import org.mockito.Mockito.verify 44 import org.mockito.kotlin.mock 45 import org.mockito.kotlin.whenever 46 47 @SmallTest 48 @RunWith(AndroidTestingRunner::class) 49 class DesktopWindowLimitRemoteHandlerTest { 50 51 private val shellExecutor = TestShellExecutor() 52 private val transition: IBinder = Binder() 53 54 private val rootTaskDisplayAreaOrganizer = mock<RootTaskDisplayAreaOrganizer>() 55 private val remoteTransition = mock<RemoteTransition>() 56 private val iRemoteTransition = mock<IRemoteTransition>() 57 private val startT = mock<Transaction>() 58 private val finishT = mock<Transaction>() 59 private val finishCallback = mock<Transitions.TransitionFinishCallback>() 60 61 @Before setUpnull62 fun setUp() { 63 whenever(remoteTransition.remoteTransition).thenReturn(iRemoteTransition) 64 whenever(iRemoteTransition.asBinder()).thenReturn(mock(IBinder::class.java)) 65 } 66 createRemoteHandlernull67 private fun createRemoteHandler(taskIdToMinimize: Int) = 68 DesktopWindowLimitRemoteHandler( 69 shellExecutor, rootTaskDisplayAreaOrganizer, remoteTransition, taskIdToMinimize) 70 71 @Test 72 fun startAnimation_dontSetTransition_returnsFalse() { 73 val minimizeTask = createDesktopTask() 74 val remoteHandler = createRemoteHandler(taskIdToMinimize = minimizeTask.taskId) 75 76 assertThat(remoteHandler.startAnimation(transition, 77 createMinimizeTransitionInfo(minimizeTask), startT, finishT, finishCallback) 78 ).isFalse() 79 } 80 81 @Test startAnimation_noMinimizeChange_returnsFalsenull82 fun startAnimation_noMinimizeChange_returnsFalse() { 83 val remoteHandler = createRemoteHandler(taskIdToMinimize = 1) 84 remoteHandler.setTransition(transition) 85 val info = createToFrontTransitionInfo() 86 87 assertThat( 88 remoteHandler.startAnimation(transition, info, startT, finishT, finishCallback) 89 ).isFalse() 90 } 91 92 @Test startAnimation_correctTransition_returnsTruenull93 fun startAnimation_correctTransition_returnsTrue() { 94 val minimizeTask = createDesktopTask() 95 val remoteHandler = createRemoteHandler(taskIdToMinimize = minimizeTask.taskId) 96 remoteHandler.setTransition(transition) 97 val info = createMinimizeTransitionInfo(minimizeTask) 98 99 assertThat( 100 remoteHandler.startAnimation(transition, info, startT, finishT, finishCallback) 101 ).isTrue() 102 } 103 104 @Test startAnimation_noMinimizeChange_doesNotReparentMinimizeChangenull105 fun startAnimation_noMinimizeChange_doesNotReparentMinimizeChange() { 106 val remoteHandler = createRemoteHandler(taskIdToMinimize = 1) 107 remoteHandler.setTransition(transition) 108 val info = createToFrontTransitionInfo() 109 110 remoteHandler.startAnimation(transition, info, startT, finishT, finishCallback) 111 112 verify(rootTaskDisplayAreaOrganizer, times(0)) 113 .reparentToDisplayArea(anyInt(), any(), any()) 114 } 115 116 @Test startAnimation_hasMinimizeChange_reparentsMinimizeChangenull117 fun startAnimation_hasMinimizeChange_reparentsMinimizeChange() { 118 val minimizeTask = createDesktopTask() 119 val remoteHandler = createRemoteHandler(taskIdToMinimize = minimizeTask.taskId) 120 remoteHandler.setTransition(transition) 121 val info = createMinimizeTransitionInfo(minimizeTask) 122 123 remoteHandler.startAnimation(transition, info, startT, finishT, finishCallback) 124 125 verify(rootTaskDisplayAreaOrganizer).reparentToDisplayArea(anyInt(), any(), any()) 126 } 127 128 @Test startAnimation_noMinimizeChange_doesNotStartRemoteAnimationnull129 fun startAnimation_noMinimizeChange_doesNotStartRemoteAnimation() { 130 val minimizeTask = createDesktopTask() 131 val remoteHandler = createRemoteHandler(taskIdToMinimize = minimizeTask.taskId) 132 remoteHandler.setTransition(transition) 133 val info = createToFrontTransitionInfo() 134 135 remoteHandler.startAnimation(transition, info, startT, finishT, finishCallback) 136 137 verify(iRemoteTransition, times(0)).startAnimation(any(), any(), any(), any()) 138 } 139 140 @Test startAnimation_hasMinimizeChange_startsRemoteAnimationnull141 fun startAnimation_hasMinimizeChange_startsRemoteAnimation() { 142 val minimizeTask = createDesktopTask() 143 val remoteHandler = createRemoteHandler(taskIdToMinimize = minimizeTask.taskId) 144 remoteHandler.setTransition(transition) 145 val info = createMinimizeTransitionInfo(minimizeTask) 146 147 remoteHandler.startAnimation(transition, info, startT, finishT, finishCallback) 148 149 verify(iRemoteTransition).startAnimation(any(), any(), any(), any()) 150 } 151 createDesktopTasknull152 private fun createDesktopTask() = 153 TestRunningTaskInfoBuilder().setWindowingMode(WINDOWING_MODE_FREEFORM).build() 154 155 private fun createToFrontTransitionInfo() = 156 TransitionInfoBuilder(TRANSIT_TO_FRONT) 157 .addChange(TRANSIT_TO_FRONT, 158 TestRunningTaskInfoBuilder().setWindowingMode(WINDOWING_MODE_FREEFORM).build()) 159 .build() 160 161 private fun createMinimizeTransitionInfo(minimizeTask: ActivityManager.RunningTaskInfo) = 162 TransitionInfoBuilder(TRANSIT_TO_FRONT) 163 .addChange(TRANSIT_TO_FRONT, 164 TestRunningTaskInfoBuilder().setWindowingMode(WINDOWING_MODE_FREEFORM).build()) 165 .addChange(TRANSIT_TO_BACK, minimizeTask) 166 .build() 167 } 168