Merge "TaskOrganizer: Add WINDOWING_MODE_MULTI_WINDOW support"
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 283be40..66c65e2 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import android.os.IBinder;
import android.os.RemoteException;
@@ -106,9 +107,11 @@
* and receive taskVanished callbacks in the process.
*/
void registerTaskOrganizer(ITaskOrganizer organizer, int windowingMode) {
- if (windowingMode != WINDOWING_MODE_PINNED) {
+ if (windowingMode != WINDOWING_MODE_PINNED &&
+ windowingMode != WINDOWING_MODE_MULTI_WINDOW) {
throw new UnsupportedOperationException(
- "As of now only Pinned windowing mode is supported for registerTaskOrganizer");
+ "As of now only Pinned and Multiwindow windowing modes are"
+ + " supported for registerTaskOrganizer");
}
clearIfNeeded(windowingMode);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
index c9fd79f..9e80cf2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
@@ -16,9 +16,9 @@
package com.android.server.wm;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
@@ -63,20 +63,24 @@
@Presubmit
@RunWith(WindowTestRunner.class)
public class TaskOrganizerTests extends WindowTestsBase {
- private ITaskOrganizer makeAndRegisterMockOrganizer() {
+ private ITaskOrganizer registerMockOrganizer(int windowingMode) {
final ITaskOrganizer organizer = mock(ITaskOrganizer.class);
when(organizer.asBinder()).thenReturn(new Binder());
- mWm.mAtmService.registerTaskOrganizer(organizer, WINDOWING_MODE_PINNED);
+ mWm.mAtmService.registerTaskOrganizer(organizer, windowingMode);
return organizer;
}
+ private ITaskOrganizer registerMockOrganizer() {
+ return registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
+ }
+
@Test
public void testAppearVanish() throws RemoteException {
final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
final Task task = createTaskInStack(stack, 0 /* userId */);
- final ITaskOrganizer organizer = makeAndRegisterMockOrganizer();
+ final ITaskOrganizer organizer = registerMockOrganizer();
task.setTaskOrganizer(organizer);
verify(organizer).taskAppeared(any(), any());
@@ -89,8 +93,8 @@
public void testSwapOrganizer() throws RemoteException {
final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
final Task task = createTaskInStack(stack, 0 /* userId */);
- final ITaskOrganizer organizer = makeAndRegisterMockOrganizer();
- final ITaskOrganizer organizer2 = makeAndRegisterMockOrganizer();
+ final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
+ final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_PINNED);
task.setTaskOrganizer(organizer);
verify(organizer).taskAppeared(any(), any());
@@ -100,10 +104,24 @@
}
@Test
+ public void testSwapWindowingModes() throws RemoteException {
+ final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
+ final Task task = createTaskInStack(stack, 0 /* userId */);
+ final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
+ final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_PINNED);
+
+ stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
+ verify(organizer).taskAppeared(any(), any());
+ stack.setWindowingMode(WINDOWING_MODE_PINNED);
+ verify(organizer).taskVanished(any());
+ verify(organizer2).taskAppeared(any(), any());
+ }
+
+ @Test
public void testClearOrganizer() throws RemoteException {
final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
final Task task = createTaskInStack(stack, 0 /* userId */);
- final ITaskOrganizer organizer = makeAndRegisterMockOrganizer();
+ final ITaskOrganizer organizer = registerMockOrganizer();
stack.setTaskOrganizer(organizer);
verify(organizer).taskAppeared(any(), any());
@@ -116,7 +134,7 @@
@Test
public void testRegisterTaskOrganizerStackWindowingModeChanges() throws RemoteException {
- final ITaskOrganizer organizer = makeAndRegisterMockOrganizer();
+ final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_PINNED);
final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
final Task task = createTaskInStack(stack, 0 /* userId */);
diff --git a/tests/TaskOrganizerTest/AndroidManifest.xml b/tests/TaskOrganizerTest/AndroidManifest.xml
index 0cb6c10..a77d7ee 100644
--- a/tests/TaskOrganizerTest/AndroidManifest.xml
+++ b/tests/TaskOrganizerTest/AndroidManifest.xml
@@ -19,5 +19,11 @@
<service android:name=".TaskOrganizerPipTest"
android:exported="true">
</service>
+ <activity android:name="TaskOrganizerMultiWindowTest" android:label="TaskOrganizer MW Test">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
</application>
</manifest>
diff --git a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerMultiWindowTest.java b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerMultiWindowTest.java
new file mode 100644
index 0000000..bc8d3c3
--- /dev/null
+++ b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerMultiWindowTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.taskembed;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+
+import android.app.ActivityManager;
+import android.app.Activity;
+import android.app.ActivityOptions;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.view.ITaskOrganizer;
+import android.view.IWindowContainer;
+import android.view.SurfaceControl;
+import android.view.SurfaceHolder;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+public class TaskOrganizerMultiWindowTest extends Activity {
+ class TaskLaunchingView extends TaskView {
+ TaskLaunchingView(Context c, ITaskOrganizer o, int windowingMode) {
+ super(c, o, windowingMode);
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceHolder h, int format, int width, int height) {
+ startCalculatorActivity(width, height);
+ }
+ }
+ TaskView mView;
+
+ class Organizer extends ITaskOrganizer.Stub {
+ @Override
+ public void taskAppeared(IWindowContainer wc, ActivityManager.RunningTaskInfo ti) {
+ mView.reparentTask(wc);
+ }
+ public void taskVanished(IWindowContainer wc) {
+ }
+ public void transactionReady(int id, SurfaceControl.Transaction t) {
+ }
+ }
+
+ Organizer mOrganizer = new Organizer();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mView = new TaskLaunchingView(this, mOrganizer, WINDOWING_MODE_MULTI_WINDOW);
+ setContentView(mView);
+ }
+
+ Intent makeCalculatorIntent() {
+ Intent intent = new Intent();
+ intent.setAction(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_APP_CALCULATOR);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ return intent;
+ }
+
+ Bundle makeLaunchOptions(int width, int height) {
+ ActivityOptions o = ActivityOptions.makeBasic();
+ o.setLaunchWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
+ o.setLaunchBounds(new Rect(0, 0, width, height));
+ return o.toBundle();
+ }
+
+ void startCalculatorActivity(int width, int height) {
+ startActivity(makeCalculatorIntent(), makeLaunchOptions(width, height));
+ }
+}
diff --git a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java
index 6ffa19d..fc1be28 100644
--- a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java
+++ b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java
@@ -16,6 +16,8 @@
package com.android.test.taskembed;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.Service;
@@ -38,48 +40,11 @@
static final int PIP_WIDTH = 640;
static final int PIP_HEIGHT = 360;
- class PipOrgView extends SurfaceView implements SurfaceHolder.Callback {
- PipOrgView(Context c) {
- super(c);
- getHolder().addCallback(this);
- setZOrderOnTop(true);
- }
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- try {
- ActivityTaskManager.getService().registerTaskOrganizer(mOrganizer,
- WindowConfiguration.WINDOWING_MODE_PINNED);
- } catch (Exception e) {
- }
- }
-
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- }
-
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- }
-
- void reparentTask(IWindowContainer wc) {
- SurfaceControl.Transaction t = new SurfaceControl.Transaction();
- SurfaceControl leash = null;
- try {
- leash = wc.getLeash();
- } catch (Exception e) {
- // System server died.. oh well
- }
- t.reparent(leash, getSurfaceControl())
- .setPosition(leash, 0, 0)
- .apply();
- }
- }
-
- PipOrgView mPipView;
+ TaskView mTaskView;
class Organizer extends ITaskOrganizer.Stub {
public void taskAppeared(IWindowContainer wc, ActivityManager.RunningTaskInfo ti) {
- mPipView.reparentTask(wc);
+ mTaskView.reparentTask(wc);
final WindowContainerTransaction wct = new WindowContainerTransaction();
wct.scheduleFinishEnterPip(wc, new Rect(0, 0, PIP_WIDTH, PIP_HEIGHT));
@@ -113,8 +78,8 @@
FrameLayout layout = new FrameLayout(this);
ViewGroup.LayoutParams lp =
new ViewGroup.LayoutParams(PIP_WIDTH, PIP_HEIGHT);
- mPipView = new PipOrgView(this);
- layout.addView(mPipView, lp);
+ mTaskView = new TaskView(this, mOrganizer, WINDOWING_MODE_PINNED);
+ layout.addView(mTaskView, lp);
WindowManager wm = getSystemService(WindowManager.class);
wm.addView(layout, wlp);
diff --git a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskView.java b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskView.java
new file mode 100644
index 0000000..ff73340
--- /dev/null
+++ b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskView.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.taskembed;
+
+import android.app.ActivityTaskManager;
+import android.content.Context;
+import android.view.ITaskOrganizer;
+import android.view.IWindowContainer;
+import android.view.SurfaceControl;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+/**
+ * Simple SurfaceView wrapper which registers a TaskOrganizer
+ * after it's Surface is ready.
+ */
+class TaskView extends SurfaceView implements SurfaceHolder.Callback {
+ final ITaskOrganizer mTaskOrganizer;
+ final int mWindowingMode;
+
+ TaskView(Context c, ITaskOrganizer o, int windowingMode) {
+ super(c);
+ getHolder().addCallback(this);
+ setZOrderOnTop(true);
+
+ mTaskOrganizer = o;
+ mWindowingMode = windowingMode;
+ }
+
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {
+ try {
+ ActivityTaskManager.getService().registerTaskOrganizer(mTaskOrganizer,
+ mWindowingMode);
+ } catch (Exception e) {
+ }
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ }
+
+ void reparentTask(IWindowContainer wc) {
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ SurfaceControl leash = null;
+ try {
+ leash = wc.getLeash();
+ } catch (Exception e) {
+ // System server died.. oh well
+ }
+ t.reparent(leash, getSurfaceControl())
+ .setPosition(leash, 0, 0)
+ .apply();
+ }
+}