summaryrefslogtreecommitdiff
path: root/tests/TaskOrganizerTest/src
diff options
context:
space:
mode:
author arthurhung <arthurhung@google.com> 2020-09-30 17:39:21 +0800
committer arthurhung <arthurhung@google.com> 2020-11-11 12:55:17 +0800
commitdc1d359a55fa1e8313a55c1686615916b68d5e32 (patch)
tree5b181091e4f769989966a21cc8010a55f776aba8 /tests/TaskOrganizerTest/src
parent782672aabd153d77e3c481c10bc67686ed648c53 (diff)
Add resizing tasks synchronously flicker tests
The test app will launch two tasks on two SurfaceViews and use TaskOrganizer that implements BLASTSyncEngine to resize two tasks synchronously. We could verify it from the layersTrace to ensure the layers of the two tasks could apply resizing at same transaction. Bug: 168505972 Test: enable mUseBLASTSync, atest ResizeTasksSyncTest Change-Id: I815325e37f3ce1e70fb5b51ec32f82a0088c4943
Diffstat (limited to 'tests/TaskOrganizerTest/src')
-rw-r--r--tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt111
-rw-r--r--tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerMultiWindowTest.java255
-rw-r--r--tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java82
-rw-r--r--tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskView.java106
4 files changed, 312 insertions, 242 deletions
diff --git a/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt b/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt
new file mode 100644
index 000000000000..abccd6cf77bd
--- /dev/null
+++ b/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt
@@ -0,0 +1,111 @@
+/*
+ * 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.Instrumentation
+import android.graphics.Rect
+import androidx.test.ext.junit.rules.ActivityScenarioRule
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.runner.AndroidJUnit4
+import com.android.server.wm.flicker.monitor.LayersTraceMonitor
+import com.android.server.wm.flicker.monitor.withSFTracing
+import com.android.server.wm.flicker.traces.layers.LayersTraceSubject.Companion.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.FixMethodOrder
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import java.util.concurrent.CountDownLatch
+import org.junit.Assert.assertNotEquals
+
+@RunWith(AndroidJUnit4::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class ResizeTasksSyncTest {
+ @get:Rule
+ var scenarioRule: ActivityScenarioRule<TaskOrganizerMultiWindowTest> =
+ ActivityScenarioRule<TaskOrganizerMultiWindowTest>(
+ TaskOrganizerMultiWindowTest::class.java)
+
+ protected val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+
+ @Before
+ fun setup() {
+ val tmpDir = instrumentation.targetContext.dataDir.toPath()
+ LayersTraceMonitor(tmpDir).stop()
+ val firstTaskBounds = Rect(0, 0, 1080, 1000)
+ val secondTaskBounds = Rect(0, 1000, 1080, 2000)
+
+ lateinit var surfaceReadyLatch: CountDownLatch
+ scenarioRule.getScenario().onActivity {
+ surfaceReadyLatch = it.openTaskView(firstTaskBounds, secondTaskBounds)
+ }
+ surfaceReadyLatch.await()
+ }
+
+ @After
+ fun teardown() {
+ scenarioRule.getScenario().close()
+ }
+
+ @Test
+ fun testResizeTwoTaskSync() {
+ val firstBounds = Rect(0, 0, 1080, 800)
+ val secondBounds = Rect(0, 1000, 1080, 1800)
+
+ val trace = withSFTracing(instrumentation, TRACE_FLAGS) {
+ lateinit var resizeReadyLatch: CountDownLatch
+ scenarioRule.getScenario().onActivity {
+ resizeReadyLatch = it.resizeTaskView(firstBounds, secondBounds)
+ }
+ resizeReadyLatch.await()
+ }
+
+ // find the frame which match resized buffer size.
+ var frame: Long = -1
+ loop@ for (trace in trace.entries) {
+ for (layer in trace.flattenedLayers) {
+ if (layer.proto.activeBuffer != null &&
+ layer.proto.activeBuffer.width == firstBounds.width() &&
+ layer.proto.activeBuffer.height == firstBounds.height()) {
+ frame = layer.proto.currFrame
+ break@loop
+ }
+ }
+ }
+ assertNotEquals(-1, frame)
+ // layer bounds should be related to parent surfaceview.
+ secondBounds.offsetTo(0, 0)
+
+ // verify buffer size should be changed to expected values.
+ assertThat(trace).layer(FIRST_ACTIVITY, frame).also {
+ it.hasLayerSize(firstBounds)
+ it.hasBufferSize(firstBounds)
+ }
+
+ assertThat(trace).layer(SECOND_ACTIVITY, frame).also {
+ it.hasLayerSize(secondBounds)
+ it.hasBufferSize(secondBounds)
+ }
+ }
+
+ companion object {
+ private const val TRACE_FLAGS = 0x1 // TRACE_CRITICAL
+ private const val FIRST_ACTIVITY = "Activity1"
+ private const val SECOND_ACTIVITY = "Activity2"
+ }
+} \ No newline at end of file
diff --git a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerMultiWindowTest.java b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerMultiWindowTest.java
index ca723b881bbd..0cf5a41de82a 100644
--- a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerMultiWindowTest.java
+++ b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerMultiWindowTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -16,189 +16,182 @@
package com.android.test.taskembed;
-import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
import android.app.Activity;
import android.app.ActivityManager;
-import android.app.ActivityOptions;
import android.content.Context;
import android.content.Intent;
+import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.Gravity;
-import android.view.MotionEvent;
import android.view.SurfaceControl;
-import android.view.SurfaceHolder;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.LinearLayout;
+import android.widget.FrameLayout;
+import android.widget.TextView;
import android.window.TaskOrganizer;
-import android.window.WindowContainerTransaction;
import android.window.WindowContainerTransactionCallback;
-public class TaskOrganizerMultiWindowTest extends Activity {
- static class SplitLayout extends LinearLayout implements View.OnTouchListener {
- View mView1;
- View mView2;
- View mDividerView;
-
- public boolean onTouch(View v, MotionEvent e) {
- if (e.getAction() != MotionEvent.ACTION_UP) {
- return true;
- }
-
- float x = e.getRawX(0);
- float ratio = (float) x / (float) getWidth() ;
- ratio = 1-ratio;
-
- LinearLayout.LayoutParams lp1 =
- new LinearLayout.LayoutParams(0,
- ViewGroup.LayoutParams.WRAP_CONTENT, ratio-0.02f);
- LinearLayout.LayoutParams lp2 =
- new LinearLayout.LayoutParams(0,
- ViewGroup.LayoutParams.WRAP_CONTENT, 1-ratio-0.02f);
- updateViewLayout(mView1, lp2);
- updateViewLayout(mView2, lp1);
- return true;
- }
-
- SplitLayout(Context c, View v1, View v2) {
- super(c);
- LinearLayout.LayoutParams lp1 =
- new LinearLayout.LayoutParams(0,
- ViewGroup.LayoutParams.WRAP_CONTENT, 0.48f);
- LinearLayout.LayoutParams lp3 =
- new LinearLayout.LayoutParams(0,
- ViewGroup.LayoutParams.WRAP_CONTENT, 0.48f);
- LinearLayout.LayoutParams lp2 =
- new LinearLayout.LayoutParams(0,
- ViewGroup.LayoutParams.FILL_PARENT, 0.04f);
- lp2.gravity = Gravity.CENTER;
-
- setWeightSum(1);
-
- mView1 = v1;
- mView2 = v2;
- addView(mView1, lp1);
-
- mDividerView = new View(getContext());
- mDividerView.setBackgroundColor(Color.BLACK);
- addView(mDividerView, lp2);
- mDividerView.setOnTouchListener(this);
-
- addView(mView2, lp3);
- }
- }
-
- class ResizingTaskView extends TaskView {
- final Intent mIntent;
- boolean launched = false;
- ResizingTaskView(Context c, Intent i) {
- super(c);
- mIntent = i;
- }
-
- @Override
- public void surfaceChanged(SurfaceHolder h, int format, int width, int height) {
- if (!launched) {
- launchOrganizedActivity(mIntent, width, height);
- launched = true;
- } else {
- resizeTask(width, height);
- }
- }
-
- void resizeTask(int width, int height) {
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- wct.setBounds(mWc, new Rect(0, 0, width, height));
- try {
- mOrganizer.applySyncTransaction(wct, mOrganizer.mTransactionCallback);
- } catch (Exception e) {
- // Oh well
- }
- }
- }
+import java.util.concurrent.CountDownLatch;
- private TaskView mTaskView1;
- private TaskView mTaskView2;
- private boolean mGotFirstTask = false;
+public class TaskOrganizerMultiWindowTest extends Activity {
+ private CountDownLatch mTasksReadyLatch;
+ private CountDownLatch mTasksResizeLatch;
class Organizer extends TaskOrganizer {
- private int receivedTransactions = 0;
- SurfaceControl.Transaction mergedTransaction = new SurfaceControl.Transaction();
+ private int mReceivedTransactions = 0;
+ private SurfaceControl.Transaction mMergedTransaction = new SurfaceControl.Transaction();
WindowContainerTransactionCallback mTransactionCallback =
new WindowContainerTransactionCallback() {
@Override
public void onTransactionReady(int id, SurfaceControl.Transaction t) {
- mergedTransaction.merge(t);
- receivedTransactions++;
- if (receivedTransactions == 2) {
- mergedTransaction.apply();
- receivedTransactions = 0;
+ mMergedTransaction.merge(t);
+ mReceivedTransactions++;
+ if (mReceivedTransactions == 2) {
+ mReceivedTransactions = 0;
+ mMergedTransaction.apply(true);
+ if (mTasksResizeLatch != null) {
+ mTasksResizeLatch.countDown();
+ }
}
}
};
@Override
public void onTaskAppeared(ActivityManager.RunningTaskInfo ti, SurfaceControl leash) {
- if (!mGotFirstTask) {
+ if (ti.baseActivity == null) {
+ return;
+ }
+
+ final String clsName = ti.baseActivity.getClassName();
+ if (clsName.contentEquals(TestActivity1.class.getName())) {
mTaskView1.reparentTask(ti.token, leash);
- mGotFirstTask = true;
- } else {
+ mOrganizer.setInterceptBackPressedOnTaskRoot(ti.token, true);
+ mTasksReadyLatch.countDown();
+ } else if (clsName.contentEquals(TestActivity2.class.getName())) {
mTaskView2.reparentTask(ti.token, leash);
+ mOrganizer.setInterceptBackPressedOnTaskRoot(ti.token, true);
+ mTasksReadyLatch.countDown();
}
}
+
+ @Override
+ public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo taskInfo) {
+ getMainThreadHandler().post(() -> {
+ finish();
+ });
+ }
}
private Organizer mOrganizer = new Organizer();
-
+ private FrameLayout mTasksLayout;
+ private TaskView mTaskView1;
+ private TaskView mTaskView2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ getWindow().getAttributes().layoutInDisplayCutoutMode =
+ LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
- mOrganizer.registerOrganizer();
-
- mTaskView1 = new ResizingTaskView(this, makeSettingsIntent());
- mTaskView2 = new ResizingTaskView(this, makeContactsIntent());
- View splitView = new SplitLayout(this, mTaskView1, mTaskView2);
+ mTasksLayout = new FrameLayout(this);
+ setContentView(mTasksLayout);
- setContentView(splitView);
+ mOrganizer.registerOrganizer();
}
@Override
protected void onDestroy() {
super.onDestroy();
mOrganizer.unregisterOrganizer();
+ mTasksLayout.removeAllViews();
}
- private void addFlags(Intent intent) {
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION);
+ private Intent makeActivityIntent(final Class<?> clazz) {
+ Intent intent = new Intent(this, clazz);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION
+ | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ return intent;
}
- private Intent makeSettingsIntent() {
- Intent intent = new Intent();
- intent.setAction(android.provider.Settings.ACTION_SETTINGS);
- addFlags(intent);
- return intent;
+ public CountDownLatch openTaskView(Rect firstBounds, Rect secondBounds) {
+ mTasksReadyLatch = new CountDownLatch(2);
+ mTaskView1 = new TaskView(this, mOrganizer, makeActivityIntent(TestActivity1.class));
+ mTaskView1.setBackgroundColor(Color.DKGRAY);
+
+ FrameLayout.LayoutParams viewLayout1 =
+ new FrameLayout.LayoutParams(firstBounds.width(), firstBounds.height(),
+ Gravity.TOP | Gravity.LEFT);
+ viewLayout1.setMargins(firstBounds.left, firstBounds.top, 0, 0);
+ mTasksLayout.addView(mTaskView1, viewLayout1);
+
+ mTaskView2 = new TaskView(this, mOrganizer, makeActivityIntent(TestActivity2.class));
+ mTaskView2.setBackgroundColor(Color.LTGRAY);
+ FrameLayout.LayoutParams viewLayout2 =
+ new FrameLayout.LayoutParams(secondBounds.width(), secondBounds.height(),
+ Gravity.TOP | Gravity.LEFT);
+ viewLayout2.setMargins(secondBounds.left, secondBounds.top, 0, 0);
+ mTasksLayout.addView(mTaskView2, viewLayout2);
+ return mTasksReadyLatch;
}
- private Intent makeContactsIntent() {
- Intent intent = new Intent();
- intent.setAction(Intent.ACTION_MAIN);
- intent.addCategory(Intent.CATEGORY_APP_CONTACTS);
- addFlags(intent);
- return intent;
+ public CountDownLatch resizeTaskView(Rect firstBounds, Rect secondBounds) {
+ mTasksResizeLatch = new CountDownLatch(1);
+
+ mTaskView1.resizeTask(firstBounds.width(), firstBounds.height());
+ mTaskView2.resizeTask(secondBounds.width(), secondBounds.height());
+
+ return mTasksResizeLatch;
}
- private 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();
+ static class InstrumentedTextView extends TextView {
+ private final boolean mSlowDraw;
+ InstrumentedTextView(Context context, boolean slowDraw) {
+ super(context);
+ mSlowDraw = slowDraw;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ if (mSlowDraw) {
+ try {
+ Thread.sleep(20);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
}
- private void launchOrganizedActivity(Intent i, int width, int height) {
- startActivity(i, makeLaunchOptions(width, height));
+ public static class TestActivity1 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ getWindow().getAttributes().layoutInDisplayCutoutMode =
+ LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+
+ TextView v = new InstrumentedTextView(this, true);
+ v.setText("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
+ + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
+ v.setBackgroundColor(Color.RED);
+ v.setTextColor(Color.BLACK);
+ setContentView(v);
+ }
+ }
+
+ public static class TestActivity2 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ getWindow().getAttributes().layoutInDisplayCutoutMode =
+ LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+ TextView v = new InstrumentedTextView(this, false);
+ v.setText("ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ + "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ v.setBackgroundColor(Color.GREEN);
+ v.setTextColor(Color.BLACK);
+ setContentView(v);
+ }
}
}
diff --git a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java
deleted file mode 100644
index 5ec949391181..000000000000
--- a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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_PINNED;
-
-import android.app.ActivityManager;
-import android.app.Service;
-import android.content.Intent;
-import android.graphics.Rect;
-import android.os.IBinder;
-import android.view.SurfaceControl;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.widget.FrameLayout;
-import android.window.TaskOrganizer;
-import android.window.WindowContainerTransaction;
-
-public class TaskOrganizerPipTest extends Service {
- private static final int PIP_WIDTH = 640;
- private static final int PIP_HEIGHT = 360;
-
- private TaskView mTaskView;
-
- class Organizer extends TaskOrganizer {
- public void onTaskAppeared(ActivityManager.RunningTaskInfo ti, SurfaceControl leash) {
- mTaskView.reparentTask(ti.token, leash);
-
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- wct.scheduleFinishEnterPip(ti.token, new Rect(0, 0, PIP_WIDTH, PIP_HEIGHT));
- applyTransaction(wct);
- }
- }
-
- private Organizer mOrganizer = new Organizer();
-
- @Override
- public IBinder onBind(Intent intent) {
- return null;
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
-
- mOrganizer.registerOrganizer();
-
- final WindowManager.LayoutParams wlp = new WindowManager.LayoutParams();
- wlp.setTitle("TaskOrganizerPipTest");
- wlp.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
- wlp.width = wlp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
-
- FrameLayout layout = new FrameLayout(this);
- ViewGroup.LayoutParams lp =
- new ViewGroup.LayoutParams(PIP_WIDTH, PIP_HEIGHT);
- mTaskView = new TaskView(this);
- layout.addView(mTaskView, lp);
-
- WindowManager wm = getSystemService(WindowManager.class);
- wm.addView(layout, wlp);
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- mOrganizer.unregisterOrganizer();
- }
-}
diff --git a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskView.java b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskView.java
index 208018c2543a..4ef91c7807f6 100644
--- a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskView.java
+++ b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskView.java
@@ -16,65 +16,113 @@
package com.android.test.taskembed;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+
+import android.app.ActivityOptions;
import android.content.Context;
+import android.content.Intent;
+import android.graphics.Rect;
+import android.os.Bundle;
import android.view.SurfaceControl;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.window.WindowContainerToken;
+import android.window.WindowContainerTransaction;
/**
* Simple SurfaceView wrapper which registers a TaskOrganizer
* after it's Surface is ready.
*/
-class TaskView extends SurfaceView implements SurfaceHolder.Callback {
- WindowContainerToken mWc;
+class TaskView extends SurfaceView {
+ private WindowContainerToken mWc;
+ private Context mContext;
private SurfaceControl mLeash;
+ private TaskOrganizerMultiWindowTest.Organizer mOrganizer;
+ private Intent mIntent;
+ private boolean mLaunched = false;
- private boolean mSurfaceCreated = false;
- private boolean mNeedsReparent;
-
- TaskView(Context c) {
+ TaskView(Context c, TaskOrganizerMultiWindowTest.Organizer organizer,
+ Intent intent) {
super(c);
- getHolder().addCallback(this);
+ mContext = c;
+ mOrganizer = organizer;
+ mIntent = intent;
+ getHolder().addCallback(
+ new SurfaceHolder.Callback() {
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {}
+
+ @Override
+ public void surfaceChanged(SurfaceHolder holder,
+ int format, int width, int height) {
+ if (!mLaunched) {
+ launchOrganizedActivity(mIntent, width, height);
+ mLaunched = true;
+ } else {
+ resizeTask(width, height);
+ }
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {}
+ }
+ );
setZOrderOnTop(true);
}
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- mSurfaceCreated = true;
- if (mNeedsReparent) {
- mNeedsReparent = false;
- reparentLeash();
- }
+ private void launchOrganizedActivity(Intent i, int width, int height) {
+ mContext.startActivity(i, makeLaunchOptions(width, height));
}
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ private Bundle makeLaunchOptions(int width, int height) {
+ ActivityOptions o = ActivityOptions.makeBasic();
+ o.setLaunchWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
+ o.setLaunchBounds(new Rect(0, 0, width, height));
+ o.setTaskOverlay(true, true);
+ o.setTaskAlwaysOnTop(true);
+ return o.toBundle();
}
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
+ void resizeTask(int width, int height) {
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ wct.setBounds(mWc, new Rect(0, 0, width, height)).setHidden(mWc, false);
+ try {
+ mOrganizer.applySyncTransaction(wct, mOrganizer.mTransactionCallback);
+ } catch (Exception e) {
+ // Oh well
+ }
+ }
+
+ void hideTask() {
+ if (mWc == null) {
+ return;
+ }
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ wct.setWindowingMode(mWc, WINDOWING_MODE_UNDEFINED).setHidden(mWc, true);
+ try {
+ mOrganizer.applySyncTransaction(wct, mOrganizer.mTransactionCallback);
+ } catch (Exception e) {
+ // Oh well
+ }
+ releaseLeash();
}
void reparentTask(WindowContainerToken wc, SurfaceControl leash) {
mWc = wc;
mLeash = leash;
- if (!mSurfaceCreated) {
- mNeedsReparent = true;
- } else {
- reparentLeash();
- }
+ reparentLeash();
}
- private void reparentLeash() {
+ void reparentLeash() {
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
- if (mLeash == null) {
- return;
- }
-
t.reparent(mLeash, getSurfaceControl())
- .setPosition(mLeash, 0, 0)
.show(mLeash)
.apply();
}
+
+ void releaseLeash() {
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ t.remove(mLeash).apply();
+ }
}