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

Commit ed39c682 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 8839047 from dcaadd7f to tm-qpr1-release

Change-Id: I47a2e5689e6c719bfda88717f295beb7c90495ac
parents 141f6dc1 dcaadd7f
Loading
Loading
Loading
Loading
+56 −3
Original line number Diff line number Diff line
@@ -17,7 +17,15 @@
package com.android.wm.shell;

import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCREEN;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_INIT;

import android.os.Build;
import android.os.SystemClock;
import android.util.Pair;

import androidx.annotation.VisibleForTesting;

import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.bubbles.BubbleController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
@@ -37,10 +45,12 @@ import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.unfold.UnfoldAnimationController;
import com.android.wm.shell.unfold.UnfoldTransitionHandler;

import java.util.ArrayList;
import java.util.Optional;

/**
 * The entry point implementation into the shell for initializing shell internal state.
 * The entry point implementation into the shell for initializing shell internal state.  Classes
 * which need to setup on start should inject an instance of this class and add an init callback.
 */
public class ShellInitImpl {
    private static final String TAG = ShellInitImpl.class.getSimpleName();
@@ -64,6 +74,9 @@ public class ShellInitImpl {
    private final Optional<RecentTasksController> mRecentTasks;

    private final InitImpl mImpl = new InitImpl();
    // An ordered list of init callbacks to be made once shell is first started
    private final ArrayList<Pair<String, Runnable>> mInitCallbacks = new ArrayList<>();
    private boolean mHasInitialized;

    public ShellInitImpl(
            DisplayController displayController,
@@ -106,7 +119,7 @@ public class ShellInitImpl {
        return mImpl;
    }

    private void init() {
    private void legacyInit() {
        // Start listening for display and insets changes
        mDisplayController.initialize();
        mDisplayInsetsController.initialize();
@@ -153,12 +166,52 @@ public class ShellInitImpl {
        mKidsModeTaskOrganizer.initialize(mStartingWindow);
    }

    /**
     * Adds a callback to the ordered list of callbacks be made when Shell is first started.  This
     * can be used in class constructors when dagger is used to ensure that the initialization order
     * matches the dependency order.
     */
    public <T extends Object> void addInitCallback(Runnable r, T instance) {
        if (mHasInitialized) {
            if (Build.isDebuggable()) {
                // All callbacks must be added prior to the Shell being initialized
                throw new IllegalArgumentException("Can not add callback after init");
            }
            return;
        }
        final String className = instance.getClass().getSimpleName();
        mInitCallbacks.add(new Pair<>(className, r));
        ProtoLog.v(WM_SHELL_INIT, "Adding init callback for %s", className);
    }

    /**
     * Calls all the init callbacks when the Shell is first starting.
     */
    @VisibleForTesting
    public void init() {
        ProtoLog.v(WM_SHELL_INIT, "Initializing Shell Components: %d", mInitCallbacks.size());
        // Init in order of registration
        for (int i = 0; i < mInitCallbacks.size(); i++) {
            final Pair<String, Runnable> info = mInitCallbacks.get(i);
            final long t1 = SystemClock.uptimeMillis();
            info.second.run();
            final long t2 = SystemClock.uptimeMillis();
            ProtoLog.v(WM_SHELL_INIT, "\t%s took %dms", info.first, (t2 - t1));
        }
        mInitCallbacks.clear();

        // TODO: To be removed
        legacyInit();

        mHasInitialized = true;
    }

    @ExternalThread
    private class InitImpl implements ShellInit {
        @Override
        public void init() {
            try {
                mMainExecutor.executeBlocking(() -> ShellInitImpl.this.init());
                mMainExecutor.executeBlocking(ShellInitImpl.this::init);
            } catch (InterruptedException e) {
                throw new RuntimeException("Failed to initialize the Shell in 2s", e);
            }
+1 −9
Original line number Diff line number Diff line
@@ -28,12 +28,10 @@ import static com.android.wm.shell.onehanded.OneHandedState.STATE_NONE;
import android.annotation.BinderThread;
import android.content.ComponentName;
import android.content.Context;
import android.content.om.IOverlayManager;
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.graphics.Rect;
import android.os.Handler;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.provider.Settings;
import android.util.Slog;
@@ -92,7 +90,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
    private final OneHandedState mState;
    private final OneHandedTutorialHandler mTutorialHandler;
    private final TaskStackListenerImpl mTaskStackListener;
    private final IOverlayManager mOverlayManager;
    private final ShellExecutor mMainExecutor;
    private final Handler mMainHandler;
    private final OneHandedImpl mImpl = new OneHandedImpl();
@@ -210,11 +207,9 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
                context, displayLayout, settingsUtil, animationController, tutorialHandler,
                jankMonitor, mainExecutor);
        OneHandedUiEventLogger oneHandedUiEventsLogger = new OneHandedUiEventLogger(uiEventLogger);
        IOverlayManager overlayManager = IOverlayManager.Stub.asInterface(
                ServiceManager.getService(Context.OVERLAY_SERVICE));
        return new OneHandedController(context, displayController, organizer, touchHandler,
                tutorialHandler, settingsUtil, accessibilityUtil, timeoutHandler, oneHandedState,
                jankMonitor, oneHandedUiEventsLogger, overlayManager, taskStackListener,
                oneHandedUiEventsLogger, taskStackListener,
                mainExecutor, mainHandler);
    }

@@ -228,9 +223,7 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
            OneHandedAccessibilityUtil oneHandedAccessibilityUtil,
            OneHandedTimeoutHandler timeoutHandler,
            OneHandedState state,
            InteractionJankMonitor jankMonitor,
            OneHandedUiEventLogger uiEventsLogger,
            IOverlayManager overlayManager,
            TaskStackListenerImpl taskStackListener,
            ShellExecutor mainExecutor,
            Handler mainHandler) {
@@ -242,7 +235,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
        mTouchHandler = touchHandler;
        mState = state;
        mTutorialHandler = tutorialHandler;
        mOverlayManager = overlayManager;
        mMainExecutor = mainExecutor;
        mMainHandler = mainHandler;
        mOneHandedUiEventLogger = uiEventsLogger;
+4 −2
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@ import com.android.internal.protolog.common.IProtoLogGroup;
public enum ShellProtoLogGroup implements IProtoLogGroup {
    // NOTE: Since we enable these from the same WM ShellCommand, these names should not conflict
    // with those in the framework ProtoLogGroup
    WM_SHELL_INIT(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true,
            Consts.TAG_WM_SHELL),
    WM_SHELL_TASK_ORG(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
            Consts.TAG_WM_SHELL),
    WM_SHELL_TRANSITIONS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true,
@@ -38,8 +40,8 @@ public enum ShellProtoLogGroup implements IProtoLogGroup {
            "ShellBackPreview"),
    WM_SHELL_RECENT_TASKS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
            Consts.TAG_WM_SHELL),
    WM_SHELL_PICTURE_IN_PICTURE(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG,
            false, Consts.TAG_WM_SHELL),
    WM_SHELL_PICTURE_IN_PICTURE(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
            Consts.TAG_WM_SHELL),
    WM_SHELL_SPLIT_SCREEN(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
            Consts.TAG_WM_SHELL),
    TEST_GROUP(true, true, false, "WindowManagerShellProtoLogTest");
+129 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.wm.shell;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;

import androidx.test.filters.SmallTest;

import com.android.wm.shell.bubbles.BubbleController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.freeform.FreeformTaskListener;
import com.android.wm.shell.fullscreen.FullscreenTaskListener;
import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer;
import com.android.wm.shell.pip.phone.PipTouchHandler;
import com.android.wm.shell.recents.RecentTasksController;
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.startingsurface.StartingWindowController;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.unfold.UnfoldAnimationController;
import com.android.wm.shell.unfold.UnfoldTransitionHandler;

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

import java.util.ArrayList;
import java.util.Optional;

@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class ShellInitImplTest extends ShellTestCase {

    @Mock private DisplayController mDisplayController;
    @Mock private DisplayImeController mDisplayImeController;
    @Mock private DisplayInsetsController mDisplayInsetsController;
    @Mock private DragAndDropController mDragAndDropController;
    @Mock private ShellTaskOrganizer mShellTaskOrganizer;
    @Mock private KidsModeTaskOrganizer mKidsModeTaskOrganizer;
    @Mock private Optional<BubbleController> mBubblesOptional;
    @Mock private Optional<SplitScreenController> mSplitScreenOptional;
    @Mock private Optional<PipTouchHandler> mPipTouchHandlerOptional;
    @Mock private FullscreenTaskListener mFullscreenTaskListener;
    @Mock private Optional<UnfoldAnimationController> mUnfoldAnimationController;
    @Mock private Optional<UnfoldTransitionHandler> mUnfoldTransitionHandler;
    @Mock private Optional<FreeformTaskListener<?>> mFreeformTaskListenerOptional;
    @Mock private Optional<RecentTasksController> mRecentTasks;
    @Mock private Transitions mTransitions;
    @Mock private StartingWindowController mStartingWindow;
    @Mock private ShellExecutor mMainExecutor;

    private ShellInitImpl mImpl;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mImpl = new ShellInitImpl(mDisplayController, mDisplayImeController,
                mDisplayInsetsController, mDragAndDropController, mShellTaskOrganizer,
                mKidsModeTaskOrganizer, mBubblesOptional, mSplitScreenOptional,
                mPipTouchHandlerOptional, mFullscreenTaskListener, mUnfoldAnimationController,
                mUnfoldTransitionHandler, mFreeformTaskListenerOptional, mRecentTasks, mTransitions,
                mStartingWindow, mMainExecutor);
    }

    @Test
    public void testAddInitCallbacks_expectCalledInOrder() {
        ArrayList<Integer> results = new ArrayList<>();
        mImpl.addInitCallback(() -> {
            results.add(1);
        }, new Object());
        mImpl.addInitCallback(() -> {
            results.add(2);
        }, new Object());
        mImpl.addInitCallback(() -> {
            results.add(3);
        }, new Object());
        mImpl.init();
        assertTrue(results.get(0) == 1);
        assertTrue(results.get(1) == 2);
        assertTrue(results.get(2) == 3);
    }

    @Test
    public void testNoInitCallbacksAfterInit_expectException() {
        mImpl.init();
        try {
            mImpl.addInitCallback(() -> {}, new Object());
            fail("Expected exception when adding callback after init");
        } catch (IllegalArgumentException e) {
            // Expected
        }
    }

    @Test
    public void testDoubleInit_expectNoOp() {
        ArrayList<Integer> results = new ArrayList<>();
        mImpl.addInitCallback(() -> {
            results.add(1);
        }, new Object());
        mImpl.init();
        assertTrue(results.size() == 1);
        mImpl.init();
        assertTrue(results.size() == 1);
    }
}
+0 −11
Original line number Diff line number Diff line
@@ -33,7 +33,6 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.om.IOverlayManager;
import android.graphics.Rect;
import android.os.Handler;
import android.os.UserHandle;
@@ -41,12 +40,10 @@ import android.testing.AndroidTestingRunner;
import android.util.ArrayMap;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceControl;
import android.window.WindowContainerTransaction;

import androidx.test.filters.SmallTest;

import com.android.internal.jank.InteractionJankMonitor;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;
@@ -87,16 +84,10 @@ public class OneHandedControllerTest extends OneHandedTestCase {
    @Mock
    OneHandedUiEventLogger mMockUiEventLogger;
    @Mock
    InteractionJankMonitor mMockJankMonitor;
    @Mock
    IOverlayManager mMockOverlayManager;
    @Mock
    TaskStackListenerImpl mMockTaskStackListener;
    @Mock
    ShellExecutor mMockShellMainExecutor;
    @Mock
    SurfaceControl mMockLeash;
    @Mock
    Handler mMockShellMainHandler;

    final boolean mDefaultEnabled = true;
@@ -140,9 +131,7 @@ public class OneHandedControllerTest extends OneHandedTestCase {
                mOneHandedAccessibilityUtil,
                mSpiedTimeoutHandler,
                mSpiedTransitionState,
                mMockJankMonitor,
                mMockUiEventLogger,
                mMockOverlayManager,
                mMockTaskStackListener,
                mMockShellMainExecutor,
                mMockShellMainHandler)
Loading