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

Commit 1e129a42 authored by Wale Ogunwale's avatar Wale Ogunwale
Browse files

Reduce object allocations in WM in some frequently called methods

With the use of lambdas to get all windows in the window container
hierarchy, we need to be careful in frequently called code paths to
make sure the number of objects we allocate isn't crazy. This CL
converts some commonly called code paths that use lambda to use a
method reference for the lambda so we only need to allocate once vs.
each time the code path is executed.

Test: Perform some common operations on the phone and make sure
      the object allocations that show-up in Allocator Tracker for
      window manager seems reasonable

Change-Id: Ie0f245980de96ec68a4e62e76130db7d98c3f7d9
parent ee41d4af
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -1386,6 +1386,8 @@ public class ActivityManagerService extends IActivityManager.Stub
    final long[] mTmpLong = new long[2];
    private final ArraySet<BroadcastQueue> mTmpBroadcastQueue = new ArraySet();
    static final class ProcessChangeItem {
        static final int CHANGE_ACTIVITIES = 1<<0;
        static final int CHANGE_PROCESS_STATE = 1<<1;
@@ -19521,7 +19523,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        int schedGroup;
        int procState;
        boolean foregroundActivities = false;
        final ArraySet<BroadcastQueue> queues = new ArraySet<BroadcastQueue>();
        mTmpBroadcastQueue.clear();
        if (app == TOP_APP) {
            // The last app on the list is the foreground app.
            adj = ProcessList.FOREGROUND_APP_ADJ;
@@ -19535,13 +19537,13 @@ public class ActivityManagerService extends IActivityManager.Stub
            schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
            app.adjType = "instrumentation";
            procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
        } else if (isReceivingBroadcastLocked(app, queues)) {
        } else if (isReceivingBroadcastLocked(app, mTmpBroadcastQueue)) {
            // An app that is currently receiving a broadcast also
            // counts as being in the foreground for OOM killer purposes.
            // It's placed in a sched group based on the nature of the
            // broadcast as reflected by which queue it's active in.
            adj = ProcessList.FOREGROUND_APP_ADJ;
            schedGroup = (queues.contains(mFgBroadcastQueue))
            schedGroup = (mTmpBroadcastQueue.contains(mFgBroadcastQueue))
                    ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
            app.adjType = "broadcast";
            procState = ActivityManager.PROCESS_STATE_RECEIVER;
+2 −1
Original line number Diff line number Diff line
@@ -1253,7 +1253,8 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
            mService.mAnimator.mAppWindowAnimating = true;
        } else if (mAppAnimator.wasAnimating) {
            // stopped animating, do one more pass through the layout
            setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER, "appToken " + this + " done");
            setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
                    DEBUG_LAYOUT_REPEATS ? "appToken " + this + " done" : null);
            if (DEBUG_ANIM) Slog.v(TAG, "updateWindowsApps...: done animating " + this);
        }
    }
+427 −391

File changed.

Preview size limit exceeded, changes collapsed.

+100 −84
Original line number Diff line number Diff line
@@ -45,12 +45,14 @@ import android.view.KeyEvent;
import android.view.WindowManager;

import android.view.WindowManagerPolicy;

import com.android.server.input.InputApplicationHandle;
import com.android.server.input.InputManagerService;
import com.android.server.input.InputWindowHandle;

import java.io.PrintWriter;
import java.util.Arrays;
import java.util.function.Consumer;

final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
    private final WindowManagerService mService;
@@ -79,6 +81,9 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
    private boolean mAddPipInputConsumerHandle;
    private boolean mAddWallpaperInputConsumerHandle;
    private boolean mDisableWallpaperTouchEvents;
    private final Rect mTmpRect = new Rect();
    private final UpdateInputForAllWindowsConsumer mUpdateInputForAllWindowsConsumer =
            new UpdateInputForAllWindowsConsumer();

    // Set to true when the first input device configuration change notification
    // is received to indicate that the input devices are ready.
@@ -381,94 +386,11 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
        }

        // Add all windows on the default display.
        updateInputWindows(inDrag);
        mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag);

        if (false) Slog.d(TAG_WM, "<<<<<<< EXITED updateInputWindowsLw");
    }

    private void updateInputWindows(boolean inDrag) {

        clearInputWindowHandlesLw();

        // TODO: multi-display
        final InputConsumerImpl navInputConsumer =
                getInputConsumer(INPUT_CONSUMER_NAVIGATION, DEFAULT_DISPLAY);
        final InputConsumerImpl pipInputConsumer =
                getInputConsumer(INPUT_CONSUMER_PIP, DEFAULT_DISPLAY);
        final InputConsumerImpl wallpaperInputConsumer =
                getInputConsumer(INPUT_CONSUMER_WALLPAPER, DEFAULT_DISPLAY);
        mAddInputConsumerHandle = navInputConsumer != null;
        mAddPipInputConsumerHandle = pipInputConsumer != null;
        mAddWallpaperInputConsumerHandle = wallpaperInputConsumer != null;
        final Rect pipTouchableBounds = mAddPipInputConsumerHandle ? new Rect() : null;
        mDisableWallpaperTouchEvents = false;

        final WallpaperController wallpaperController = mService.mRoot.mWallpaperController;
        mService.mRoot.forAllWindows(w -> {
            final InputChannel inputChannel = w.mInputChannel;
            final InputWindowHandle inputWindowHandle = w.mInputWindowHandle;
            if (inputChannel == null || inputWindowHandle == null || w.mRemoved
                    || w.isAdjustedForMinimizedDock()) {
                // Skip this window because it cannot possibly receive input.
                return;
            }

            if (mAddPipInputConsumerHandle
                    && w.getStackId() == PINNED_STACK_ID
                    && inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer) {
                // Update the bounds of the Pip input consumer to match the Pinned stack
                w.getStack().getBounds(pipTouchableBounds);
                pipInputConsumer.mWindowHandle.touchableRegion.set(pipTouchableBounds);
                addInputWindowHandle(pipInputConsumer.mWindowHandle);
                mAddPipInputConsumerHandle = false;
            }

            if (mAddInputConsumerHandle
                    && inputWindowHandle.layer <= navInputConsumer.mWindowHandle.layer) {
                addInputWindowHandle(navInputConsumer.mWindowHandle);
                mAddInputConsumerHandle = false;
            }

            if (mAddWallpaperInputConsumerHandle) {
                if (w.mAttrs.type == TYPE_WALLPAPER && w.isVisibleLw()) {
                    // Add the wallpaper input consumer above the first visible wallpaper.
                    addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
                    mAddWallpaperInputConsumerHandle = false;
                }
            }

            final int flags = w.mAttrs.flags;
            final int privateFlags = w.mAttrs.privateFlags;
            final int type = w.mAttrs.type;

            final boolean hasFocus = w == mInputFocus;
            final boolean isVisible = w.isVisibleLw();
            if ((privateFlags & PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS) != 0) {
                mDisableWallpaperTouchEvents = true;
            }
            final boolean hasWallpaper = wallpaperController.isWallpaperTarget(w)
                    && (privateFlags & PRIVATE_FLAG_KEYGUARD) == 0
                    && !mDisableWallpaperTouchEvents;

            // If there's a drag in progress and 'child' is a potential drop target,
            // make sure it's been told about the drag
            if (inDrag && isVisible && w.getDisplayContent().isDefaultDisplay) {
                mService.mDragState.sendDragStartedIfNeededLw(w);
            }

            addInputWindowHandle(
                    inputWindowHandle, w, flags, type, isVisible, hasFocus, hasWallpaper);
        }, true /* traverseTopToBottom */);

        if (mAddWallpaperInputConsumerHandle) {
            // No visible wallpaper found, add the wallpaper input consumer at the end.
            addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
        }

        // Send windows to native code.
        mService.mInputManager.setInputWindows(mInputWindowHandles);
    }

    /* Notifies that the input device configuration has changed. */
    @Override
    public void notifyConfigurationChanged() {
@@ -657,4 +579,98 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
            pw.println(prefix + "mInputFreezeReason=" + mInputFreezeReason);
        }
    }

    private final class UpdateInputForAllWindowsConsumer implements Consumer<WindowState> {

        InputConsumerImpl navInputConsumer;
        InputConsumerImpl pipInputConsumer;
        InputConsumerImpl wallpaperInputConsumer;
        Rect pipTouchableBounds;
        boolean inDrag;
        WallpaperController wallpaperController;

        private void updateInputWindows(boolean inDrag) {

            clearInputWindowHandlesLw();

            // TODO: multi-display
            navInputConsumer = getInputConsumer(INPUT_CONSUMER_NAVIGATION, DEFAULT_DISPLAY);
            pipInputConsumer = getInputConsumer(INPUT_CONSUMER_PIP, DEFAULT_DISPLAY);
            wallpaperInputConsumer = getInputConsumer(INPUT_CONSUMER_WALLPAPER, DEFAULT_DISPLAY);
            mAddInputConsumerHandle = navInputConsumer != null;
            mAddPipInputConsumerHandle = pipInputConsumer != null;
            mAddWallpaperInputConsumerHandle = wallpaperInputConsumer != null;
            mTmpRect.setEmpty();
            pipTouchableBounds = mAddPipInputConsumerHandle ? mTmpRect : null;
            mDisableWallpaperTouchEvents = false;
            this.inDrag = inDrag;
            wallpaperController = mService.mRoot.mWallpaperController;

            mService.mRoot.forAllWindows(this, true /* traverseTopToBottom */);
            if (mAddWallpaperInputConsumerHandle) {
                // No visible wallpaper found, add the wallpaper input consumer at the end.
                addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
            }

            // Send windows to native code.
            mService.mInputManager.setInputWindows(mInputWindowHandles);
        }

        @Override
        public void accept(WindowState w) {
            final InputChannel inputChannel = w.mInputChannel;
            final InputWindowHandle inputWindowHandle = w.mInputWindowHandle;
            if (inputChannel == null || inputWindowHandle == null || w.mRemoved
                    || w.isAdjustedForMinimizedDock()) {
                // Skip this window because it cannot possibly receive input.
                return;
            }

            if (mAddPipInputConsumerHandle
                    && w.getStackId() == PINNED_STACK_ID
                    && inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer) {
                // Update the bounds of the Pip input consumer to match the Pinned stack
                w.getStack().getBounds(pipTouchableBounds);
                pipInputConsumer.mWindowHandle.touchableRegion.set(pipTouchableBounds);
                addInputWindowHandle(pipInputConsumer.mWindowHandle);
                mAddPipInputConsumerHandle = false;
            }

            if (mAddInputConsumerHandle
                    && inputWindowHandle.layer <= navInputConsumer.mWindowHandle.layer) {
                addInputWindowHandle(navInputConsumer.mWindowHandle);
                mAddInputConsumerHandle = false;
            }

            if (mAddWallpaperInputConsumerHandle) {
                if (w.mAttrs.type == TYPE_WALLPAPER && w.isVisibleLw()) {
                    // Add the wallpaper input consumer above the first visible wallpaper.
                    addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
                    mAddWallpaperInputConsumerHandle = false;
                }
            }

            final int flags = w.mAttrs.flags;
            final int privateFlags = w.mAttrs.privateFlags;
            final int type = w.mAttrs.type;

            final boolean hasFocus = w == mInputFocus;
            final boolean isVisible = w.isVisibleLw();
            if ((privateFlags & PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS) != 0) {
                mDisableWallpaperTouchEvents = true;
            }
            final boolean hasWallpaper = wallpaperController.isWallpaperTarget(w)
                    && (privateFlags & PRIVATE_FLAG_KEYGUARD) == 0
                    && !mDisableWallpaperTouchEvents;

            // If there's a drag in progress and 'child' is a potential drop target,
            // make sure it's been told about the drag
            if (inDrag && isVisible && w.getDisplayContent().isDefaultDisplay) {
                mService.mDragState.sendDragStartedIfNeededLw(w);
            }

            addInputWindowHandle(
                    inputWindowHandle, w, flags, type, isVisible, hasFocus, hasWallpaper);
        }
    }
}
+21 −14
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import com.android.server.EventLogTags;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.function.Consumer;

import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT;
@@ -129,6 +130,23 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
    private final WindowLayersController mLayersController;
    final WallpaperController mWallpaperController;

    private String mCloseSystemDialogsReason;
    private final Consumer<WindowState> mCloseSystemDialogsConsumer = w -> {
        if (w.mHasSurface) {
            try {
                w.mClient.closeSystemDialogs(mCloseSystemDialogsReason);
            } catch (RemoteException e) {
            }
        }
    };

    private static final Consumer<WindowState> sRemoveReplacedWindowsConsumer = w -> {
        final AppWindowToken aToken = w.mAppToken;
        if (aToken != null) {
            aToken.removeReplacedWindowIfNeeded(w);
        }
    };

    RootWindowContainer(WindowManagerService service) {
        mService = service;
        mLayersController = new WindowLayersController(mService);
@@ -376,26 +394,15 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
    }

    void closeSystemDialogs(String reason) {
        forAllWindows((w) -> {
            if (w.mHasSurface) {
                try {
                    w.mClient.closeSystemDialogs(reason);
                } catch (RemoteException e) {
                }
            }
        }, false /* traverseTopToBottom */);
        mCloseSystemDialogsReason = reason;
        forAllWindows(mCloseSystemDialogsConsumer, false /* traverseTopToBottom */);
    }

    void removeReplacedWindows() {
        if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION removeReplacedWindows");
        mService.openSurfaceTransaction();
        try {
            forAllWindows((w) -> {
                final AppWindowToken aToken = w.mAppToken;
                if (aToken != null) {
                    aToken.removeReplacedWindowIfNeeded(w);
                }
            }, true /* traverseTopToBottom */);
            forAllWindows(sRemoveReplacedWindowsConsumer, true /* traverseTopToBottom */);
        } finally {
            mService.closeSurfaceTransaction();
            if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION removeReplacedWindows");
Loading