From 367b35a84d264a5ec3bf9912afcb8b54caa1de08 Mon Sep 17 00:00:00 2001 From: Garfield Tan Date: Wed, 13 Dec 2017 12:16:21 -0800 Subject: [PATCH] Restore bounds w/o adjusting it. Looking at existing code in updateOverrideConfiguration(Rect), it should be fine to skip them at restoring stage because: 1) If bounds is null/empty, it unsets Configuration. This task was only restored from XML so the Configuration is for sure empty; 2) If bounds is concrete, it adjusts bounds to allowed values based on context -- minHeight/minWidth and ActivityStack. If the logic is correct there isn't need to adjust it based on minimal dimensions because it was restored, while there is not an ActivityStack at that time, so we have no choice but to delay that adjustment to when it is added to an ActivityStack. Note this is a rather short term solution, because there is not a complete story about persisting Configuration yet, which may be necessary for a better support of freeform tasks -- such as previous windowing mode and display ID etc. Bug: 70573444 Test: go/wm-smoke w/o PiP on sailfish. Task restoration works on ARC branch. Change-Id: Ie2cfce6bb8ef7b521316253268d788ecf746eabf --- .../com/android/server/am/TaskRecord.java | 7 +- .../android/server/am/TaskRecordTests.java | 75 ++++++++++++++++++- 2 files changed, 75 insertions(+), 7 deletions(-) diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index dabcbcdcbb7cf..4a648fc9264f5 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -2251,7 +2251,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi String callingPackage = ""; int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE; boolean supportsPictureInPicture = false; - Rect bounds = null; + Rect lastNonFullscreenBounds = null; int minWidth = INVALID_MIN_SIZE; int minHeight = INVALID_MIN_SIZE; int persistTaskVersion = 0; @@ -2336,7 +2336,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi supportsPictureInPicture = Boolean.parseBoolean(attrValue); break; case ATTR_NON_FULLSCREEN_BOUNDS: - bounds = Rect.unflattenFromString(attrValue); + lastNonFullscreenBounds = Rect.unflattenFromString(attrValue); break; case ATTR_MIN_WIDTH: minWidth = Integer.parseInt(attrValue); @@ -2431,7 +2431,8 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor, callingUid, callingPackage, resizeMode, supportsPictureInPicture, realActivitySuspended, userSetupComplete, minWidth, minHeight); - task.updateOverrideConfiguration(bounds); + task.mLastNonFullscreenBounds = lastNonFullscreenBounds; + task.setBounds(lastNonFullscreenBounds); for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) { activities.get(activityNdx).setTask(task); diff --git a/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java b/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java index 5520bd71ad575..c91e22f84a07f 100644 --- a/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java +++ b/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java @@ -17,33 +17,46 @@ package com.android.server.am; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; import android.app.ActivityManager; import android.content.ComponentName; import android.content.Intent; import android.content.pm.ActivityInfo; +import android.content.res.XmlResourceParser; +import android.graphics.Rect; import android.platform.test.annotations.Presubmit; import android.service.voice.IVoiceInteractionSession; +import android.support.test.InstrumentationRegistry; import android.support.test.filters.MediumTest; import android.support.test.runner.AndroidJUnit4; +import android.util.Xml; +import com.android.frameworks.servicestests.R; import com.android.internal.app.IVoiceInteractor; import com.android.server.am.TaskRecord.TaskRecordFactory; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; import java.io.IOException; +import java.io.OutputStream; +import java.io.Reader; +import java.nio.file.Files; import java.util.ArrayList; +import java.util.Comparator; /** * Tests for exercising {@link TaskRecord}. @@ -54,11 +67,33 @@ import java.util.ArrayList; @MediumTest @Presubmit @RunWith(AndroidJUnit4.class) -public class TaskRecordTests { +public class TaskRecordTests extends ActivityTestsBase { + + private static final String TASK_TAG = "task"; + + private ActivityManagerService mService; @Before public void setUp() throws Exception { + super.setUp(); TaskRecord.setTaskRecordFactory(null); + mService = createActivityManagerService(); + } + + @Test + public void testRestoreWindowedTask() throws Exception { + final TaskRecord expected = createTaskRecord(64); + expected.mLastNonFullscreenBounds = new Rect(50, 50, 100, 100); + + final File serializedFile = serializeToFile(expected); + + try { + final TaskRecord actual = restoreFromFile(serializedFile); + assertEquals(expected.taskId, actual.taskId); + assertEquals(expected.mLastNonFullscreenBounds, actual.mLastNonFullscreenBounds); + } finally { + serializedFile.delete(); + } } @Test @@ -78,6 +113,38 @@ public class TaskRecordTests { assertTrue(factory.mCreated); } + private File serializeToFile(TaskRecord r) throws IOException, XmlPullParserException { + final File tmpFile = File.createTempFile(r.taskId + "_task_", "xml"); + + try (final OutputStream os = new FileOutputStream(tmpFile)) { + final XmlSerializer serializer = Xml.newSerializer(); + serializer.setOutput(os, "UTF-8"); + serializer.startDocument(null, true); + serializer.startTag(null, TASK_TAG); + r.saveToXml(serializer); + serializer.endTag(null, TASK_TAG); + serializer.endDocument(); + } + + return tmpFile; + } + + private TaskRecord restoreFromFile(File file) throws IOException, XmlPullParserException { + try (final Reader reader = new BufferedReader(new FileReader(file))) { + final XmlPullParser parser = Xml.newPullParser(); + parser.setInput(reader); + assertEquals(XmlPullParser.START_TAG, parser.next()); + assertEquals(TASK_TAG, parser.getName()); + return TaskRecord.restoreFromXml(parser, mService.mStackSupervisor); + } + } + + private TaskRecord createTaskRecord(int taskId) { + return new TaskRecord(mService, taskId, new Intent(), null, null, null, null, null, false, + false, false, 0, 10050, null, new ArrayList<>(), 0, false, null, 0, 0, 0, 0, 0, + null, 0, false, false, false, 0, 0); + } + private static class TestTaskRecordFactory extends TaskRecordFactory { private boolean mCreated = false;