Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cfca2586 authored by Wale Ogunwale's avatar Wale Ogunwale
Browse files

Fixed monkey test failure

Avoid duplicate attempt to remove WindowToken from its parent
container when removeImmediately is called by first removing the
token from the display before calling super.removeImmediately
which only tries to remove the child from the parent container
if it is still attached to the parent.

Also, added test for the failure case the monkey test was
triggering.

Bug: 32239922
Test: WindowTokenTests.testChildRemoval passes
Change-Id: I4153669d18260d956c4b570944d2f48516d692ac
parent c69694ab
Loading
Loading
Loading
Loading
+6 −7
Original line number Diff line number Diff line
@@ -58,26 +58,25 @@ import java.io.PrintWriter;
 * This class represents an active client session.  There is generally one
 * Session object per process that is interacting with the window manager.
 */
final class Session extends IWindowSession.Stub
// Needs to be public and not final so we can mock during tests...sucks I know :(
public class Session extends IWindowSession.Stub
        implements IBinder.DeathRecipient {
    final WindowManagerService mService;
    final IWindowSessionCallback mCallback;
    final IInputMethodClient mClient;
    final IInputContext mInputContext;
    final int mUid;
    final int mPid;
    final String mStringName;
    private final String mStringName;
    SurfaceSession mSurfaceSession;
    int mNumWindow = 0;
    boolean mClientDead = false;
    float mLastReportedAnimatorScale;
    private int mNumWindow = 0;
    private boolean mClientDead = false;
    private float mLastReportedAnimatorScale;

    public Session(WindowManagerService service, IWindowSessionCallback callback,
            IInputMethodClient client, IInputContext inputContext) {
        mService = service;
        mCallback = callback;
        mClient = client;
        mInputContext = inputContext;
        mUid = Binder.getCallingUid();
        mPid = Binder.getCallingPid();
        mLastReportedAnimatorScale = service.getCurrentAnimatorScale();
+7 −2
Original line number Diff line number Diff line
@@ -974,8 +974,13 @@ public class WindowManagerService extends IWindowManager.Stub

        LocalServices.addService(WindowManagerPolicy.class, mPolicy);

        mPointerEventDispatcher = mInputManager != null
                ? new PointerEventDispatcher(mInputManager.monitorInput(TAG_WM)) : null;
        if(mInputManager != null) {
            final InputChannel inputChannel = mInputManager.monitorInput(TAG_WM);
            mPointerEventDispatcher = inputChannel != null
                    ? new PointerEventDispatcher(inputChannel) : null;
        } else {
            mPointerEventDispatcher = null;
        }

        mFxSession = new SurfaceSession();
        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
+3 −1
Original line number Diff line number Diff line
@@ -427,11 +427,13 @@ class WindowToken extends WindowContainer<WindowState> {

    @Override
    void removeImmediately() {
        super.removeImmediately();
        if (mDisplayContent != null) {
            mDisplayContent.removeWindowToken(token);
            mService.mRoot.removeWindowTokenIfPossible(token);
        }
        // Needs to occur after the token is removed from the display above to avoid attempt at
        // duplicate removal of this window container from it's parent.
        super.removeImmediately();
    }

    void onDisplayChanged(DisplayContent dc) {
+6 −3
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.wm;

import com.android.internal.policy.IShortcutService;
import com.android.server.input.InputManagerService;

import android.content.Context;
import android.content.res.CompatibilityInfo;
@@ -79,7 +80,9 @@ import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STA
import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;

public class TestWindowManagerPolicy implements WindowManagerPolicy {
import static org.mockito.Mockito.mock;

class TestWindowManagerPolicy implements WindowManagerPolicy {
    private static final String TAG = "TestWindowManagerPolicy";

    private static WindowManagerService sWm = null;
@@ -88,8 +91,8 @@ public class TestWindowManagerPolicy implements WindowManagerPolicy {
        if (sWm == null) {
            // We only want to do this once for the test process as we don't want WM to try to
            // register a bunch of local services again.
            sWm = WindowManagerService.main(
                    context, null, true, false, false, new TestWindowManagerPolicy());
            sWm = WindowManagerService.main(context, mock(InputManagerService.class), true, false,
                    false, new TestWindowManagerPolicy());
        }
        return sWm;
    }
+28 −2
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;

import android.content.Context;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
@@ -28,12 +29,14 @@ import android.support.test.runner.AndroidJUnit4;
import android.view.IWindow;
import android.view.WindowManager;

import static android.app.AppOpsManager.OP_NONE;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;

/**
 * Tests for the {@link WindowState} class.
@@ -49,6 +52,7 @@ public class WindowTokenTests {

    private WindowManagerService mWm = null;
    private final IWindow mIWindow = new TestIWindow();
    private final Session mMockSession = mock(Session.class);

    @Before
    public void setUp() throws Exception {
@@ -85,6 +89,28 @@ public class WindowTokenTests {
        assertTrue(token.hasWindow(window3));
    }

    @Test
    public void testChildRemoval() throws Exception {
        final TestWindowToken token = new TestWindowToken();
        final DisplayContent dc = mWm.getDefaultDisplayContentLocked();

        assertEquals(token, dc.getWindowToken(token.token));

        final WindowState window1 = createWindow(null, TYPE_APPLICATION, token);
        final WindowState window2 = createWindow(null, TYPE_APPLICATION, token);
        token.addWindow(window1);
        token.addWindow(window2);

        window2.removeImmediately();
        // The token should still be mapped in the display content since it still has a child.
        assertEquals(token, dc.getWindowToken(token.token));

        window1.removeImmediately();
        // The token should have been removed from the display content since it no longer has a
        // child.
        assertEquals(null, dc.getWindowToken(token.token));
    }

    @Test
    public void testAdjustAnimLayer() throws Exception {
        final TestWindowToken token = new TestWindowToken();
@@ -157,14 +183,14 @@ public class WindowTokenTests {
    private WindowState createWindow(WindowState parent, int type, WindowToken token) {
        final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(type);

        return new WindowState(mWm, null, mIWindow, token, parent, 0, 0, attrs, 0, 0);
        return new WindowState(mWm, mMockSession, mIWindow, token, parent, OP_NONE, 0, attrs, 0, 0);
    }

    /* Used so we can gain access to some protected members of the {@link WindowToken} class */
    private class TestWindowToken extends WindowToken {

        TestWindowToken() {
            super(mWm, null, 0, false, mWm.getDefaultDisplayContentLocked());
            super(mWm, mock(IBinder.class), 0, false, mWm.getDefaultDisplayContentLocked());
        }

        int getWindowsCount() {