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

Commit cc136cb7 authored by Chris Li's avatar Chris Li
Browse files

Migrate WindowContext#onConfigurationChanged to ClientTransaction (9/n)

Dispatch WindowContext events through ClientTransactionItem.

Bug: 290876897
Test: atest WmTests:WindowContextListenerControllerTests
Change-Id: I2ccb9258376df35b6f916656d9e7c350f81f4704
parent 7ef648e6
Loading
Loading
Loading
Loading
+3 −11
Original line number Diff line number Diff line
@@ -95,11 +95,10 @@ public class WindowTokenClient extends IWindowToken.Stub {
     * @param newConfig the updated {@link Configuration}
     * @param newDisplayId the updated {@link android.view.Display} ID
     */
    @AnyThread
    @MainThread
    @Override
    public void onConfigurationChanged(Configuration newConfig, int newDisplayId) {
        // TODO(b/290876897): No need to post on mHandler after migrating to ClientTransaction
        postOnConfigurationChanged(newConfig, newDisplayId);
        onConfigurationChanged(newConfig, newDisplayId, true /* shouldReportConfigChange */);
    }

    /**
@@ -193,16 +192,9 @@ public class WindowTokenClient extends IWindowToken.Stub {
        }
    }

    @AnyThread
    @MainThread
    @Override
    public void onWindowTokenRemoved() {
        // TODO(b/290876897): No need to post on mHandler after migrating to ClientTransaction
        mHandler.post(PooledLambda.obtainRunnable(
                WindowTokenClient::onWindowTokenRemovedInner, this).recycleOnUse());
    }

    @MainThread
    private void onWindowTokenRemovedInner() {
        final Context context = mContextRef.get();
        if (context != null) {
            context.destroy();
+6 −12
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_ERROR;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.IWindowToken;
import android.app.servertransaction.WindowContextInfoChangeItem;
import android.app.servertransaction.WindowContextWindowRemovalItem;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
@@ -329,12 +331,8 @@ class WindowContextListenerController {
            mLastReportedConfig.setTo(config);
            mLastReportedDisplay = displayId;

            try {
                // TODO(b/290876897): migrate to dispatch through wpc
                mClientToken.onConfigurationChanged(config, displayId);
            } catch (RemoteException e) {
                ProtoLog.w(WM_ERROR, "Could not report config changes to the window token client.");
            }
            mWpc.scheduleClientTransactionItem(WindowContextInfoChangeItem.obtain(
                    mClientToken.asBinder(), config, displayId));
            mHasPendingConfiguration = false;
        }

@@ -359,12 +357,8 @@ class WindowContextListenerController {
                }
            }
            mDeathRecipient.unlinkToDeath();
            try {
                // TODO(b/290876897): migrate to dispatch through wpc
                mClientToken.onWindowTokenRemoved();
            } catch (RemoteException e) {
                ProtoLog.w(WM_ERROR, "Could not report token removal to the window token client.");
            }
            mWpc.scheduleClientTransactionItem(WindowContextWindowRemovalItem.obtain(
                    mClientToken.asBinder()));
            unregister();
        }

+29 −7
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ import android.app.ActivityThread;
import android.app.BackgroundStartPrivileges;
import android.app.IApplicationThread;
import android.app.ProfilerInfo;
import android.app.servertransaction.ClientTransactionItem;
import android.app.servertransaction.ConfigurationChangeItem;
import android.content.ComponentName;
import android.content.Context;
@@ -1584,9 +1585,10 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
        resolvedConfig.seq = newParentConfig.seq;
    }

    void dispatchConfiguration(Configuration config) {
    void dispatchConfiguration(@NonNull Configuration config) {
        mHasPendingConfigurationChange = false;
        if (mThread == null) {
        final IApplicationThread thread = mThread;
        if (thread == null) {
            if (Build.IS_DEBUGGABLE && mHasImeService) {
                // TODO (b/135719017): Temporary log for debugging IME service.
                Slog.w(TAG_CONFIGURATION, "Unable to send config for IME proc " + mName
@@ -1611,10 +1613,11 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
            }
        }

        scheduleConfigurationChange(mThread, config);
        scheduleConfigurationChange(thread, config);
    }

    private void scheduleConfigurationChange(IApplicationThread thread, Configuration config) {
    private void scheduleConfigurationChange(@NonNull IApplicationThread thread,
            @NonNull Configuration config) {
        ProtoLog.v(WM_DEBUG_CONFIGURATION, "Sending to proc %s new config %s", mName,
                config);
        if (Build.IS_DEBUGGABLE && mHasImeService) {
@@ -1622,11 +1625,30 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
            Slog.v(TAG_CONFIGURATION, "Sending to IME proc " + mName + " new config " + config);
        }
        mHasCachedConfiguration = false;
        scheduleClientTransactionItem(thread, ConfigurationChangeItem.obtain(
                config, mLastTopActivityDeviceId));
    }

    @VisibleForTesting
    void scheduleClientTransactionItem(@NonNull ClientTransactionItem transactionItem) {
        final IApplicationThread thread = mThread;
        if (thread == null) {
            if (Build.IS_DEBUGGABLE) {
                Slog.w(TAG_CONFIGURATION, "Unable to send transaction to client proc " + mName
                        + ": no app thread");
            }
            return;
        }
        scheduleClientTransactionItem(thread, transactionItem);
    }

    private void scheduleClientTransactionItem(@NonNull IApplicationThread thread,
            @NonNull ClientTransactionItem transactionItem) {
        try {
            mAtm.getLifecycleManager().scheduleTransaction(thread,
                    ConfigurationChangeItem.obtain(config, mLastTopActivityDeviceId));
            mAtm.getLifecycleManager().scheduleTransaction(thread, transactionItem);
        } catch (Exception e) {
            Slog.e(TAG_CONFIGURATION, "Failed to schedule configuration change: " + mOwner, e);
            Slog.e(TAG_CONFIGURATION, "Failed to schedule ClientTransactionItem="
                    + transactionItem + " owner=" + mOwner, e);
        }
    }

+45 −1
Original line number Diff line number Diff line
@@ -34,25 +34,33 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.MockitoAnnotations.initMocks;

import android.app.ClientTransactionHandler;
import android.app.IWindowToken;
import android.app.servertransaction.ClientTransactionItem;
import android.app.servertransaction.WindowContextInfoChangeItem;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
import android.util.ArrayMap;
import android.view.Display;
import android.view.DisplayInfo;
import android.window.WindowContextInfo;

import androidx.test.filters.SmallTest;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;

/**
@@ -68,20 +76,52 @@ public class WindowContextListenerControllerTests extends WindowTestsBase {
    private static final int TEST_UID = 12345;
    private static final int ANOTHER_UID = 1000;

    @Mock
    private ClientTransactionHandler mHandler;

    private WindowProcessController mWpc;
    private final IBinder mClientToken = new Binder();
    private WindowContainer<?> mContainer;
    private ArrayMap<IBinder, TestWindowTokenClient> mWindowTokenClientMap;

    @Before
    public void setUp() {
        initMocks(this);
        mController = new WindowContextListenerController();
        mContainer = createTestWindowToken(TYPE_APPLICATION_OVERLAY, mDisplayContent);
        // Make display on to verify configuration propagation.
        mDefaultDisplay.getDisplayInfo().state = STATE_ON;
        mDisplayContent.getDisplayInfo().state = STATE_ON;
        mWindowTokenClientMap = new ArrayMap<>();

        mWpc = mSystemServicesTestRule.addProcess(
                DEFAULT_COMPONENT_PACKAGE_NAME, DEFAULT_COMPONENT_PACKAGE_NAME, 0 /* pid */,
                TEST_UID);
        // Mock the behaviors on ClientTransaction
        spyOn(mWpc);
        doAnswer(invocation -> {
            // Mock ActivityThread
            final Object[] args = invocation.getArguments();
            final IBinder clientToken = (IBinder) args[0];
            final WindowContextInfo info = (WindowContextInfo) args[1];
            final TestWindowTokenClient client = mWindowTokenClientMap.get(clientToken);
            if (client != null) {
                // Can be null for mock client.
                client.onConfigurationChanged(info.getConfiguration(), info.getDisplayId());
            }
            return null;
        }).when(mHandler).handleWindowContextInfoChanged(any(), any());
        doAnswer(invocation -> {
            // Mock WindowProcessController
            final Object[] args = invocation.getArguments();
            final ClientTransactionItem item = (ClientTransactionItem) args[0];
            if (!(item instanceof WindowContextInfoChangeItem)) {
                return null;
            }
            final WindowContextInfoChangeItem infoChangeItem = (WindowContextInfoChangeItem) item;
            infoChangeItem.execute(mHandler, null, null);
            return null;
        }).when(mWpc).scheduleClientTransactionItem(any());
    }

    @Test
@@ -304,11 +344,15 @@ public class WindowContextListenerControllerTests extends WindowTestsBase {
        assertThat(clientToken.mDisplayId).isEqualTo(mDisplayContent.mDisplayId);
    }

    private static class TestWindowTokenClient extends IWindowToken.Stub {
    private class TestWindowTokenClient extends IWindowToken.Stub {
        private Configuration mConfiguration;
        private int mDisplayId;
        private boolean mRemoved;

        TestWindowTokenClient() {
            mWindowTokenClientMap.put(asBinder(), this);
        }

        @Override
        public void onConfigurationChanged(Configuration configuration, int displayId) {
            mConfiguration = configuration;