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

Commit 09c8bd30 authored by Leonardo Blanger's avatar Leonardo Blanger
Browse files

Expose listener interface for display IME changes



Test: atest WMShellUnitTests:ShellControllerTest
Bug: 314051427

Change-Id: I7156db40507eb3fd4043244aab6315345b3fd45a
Signed-off-by: default avatarLeonardo Blanger <leoblanger@google.com>
parent cd85aff3
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -846,8 +846,10 @@ public abstract class WMShellBaseModule {
    static ShellController provideShellController(Context context,
            ShellInit shellInit,
            ShellCommandHandler shellCommandHandler,
            DisplayInsetsController displayInsetsController,
            @ShellMainThread ShellExecutor mainExecutor) {
        return new ShellController(context, shellInit, shellCommandHandler, mainExecutor);
        return new ShellController(context, shellInit, shellCommandHandler,
                displayInsetsController, mainExecutor);
    }

    //
+34 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.sysui;

import android.graphics.Rect;

/**
 * Callbacks for when the Display IME changes.
 */
public interface DisplayImeChangeListener {
    /**
     * Called when the ime bounds change.
     */
    default void onImeBoundsChanged(int displayId, Rect bounds) {}

    /**
     * Called when the IME visibility change.
     */
    default void onImeVisibilityChanged(int displayId, boolean isShowing) {}
}
+75 −0
Original line number Diff line number Diff line
@@ -30,21 +30,28 @@ import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
import android.util.ArrayMap;
import android.view.InsetsSource;
import android.view.InsetsState;
import android.view.SurfaceControlRegistry;

import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;

import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.DisplayInsetsController.OnInsetsChangedListener;
import com.android.wm.shell.common.ExternalInterfaceBinder;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.annotations.ExternalThread;

import java.io.PrintWriter;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import java.util.function.Supplier;

/**
@@ -57,6 +64,7 @@ public class ShellController {
    private final ShellInit mShellInit;
    private final ShellCommandHandler mShellCommandHandler;
    private final ShellExecutor mMainExecutor;
    private final DisplayInsetsController mDisplayInsetsController;
    private final ShellInterfaceImpl mImpl = new ShellInterfaceImpl();

    private final CopyOnWriteArrayList<ConfigurationChangeListener> mConfigChangeListeners =
@@ -65,6 +73,8 @@ public class ShellController {
            new CopyOnWriteArrayList<>();
    private final CopyOnWriteArrayList<UserChangeListener> mUserChangeListeners =
            new CopyOnWriteArrayList<>();
    private final ConcurrentHashMap<DisplayImeChangeListener, Executor> mDisplayImeChangeListeners =
            new ConcurrentHashMap<>();

    private ArrayMap<String, Supplier<ExternalInterfaceBinder>> mExternalInterfaceSuppliers =
            new ArrayMap<>();
@@ -73,20 +83,53 @@ public class ShellController {

    private Configuration mLastConfiguration;

    private OnInsetsChangedListener mInsetsChangeListener = new OnInsetsChangedListener() {
        private InsetsState mInsetsState = new InsetsState();

        @Override
        public void insetsChanged(InsetsState insetsState) {
            if (mInsetsState == insetsState) {
                return;
            }

            InsetsSource oldSource = mInsetsState.peekSource(InsetsSource.ID_IME);
            boolean wasVisible = (oldSource != null && oldSource.isVisible());
            Rect oldFrame = wasVisible ? oldSource.getFrame() : null;

            InsetsSource newSource = insetsState.peekSource(InsetsSource.ID_IME);
            boolean isVisible = (newSource != null && newSource.isVisible());
            Rect newFrame = isVisible ? newSource.getFrame() : null;

            if (wasVisible != isVisible) {
                onImeVisibilityChanged(isVisible);
            }

            if (newFrame != null && !newFrame.equals(oldFrame)) {
                onImeBoundsChanged(newFrame);
            }

            mInsetsState = insetsState;
        }
    };


    public ShellController(Context context,
            ShellInit shellInit,
            ShellCommandHandler shellCommandHandler,
            DisplayInsetsController displayInsetsController,
            ShellExecutor mainExecutor) {
        mContext = context;
        mShellInit = shellInit;
        mShellCommandHandler = shellCommandHandler;
        mDisplayInsetsController = displayInsetsController;
        mMainExecutor = mainExecutor;
        shellInit.addInitCallback(this::onInit, this);
    }

    private void onInit() {
        mShellCommandHandler.addDumpCallback(this::dump, this);
        mDisplayInsetsController.addInsetsChangedListener(
                mContext.getDisplayId(), mInsetsChangeListener);
    }

    /**
@@ -259,6 +302,25 @@ public class ShellController {
        }
    }

    @VisibleForTesting
    void onImeBoundsChanged(Rect bounds) {
        ProtoLog.v(WM_SHELL_SYSUI_EVENTS, "Display Ime bounds changed");
        mDisplayImeChangeListeners.forEach(
                (DisplayImeChangeListener listener, Executor executor) ->
                executor.execute(() -> listener.onImeBoundsChanged(
                    mContext.getDisplayId(), bounds)));
    }

    @VisibleForTesting
    void onImeVisibilityChanged(boolean isShowing) {
        ProtoLog.v(WM_SHELL_SYSUI_EVENTS, "Display Ime visibility changed: isShowing=%b",
                isShowing);
        mDisplayImeChangeListeners.forEach(
                (DisplayImeChangeListener listener, Executor executor) ->
                executor.execute(() -> listener.onImeVisibilityChanged(
                    mContext.getDisplayId(), isShowing)));
    }

    private void handleInit() {
        SurfaceControlRegistry.createProcessInstance(mContext);
        mShellInit.init();
@@ -328,6 +390,19 @@ public class ShellController {
                    ShellController.this.onUserProfilesChanged(profiles));
        }

        @Override
        public void addDisplayImeChangeListener(DisplayImeChangeListener listener,
                Executor executor) {
            ProtoLog.v(WM_SHELL_SYSUI_EVENTS, "Adding new DisplayImeChangeListener");
            mDisplayImeChangeListeners.put(listener, executor);
        }

        @Override
        public void removeDisplayImeChangeListener(DisplayImeChangeListener listener) {
            ProtoLog.v(WM_SHELL_SYSUI_EVENTS, "Removing DisplayImeChangeListener");
            mDisplayImeChangeListeners.remove(listener);
        }

        @Override
        public boolean handleCommand(String[] args, PrintWriter pw) {
            try {
+13 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import androidx.annotation.NonNull;

import java.io.PrintWriter;
import java.util.List;
import java.util.concurrent.Executor;

/**
 * General interface for notifying the Shell of common SysUI events like configuration or keyguard
@@ -64,6 +65,18 @@ public interface ShellInterface {
     */
    default void onUserProfilesChanged(@NonNull List<UserInfo> profiles) {}

    /**
     * Registers a DisplayImeChangeListener to monitor for changes on Ime
     * position and visibility.
     */
    default void addDisplayImeChangeListener(DisplayImeChangeListener listener,
            Executor executor) {}

    /**
     * Removes a registered DisplayImeChangeListener.
     */
    default void removeDisplayImeChangeListener(DisplayImeChangeListener listener) {}

    /**
     * Handles a shell command.
     */
+3 −1
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import com.android.wm.shell.WindowManagerShellWrapper
import com.android.wm.shell.bubbles.bar.BubbleBarLayerView
import com.android.wm.shell.bubbles.properties.BubbleProperties
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.DisplayInsetsController
import com.android.wm.shell.common.FloatingContentCoordinator
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.common.SyncTransactionQueue
@@ -94,7 +95,8 @@ class BubbleViewInfoTest : ShellTestCase() {
        val windowManager = context.getSystemService(WindowManager::class.java)
        val shellInit = ShellInit(mainExecutor)
        val shellCommandHandler = ShellCommandHandler()
        val shellController = ShellController(context, shellInit, shellCommandHandler, mainExecutor)
        val shellController = ShellController(context, shellInit, shellCommandHandler,
					      mock<DisplayInsetsController>(), mainExecutor)
        bubblePositioner = BubblePositioner(context, windowManager)
        val bubbleData =
            BubbleData(
Loading