From 79c9767d4170451a2d7acef04357bee4e083cf89 Mon Sep 17 00:00:00 2001 From: "yj81.kwon" Date: Tue, 16 Apr 2019 19:44:48 -0700 Subject: [PATCH] [wm]: ensure task positioner controller is always cleaned up If freeform windowing app is killed while moving, future touch action does not work. TaskPositioner state is not reset properly. So InputChannel for positioning a task consumes all touch event. Finish task positioning when calling session process is killed. Test: manual - Kill freefrom windowing task process while dragging it Test: atest WmTests:TaskPositionerTests Bug: 129492888 Change-Id: I7eb392d6d87a118dd85e7d752eaabfe600920794 (cherry picked from commit 70fe14b649461d9632f24db844b6054879df60b9) --- .../com/android/server/wm/TaskPositioner.java | 21 +++++++++++++++++-- .../server/wm/TaskPositionerTests.java | 15 +++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java index 7714458bb1671..7f1b4c0d0dd3b 100644 --- a/services/core/java/com/android/server/wm/TaskPositioner.java +++ b/services/core/java/com/android/server/wm/TaskPositioner.java @@ -34,6 +34,7 @@ import android.app.IActivityTaskManager; import android.graphics.Point; import android.graphics.Rect; import android.os.Binder; +import android.os.IBinder; import android.os.Looper; import android.os.Process; import android.os.RemoteException; @@ -56,7 +57,7 @@ import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -class TaskPositioner { +class TaskPositioner implements IBinder.DeathRecipient { private static final boolean DEBUG_ORIENTATION_VIOLATIONS = false; private static final String TAG_LOCAL = "TaskPositioner"; private static final String TAG = TAG_WITH_CLASS_NAME ? TAG_LOCAL : TAG_WM; @@ -116,7 +117,9 @@ class TaskPositioner { private float mStartDragY; @CtrlType private int mCtrlType = CTRL_NONE; - private boolean mDragEnded = false; + @VisibleForTesting + boolean mDragEnded; + private IBinder mClientCallback; InputChannel mServerChannel; InputChannel mClientChannel; @@ -346,6 +349,7 @@ class TaskPositioner { } mDisplayContent.resumeRotationLocked(); mDisplayContent = null; + mClientCallback.unlinkToDeath(this, 0 /* flags */); } void startDrag(WindowState win, boolean resize, boolean preserveOrientation, float startX, @@ -355,6 +359,14 @@ class TaskPositioner { + ", preserveOrientation=" + preserveOrientation + ", {" + startX + ", " + startY + "}"); } + try { + mClientCallback = win.mClient.asBinder(); + mClientCallback.linkToDeath(this, 0 /* flags */); + } catch (RemoteException e) { + // The caller has died, so clean up TaskPositioningController. + mService.mTaskPositioningController.finishTaskPositioning(); + return; + } mTask = win.getTask(); // Use the bounds of the task which accounts for // multiple app windows. Don't use any bounds from win itself as it @@ -651,6 +663,11 @@ class TaskPositioner { return sFactory.create(service); } + @Override + public void binderDied() { + mService.mTaskPositioningController.finishTaskPositioning(); + } + interface Factory { default TaskPositioner create(WindowManagerService service) { return new TaskPositioner(service); diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java index 9cdb465dc445c..df55b39b08178 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java @@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.TaskPositioner.MIN_ASPECT; import static com.android.server.wm.WindowManagerService.dipToPixel; import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP; @@ -29,6 +30,8 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; import android.app.IActivityTaskManager; import android.graphics.Rect; @@ -37,6 +40,7 @@ import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; +import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; import org.junit.After; @@ -494,4 +498,15 @@ public class TaskPositionerTests extends WindowTestsBase { assertEquals("top", expected.top, actual.top); assertEquals("bottom", expected.bottom, actual.bottom); } + + @FlakyTest(bugId = 129492888) + @Test + public void testFinishingMovingWhenBinderDied() { + spyOn(mWm.mTaskPositioningController); + + mPositioner.startDrag(mWindow, false, false, 0 /* startX */, 0 /* startY */); + verify(mWm.mTaskPositioningController, never()).finishTaskPositioning(); + mPositioner.binderDied(); + verify(mWm.mTaskPositioningController).finishTaskPositioning(); + } }