diff options
5 files changed, 115 insertions, 28 deletions
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java index c3bc7d9ac8..ebff620159 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java @@ -17,8 +17,8 @@ package com.android.launcher3.taskbar; import static android.content.Context.RECEIVER_EXPORTED; import static android.content.Context.RECEIVER_NOT_EXPORTED; -import static android.content.pm.PackageManager.FEATURE_PC; import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT; +import static android.content.pm.PackageManager.FEATURE_PC; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; @@ -82,6 +82,8 @@ import com.android.launcher3.util.SettingsCache; import com.android.launcher3.util.SimpleBroadcastReceiver; import com.android.quickstep.AllAppsActionManager; import com.android.quickstep.RecentsActivity; +import com.android.quickstep.SystemDecorationChangeObserver; +import com.android.quickstep.SystemDecorationChangeObserver.DisplayDecorationListener; import com.android.quickstep.SystemUiProxy; import com.android.quickstep.fallback.window.RecentsDisplayModel; import com.android.quickstep.fallback.window.RecentsWindowFlags; @@ -107,7 +109,7 @@ import java.util.StringJoiner; /** * Class to manage taskbar lifecycle */ -public class TaskbarManager { +public class TaskbarManager implements DisplayDecorationListener { private static final String TAG = "TaskbarManager"; private static final boolean DEBUG = false; private static final int TASKBAR_DESTROY_DURATION = 100; @@ -454,6 +456,8 @@ public class TaskbarManager { .register(USER_SETUP_COMPLETE_URI, mOnSettingsChangeListener); SettingsCache.INSTANCE.get(mPrimaryWindowContext) .register(NAV_BAR_KIDS_MODE, mOnSettingsChangeListener); + SystemDecorationChangeObserver.getINSTANCE().get(mPrimaryWindowContext) + .registerDisplayDecorationListener(this); mShutdownReceiver = new SimpleBroadcastReceiver( mPrimaryWindowContext, UI_HELPER_EXECUTOR, i -> destroyAllTaskbars()); @@ -957,6 +961,7 @@ public class TaskbarManager { * Signal from SysUI indicating that a non-mirroring display was just connected to the * primary device or a previously mirroring display is switched to extended mode. */ + @Override public void onDisplayAddSystemDecorations(int displayId) { debugTaskbarManager("onDisplayAddSystemDecorations: ", displayId); Display display = getDisplay(displayId); @@ -1020,6 +1025,7 @@ public class TaskbarManager { * Signal from SysUI indicating that a previously connected non-mirroring display was just * removed from the primary device. */ + @Override public void onDisplayRemoved(int displayId) { debugTaskbarManager("onDisplayRemoved: ", displayId); if (!DesktopExperienceFlags.ENABLE_TASKBAR_CONNECTED_DISPLAYS.isTrue() || isDefaultDisplay( @@ -1059,6 +1065,7 @@ public class TaskbarManager { /** * Signal from SysUI indicating that system decorations should be removed from the display. */ + @Override public void onDisplayRemoveSystemDecorations(int displayId) { // The display mirroring starts. The handling logic is the same as when removing a // display. @@ -1102,6 +1109,8 @@ public class TaskbarManager { .unregister(USER_SETUP_COMPLETE_URI, mOnSettingsChangeListener); SettingsCache.INSTANCE.get(mPrimaryWindowContext) .unregister(NAV_BAR_KIDS_MODE, mOnSettingsChangeListener); + SystemDecorationChangeObserver.getINSTANCE().get(mPrimaryWindowContext) + .unregisterDisplayDecorationListener(this); debugPrimaryTaskbar("destroy: unregistering component callbacks"); removeAndUnregisterComponentCallbacks(getDefaultDisplayId()); mShutdownReceiver.unregisterReceiverSafely(); diff --git a/quickstep/src/com/android/quickstep/DisplayModel.kt b/quickstep/src/com/android/quickstep/DisplayModel.kt index 3de6fd05ed..0b8af4045b 100644 --- a/quickstep/src/com/android/quickstep/DisplayModel.kt +++ b/quickstep/src/com/android/quickstep/DisplayModel.kt @@ -23,10 +23,13 @@ import android.util.SparseArray import android.view.Display import androidx.core.util.valueIterator import com.android.quickstep.DisplayModel.DisplayResource +import com.android.quickstep.SystemDecorationChangeObserver.Companion.INSTANCE +import com.android.quickstep.SystemDecorationChangeObserver.DisplayDecorationListener import java.io.PrintWriter /** data model for managing resources with lifecycles that match that of the connected display */ -abstract class DisplayModel<RESOURCE_TYPE : DisplayResource>(val context: Context) { +abstract class DisplayModel<RESOURCE_TYPE : DisplayResource>(val context: Context) : + DisplayDecorationListener { companion object { private const val TAG = "DisplayModel" @@ -34,19 +37,20 @@ abstract class DisplayModel<RESOURCE_TYPE : DisplayResource>(val context: Contex } private val displayManager = context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager + private var systemDecorationChangeObserver: SystemDecorationChangeObserver? = null protected val displayResourceArray = SparseArray<RESOURCE_TYPE>() - fun onDisplayAddSystemDecorations(displayId: Int) { + override fun onDisplayAddSystemDecorations(displayId: Int) { if (DEBUG) Log.d(TAG, "onDisplayAdded: displayId=$displayId") storeDisplayResource(displayId) } - fun onDisplayRemoved(displayId: Int) { + override fun onDisplayRemoved(displayId: Int) { if (DEBUG) Log.d(TAG, "onDisplayRemoved: displayId=$displayId") deleteDisplayResource(displayId) } - fun onDisplayRemoveSystemDecorations(displayId: Int) { + override fun onDisplayRemoveSystemDecorations(displayId: Int) { if (DEBUG) Log.d(TAG, "onDisplayRemoveSystemDecorations: displayId=$displayId") deleteDisplayResource(displayId) } @@ -54,12 +58,16 @@ abstract class DisplayModel<RESOURCE_TYPE : DisplayResource>(val context: Contex protected abstract fun createDisplayResource(display: Display): RESOURCE_TYPE protected fun initializeDisplays() { + systemDecorationChangeObserver = INSTANCE[context] + systemDecorationChangeObserver?.registerDisplayDecorationListener(this) displayManager.displays .filter { getDisplayResource(it.displayId) == null } .forEach { storeDisplayResource(it.displayId) } } fun destroy() { + systemDecorationChangeObserver?.unregisterDisplayDecorationListener(this) + systemDecorationChangeObserver = null displayResourceArray.valueIterator().forEach { displayResource -> displayResource.cleanup() } diff --git a/quickstep/src/com/android/quickstep/SystemDecorationChangeObserver.kt b/quickstep/src/com/android/quickstep/SystemDecorationChangeObserver.kt new file mode 100644 index 0000000000..45594786aa --- /dev/null +++ b/quickstep/src/com/android/quickstep/SystemDecorationChangeObserver.kt @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2025 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.quickstep + +import android.content.Context +import android.util.Log +import com.android.launcher3.dagger.ApplicationContext +import com.android.launcher3.dagger.LauncherAppSingleton +import com.android.launcher3.util.DaggerSingletonObject +import com.android.launcher3.util.Executors.MAIN_EXECUTOR +import com.android.quickstep.dagger.QuickstepBaseAppComponent +import javax.inject.Inject + +@LauncherAppSingleton +class SystemDecorationChangeObserver @Inject constructor(@ApplicationContext context: Context) { + companion object { + private const val TAG = "SystemDecorationChangeObserver" + private const val DEBUG = false + + @JvmStatic + val INSTANCE: DaggerSingletonObject<SystemDecorationChangeObserver> = + DaggerSingletonObject<SystemDecorationChangeObserver>( + QuickstepBaseAppComponent::getSystemDecorationChangeObserver + ) + } + + interface DisplayDecorationListener { + fun onDisplayAddSystemDecorations(displayId: Int) + + fun onDisplayRemoved(displayId: Int) + + fun onDisplayRemoveSystemDecorations(displayId: Int) + } + + fun notifyAddSystemDecorations(displayId: Int) { + if (DEBUG) Log.d(TAG, "SystemDecorationAdded: $displayId") + for (listener in mDisplayDecorationListeners) { + MAIN_EXECUTOR.execute { listener.onDisplayAddSystemDecorations(displayId) } + } + } + + fun notifyOnDisplayRemoved(displayId: Int) { + if (DEBUG) Log.d(TAG, "displayRemoved: $displayId") + for (listener in mDisplayDecorationListeners) { + MAIN_EXECUTOR.execute { listener.onDisplayRemoved(displayId) } + } + } + + fun notifyDisplayRemoveSystemDecorations(displayId: Int) { + if (DEBUG) Log.d(TAG, "SystemDecorationRemoved: $displayId") + for (listener in mDisplayDecorationListeners) { + MAIN_EXECUTOR.execute { listener.onDisplayRemoveSystemDecorations(displayId) } + } + } + + private val mDisplayDecorationListeners = ArrayList<DisplayDecorationListener>() + + fun registerDisplayDecorationListener(listener: DisplayDecorationListener) { + if (DEBUG) Log.d(TAG, "registerDisplayDecorationListener") + mDisplayDecorationListeners.add(listener) + } + + fun unregisterDisplayDecorationListener(listener: DisplayDecorationListener) { + if (DEBUG) Log.d(TAG, "unregisterDisplayDecorationListener") + mDisplayDecorationListeners.remove(listener) + } +} diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index c87f4c3801..3543ad1427 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -314,32 +314,25 @@ public class TouchInteractionService extends Service { @BinderThread @Override public void onDisplayAddSystemDecorations(int displayId) { - executeForTaskbarManager(taskbarManager -> - taskbarManager.onDisplayAddSystemDecorations(displayId)); - - executeForRecentsDisplayModel(displayModel -> - displayModel.onDisplayAddSystemDecorations(displayId)); + executeForTouchInteractionService(tis -> + tis.mSystemDecorationChangeObserver.notifyAddSystemDecorations(displayId)); } @BinderThread @Override public void onDisplayRemoved(int displayId) { - executeForTaskbarManager(taskbarManager -> - taskbarManager.onDisplayRemoved(displayId)); executeForTouchInteractionService(tis -> { + tis.mSystemDecorationChangeObserver.notifyOnDisplayRemoved(displayId); tis.mDeviceState.clearSysUIStateFlagsForDisplay(displayId); }); - executeForRecentsDisplayModel(displayModel -> - displayModel.onDisplayRemoved(displayId)); } @BinderThread @Override public void onDisplayRemoveSystemDecorations(int displayId) { - executeForTaskbarManager(taskbarManager -> - taskbarManager.onDisplayRemoveSystemDecorations(displayId)); - executeForRecentsDisplayModel(displayModel -> - displayModel.onDisplayRemoveSystemDecorations(displayId)); + executeForTouchInteractionService(tis -> { + tis.mSystemDecorationChangeObserver.notifyDisplayRemoveSystemDecorations(displayId); + }); } @BinderThread @@ -451,15 +444,6 @@ public class TouchInteractionService extends Service { })); } - private void executeForRecentsDisplayModel( - @NonNull Consumer<RecentsDisplayModel> recentsDisplayModelConsumer) { - MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(tis -> { - RecentsDisplayModel recentsDisplayModel = tis.mRecentsDisplayModel; - if (recentsDisplayModel == null) return; - recentsDisplayModelConsumer.accept(recentsDisplayModel); - })); - } - /** * Returns the {@link TaskbarManager}. * <p> @@ -596,6 +580,8 @@ public class TouchInteractionService extends Service { private RecentsDisplayModel mRecentsDisplayModel; + private SystemDecorationChangeObserver mSystemDecorationChangeObserver; + @Override public void onCreate() { super.onCreate(); @@ -607,6 +593,7 @@ public class TouchInteractionService extends Service { mDeviceState = RecentsAnimationDeviceState.INSTANCE.get(this); mRotationTouchHelper = RotationTouchHelper.INSTANCE.get(this); mRecentsDisplayModel = RecentsDisplayModel.getINSTANCE().get(this); + mSystemDecorationChangeObserver = SystemDecorationChangeObserver.getINSTANCE().get(this); mAllAppsActionManager = new AllAppsActionManager( this, UI_HELPER_EXECUTOR, this::createAllAppsPendingIntent); mTrackpadsConnected = new ActiveTrackpadList(this, () -> { diff --git a/quickstep/src/com/android/quickstep/dagger/QuickstepBaseAppComponent.java b/quickstep/src/com/android/quickstep/dagger/QuickstepBaseAppComponent.java index d79a8eaca1..23b8a82b2a 100644 --- a/quickstep/src/com/android/quickstep/dagger/QuickstepBaseAppComponent.java +++ b/quickstep/src/com/android/quickstep/dagger/QuickstepBaseAppComponent.java @@ -25,6 +25,7 @@ import com.android.quickstep.RecentsAnimationDeviceState; import com.android.quickstep.RecentsModel; import com.android.quickstep.RotationTouchHelper; import com.android.quickstep.SimpleOrientationTouchTransformer; +import com.android.quickstep.SystemDecorationChangeObserver; import com.android.quickstep.SystemUiProxy; import com.android.quickstep.TopTaskTracker; import com.android.quickstep.fallback.window.RecentsDisplayModel; @@ -71,4 +72,5 @@ public interface QuickstepBaseAppComponent extends LauncherBaseAppComponent { SimpleOrientationTouchTransformer getSimpleOrientationTouchTransformer(); + SystemDecorationChangeObserver getSystemDecorationChangeObserver(); } |