blob: 5acc0f2735546c32f575a9970ea44084f25a064e [file] [log] [blame]
Daichi Hirono1821c5a2017-12-12 17:54:12 +09001/*
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
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070014 * limitations under the License.
Daichi Hirono1821c5a2017-12-12 17:54:12 +090015 */
16
17package com.android.server.wm;
18
Daichi Hironoda0748d2017-12-13 12:48:59 +090019import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
20import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
Daichi Hirono1821c5a2017-12-12 17:54:12 +090021import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Brett Chabota26eda92018-07-23 13:08:30 -070022
Arthur Hungfd9d94d2019-08-28 16:06:07 +080023import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090024import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
25import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
Arthur Hungfd9d94d2019-08-28 16:06:07 +080026import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090027
Daichi Hirono1821c5a2017-12-12 17:54:12 +090028import static org.junit.Assert.assertNotNull;
Daichi Hirono1821c5a2017-12-12 17:54:12 +090029import static org.junit.Assert.assertTrue;
Daichi Hirono1821c5a2017-12-12 17:54:12 +090030
Daichi Hironoda0748d2017-12-13 12:48:59 +090031import android.content.ClipData;
Daichi Hironoa1fb9be2017-12-18 17:02:54 +090032import android.graphics.PixelFormat;
Daichi Hirono1821c5a2017-12-12 17:54:12 +090033import android.os.IBinder;
Daichi Hironoda0748d2017-12-13 12:48:59 +090034import android.os.Looper;
35import android.os.UserHandle;
36import android.os.UserManagerInternal;
Daichi Hirono1821c5a2017-12-12 17:54:12 +090037import android.platform.test.annotations.Presubmit;
Daichi Hirono1821c5a2017-12-12 17:54:12 +090038import android.view.InputChannel;
Daichi Hironoa1fb9be2017-12-18 17:02:54 +090039import android.view.SurfaceControl;
Daichi Hirono1821c5a2017-12-12 17:54:12 +090040import android.view.SurfaceSession;
Daichi Hironoda0748d2017-12-13 12:48:59 +090041import android.view.View;
Brett Chabota26eda92018-07-23 13:08:30 -070042
Wale Ogunwale8e85aee2019-04-30 15:55:05 -070043import androidx.test.filters.FlakyTest;
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070044import androidx.test.filters.SmallTest;
45
Daichi Hironoda0748d2017-12-13 12:48:59 +090046import com.android.server.LocalServices;
Brett Chabota26eda92018-07-23 13:08:30 -070047
Daichi Hirono1821c5a2017-12-12 17:54:12 +090048import org.junit.After;
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070049import org.junit.AfterClass;
Daichi Hirono1821c5a2017-12-12 17:54:12 +090050import org.junit.Before;
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070051import org.junit.BeforeClass;
Daichi Hirono1821c5a2017-12-12 17:54:12 +090052import org.junit.Test;
Riddle Hsu73f53572019-09-23 23:13:01 +080053import org.junit.runner.RunWith;
Daichi Hironoda0748d2017-12-13 12:48:59 +090054
Brett Chabota26eda92018-07-23 13:08:30 -070055import java.util.concurrent.CountDownLatch;
56import java.util.concurrent.TimeUnit;
57
Daichi Hirono1821c5a2017-12-12 17:54:12 +090058/**
59 * Tests for the {@link DragDropController} class.
60 *
Tadashi G. Takaokac8f2c142018-10-11 16:30:28 +090061 * Build/Install/Run:
Riddle Hsu73f53572019-09-23 23:13:01 +080062 * atest WmTests:DragDropControllerTests
Daichi Hirono1821c5a2017-12-12 17:54:12 +090063 */
64@SmallTest
Daichi Hirono1821c5a2017-12-12 17:54:12 +090065@Presubmit
Riddle Hsu73f53572019-09-23 23:13:01 +080066@RunWith(WindowTestRunner.class)
Daichi Hirono1821c5a2017-12-12 17:54:12 +090067public class DragDropControllerTests extends WindowTestsBase {
Daichi Hironoda0748d2017-12-13 12:48:59 +090068 private static final int TIMEOUT_MS = 3000;
69 private TestDragDropController mTarget;
Daichi Hirono1821c5a2017-12-12 17:54:12 +090070 private WindowState mWindow;
71 private IBinder mToken;
72
Daichi Hironoda0748d2017-12-13 12:48:59 +090073 static class TestDragDropController extends DragDropController {
Daichi Hironoda0748d2017-12-13 12:48:59 +090074 private Runnable mCloseCallback;
75
76 TestDragDropController(WindowManagerService service, Looper looper) {
77 super(service, looper);
78 }
79
80 void setOnClosedCallbackLocked(Runnable runnable) {
81 assertTrue(dragDropActiveLocked());
82 mCloseCallback = runnable;
83 }
84
85 @Override
86 void onDragStateClosedLocked(DragState dragState) {
87 super.onDragStateClosedLocked(dragState);
88 if (mCloseCallback != null) {
89 mCloseCallback.run();
90 mCloseCallback = null;
91 }
92 }
93 }
94
95 /**
96 * Creates a window state which can be used as a drop target.
97 */
98 private WindowState createDropTargetWindow(String name, int ownerId) {
Garfield Tane8d84ab2019-10-11 09:49:40 -070099 final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(
Daichi Hironoda0748d2017-12-13 12:48:59 +0900100 mDisplayContent);
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700101 final ActivityStack stack = createTaskStackOnDisplay(
Yunfan Chen279f5582018-12-12 15:24:50 -0800102 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent);
Daichi Hironoda0748d2017-12-13 12:48:59 +0900103 final Task task = createTaskInStack(stack, ownerId);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700104 task.addChild(activity, 0);
Daichi Hironoda0748d2017-12-13 12:48:59 +0900105
106 final WindowState window = createWindow(
Garfield Tane8d84ab2019-10-11 09:49:40 -0700107 null, TYPE_BASE_APPLICATION, activity, name, ownerId, false);
Daichi Hironoda0748d2017-12-13 12:48:59 +0900108 window.mInputChannel = new InputChannel();
109 window.mHasSurface = true;
110 return window;
111 }
112
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700113 @BeforeClass
114 public static void setUpOnce() {
Daichi Hironoda0748d2017-12-13 12:48:59 +0900115 final UserManagerInternal userManager = mock(UserManagerInternal.class);
116 LocalServices.addService(UserManagerInternal.class, userManager);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700117 }
Daichi Hironoda0748d2017-12-13 12:48:59 +0900118
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700119 @AfterClass
120 public static void tearDownOnce() {
121 LocalServices.removeServiceForTest(UserManagerInternal.class);
122 }
Daichi Hironoda0748d2017-12-13 12:48:59 +0900123
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700124 @Before
125 public void setUp() throws Exception {
126 mTarget = new TestDragDropController(mWm, mWm.mH.getLooper());
Daichi Hironoda0748d2017-12-13 12:48:59 +0900127 mWindow = createDropTargetWindow("Drag test window", 0);
Vishnu Nair7f9c16c2018-08-20 12:58:43 -0700128 doReturn(mWindow).when(mDisplayContent).getTouchableWinAtPointLocked(0, 0);
Arthur Hungfd9d94d2019-08-28 16:06:07 +0800129 when(mWm.mInputManager.transferTouchFocus(any(), any())).thenReturn(true);
Daichi Hironoda0748d2017-12-13 12:48:59 +0900130
Riddle Hsu73f53572019-09-23 23:13:01 +0800131 mWm.mWindowMap.put(mWindow.mClient.asBinder(), mWindow);
Daichi Hirono1821c5a2017-12-12 17:54:12 +0900132 }
133
134 @After
Daichi Hironoda0748d2017-12-13 12:48:59 +0900135 public void tearDown() throws Exception {
Daichi Hironoda0748d2017-12-13 12:48:59 +0900136 final CountDownLatch latch;
Riddle Hsu73f53572019-09-23 23:13:01 +0800137 if (!mTarget.dragDropActiveLocked()) {
138 return;
Daichi Hirono1821c5a2017-12-12 17:54:12 +0900139 }
Riddle Hsu73f53572019-09-23 23:13:01 +0800140 if (mToken != null) {
141 mTarget.cancelDragAndDrop(mToken, false);
142 }
143 latch = new CountDownLatch(1);
144 mTarget.setOnClosedCallbackLocked(latch::countDown);
145 assertTrue(awaitInWmLock(() -> latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)));
Daichi Hirono1821c5a2017-12-12 17:54:12 +0900146 }
147
148 @Test
Wale Ogunwale8e85aee2019-04-30 15:55:05 -0700149 @FlakyTest(bugId = 131005232)
Tadashi G. Takaokac8f2c142018-10-11 16:30:28 +0900150 public void testDragFlow() {
Daichi Hironoda0748d2017-12-13 12:48:59 +0900151 dragFlow(0, ClipData.newPlainText("label", "Test"), 0, 0);
Daichi Hirono1821c5a2017-12-12 17:54:12 +0900152 }
153
154 @Test
Wale Ogunwale8e85aee2019-04-30 15:55:05 -0700155 @FlakyTest(bugId = 131005232)
Tadashi G. Takaokac8f2c142018-10-11 16:30:28 +0900156 public void testPerformDrag_NullDataWithGrantUri() {
Daichi Hironoda0748d2017-12-13 12:48:59 +0900157 dragFlow(View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_GLOBAL_URI_READ, null, 0, 0);
158 }
159
160 @Test
Wale Ogunwale8e85aee2019-04-30 15:55:05 -0700161 @FlakyTest(bugId = 131005232)
Tadashi G. Takaokac8f2c142018-10-11 16:30:28 +0900162 public void testPerformDrag_NullDataToOtherUser() {
Daichi Hironoda0748d2017-12-13 12:48:59 +0900163 final WindowState otherUsersWindow =
164 createDropTargetWindow("Other user's window", 1 * UserHandle.PER_USER_RANGE);
Vishnu Nair7f9c16c2018-08-20 12:58:43 -0700165 doReturn(otherUsersWindow).when(mDisplayContent).getTouchableWinAtPointLocked(10, 10);
Daichi Hironoda0748d2017-12-13 12:48:59 +0900166
167 dragFlow(0, null, 10, 10);
168 }
169
170 private void dragFlow(int flag, ClipData data, float dropX, float dropY) {
Daichi Hironoa1fb9be2017-12-18 17:02:54 +0900171 final SurfaceSession appSession = new SurfaceSession();
172 try {
173 final SurfaceControl surface = new SurfaceControl.Builder(appSession)
174 .setName("drag surface")
Vishnu Naire86bd982018-11-28 13:23:17 -0800175 .setBufferSize(100, 100)
Daichi Hironoa1fb9be2017-12-18 17:02:54 +0900176 .setFormat(PixelFormat.TRANSLUCENT)
177 .build();
Daichi Hironoda0748d2017-12-13 12:48:59 +0900178
Arthur Hungfd9d94d2019-08-28 16:06:07 +0800179 assertTrue(mWm.mInputManager.transferTouchFocus(null, null));
Daichi Hironofabca092017-12-19 15:02:50 +0900180 mToken = mTarget.performDrag(
181 new SurfaceSession(), 0, 0, mWindow.mClient, flag, surface, 0, 0, 0, 0, 0,
182 data);
183 assertNotNull(mToken);
Daichi Hironoda0748d2017-12-13 12:48:59 +0900184
Daichi Hironoa1fb9be2017-12-18 17:02:54 +0900185 mTarget.handleMotionEvent(false, dropX, dropY);
186 mToken = mWindow.mClient.asBinder();
187 } finally {
188 appSession.kill();
189 }
Daichi Hironoda0748d2017-12-13 12:48:59 +0900190 }
Daichi Hirono1821c5a2017-12-12 17:54:12 +0900191}