Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java +3 −1 Original line number Diff line number Diff line Loading @@ -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); } // Loading libs/WindowManager/Shell/src/com/android/wm/shell/sysui/DisplayImeChangeListener.java 0 → 100644 +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) {} } libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellController.java +75 −0 Original line number Diff line number Diff line Loading @@ -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; /** Loading @@ -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 = Loading @@ -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<>(); Loading @@ -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); } /** Loading Loading @@ -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(); Loading Loading @@ -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 { Loading libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInterface.java +13 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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. */ Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt +3 −1 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java +3 −1 Original line number Diff line number Diff line Loading @@ -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); } // Loading
libs/WindowManager/Shell/src/com/android/wm/shell/sysui/DisplayImeChangeListener.java 0 → 100644 +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) {} }
libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellController.java +75 −0 Original line number Diff line number Diff line Loading @@ -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; /** Loading @@ -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 = Loading @@ -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<>(); Loading @@ -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); } /** Loading Loading @@ -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(); Loading Loading @@ -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 { Loading
libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInterface.java +13 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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. */ Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt +3 −1 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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