Merge "Install archived package." into main
diff --git a/boot/preloaded-classes b/boot/preloaded-classes
index 2a9375c..19d6f04 100644
--- a/boot/preloaded-classes
+++ b/boot/preloaded-classes
@@ -12682,7 +12682,6 @@
 com.android.internal.util.LatencyTracker$Action
 com.android.internal.util.LatencyTracker$ActionProperties
 com.android.internal.util.LatencyTracker$FrameworkStatsLogEvent
-com.android.internal.util.LatencyTracker$SLatencyTrackerHolder
 com.android.internal.util.LatencyTracker$Session$$ExternalSyntheticLambda0
 com.android.internal.util.LatencyTracker$Session
 com.android.internal.util.LatencyTracker
diff --git a/config/preloaded-classes b/config/preloaded-classes
index 214b12c..0351a00 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -12713,7 +12713,6 @@
 com.android.internal.util.LatencyTracker$Action
 com.android.internal.util.LatencyTracker$ActionProperties
 com.android.internal.util.LatencyTracker$FrameworkStatsLogEvent
-com.android.internal.util.LatencyTracker$SLatencyTrackerHolder
 com.android.internal.util.LatencyTracker$Session$$ExternalSyntheticLambda0
 com.android.internal.util.LatencyTracker$Session
 com.android.internal.util.LatencyTracker
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 522caac..c3c802b 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5885,15 +5885,6 @@
         public static final String MULTI_AUDIO_FOCUS_ENABLED = "multi_audio_focus_enabled";
 
         /**
-         * Whether desktop mode is enabled or not.
-         * 0 = off
-         * 1 = on
-         * @hide
-         */
-        @Readable
-        public static final String DESKTOP_MODE = "desktop_mode";
-
-        /**
          * The information of locale preference. This records user's preference to avoid
          * unsynchronized and existing locale preference in
          * {@link Locale#getDefault(Locale.Category)}.
@@ -6066,7 +6057,6 @@
             PRIVATE_SETTINGS.add(SHOW_BATTERY_PERCENT);
             PRIVATE_SETTINGS.add(DISPLAY_COLOR_MODE);
             PRIVATE_SETTINGS.add(DISPLAY_COLOR_MODE_VENDOR_HINT);
-            PRIVATE_SETTINGS.add(DESKTOP_MODE);
             PRIVATE_SETTINGS.add(LOCALE_PREFERENCES);
             PRIVATE_SETTINGS.add(TOUCHPAD_POINTER_SPEED);
             PRIVATE_SETTINGS.add(TOUCHPAD_NATURAL_SCROLLING);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index 1c2cee5..998cd5d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -72,7 +72,6 @@
 import com.android.wm.shell.compatui.CompatUIController;
 import com.android.wm.shell.compatui.CompatUIShellCommandHandler;
 import com.android.wm.shell.desktopmode.DesktopMode;
-import com.android.wm.shell.desktopmode.DesktopModeController;
 import com.android.wm.shell.desktopmode.DesktopModeStatus;
 import com.android.wm.shell.desktopmode.DesktopModeTaskRepository;
 import com.android.wm.shell.desktopmode.DesktopTasksController;
@@ -109,13 +108,13 @@
 import com.android.wm.shell.unfold.UnfoldTransitionHandler;
 import com.android.wm.shell.windowdecor.WindowDecorViewModel;
 
+import java.util.Optional;
+
 import dagger.BindsOptionalOf;
 import dagger.Lazy;
 import dagger.Module;
 import dagger.Provides;
 
-import java.util.Optional;
-
 /**
  * Provides basic dependencies from {@link com.android.wm.shell}, these dependencies are only
  * accessible from components within the WM subcomponent (can be explicitly exposed to the
@@ -800,30 +799,10 @@
     @WMSingleton
     @Provides
     static Optional<DesktopMode> provideDesktopMode(
-            Optional<DesktopModeController> desktopModeController,
             Optional<DesktopTasksController> desktopTasksController) {
-        if (DesktopModeStatus.isProto2Enabled()) {
-            return desktopTasksController.map(DesktopTasksController::asDesktopMode);
-        }
-        return desktopModeController.map(DesktopModeController::asDesktopMode);
+        return desktopTasksController.map(DesktopTasksController::asDesktopMode);
     }
 
-    @BindsOptionalOf
-    @DynamicOverride
-    abstract DesktopModeController optionalDesktopModeController();
-
-    @WMSingleton
-    @Provides
-    static Optional<DesktopModeController> provideDesktopModeController(
-            @DynamicOverride Optional<Lazy<DesktopModeController>> desktopModeController) {
-        // Use optional-of-lazy for the dependency that this provider relies on.
-        // Lazy ensures that this provider will not be the cause the dependency is created
-        // when it will not be returned due to the condition below.
-        if (DesktopModeStatus.isProto1Enabled()) {
-            return desktopModeController.map(Lazy::get);
-        }
-        return Optional.empty();
-    }
 
     @BindsOptionalOf
     @DynamicOverride
@@ -836,7 +815,7 @@
         // Use optional-of-lazy for the dependency that this provider relies on.
         // Lazy ensures that this provider will not be the cause the dependency is created
         // when it will not be returned due to the condition below.
-        if (DesktopModeStatus.isProto2Enabled()) {
+        if (DesktopModeStatus.isEnabled()) {
             return desktopTasksController.map(Lazy::get);
         }
         return Optional.empty();
@@ -853,7 +832,7 @@
         // Use optional-of-lazy for the dependency that this provider relies on.
         // Lazy ensures that this provider will not be the cause the dependency is created
         // when it will not be returned due to the condition below.
-        if (DesktopModeStatus.isAnyEnabled()) {
+        if (DesktopModeStatus.isEnabled()) {
             return desktopModeTaskRepository.map(Lazy::get);
         }
         return Optional.empty();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index c641e87..e9f3e1a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -54,7 +54,6 @@
 import com.android.wm.shell.common.annotations.ShellMainThread;
 import com.android.wm.shell.dagger.back.ShellBackAnimationModule;
 import com.android.wm.shell.dagger.pip.PipModule;
-import com.android.wm.shell.desktopmode.DesktopModeController;
 import com.android.wm.shell.desktopmode.DesktopModeStatus;
 import com.android.wm.shell.desktopmode.DesktopModeTaskRepository;
 import com.android.wm.shell.desktopmode.DesktopTasksController;
@@ -197,10 +196,9 @@
             ShellController shellController,
             SyncTransactionQueue syncQueue,
             Transitions transitions,
-            Optional<DesktopModeController> desktopModeController,
             Optional<DesktopTasksController> desktopTasksController,
             RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer) {
-        if (DesktopModeStatus.isAnyEnabled()) {
+        if (DesktopModeStatus.isEnabled()) {
             return new DesktopModeWindowDecorViewModel(
                     context,
                     mainHandler,
@@ -211,7 +209,6 @@
                     shellController,
                     syncQueue,
                     transitions,
-                    desktopModeController,
                     desktopTasksController,
                     rootTaskDisplayAreaOrganizer);
         }
@@ -353,13 +350,12 @@
             @Nullable PipTransitionController pipTransitionController,
             Optional<RecentsTransitionHandler> recentsTransitionHandler,
             KeyguardTransitionHandler keyguardTransitionHandler,
-            Optional<DesktopModeController> desktopModeController,
             Optional<DesktopTasksController> desktopTasksController,
             Optional<UnfoldTransitionHandler> unfoldHandler,
             Transitions transitions) {
         return new DefaultMixedHandler(shellInit, transitions, splitScreenOptional,
                 pipTransitionController, recentsTransitionHandler,
-                keyguardTransitionHandler, desktopModeController, desktopTasksController,
+                keyguardTransitionHandler, desktopTasksController,
                 unfoldHandler);
     }
 
@@ -471,24 +467,6 @@
     @WMSingleton
     @Provides
     @DynamicOverride
-    static DesktopModeController provideDesktopModeController(Context context,
-            ShellInit shellInit,
-            ShellController shellController,
-            ShellTaskOrganizer shellTaskOrganizer,
-            RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
-            Transitions transitions,
-            @DynamicOverride DesktopModeTaskRepository desktopModeTaskRepository,
-            @ShellMainThread Handler mainHandler,
-            @ShellMainThread ShellExecutor mainExecutor
-    ) {
-        return new DesktopModeController(context, shellInit, shellController, shellTaskOrganizer,
-                rootTaskDisplayAreaOrganizer, transitions, desktopModeTaskRepository, mainHandler,
-                mainExecutor);
-    }
-
-    @WMSingleton
-    @Provides
-    @DynamicOverride
     static DesktopTasksController provideDesktopTasksController(
             Context context,
             ShellInit shellInit,
@@ -553,8 +531,7 @@
     @ShellCreateTriggerOverride
     @Provides
     static Object provideIndependentShellComponentsToCreate(
-            DefaultMixedHandler defaultMixedHandler,
-            Optional<DesktopModeController> desktopModeController) {
+            DefaultMixedHandler defaultMixedHandler) {
         return new Object();
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
deleted file mode 100644
index 5b24d7a..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
+++ /dev/null
@@ -1,557 +0,0 @@
-/*
- * 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.desktopmode;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.view.WindowManager.TRANSIT_CHANGE;
-import static android.view.WindowManager.TRANSIT_NONE;
-import static android.view.WindowManager.TRANSIT_OPEN;
-import static android.view.WindowManager.TRANSIT_TO_FRONT;
-
-import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
-import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE;
-import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_DESKTOP_MODE;
-
-import android.app.ActivityManager.RunningTaskInfo;
-import android.app.WindowConfiguration;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.database.ContentObserver;
-import android.graphics.Region;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.util.ArraySet;
-import android.view.SurfaceControl;
-import android.view.WindowManager;
-import android.window.DisplayAreaInfo;
-import android.window.TransitionInfo;
-import android.window.TransitionRequestInfo;
-import android.window.WindowContainerTransaction;
-
-import androidx.annotation.BinderThread;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.protolog.common.ProtoLog;
-import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
-import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.common.ExternalInterfaceBinder;
-import com.android.wm.shell.common.RemoteCallable;
-import com.android.wm.shell.common.ShellExecutor;
-import com.android.wm.shell.common.annotations.ExternalThread;
-import com.android.wm.shell.common.annotations.ShellMainThread;
-import com.android.wm.shell.sysui.ShellController;
-import com.android.wm.shell.sysui.ShellInit;
-import com.android.wm.shell.transition.Transitions;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.List;
-import java.util.concurrent.Executor;
-import java.util.function.Consumer;
-
-/**
- * Handles windowing changes when desktop mode system setting changes
- */
-public class DesktopModeController implements RemoteCallable<DesktopModeController>,
-        Transitions.TransitionHandler {
-
-    private final Context mContext;
-    private final ShellController mShellController;
-    private final ShellTaskOrganizer mShellTaskOrganizer;
-    private final RootTaskDisplayAreaOrganizer mRootTaskDisplayAreaOrganizer;
-    private final Transitions mTransitions;
-    private final DesktopModeTaskRepository mDesktopModeTaskRepository;
-    private final ShellExecutor mMainExecutor;
-    private final DesktopModeImpl mDesktopModeImpl = new DesktopModeImpl();
-    private final SettingsObserver mSettingsObserver;
-
-    public DesktopModeController(Context context,
-            ShellInit shellInit,
-            ShellController shellController,
-            ShellTaskOrganizer shellTaskOrganizer,
-            RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
-            Transitions transitions,
-            DesktopModeTaskRepository desktopModeTaskRepository,
-            @ShellMainThread Handler mainHandler,
-            @ShellMainThread ShellExecutor mainExecutor) {
-        mContext = context;
-        mShellController = shellController;
-        mShellTaskOrganizer = shellTaskOrganizer;
-        mRootTaskDisplayAreaOrganizer = rootTaskDisplayAreaOrganizer;
-        mTransitions = transitions;
-        mDesktopModeTaskRepository = desktopModeTaskRepository;
-        mMainExecutor = mainExecutor;
-        mSettingsObserver = new SettingsObserver(mContext, mainHandler);
-        if (DesktopModeStatus.isProto1Enabled()) {
-            shellInit.addInitCallback(this::onInit, this);
-        }
-    }
-
-    private void onInit() {
-        ProtoLog.d(WM_SHELL_DESKTOP_MODE, "Initialize DesktopModeController");
-        mShellController.addExternalInterface(KEY_EXTRA_SHELL_DESKTOP_MODE,
-                this::createExternalInterface, this);
-        mSettingsObserver.observe();
-        if (DesktopModeStatus.isActive(mContext)) {
-            updateDesktopModeActive(true);
-        }
-        mTransitions.addHandler(this);
-    }
-
-    @Override
-    public Context getContext() {
-        return mContext;
-    }
-
-    @Override
-    public ShellExecutor getRemoteCallExecutor() {
-        return mMainExecutor;
-    }
-
-    /**
-     * Get connection interface between sysui and shell
-     */
-    public DesktopMode asDesktopMode() {
-        return mDesktopModeImpl;
-    }
-
-    /**
-     * Creates a new instance of the external interface to pass to another process.
-     */
-    private ExternalInterfaceBinder createExternalInterface() {
-        return new IDesktopModeImpl(this);
-    }
-
-    /**
-     * Adds a listener to find out about changes in the visibility of freeform tasks.
-     *
-     * @param listener the listener to add.
-     * @param callbackExecutor the executor to call the listener on.
-     */
-    public void addVisibleTasksListener(DesktopModeTaskRepository.VisibleTasksListener listener,
-            Executor callbackExecutor) {
-        mDesktopModeTaskRepository.addVisibleTasksListener(listener, callbackExecutor);
-    }
-
-    /**
-     * Adds a listener to track changes to corners of desktop mode tasks.
-     * @param listener the listener to add.
-     * @param callbackExecutor the executor to call the listener on.
-     */
-    public void addTaskCornerListener(Consumer<Region> listener,
-            Executor callbackExecutor) {
-        mDesktopModeTaskRepository.setTaskCornerListener(listener, callbackExecutor);
-    }
-
-    @VisibleForTesting
-    void updateDesktopModeActive(boolean active) {
-        ProtoLog.d(WM_SHELL_DESKTOP_MODE, "updateDesktopModeActive: active=%s", active);
-
-        int displayId = mContext.getDisplayId();
-
-        ArrayList<RunningTaskInfo> runningTasks = mShellTaskOrganizer.getRunningTasks(displayId);
-
-        WindowContainerTransaction wct = new WindowContainerTransaction();
-        // Reset freeform windowing mode that is set per task level so tasks inherit it
-        clearFreeformForStandardTasks(runningTasks, wct);
-        if (active) {
-            moveHomeBehindVisibleTasks(runningTasks, wct);
-            setDisplayAreaWindowingMode(displayId, WINDOWING_MODE_FREEFORM, wct);
-        } else {
-            clearBoundsForStandardTasks(runningTasks, wct);
-            setDisplayAreaWindowingMode(displayId, WINDOWING_MODE_FULLSCREEN, wct);
-        }
-        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
-            mTransitions.startTransition(TRANSIT_CHANGE, wct, null);
-        } else {
-            mRootTaskDisplayAreaOrganizer.applyTransaction(wct);
-        }
-    }
-
-    private WindowContainerTransaction clearBoundsForStandardTasks(
-            ArrayList<RunningTaskInfo> runningTasks, WindowContainerTransaction wct) {
-        ProtoLog.v(WM_SHELL_DESKTOP_MODE, "prepareClearBoundsForTasks");
-        for (RunningTaskInfo taskInfo : runningTasks) {
-            if (taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD) {
-                ProtoLog.v(WM_SHELL_DESKTOP_MODE, "clearing bounds for token=%s taskInfo=%s",
-                        taskInfo.token, taskInfo);
-                wct.setBounds(taskInfo.token, null);
-            }
-        }
-        return wct;
-    }
-
-    private void clearFreeformForStandardTasks(ArrayList<RunningTaskInfo> runningTasks,
-            WindowContainerTransaction wct) {
-        ProtoLog.v(WM_SHELL_DESKTOP_MODE, "prepareClearFreeformForTasks");
-        for (RunningTaskInfo taskInfo : runningTasks) {
-            if (taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM
-                    && taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD) {
-                ProtoLog.v(WM_SHELL_DESKTOP_MODE,
-                        "clearing windowing mode for token=%s taskInfo=%s", taskInfo.token,
-                        taskInfo);
-                wct.setWindowingMode(taskInfo.token, WINDOWING_MODE_UNDEFINED);
-            }
-        }
-    }
-
-    private void moveHomeBehindVisibleTasks(ArrayList<RunningTaskInfo> runningTasks,
-            WindowContainerTransaction wct) {
-        ProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveHomeBehindVisibleTasks");
-        RunningTaskInfo homeTask = null;
-        ArrayList<RunningTaskInfo> visibleTasks = new ArrayList<>();
-        for (RunningTaskInfo taskInfo : runningTasks) {
-            if (taskInfo.getActivityType() == ACTIVITY_TYPE_HOME) {
-                homeTask = taskInfo;
-            } else if (taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD
-                    && taskInfo.isVisible()) {
-                visibleTasks.add(taskInfo);
-            }
-        }
-        if (homeTask == null) {
-            ProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveHomeBehindVisibleTasks: home task not found");
-        } else {
-            ProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveHomeBehindVisibleTasks: visible tasks %d",
-                    visibleTasks.size());
-            wct.reorder(homeTask.getToken(), true /* onTop */);
-            for (RunningTaskInfo task : visibleTasks) {
-                wct.reorder(task.getToken(), true /* onTop */);
-            }
-        }
-    }
-
-    private void setDisplayAreaWindowingMode(int displayId,
-            @WindowConfiguration.WindowingMode int windowingMode, WindowContainerTransaction wct) {
-        DisplayAreaInfo displayAreaInfo = mRootTaskDisplayAreaOrganizer.getDisplayAreaInfo(
-                displayId);
-        if (displayAreaInfo == null) {
-            ProtoLog.e(WM_SHELL_DESKTOP_MODE,
-                    "unable to update windowing mode for display %d display not found", displayId);
-            return;
-        }
-
-        ProtoLog.v(WM_SHELL_DESKTOP_MODE,
-                "setWindowingMode: displayId=%d current wmMode=%d new wmMode=%d", displayId,
-                displayAreaInfo.configuration.windowConfiguration.getWindowingMode(),
-                windowingMode);
-
-        wct.setWindowingMode(displayAreaInfo.token, windowingMode);
-    }
-
-    /**
-     * Show apps on desktop
-     */
-    void showDesktopApps(int displayId) {
-        // Bring apps to front, ignoring their visibility status to always ensure they are on top.
-        WindowContainerTransaction wct = new WindowContainerTransaction();
-        bringDesktopAppsToFront(displayId, wct);
-
-        if (!wct.isEmpty()) {
-            if (Transitions.ENABLE_SHELL_TRANSITIONS) {
-                // TODO(b/268662477): add animation for the transition
-                mTransitions.startTransition(TRANSIT_NONE, wct, null /* handler */);
-            } else {
-                mShellTaskOrganizer.applyTransaction(wct);
-            }
-        }
-    }
-
-    /** Get number of tasks that are marked as visible */
-    int getVisibleTaskCount(int displayId) {
-        return mDesktopModeTaskRepository.getVisibleTaskCount(displayId);
-    }
-
-    private void bringDesktopAppsToFront(int displayId, WindowContainerTransaction wct) {
-        final ArraySet<Integer> activeTasks = mDesktopModeTaskRepository.getActiveTasks(displayId);
-        ProtoLog.d(WM_SHELL_DESKTOP_MODE, "bringDesktopAppsToFront: tasks=%s", activeTasks.size());
-
-        final List<RunningTaskInfo> taskInfos = new ArrayList<>();
-        for (Integer taskId : activeTasks) {
-            RunningTaskInfo taskInfo = mShellTaskOrganizer.getRunningTaskInfo(taskId);
-            if (taskInfo != null) {
-                taskInfos.add(taskInfo);
-            }
-        }
-
-        if (taskInfos.isEmpty()) {
-            return;
-        }
-
-        moveHomeTaskToFront(wct);
-
-        ProtoLog.d(WM_SHELL_DESKTOP_MODE,
-                "bringDesktopAppsToFront: reordering all active tasks to the front");
-        final List<Integer> allTasksInZOrder =
-                mDesktopModeTaskRepository.getFreeformTasksInZOrder();
-        // Sort by z-order, bottom to top, so that the top-most task is reordered to the top last
-        // in the WCT.
-        taskInfos.sort(Comparator.comparingInt(task -> -allTasksInZOrder.indexOf(task.taskId)));
-        for (RunningTaskInfo task : taskInfos) {
-            wct.reorder(task.token, true);
-        }
-    }
-
-    private void moveHomeTaskToFront(WindowContainerTransaction wct) {
-        for (RunningTaskInfo task : mShellTaskOrganizer.getRunningTasks(mContext.getDisplayId())) {
-            if (task.getActivityType() == ACTIVITY_TYPE_HOME) {
-                wct.reorder(task.token, true /* onTop */);
-                return;
-            }
-        }
-    }
-
-    /**
-     * Update corner rects stored for a specific task
-     * @param taskId task to update
-     * @param taskCorners task's new corner handles
-     */
-    public void onTaskCornersChanged(int taskId, Region taskCorners) {
-        mDesktopModeTaskRepository.updateTaskCorners(taskId, taskCorners);
-    }
-
-    /**
-     * Remove corners saved for a task. Likely used due to task closure.
-     * @param taskId task to remove
-     */
-    public void removeCornersForTask(int taskId) {
-        mDesktopModeTaskRepository.removeTaskCorners(taskId);
-    }
-
-    /**
-     * Moves a specifc task to the front.
-     * @param taskInfo the task to show in front.
-     */
-    public void moveTaskToFront(RunningTaskInfo taskInfo) {
-        WindowContainerTransaction wct = new WindowContainerTransaction();
-        wct.reorder(taskInfo.token, true /* onTop */);
-        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
-            mTransitions.startTransition(TRANSIT_TO_FRONT, wct, null);
-        } else {
-            mShellTaskOrganizer.applyTransaction(wct);
-        }
-    }
-
-    /**
-     * Turn desktop mode on or off
-     * @param active the desired state for desktop mode setting
-     */
-    public void setDesktopModeActive(boolean active) {
-        int value = active ? 1 : 0;
-        Settings.System.putInt(mContext.getContentResolver(), Settings.System.DESKTOP_MODE, value);
-    }
-
-    /**
-     * Returns the windowing mode of the display area with the specified displayId.
-     * @param displayId
-     * @return
-     */
-    public int getDisplayAreaWindowingMode(int displayId) {
-        return mRootTaskDisplayAreaOrganizer.getDisplayAreaInfo(displayId)
-                .configuration.windowConfiguration.getWindowingMode();
-    }
-
-    @Override
-    public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
-            @NonNull SurfaceControl.Transaction startTransaction,
-            @NonNull SurfaceControl.Transaction finishTransaction,
-            @NonNull Transitions.TransitionFinishCallback finishCallback) {
-        // This handler should never be the sole handler, so should not animate anything.
-        return false;
-    }
-
-    @Nullable
-    @Override
-    public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
-            @NonNull TransitionRequestInfo request) {
-        RunningTaskInfo triggerTask = request.getTriggerTask();
-        // Only do anything if we are in desktop mode and opening/moving-to-front a task/app in
-        // freeform
-        if (!DesktopModeStatus.isActive(mContext)) {
-            ProtoLog.d(WM_SHELL_DESKTOP_MODE,
-                    "skip shell transition request: desktop mode not active");
-            return null;
-        }
-        if (request.getType() != TRANSIT_OPEN && request.getType() != TRANSIT_TO_FRONT) {
-            ProtoLog.d(WM_SHELL_DESKTOP_MODE,
-                    "skip shell transition request: unsupported type %s",
-                    WindowManager.transitTypeToString(request.getType()));
-            return null;
-        }
-        if (triggerTask == null || triggerTask.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
-            ProtoLog.d(WM_SHELL_DESKTOP_MODE, "skip shell transition request: not freeform task");
-            return null;
-        }
-        ProtoLog.d(WM_SHELL_DESKTOP_MODE, "handle shell transition request: %s", request);
-
-        WindowContainerTransaction wct = new WindowContainerTransaction();
-        bringDesktopAppsToFront(triggerTask.displayId, wct);
-        wct.reorder(triggerTask.token, true /* onTop */);
-
-        return wct;
-    }
-
-    /**
-     * Applies the proper surface states (rounded corners) to tasks when desktop mode is active.
-     * This is intended to be used when desktop mode is part of another animation but isn't, itself,
-     * animating.
-     */
-    public void syncSurfaceState(@NonNull TransitionInfo info,
-            SurfaceControl.Transaction finishTransaction) {
-        // Add rounded corners to freeform windows
-        final TypedArray ta = mContext.obtainStyledAttributes(
-                new int[]{android.R.attr.dialogCornerRadius});
-        final int cornerRadius = ta.getDimensionPixelSize(0, 0);
-        ta.recycle();
-        for (TransitionInfo.Change change: info.getChanges()) {
-            if (change.getTaskInfo().getWindowingMode() == WINDOWING_MODE_FREEFORM) {
-                finishTransaction.setCornerRadius(change.getLeash(), cornerRadius);
-            }
-        }
-    }
-
-    /**
-     * A {@link ContentObserver} for listening to changes to {@link Settings.System#DESKTOP_MODE}
-     */
-    private final class SettingsObserver extends ContentObserver {
-
-        private final Uri mDesktopModeSetting = Settings.System.getUriFor(
-                Settings.System.DESKTOP_MODE);
-
-        private final Context mContext;
-
-        SettingsObserver(Context context, Handler handler) {
-            super(handler);
-            mContext = context;
-        }
-
-        public void observe() {
-            // TODO(b/242867463): listen for setting change for all users
-            mContext.getContentResolver().registerContentObserver(mDesktopModeSetting,
-                    false /* notifyForDescendants */, this /* observer */, UserHandle.USER_CURRENT);
-        }
-
-        @Override
-        public void onChange(boolean selfChange, @Nullable Uri uri) {
-            if (mDesktopModeSetting.equals(uri)) {
-                ProtoLog.d(WM_SHELL_DESKTOP_MODE, "Received update for desktop mode setting");
-                desktopModeSettingChanged();
-            }
-        }
-
-        private void desktopModeSettingChanged() {
-            boolean enabled = DesktopModeStatus.isActive(mContext);
-            updateDesktopModeActive(enabled);
-        }
-    }
-
-    /**
-     * The interface for calls from outside the shell, within the host process.
-     */
-    @ExternalThread
-    private final class DesktopModeImpl implements DesktopMode {
-
-        @Override
-        public void addVisibleTasksListener(
-                DesktopModeTaskRepository.VisibleTasksListener listener,
-                Executor callbackExecutor) {
-            mMainExecutor.execute(() -> {
-                DesktopModeController.this.addVisibleTasksListener(listener, callbackExecutor);
-            });
-        }
-
-        @Override
-        public void addDesktopGestureExclusionRegionListener(Consumer<Region> listener,
-                Executor callbackExecutor) {
-            mMainExecutor.execute(() -> {
-                DesktopModeController.this.addTaskCornerListener(listener, callbackExecutor);
-            });
-        }
-    }
-
-    /**
-     * The interface for calls from outside the host process.
-     */
-    @BinderThread
-    private static class IDesktopModeImpl extends IDesktopMode.Stub
-            implements ExternalInterfaceBinder {
-
-        private DesktopModeController mController;
-
-        IDesktopModeImpl(DesktopModeController controller) {
-            mController = controller;
-        }
-
-        /**
-         * Invalidates this instance, preventing future calls from updating the controller.
-         */
-        @Override
-        public void invalidate() {
-            mController = null;
-        }
-
-        @Override
-        public void showDesktopApps(int displayId) {
-            executeRemoteCallWithTaskPermission(mController, "showDesktopApps",
-                    controller -> controller.showDesktopApps(displayId));
-        }
-
-        @Override
-        public void showDesktopApp(int taskId) throws RemoteException {
-            // TODO
-        }
-
-        @Override
-        public int getVisibleTaskCount(int displayId) throws RemoteException {
-            int[] result = new int[1];
-            executeRemoteCallWithTaskPermission(mController, "getVisibleTaskCount",
-                    controller -> result[0] = controller.getVisibleTaskCount(displayId),
-                    true /* blocking */
-            );
-            return result[0];
-        }
-
-        @Override
-        public void onDesktopSplitSelectAnimComplete(RunningTaskInfo taskInfo) {
-
-        }
-
-        @Override
-        public void stashDesktopApps(int displayId) throws RemoteException {
-            // Stashing of desktop apps not needed. Apps always launch on desktop
-        }
-
-        @Override
-        public void hideStashedDesktopApps(int displayId) throws RemoteException {
-            // Stashing of desktop apps not needed. Apps always launch on desktop
-        }
-
-        @Override
-        public void setTaskListener(IDesktopTaskListener listener) throws RemoteException {
-            // TODO(b/261234402): move visibility from sysui state to listener
-        }
-    }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
index 517f9f2..7783113 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
@@ -16,14 +16,7 @@
 
 package com.android.wm.shell.desktopmode;
 
-import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE;
-
-import android.content.Context;
 import android.os.SystemProperties;
-import android.os.UserHandle;
-import android.provider.Settings;
-
-import com.android.internal.protolog.common.ProtoLog;
 
 /**
  * Constants for desktop mode feature
@@ -31,13 +24,7 @@
 public class DesktopModeStatus {
 
     /**
-     * Flag to indicate whether desktop mode is available on the device
-     */
-    private static final boolean IS_SUPPORTED = SystemProperties.getBoolean(
-            "persist.wm.debug.desktop_mode", false);
-
-    /**
-     * Flag to indicate whether desktop mode proto 2 is available on the device
+     * Flag to indicate whether desktop mode proto is available on the device
      */
     private static final boolean IS_PROTO2_ENABLED = SystemProperties.getBoolean(
             "persist.wm.debug.desktop_mode_2", false);
@@ -64,28 +51,13 @@
             "persist.wm.debug.desktop_stashing", false);
 
     /**
-     * Return {@code true} if desktop mode support is enabled
-     */
-    public static boolean isProto1Enabled() {
-        return IS_SUPPORTED;
-    }
-
-    /**
      * Return {@code true} is desktop windowing proto 2 is enabled
      */
-    public static boolean isProto2Enabled() {
+    public static boolean isEnabled() {
         return IS_PROTO2_ENABLED;
     }
 
     /**
-     * Return {@code true} if proto 1 or 2 is enabled.
-     * Can be used to guard logic that is common for both prototypes.
-     */
-    public static boolean isAnyEnabled() {
-        return isProto1Enabled() || isProto2Enabled();
-    }
-
-    /**
      * Return {@code true} if veiled resizing is active. If false, fluid resizing is used.
      */
     public static boolean isVeiledResizeEnabled() {
@@ -99,26 +71,4 @@
     public static boolean isStashingEnabled() {
         return IS_STASHING_ENABLED;
     }
-    /**
-     * Check if desktop mode is active
-     *
-     * @return {@code true} if active
-     */
-    public static boolean isActive(Context context) {
-        if (!isAnyEnabled()) {
-            return false;
-        }
-        if (isProto2Enabled()) {
-            // Desktop mode is always active in prototype 2
-            return true;
-        }
-        try {
-            int result = Settings.System.getIntForUser(context.getContentResolver(),
-                    Settings.System.DESKTOP_MODE, UserHandle.USER_CURRENT);
-            return result != 0;
-        } catch (Exception e) {
-            ProtoLog.e(WM_SHELL_DESKTOP_MODE, "Failed to read DESKTOP_MODE setting %s", e);
-            return false;
-        }
-    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index 236dec0..b918c83 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -122,7 +122,7 @@
 
     init {
         desktopMode = DesktopModeImpl()
-        if (DesktopModeStatus.isProto2Enabled()) {
+        if (DesktopModeStatus.isEnabled()) {
             shellInit.addInitCallback({ onInit() }, this)
         }
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
index 22541bbd..a80241e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
@@ -68,7 +68,7 @@
 
     private void onInit() {
         mShellTaskOrganizer.addListenerForType(this, TASK_LISTENER_TYPE_FREEFORM);
-        if (DesktopModeStatus.isAnyEnabled()) {
+        if (DesktopModeStatus.isEnabled()) {
             mShellTaskOrganizer.addFocusListener(this);
         }
     }
@@ -90,7 +90,7 @@
             t.apply();
         }
 
-        if (DesktopModeStatus.isAnyEnabled()) {
+        if (DesktopModeStatus.isEnabled()) {
             mDesktopModeTaskRepository.ifPresent(repository -> {
                 repository.addOrMoveFreeformTaskToTop(taskInfo.taskId);
                 if (taskInfo.isVisible) {
@@ -111,7 +111,7 @@
                 taskInfo.taskId);
         mTasks.remove(taskInfo.taskId);
 
-        if (DesktopModeStatus.isAnyEnabled()) {
+        if (DesktopModeStatus.isEnabled()) {
             mDesktopModeTaskRepository.ifPresent(repository -> {
                 repository.removeFreeformTask(taskInfo.taskId);
                 if (repository.removeActiveTask(taskInfo.taskId)) {
@@ -135,7 +135,7 @@
                 taskInfo.taskId);
         mWindowDecorationViewModel.onTaskInfoChanged(taskInfo);
         state.mTaskInfo = taskInfo;
-        if (DesktopModeStatus.isAnyEnabled()) {
+        if (DesktopModeStatus.isEnabled()) {
             mDesktopModeTaskRepository.ifPresent(repository -> {
                 if (taskInfo.isVisible) {
                     if (repository.addActiveTask(taskInfo.displayId, taskInfo.taskId)) {
@@ -154,7 +154,7 @@
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG,
                 "Freeform Task Focus Changed: #%d focused=%b",
                 taskInfo.taskId, taskInfo.isFocused);
-        if (DesktopModeStatus.isAnyEnabled() && taskInfo.isFocused) {
+        if (DesktopModeStatus.isEnabled() && taskInfo.isFocused) {
             mDesktopModeTaskRepository.ifPresent(repository -> {
                 repository.addOrMoveFreeformTaskToTop(taskInfo.taskId);
             });
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
index ac142e9..94e1b33 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
@@ -340,7 +340,7 @@
                 continue;
             }
 
-            if (DesktopModeStatus.isProto2Enabled() && mDesktopModeTaskRepository.isPresent()
+            if (DesktopModeStatus.isEnabled() && mDesktopModeTaskRepository.isPresent()
                     && mDesktopModeTaskRepository.get().isActiveTask(taskInfo.taskId)) {
                 // Freeform tasks will be added as a separate entry
                 freeformTasks.add(taskInfo);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
index 986560b..87ceaa4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
@@ -43,7 +43,6 @@
 
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.common.split.SplitScreenUtils;
-import com.android.wm.shell.desktopmode.DesktopModeController;
 import com.android.wm.shell.desktopmode.DesktopModeStatus;
 import com.android.wm.shell.desktopmode.DesktopTasksController;
 import com.android.wm.shell.keyguard.KeyguardTransitionHandler;
@@ -71,7 +70,6 @@
     private RecentsTransitionHandler mRecentsHandler;
     private StageCoordinator mSplitHandler;
     private final KeyguardTransitionHandler mKeyguardHandler;
-    private DesktopModeController mDesktopModeController;
     private DesktopTasksController mDesktopTasksController;
     private UnfoldTransitionHandler mUnfoldHandler;
 
@@ -141,7 +139,6 @@
             @Nullable PipTransitionController pipTransitionController,
             Optional<RecentsTransitionHandler> recentsHandlerOptional,
             KeyguardTransitionHandler keyguardHandler,
-            Optional<DesktopModeController> desktopModeControllerOptional,
             Optional<DesktopTasksController> desktopTasksControllerOptional,
             Optional<UnfoldTransitionHandler> unfoldHandler) {
         mPlayer = player;
@@ -161,7 +158,6 @@
                 if (mRecentsHandler != null) {
                     mRecentsHandler.addMixer(this);
                 }
-                mDesktopModeController = desktopModeControllerOptional.orElse(null);
                 mDesktopTasksController = desktopTasksControllerOptional.orElse(null);
                 mUnfoldHandler = unfoldHandler.orElse(null);
             }, this);
@@ -244,7 +240,7 @@
     @Override
     public Transitions.TransitionHandler handleRecentsRequest(WindowContainerTransaction outWCT) {
         if (mRecentsHandler != null && (mSplitHandler.isSplitScreenVisible()
-                || DesktopModeStatus.isActive(mPlayer.getContext()))) {
+                || DesktopModeStatus.isEnabled())) {
             return this;
         }
         return null;
@@ -259,7 +255,7 @@
                     MixedTransition.TYPE_RECENTS_DURING_SPLIT, transition);
             mixed.mLeftoversHandler = mRecentsHandler;
             mActiveTransitions.add(mixed);
-        } else if (DesktopModeStatus.isActive(mPlayer.getContext())) {
+        } else if (DesktopModeStatus.isEnabled()) {
             ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a recents request while "
                     + "desktop mode is active, so treat it as Mixed.");
             final MixedTransition mixed = new MixedTransition(
@@ -666,11 +662,6 @@
         if (!consumed) {
             return false;
         }
-        //Sync desktop mode state (proto 1)
-        if (mDesktopModeController != null) {
-            mDesktopModeController.syncSurfaceState(info, finishTransaction);
-            return true;
-        }
         //Sync desktop mode state (proto 2)
         if (mDesktopTasksController != null) {
             mDesktopTasksController.syncSurfaceState(info, finishTransaction);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index 92b44d4..abd2ad4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -69,7 +69,6 @@
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.common.SyncTransactionQueue;
-import com.android.wm.shell.desktopmode.DesktopModeController;
 import com.android.wm.shell.desktopmode.DesktopModeStatus;
 import com.android.wm.shell.desktopmode.DesktopTasksController;
 import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition;
@@ -102,7 +101,6 @@
     private final Choreographer mMainChoreographer;
     private final DisplayController mDisplayController;
     private final SyncTransactionQueue mSyncQueue;
-    private final Optional<DesktopModeController> mDesktopModeController;
     private final Optional<DesktopTasksController> mDesktopTasksController;
     private boolean mTransitionDragActive;
 
@@ -135,7 +133,6 @@
             ShellController shellController,
             SyncTransactionQueue syncQueue,
             Transitions transitions,
-            Optional<DesktopModeController> desktopModeController,
             Optional<DesktopTasksController> desktopTasksController,
             RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer
     ) {
@@ -149,7 +146,6 @@
                 shellController,
                 syncQueue,
                 transitions,
-                desktopModeController,
                 desktopTasksController,
                 new DesktopModeWindowDecoration.Factory(),
                 new InputMonitorFactory(),
@@ -169,7 +165,6 @@
             ShellController shellController,
             SyncTransactionQueue syncQueue,
             Transitions transitions,
-            Optional<DesktopModeController> desktopModeController,
             Optional<DesktopTasksController> desktopTasksController,
             DesktopModeWindowDecoration.Factory desktopModeWindowDecorFactory,
             InputMonitorFactory inputMonitorFactory,
@@ -185,7 +180,6 @@
         mDisplayController = displayController;
         mSyncQueue = syncQueue;
         mTransitions = transitions;
-        mDesktopModeController = desktopModeController;
         mDesktopTasksController = desktopTasksController;
 
         mDesktopModeWindowDecorFactory = desktopModeWindowDecorFactory;
@@ -214,9 +208,8 @@
             public void onTaskStageChanged(int taskId, int stage, boolean visible) {
                 if (visible) {
                     DesktopModeWindowDecoration decor = mWindowDecorByTaskId.get(taskId);
-                    if (decor != null && DesktopModeStatus.isActive(mContext)
+                    if (decor != null && DesktopModeStatus.isEnabled()
                             && decor.mTaskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
-                        mDesktopModeController.ifPresent(c -> c.setDesktopModeActive(false));
                         mDesktopTasksController.ifPresent(c -> c.moveToSplit(decor.mTaskInfo));
                     }
                 }
@@ -376,7 +369,6 @@
                     decoration.closeHandleMenu();
                 }
             } else if (id == R.id.desktop_button) {
-                mDesktopModeController.ifPresent(c -> c.setDesktopModeActive(true));
                 if (mDesktopTasksController.isPresent()) {
                     final WindowContainerTransaction wct = new WindowContainerTransaction();
                     // App sometimes draws before the insets from WindowDecoration#relayout have
@@ -387,7 +379,6 @@
                 }
                 decoration.closeHandleMenu();
             } else if (id == R.id.fullscreen_button) {
-                mDesktopModeController.ifPresent(c -> c.setDesktopModeActive(false));
                 mDesktopTasksController.ifPresent(c -> c.moveToFullscreen(mTaskId));
                 decoration.closeHandleMenu();
             } else if (id == R.id.split_screen_button) {
@@ -465,7 +456,6 @@
         private void moveTaskToFront(RunningTaskInfo taskInfo) {
             if (!taskInfo.isFocused) {
                 mDesktopTasksController.ifPresent(c -> c.moveTaskToFront(taskInfo));
-                mDesktopModeController.ifPresent(c -> c.moveTaskToFront(taskInfo));
             }
         }
 
@@ -476,15 +466,10 @@
         @Override
         public boolean handleMotionEvent(@Nullable View v, MotionEvent e) {
             final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
-            if (DesktopModeStatus.isProto2Enabled()
+            if (DesktopModeStatus.isEnabled()
                     && taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
                 return false;
             }
-            if (DesktopModeStatus.isProto1Enabled() && mDesktopModeController.isPresent()
-                    && mDesktopModeController.get().getDisplayAreaWindowingMode(taskInfo.displayId)
-                    == WINDOWING_MODE_FULLSCREEN) {
-                return false;
-            }
             if (mGestureDetector.onTouchEvent(e)) {
                 return true;
             }
@@ -634,7 +619,7 @@
      */
     private void handleReceivedMotionEvent(MotionEvent ev, InputMonitor inputMonitor) {
         final DesktopModeWindowDecoration relevantDecor = getRelevantWindowDecor(ev);
-        if (DesktopModeStatus.isProto2Enabled()) {
+        if (DesktopModeStatus.isEnabled()) {
             if (relevantDecor == null
                     || relevantDecor.mTaskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM
                     || mTransitionDragActive) {
@@ -643,14 +628,10 @@
         }
         handleEventOutsideFocusedCaption(ev, relevantDecor);
         // Prevent status bar from reacting to a caption drag.
-        if (DesktopModeStatus.isProto2Enabled()) {
+        if (DesktopModeStatus.isEnabled()) {
             if (mTransitionDragActive) {
                 inputMonitor.pilferPointers();
             }
-        } else if (DesktopModeStatus.isProto1Enabled()) {
-            if (mTransitionDragActive && !DesktopModeStatus.isActive(mContext)) {
-                inputMonitor.pilferPointers();
-            }
         }
     }
 
@@ -683,7 +664,7 @@
                     mDragToDesktopAnimationStartBounds.set(
                             relevantDecor.mTaskInfo.configuration.windowConfiguration.getBounds());
                     boolean dragFromStatusBarAllowed = false;
-                    if (DesktopModeStatus.isProto2Enabled()) {
+                    if (DesktopModeStatus.isEnabled()) {
                         // In proto2 any full screen or multi-window task can be dragged to
                         // freeform.
                         final int windowingMode = relevantDecor.mTaskInfo.getWindowingMode();
@@ -708,10 +689,8 @@
                     final int statusBarHeight = getStatusBarHeight(
                             relevantDecor.mTaskInfo.displayId);
                     if (ev.getY() > 2 * statusBarHeight) {
-                        if (DesktopModeStatus.isProto2Enabled()) {
+                        if (DesktopModeStatus.isEnabled()) {
                             animateToDesktop(relevantDecor, ev);
-                        } else if (DesktopModeStatus.isProto1Enabled()) {
-                            mDesktopModeController.ifPresent(c -> c.setDesktopModeActive(true));
                         }
                         mMoveToDesktopAnimator = null;
                         return;
@@ -902,7 +881,7 @@
                 && taskInfo.isFocused) {
             return false;
         }
-        return DesktopModeStatus.isProto2Enabled()
+        return DesktopModeStatus.isEnabled()
                 && taskInfo.getWindowingMode() != WINDOWING_MODE_PINNED
                 && taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD
                 && !taskInfo.configuration.windowConfiguration.isAlwaysOnTop()
@@ -984,13 +963,11 @@
 
         @Override
         public void onTaskCornersChanged(int taskId, Region corner) {
-            mDesktopModeController.ifPresent(d -> d.onTaskCornersChanged(taskId, corner));
             mDesktopTasksController.ifPresent(d -> d.onTaskCornersChanged(taskId, corner));
         }
 
         @Override
         public void onTaskCornersRemoved(int taskId) {
-            mDesktopModeController.ifPresent(d -> d.removeCornersForTask(taskId));
             mDesktopTasksController.ifPresent(d -> d.removeCornersForTask(taskId));
         }
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index a75dce2..3e21c8c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -428,7 +428,7 @@
                 .setOnTouchListener(mOnCaptionTouchListener)
                 .setLayoutId(mRelayoutParams.mLayoutResId)
                 .setCaptionPosition(mRelayoutParams.mCaptionX, mRelayoutParams.mCaptionY)
-                .setWindowingButtonsVisible(DesktopModeStatus.isProto2Enabled())
+                .setWindowingButtonsVisible(DesktopModeStatus.isEnabled())
                 .build();
         mHandleMenu.show();
     }
@@ -549,9 +549,6 @@
     }
 
     private int getDesktopModeWindowDecorLayoutId(int windowingMode) {
-        if (DesktopModeStatus.isProto1Enabled()) {
-            return R.layout.desktop_mode_app_controls_window_decor;
-        }
         return windowingMode == WINDOWING_MODE_FREEFORM
                 ? R.layout.desktop_mode_app_controls_window_decor
                 : R.layout.desktop_mode_focused_window_decor;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java
index ac4a597..ca7cbfd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java
@@ -236,7 +236,7 @@
             t.setPosition(mAppInfoPill.mWindowSurface,
                     mAppInfoPillPosition.x, mAppInfoPillPosition.y);
             // Only show windowing buttons in proto2. Proto1 uses a system-level mode only.
-            final boolean shouldShowWindowingPill = DesktopModeStatus.isProto2Enabled();
+            final boolean shouldShowWindowingPill = DesktopModeStatus.isEnabled();
             if (shouldShowWindowingPill) {
                 t.setPosition(mWindowingPill.mWindowSurface,
                         mWindowingPillPosition.x, mWindowingPillPosition.y);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java
deleted file mode 100644
index 605a762..0000000
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java
+++ /dev/null
@@ -1,531 +0,0 @@
-/*
- * 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.desktopmode;
-
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOW_CONFIG_BOUNDS;
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManager.TRANSIT_CHANGE;
-import static android.view.WindowManager.TRANSIT_CLOSE;
-import static android.view.WindowManager.TRANSIT_NONE;
-import static android.view.WindowManager.TRANSIT_OPEN;
-import static android.view.WindowManager.TRANSIT_TO_FRONT;
-import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER;
-
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
-import static com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask;
-import static com.android.wm.shell.desktopmode.DesktopTestHelpers.createFullscreenTask;
-import static com.android.wm.shell.desktopmode.DesktopTestHelpers.createHomeTask;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-
-import android.app.ActivityManager.RunningTaskInfo;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.IBinder;
-import android.testing.AndroidTestingRunner;
-import android.window.DisplayAreaInfo;
-import android.window.TransitionRequestInfo;
-import android.window.WindowContainerTransaction;
-import android.window.WindowContainerTransaction.Change;
-import android.window.WindowContainerTransaction.HierarchyOp;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.dx.mockito.inline.extended.StaticMockitoSession;
-import com.android.wm.shell.MockToken;
-import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
-import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.ShellTestCase;
-import com.android.wm.shell.TestShellExecutor;
-import com.android.wm.shell.common.ShellExecutor;
-import com.android.wm.shell.sysui.ShellController;
-import com.android.wm.shell.sysui.ShellInit;
-import com.android.wm.shell.transition.Transitions;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-public class DesktopModeControllerTest extends ShellTestCase {
-
-    private static final int SECOND_DISPLAY = 2;
-
-    @Mock
-    private ShellController mShellController;
-    @Mock
-    private ShellTaskOrganizer mShellTaskOrganizer;
-    @Mock
-    private RootTaskDisplayAreaOrganizer mRootTaskDisplayAreaOrganizer;
-    @Mock
-    private ShellExecutor mTestExecutor;
-    @Mock
-    private Handler mMockHandler;
-    @Mock
-    private Transitions mTransitions;
-    private DesktopModeController mController;
-    private DesktopModeTaskRepository mDesktopModeTaskRepository;
-    private ShellInit mShellInit;
-    private StaticMockitoSession mMockitoSession;
-
-    @Before
-    public void setUp() {
-        mMockitoSession = mockitoSession().mockStatic(DesktopModeStatus.class).startMocking();
-        when(DesktopModeStatus.isProto1Enabled()).thenReturn(true);
-        when(DesktopModeStatus.isActive(any())).thenReturn(true);
-
-        mShellInit = Mockito.spy(new ShellInit(mTestExecutor));
-
-        mDesktopModeTaskRepository = new DesktopModeTaskRepository();
-
-        mController = createController();
-
-        when(mShellTaskOrganizer.getRunningTasks(anyInt())).thenReturn(new ArrayList<>());
-
-        mShellInit.init();
-        clearInvocations(mShellTaskOrganizer);
-        clearInvocations(mRootTaskDisplayAreaOrganizer);
-        clearInvocations(mTransitions);
-    }
-
-    @After
-    public void tearDown() {
-        mMockitoSession.finishMocking();
-    }
-
-    @Test
-    public void instantiate_addInitCallback() {
-        verify(mShellInit).addInitCallback(any(), any());
-    }
-
-    @Test
-    public void instantiate_flagOff_doNotAddInitCallback() {
-        when(DesktopModeStatus.isProto1Enabled()).thenReturn(false);
-        clearInvocations(mShellInit);
-
-        createController();
-
-        verify(mShellInit, never()).addInitCallback(any(), any());
-    }
-
-    @Test
-    public void testDesktopModeEnabled_rootTdaSetToFreeform() {
-        DisplayAreaInfo displayAreaInfo = createMockDisplayArea();
-
-        mController.updateDesktopModeActive(true);
-        WindowContainerTransaction wct = getDesktopModeSwitchTransaction();
-
-        // 1 change: Root TDA windowing mode
-        assertThat(wct.getChanges().size()).isEqualTo(1);
-        // Verify WCT has a change for setting windowing mode to freeform
-        Change change = wct.getChanges().get(displayAreaInfo.token.asBinder());
-        assertThat(change).isNotNull();
-        assertThat(change.getWindowingMode()).isEqualTo(WINDOWING_MODE_FREEFORM);
-    }
-
-    @Test
-    public void testDesktopModeDisabled_rootTdaSetToFullscreen() {
-        DisplayAreaInfo displayAreaInfo = createMockDisplayArea();
-
-        mController.updateDesktopModeActive(false);
-        WindowContainerTransaction wct = getDesktopModeSwitchTransaction();
-
-        // 1 change: Root TDA windowing mode
-        assertThat(wct.getChanges().size()).isEqualTo(1);
-        // Verify WCT has a change for setting windowing mode to fullscreen
-        Change change = wct.getChanges().get(displayAreaInfo.token.asBinder());
-        assertThat(change).isNotNull();
-        assertThat(change.getWindowingMode()).isEqualTo(WINDOWING_MODE_FULLSCREEN);
-    }
-
-    @Test
-    public void testDesktopModeEnabled_windowingModeCleared() {
-        createMockDisplayArea();
-        RunningTaskInfo freeformTask = createFreeformTask();
-        RunningTaskInfo fullscreenTask = createFullscreenTask();
-        RunningTaskInfo homeTask = createHomeTask();
-        when(mShellTaskOrganizer.getRunningTasks(anyInt())).thenReturn(new ArrayList<>(
-                Arrays.asList(freeformTask, fullscreenTask, homeTask)));
-
-        mController.updateDesktopModeActive(true);
-        WindowContainerTransaction wct = getDesktopModeSwitchTransaction();
-
-        // 2 changes: Root TDA windowing mode and 1 task
-        assertThat(wct.getChanges().size()).isEqualTo(2);
-        // No changes for tasks that are not standard or freeform
-        assertThat(wct.getChanges().get(fullscreenTask.token.asBinder())).isNull();
-        assertThat(wct.getChanges().get(homeTask.token.asBinder())).isNull();
-        // Standard freeform task has windowing mode cleared
-        Change change = wct.getChanges().get(freeformTask.token.asBinder());
-        assertThat(change).isNotNull();
-        assertThat(change.getWindowingMode()).isEqualTo(WINDOWING_MODE_UNDEFINED);
-    }
-
-    @Test
-    public void testDesktopModeDisabled_windowingModeAndBoundsCleared() {
-        createMockDisplayArea();
-        RunningTaskInfo freeformTask = createFreeformTask();
-        RunningTaskInfo fullscreenTask = createFullscreenTask();
-        RunningTaskInfo homeTask = createHomeTask();
-        when(mShellTaskOrganizer.getRunningTasks(anyInt())).thenReturn(new ArrayList<>(
-                Arrays.asList(freeformTask, fullscreenTask, homeTask)));
-
-        mController.updateDesktopModeActive(false);
-        WindowContainerTransaction wct = getDesktopModeSwitchTransaction();
-
-        // 3 changes: Root TDA windowing mode and 2 tasks
-        assertThat(wct.getChanges().size()).isEqualTo(3);
-        // No changes to home task
-        assertThat(wct.getChanges().get(homeTask.token.asBinder())).isNull();
-        // Standard tasks have bounds cleared
-        assertThatBoundsCleared(wct.getChanges().get(freeformTask.token.asBinder()));
-        assertThatBoundsCleared(wct.getChanges().get(fullscreenTask.token.asBinder()));
-        // Freeform standard tasks have windowing mode cleared
-        assertThat(wct.getChanges().get(
-                freeformTask.token.asBinder()).getWindowingMode()).isEqualTo(
-                WINDOWING_MODE_UNDEFINED);
-    }
-
-    @Test
-    public void testDesktopModeEnabled_homeTaskBehindVisibleTask() {
-        createMockDisplayArea();
-        RunningTaskInfo fullscreenTask1 = createFullscreenTask();
-        fullscreenTask1.isVisible = true;
-        RunningTaskInfo fullscreenTask2 = createFullscreenTask();
-        fullscreenTask2.isVisible = false;
-        RunningTaskInfo homeTask = createHomeTask();
-        when(mShellTaskOrganizer.getRunningTasks(anyInt())).thenReturn(new ArrayList<>(
-                Arrays.asList(fullscreenTask1, fullscreenTask2, homeTask)));
-
-        mController.updateDesktopModeActive(true);
-        WindowContainerTransaction wct = getDesktopModeSwitchTransaction();
-
-        // Check that there are hierarchy changes for home task and visible task
-        assertThat(wct.getHierarchyOps()).hasSize(2);
-        // First show home task
-        HierarchyOp op1 = wct.getHierarchyOps().get(0);
-        assertThat(op1.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
-        assertThat(op1.getContainer()).isEqualTo(homeTask.token.asBinder());
-
-        // Then visible task on top of it
-        HierarchyOp op2 = wct.getHierarchyOps().get(1);
-        assertThat(op2.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
-        assertThat(op2.getContainer()).isEqualTo(fullscreenTask1.token.asBinder());
-    }
-
-    @Test
-    public void testShowDesktopApps_allAppsInvisible_bringsToFront() {
-        // Set up two active tasks on desktop, task2 is on top of task1.
-        RunningTaskInfo freeformTask1 = createFreeformTask();
-        mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, freeformTask1.taskId);
-        mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(freeformTask1.taskId);
-        mDesktopModeTaskRepository.updateVisibleFreeformTasks(
-                DEFAULT_DISPLAY, freeformTask1.taskId, false /* visible */);
-        RunningTaskInfo freeformTask2 = createFreeformTask();
-        mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, freeformTask2.taskId);
-        mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(freeformTask2.taskId);
-        mDesktopModeTaskRepository.updateVisibleFreeformTasks(
-                DEFAULT_DISPLAY, freeformTask2.taskId, false /* visible */);
-        when(mShellTaskOrganizer.getRunningTaskInfo(freeformTask1.taskId)).thenReturn(
-                freeformTask1);
-        when(mShellTaskOrganizer.getRunningTaskInfo(freeformTask2.taskId)).thenReturn(
-                freeformTask2);
-
-        // Run show desktop apps logic
-        mController.showDesktopApps(DEFAULT_DISPLAY);
-
-        final WindowContainerTransaction wct = getBringAppsToFrontTransaction();
-        // Check wct has reorder calls
-        assertThat(wct.getHierarchyOps()).hasSize(2);
-
-        // Task 1 appeared first, must be first reorder to top.
-        HierarchyOp op1 = wct.getHierarchyOps().get(0);
-        assertThat(op1.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
-        assertThat(op1.getContainer()).isEqualTo(freeformTask1.token.asBinder());
-
-        // Task 2 appeared last, must be last reorder to top.
-        HierarchyOp op2 = wct.getHierarchyOps().get(1);
-        assertThat(op2.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
-        assertThat(op2.getContainer()).isEqualTo(freeformTask2.token.asBinder());
-    }
-
-    @Test
-    public void testShowDesktopApps_appsAlreadyVisible_bringsToFront() {
-        final RunningTaskInfo task1 = createFreeformTask();
-        mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task1.taskId);
-        mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task1.taskId);
-        mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task1.taskId,
-                true /* visible */);
-        when(mShellTaskOrganizer.getRunningTaskInfo(task1.taskId)).thenReturn(task1);
-        final RunningTaskInfo task2 = createFreeformTask();
-        mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task2.taskId);
-        mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task2.taskId);
-        mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task2.taskId,
-                true /* visible */);
-        when(mShellTaskOrganizer.getRunningTaskInfo(task2.taskId)).thenReturn(task2);
-
-        mController.showDesktopApps(DEFAULT_DISPLAY);
-
-        final WindowContainerTransaction wct = getBringAppsToFrontTransaction();
-        // Check wct has reorder calls
-        assertThat(wct.getHierarchyOps()).hasSize(2);
-        // Task 1 appeared first, must be first reorder to top.
-        HierarchyOp op1 = wct.getHierarchyOps().get(0);
-        assertThat(op1.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
-        assertThat(op1.getContainer()).isEqualTo(task1.token.asBinder());
-
-        // Task 2 appeared last, must be last reorder to top.
-        HierarchyOp op2 = wct.getHierarchyOps().get(1);
-        assertThat(op2.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
-        assertThat(op2.getContainer()).isEqualTo(task2.token.asBinder());
-    }
-
-    @Test
-    public void testShowDesktopApps_someAppsInvisible_reordersAll() {
-        final RunningTaskInfo task1 = createFreeformTask();
-        mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task1.taskId);
-        mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task1.taskId);
-        mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task1.taskId,
-                false /* visible */);
-        when(mShellTaskOrganizer.getRunningTaskInfo(task1.taskId)).thenReturn(task1);
-        final RunningTaskInfo task2 = createFreeformTask();
-        mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task2.taskId);
-        mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task2.taskId);
-        mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task2.taskId,
-                true /* visible */);
-        when(mShellTaskOrganizer.getRunningTaskInfo(task2.taskId)).thenReturn(task2);
-
-        mController.showDesktopApps(DEFAULT_DISPLAY);
-
-        final WindowContainerTransaction wct = getBringAppsToFrontTransaction();
-        // Both tasks should be reordered to top, even if one was already visible.
-        assertThat(wct.getHierarchyOps()).hasSize(2);
-        final HierarchyOp op1 = wct.getHierarchyOps().get(0);
-        assertThat(op1.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
-        assertThat(op1.getContainer()).isEqualTo(task1.token.asBinder());
-        final HierarchyOp op2 = wct.getHierarchyOps().get(1);
-        assertThat(op2.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
-        assertThat(op2.getContainer()).isEqualTo(task2.token.asBinder());
-    }
-
-    @Test
-    public void testShowDesktopApps_twoDisplays_bringsToFrontOnlyOneDisplay() {
-        RunningTaskInfo taskDefaultDisplay = createFreeformTask(DEFAULT_DISPLAY);
-        mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, taskDefaultDisplay.taskId);
-        mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(taskDefaultDisplay.taskId);
-        mDesktopModeTaskRepository.updateVisibleFreeformTasks(
-                DEFAULT_DISPLAY, taskDefaultDisplay.taskId, false /* visible */);
-        when(mShellTaskOrganizer.getRunningTaskInfo(taskDefaultDisplay.taskId)).thenReturn(
-                taskDefaultDisplay);
-
-        RunningTaskInfo taskSecondDisplay = createFreeformTask(SECOND_DISPLAY);
-        mDesktopModeTaskRepository.addActiveTask(SECOND_DISPLAY, taskSecondDisplay.taskId);
-        mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(taskSecondDisplay.taskId);
-        mDesktopModeTaskRepository.updateVisibleFreeformTasks(
-                SECOND_DISPLAY, taskSecondDisplay.taskId, false /* visible */);
-        when(mShellTaskOrganizer.getRunningTaskInfo(taskSecondDisplay.taskId)).thenReturn(
-                taskSecondDisplay);
-
-        mController.showDesktopApps(DEFAULT_DISPLAY);
-
-        WindowContainerTransaction wct = getBringAppsToFrontTransaction();
-        assertThat(wct.getHierarchyOps()).hasSize(1);
-        HierarchyOp op = wct.getHierarchyOps().get(0);
-        assertThat(op.getContainer()).isEqualTo(taskDefaultDisplay.token.asBinder());
-    }
-
-    @Test
-    public void testGetVisibleTaskCount_noTasks_returnsZero() {
-        assertThat(mController.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(0);
-    }
-
-    @Test
-    public void testGetVisibleTaskCount_twoTasks_bothVisible_returnsTwo() {
-        RunningTaskInfo task1 = createFreeformTask();
-        mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task1.taskId);
-        mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task1.taskId);
-        mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task1.taskId,
-                true /* visible */);
-
-        RunningTaskInfo task2 = createFreeformTask();
-        mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task2.taskId);
-        mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task2.taskId);
-        mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task2.taskId,
-                true /* visible */);
-
-        assertThat(mController.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(2);
-    }
-
-    @Test
-    public void testGetVisibleTaskCount_twoTasks_oneVisible_returnsOne() {
-        RunningTaskInfo task1 = createFreeformTask();
-        mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task1.taskId);
-        mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task1.taskId);
-        mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task1.taskId,
-                true /* visible */);
-
-        RunningTaskInfo task2 = createFreeformTask();
-        mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task2.taskId);
-        mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task2.taskId);
-        mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task2.taskId,
-                false /* visible */);
-
-        assertThat(mController.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(1);
-    }
-
-    @Test
-    public void testGetVisibleTaskCount_twoTasksVisibleOnDifferentDisplays_returnsOne() {
-        RunningTaskInfo taskDefaultDisplay = createFreeformTask();
-        mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, taskDefaultDisplay.taskId);
-        mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(taskDefaultDisplay.taskId);
-        mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY,
-                taskDefaultDisplay.taskId,
-                true /* visible */);
-
-        RunningTaskInfo taskSecondDisplay = createFreeformTask();
-        mDesktopModeTaskRepository.addActiveTask(SECOND_DISPLAY, taskSecondDisplay.taskId);
-        mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(taskSecondDisplay.taskId);
-        mDesktopModeTaskRepository.updateVisibleFreeformTasks(SECOND_DISPLAY,
-                taskSecondDisplay.taskId,
-                true /* visible */);
-
-        assertThat(mController.getVisibleTaskCount(SECOND_DISPLAY)).isEqualTo(1);
-    }
-
-    @Test
-    public void testHandleTransitionRequest_desktopModeNotActive_returnsNull() {
-        when(DesktopModeStatus.isActive(any())).thenReturn(false);
-        WindowContainerTransaction wct = mController.handleRequest(
-                new Binder(),
-                new TransitionRequestInfo(TRANSIT_OPEN, null /* trigger */, null /* remote */));
-        assertThat(wct).isNull();
-    }
-
-    @Test
-    public void testHandleTransitionRequest_unsupportedTransit_returnsNull() {
-        WindowContainerTransaction wct = mController.handleRequest(
-                new Binder(),
-                new TransitionRequestInfo(TRANSIT_CLOSE, null /* trigger */, null /* remote */));
-        assertThat(wct).isNull();
-    }
-
-    @Test
-    public void testHandleTransitionRequest_notFreeform_returnsNull() {
-        RunningTaskInfo trigger = new RunningTaskInfo();
-        trigger.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
-        WindowContainerTransaction wct = mController.handleRequest(
-                new Binder(),
-                new TransitionRequestInfo(TRANSIT_TO_FRONT, trigger, null /* remote */));
-        assertThat(wct).isNull();
-    }
-
-    @Test
-    public void testHandleTransitionRequest_taskOpen_returnsWct() {
-        RunningTaskInfo trigger = new RunningTaskInfo();
-        trigger.token = new MockToken().token();
-        trigger.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
-        WindowContainerTransaction wct = mController.handleRequest(
-                mock(IBinder.class),
-                new TransitionRequestInfo(TRANSIT_OPEN, trigger, null /* remote */));
-        assertThat(wct).isNotNull();
-    }
-
-    @Test
-    public void testHandleTransitionRequest_taskToFront_returnsWct() {
-        RunningTaskInfo trigger = new RunningTaskInfo();
-        trigger.token = new MockToken().token();
-        trigger.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
-        WindowContainerTransaction wct = mController.handleRequest(
-                mock(IBinder.class),
-                new TransitionRequestInfo(TRANSIT_TO_FRONT, trigger, null /* remote */));
-        assertThat(wct).isNotNull();
-    }
-
-    @Test
-    public void testHandleTransitionRequest_taskOpen_doesNotStartAnotherTransition() {
-        RunningTaskInfo trigger = new RunningTaskInfo();
-        trigger.token = new MockToken().token();
-        trigger.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
-        mController.handleRequest(
-                mock(IBinder.class),
-                new TransitionRequestInfo(TRANSIT_OPEN, trigger, null /* remote */));
-        verifyZeroInteractions(mTransitions);
-    }
-
-    private DesktopModeController createController() {
-        return new DesktopModeController(mContext, mShellInit, mShellController,
-                mShellTaskOrganizer, mRootTaskDisplayAreaOrganizer, mTransitions,
-                mDesktopModeTaskRepository, mMockHandler, new TestShellExecutor());
-    }
-
-    private DisplayAreaInfo createMockDisplayArea() {
-        DisplayAreaInfo displayAreaInfo = new DisplayAreaInfo(new MockToken().token(),
-                mContext.getDisplayId(), 0);
-        when(mRootTaskDisplayAreaOrganizer.getDisplayAreaInfo(mContext.getDisplayId()))
-                .thenReturn(displayAreaInfo);
-        return displayAreaInfo;
-    }
-
-    private WindowContainerTransaction getDesktopModeSwitchTransaction() {
-        ArgumentCaptor<WindowContainerTransaction> arg = ArgumentCaptor.forClass(
-                WindowContainerTransaction.class);
-        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
-            verify(mTransitions).startTransition(eq(TRANSIT_CHANGE), arg.capture(), any());
-        } else {
-            verify(mRootTaskDisplayAreaOrganizer).applyTransaction(arg.capture());
-        }
-        return arg.getValue();
-    }
-
-    private WindowContainerTransaction getBringAppsToFrontTransaction() {
-        final ArgumentCaptor<WindowContainerTransaction> arg = ArgumentCaptor.forClass(
-                WindowContainerTransaction.class);
-        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
-            verify(mTransitions).startTransition(eq(TRANSIT_NONE), arg.capture(), any());
-        } else {
-            verify(mShellTaskOrganizer).applyTransaction(arg.capture());
-        }
-        return arg.getValue();
-    }
-
-    private void assertThatBoundsCleared(Change change) {
-        assertThat((change.getWindowSetMask() & WINDOW_CONFIG_BOUNDS) != 0).isTrue();
-        assertThat(change.getConfiguration().windowConfiguration.getBounds().isEmpty()).isTrue();
-    }
-
-}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
index 5d87cf8..be4a287 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -107,7 +107,7 @@
     @Before
     fun setUp() {
         mockitoSession = mockitoSession().mockStatic(DesktopModeStatus::class.java).startMocking()
-        whenever(DesktopModeStatus.isProto2Enabled()).thenReturn(true)
+        whenever(DesktopModeStatus.isEnabled()).thenReturn(true)
 
         shellInit = Mockito.spy(ShellInit(testExecutor))
         desktopModeTaskRepository = DesktopModeTaskRepository()
@@ -154,7 +154,7 @@
 
     @Test
     fun instantiate_flagOff_doNotAddInitCallback() {
-        whenever(DesktopModeStatus.isProto2Enabled()).thenReturn(false)
+        whenever(DesktopModeStatus.isEnabled()).thenReturn(false)
         clearInvocations(shellInit)
 
         createController()
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
index 9e9e1ca..40ce785 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
@@ -257,7 +257,7 @@
     public void testGetRecentTasks_hasActiveDesktopTasks_proto2Enabled_groupFreeformTasks() {
         StaticMockitoSession mockitoSession = mockitoSession().mockStatic(
                 DesktopModeStatus.class).startMocking();
-        when(DesktopModeStatus.isProto2Enabled()).thenReturn(true);
+        when(DesktopModeStatus.isEnabled()).thenReturn(true);
 
         ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1);
         ActivityManager.RecentTaskInfo t2 = makeTaskInfo(2);
@@ -297,7 +297,7 @@
     public void testGetRecentTasks_hasActiveDesktopTasks_proto2Disabled_doNotGroupFreeformTasks() {
         StaticMockitoSession mockitoSession = mockitoSession().mockStatic(
                 DesktopModeStatus.class).startMocking();
-        when(DesktopModeStatus.isProto2Enabled()).thenReturn(false);
+        when(DesktopModeStatus.isEnabled()).thenReturn(false);
 
         ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1);
         ActivityManager.RecentTaskInfo t2 = makeTaskInfo(2);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
index 7f0465a..d8afe68 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
@@ -55,7 +55,6 @@
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.common.SyncTransactionQueue;
-import com.android.wm.shell.desktopmode.DesktopModeController;
 import com.android.wm.shell.desktopmode.DesktopTasksController;
 import com.android.wm.shell.sysui.ShellController;
 import com.android.wm.shell.sysui.ShellInit;
@@ -88,7 +87,6 @@
     @Mock private DisplayController mDisplayController;
     @Mock private DisplayLayout mDisplayLayout;
     @Mock private SyncTransactionQueue mSyncQueue;
-    @Mock private DesktopModeController mDesktopModeController;
     @Mock private DesktopTasksController mDesktopTasksController;
     @Mock private InputMonitor mInputMonitor;
     @Mock private InputManager mInputManager;
@@ -121,7 +119,6 @@
                         mShellController,
                         mSyncQueue,
                         mTransitions,
-                        Optional.of(mDesktopModeController),
                         Optional.of(mDesktopTasksController),
                         mDesktopModeWindowDecorFactory,
                         mMockInputMonitorFactory,
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 0acce03..ec24ab7 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -954,9 +954,6 @@
     <!-- UI debug setting: enable freeform window support summary [CHAR LIMIT=150] -->
     <string name="enable_freeform_support_summary">Enable support for experimental freeform windows.</string>
 
-    <!-- UI debug setting: enable desktop mode [CHAR LIMIT=25] -->
-    <string name="desktop_mode">Desktop mode</string>
-
     <!-- Local (desktop) backup password menu title [CHAR LIMIT=25] -->
     <string name="local_backup_password_title">Desktop backup password</string>
     <!-- Summary text of the "local backup password" setting when the user has not supplied a password -->
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 92f65d6..c0f6231 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -98,7 +98,6 @@
                     Settings.System.VOLUME_VOICE, // deprecated since API 2?
                     Settings.System.WHEN_TO_MAKE_WIFI_CALLS, // bug?
                     Settings.System.WINDOW_ORIENTATION_LISTENER_LOG, // used for debugging only
-                    Settings.System.DESKTOP_MODE, // developer setting for internal prototyping
                     Settings.System.MIN_REFRESH_RATE, // depends on hardware capabilities
                     Settings.System.PEAK_REFRESH_RATE, // depends on hardware capabilities
                     Settings.System.SCREEN_BRIGHTNESS_FLOAT,
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/dialog/ui/composable/AlertDialogContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/dialog/ui/composable/AlertDialogContent.kt
index 48f40e7..418df5c 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/dialog/ui/composable/AlertDialogContent.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/dialog/ui/composable/AlertDialogContent.kt
@@ -19,13 +19,11 @@
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.PaddingValues
-import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.defaultMinSize
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.rememberScrollState
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.material3.LocalContentColor
@@ -35,9 +33,13 @@
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.layout.Layout
+import androidx.compose.ui.layout.Placeable
+import androidx.compose.ui.layout.layoutId
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.unit.dp
 import com.android.compose.theme.LocalAndroidColorScheme
+import kotlin.math.roundToInt
 
 /**
  * The content of an AlertDialog which can be used together with
@@ -99,28 +101,101 @@
         Spacer(Modifier.height(32.dp))
 
         // Buttons.
-        // TODO(b/283817398): If there is not enough space, the buttons should automatically stack
-        // as shown in go/sysui-dialog-styling.
         if (positiveButton != null || negativeButton != null || neutralButton != null) {
-            Row(Modifier.fillMaxWidth()) {
-                if (neutralButton != null) {
-                    neutralButton()
-                    Spacer(Modifier.width(8.dp))
-                }
+            AlertDialogButtons(
+                positiveButton = positiveButton,
+                negativeButton = negativeButton,
+                neutralButton = neutralButton,
+            )
+        }
+    }
+}
 
-                Spacer(Modifier.weight(1f))
+@Composable
+private fun AlertDialogButtons(
+    positiveButton: (@Composable () -> Unit)?,
+    negativeButton: (@Composable () -> Unit)?,
+    neutralButton: (@Composable () -> Unit)?,
+    modifier: Modifier = Modifier,
+) {
+    Layout(
+        content = {
+            positiveButton?.let { Box(Modifier.layoutId("positive")) { it() } }
+            negativeButton?.let { Box(Modifier.layoutId("negative")) { it() } }
+            neutralButton?.let { Box(Modifier.layoutId("neutral")) { it() } }
+        },
+        modifier,
+    ) { measurables, constraints ->
+        check(constraints.hasBoundedWidth) {
+            "AlertDialogButtons should not be composed in an horizontally scrollable layout"
+        }
+        val maxWidth = constraints.maxWidth
 
-                if (negativeButton != null) {
-                    negativeButton()
-                }
+        // Measure the buttons.
+        var positive: Placeable? = null
+        var negative: Placeable? = null
+        var neutral: Placeable? = null
+        for (i in measurables.indices) {
+            val measurable = measurables[i]
+            when (val layoutId = measurable.layoutId) {
+                "positive" -> positive = measurable.measure(constraints)
+                "negative" -> negative = measurable.measure(constraints)
+                "neutral" -> neutral = measurable.measure(constraints)
+                else -> error("Unexpected layoutId=$layoutId")
+            }
+        }
 
-                if (positiveButton != null) {
-                    if (negativeButton != null) {
-                        Spacer(Modifier.width(8.dp))
+        fun Placeable?.width() = this?.width ?: 0
+        fun Placeable?.height() = this?.height ?: 0
+
+        // The min horizontal spacing between buttons.
+        val horizontalSpacing = 8.dp.toPx()
+        val totalHorizontalSpacing = (measurables.size - 1) * horizontalSpacing
+        val requiredWidth =
+            positive.width() + negative.width() + neutral.width() + totalHorizontalSpacing
+
+        if (requiredWidth <= maxWidth) {
+            // Stack horizontally: [neutral][flexSpace][negative][positive].
+            val height = maxOf(positive.height(), negative.height(), neutral.height())
+            layout(maxWidth, height) {
+                positive?.let { it.placeRelative(maxWidth - it.width, 0) }
+
+                negative?.let { negative ->
+                    if (positive == null) {
+                        negative.placeRelative(maxWidth - negative.width, 0)
+                    } else {
+                        negative.placeRelative(
+                            maxWidth -
+                                negative.width -
+                                positive.width -
+                                horizontalSpacing.roundToInt(),
+                            0
+                        )
                     }
-
-                    positiveButton()
                 }
+
+                neutral?.placeRelative(0, 0)
+            }
+        } else {
+            // Stack vertically, aligned on the right (in LTR layouts):
+            //   [positive]
+            //   [negative]
+            //    [neutral]
+            //
+            // TODO(b/283817398): Introduce a ResponsiveDialogButtons composable to create buttons
+            // that have different styles when stacked horizontally, as shown in
+            // go/sysui-dialog-styling.
+            val height = positive.height() + negative.height() + neutral.height()
+            layout(maxWidth, height) {
+                var y = 0
+                fun Placeable.place() {
+                    placeRelative(maxWidth - width, y)
+                    y += this.height
+                }
+
+                positive?.place()
+                negative?.place()
+                neutral?.place()
             }
         }
     }
diff --git a/packages/SystemUI/proguard_common.flags b/packages/SystemUI/proguard_common.flags
index 3194815..75de943 100644
--- a/packages/SystemUI/proguard_common.flags
+++ b/packages/SystemUI/proguard_common.flags
@@ -70,9 +70,6 @@
 -keep class com.android.systemui.log.core.** {
     *;
 }
--keep class com.android.systemui.fragments.FragmentService$FragmentCreator {
-    *;
-}
 -keep class androidx.core.app.CoreComponentFactory
 
 # Keep the wm shell lib
diff --git a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
index 94e5633..88b9612 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
@@ -16,7 +16,6 @@
 
 package com.android.systemui.controls.dagger
 
-import android.content.Context
 import com.android.internal.widget.LockPatternUtils
 import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT
 import com.android.systemui.controls.controller.ControlsController
@@ -44,10 +43,9 @@
 @Inject
 constructor(
     @ControlsFeatureEnabled private val featureEnabled: Boolean,
-    private val context: Context,
-    private val lazyControlsController: Lazy<ControlsController>,
-    private val lazyControlsUiController: Lazy<ControlsUiController>,
-    private val lazyControlsListingController: Lazy<ControlsListingController>,
+    lazyControlsController: Lazy<ControlsController>,
+    lazyControlsUiController: Lazy<ControlsUiController>,
+    lazyControlsListingController: Lazy<ControlsListingController>,
     private val lockPatternUtils: LockPatternUtils,
     private val keyguardStateController: KeyguardStateController,
     private val userTracker: UserTracker,
@@ -55,27 +53,25 @@
     optionalControlsTileResourceConfiguration: Optional<ControlsTileResourceConfiguration>
 ) {
 
+    private val controlsController: Optional<ControlsController> =
+        optionalIf(isEnabled(), lazyControlsController)
+    private val controlsUiController: Optional<ControlsUiController> =
+        optionalIf(isEnabled(), lazyControlsUiController)
+    private val controlsListingController: Optional<ControlsListingController> =
+        optionalIf(isEnabled(), lazyControlsListingController)
+
     val canShowWhileLockedSetting: StateFlow<Boolean> =
         controlsSettingsRepository.canShowControlsInLockscreen
 
     private val controlsTileResourceConfiguration: ControlsTileResourceConfiguration =
         optionalControlsTileResourceConfiguration.orElse(ControlsTileResourceConfigurationImpl())
 
-    fun getControlsController(): Optional<ControlsController> {
-        return if (featureEnabled) Optional.of(lazyControlsController.get()) else Optional.empty()
-    }
+    fun getControlsController(): Optional<ControlsController> = controlsController
 
-    fun getControlsUiController(): Optional<ControlsUiController> {
-        return if (featureEnabled) Optional.of(lazyControlsUiController.get()) else Optional.empty()
-    }
+    fun getControlsUiController(): Optional<ControlsUiController> = controlsUiController
 
-    fun getControlsListingController(): Optional<ControlsListingController> {
-        return if (featureEnabled) {
-            Optional.of(lazyControlsListingController.get())
-        } else {
-            Optional.empty()
-        }
-    }
+    fun getControlsListingController(): Optional<ControlsListingController> =
+        controlsListingController
 
     /** @return true if controls are feature-enabled and the user has the setting enabled */
     fun isEnabled() = featureEnabled
@@ -118,4 +114,11 @@
     fun getTileImageId(): Int {
         return controlsTileResourceConfiguration.getTileImageId()
     }
+
+    private fun <T : Any> optionalIf(condition: Boolean, provider: Lazy<T>): Optional<T> =
+        if (condition) {
+            Optional.of(provider.get())
+        } else {
+            Optional.empty()
+        }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 907e106..74b9b09 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -500,11 +500,6 @@
 
     @Keep
     @JvmField
-    val WM_DESKTOP_WINDOWING =
-        sysPropBooleanFlag("persist.wm.debug.desktop_mode", default = false)
-
-    @Keep
-    @JvmField
     val WM_CAPTION_ON_SHELL =
         sysPropBooleanFlag("persist.wm.debug.caption_on_shell", default = true)
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
index d2034d7..8d2a63e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
@@ -276,14 +276,16 @@
         }
     }
 
-    @GuardedBy("mDozingLock")
     public void startNotificationLogging() {
         if (!mLogging) {
             mLogging = true;
             if (DEBUG) {
                 Log.i(TAG, "startNotificationLogging");
             }
-            boolean lockscreen = mLockscreen != null && mLockscreen;
+            boolean lockscreen;
+            synchronized (mDozingLock) {
+                lockscreen = mLockscreen != null && mLockscreen;
+            }
             mNotificationPanelLogger.logPanelShown(lockscreen, getVisibleNotifications());
             mListContainer.setChildLocationsChangedListener(this::onChildLocationsChanged);
             // Sometimes, the transition from lockscreenOrShadeVisible=false ->
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt
index 0b27bc9..54f66dc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt
@@ -29,7 +29,6 @@
 import com.android.systemui.controls.ui.ControlsUiController
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.statusbar.policy.KeyguardStateController
-import dagger.Lazy
 import java.util.Optional
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
@@ -173,10 +172,9 @@
     private fun setupComponent(enabled: Boolean): ControlsComponent {
         return ControlsComponent(
             enabled,
-            mContext,
-            Lazy { controller },
-            Lazy { uiController },
-            Lazy { listingController },
+            { controller },
+            { uiController },
+            { listingController },
             lockPatternUtils,
             keyguardStateController,
             userTracker,
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java b/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java
index 0fc8aba..f1c74f0 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java
@@ -78,7 +78,8 @@
                 null /* options */, UserHandle.CURRENT);
 
         showNotificationHelper(context, name, title, content, pendingIntent, FACE_RE_ENROLL_CHANNEL,
-                FACE_RE_ENROLL_NOTIFICATION_TAG, Notification.VISIBILITY_SECRET);
+                Notification.CATEGORY_SYSTEM, FACE_RE_ENROLL_NOTIFICATION_TAG,
+                Notification.VISIBILITY_SECRET);
     }
 
     /**
@@ -101,7 +102,8 @@
                 null /* options */, UserHandle.CURRENT);
 
         showNotificationHelper(context, name, title, content, pendingIntent, FACE_ENROLL_CHANNEL,
-                FACE_ENROLL_NOTIFICATION_TAG, Notification.VISIBILITY_PUBLIC);
+                Notification.CATEGORY_RECOMMENDATION, FACE_ENROLL_NOTIFICATION_TAG,
+                Notification.VISIBILITY_PUBLIC);
     }
 
     /**
@@ -124,8 +126,8 @@
                 null /* options */, UserHandle.CURRENT);
 
         showNotificationHelper(context, name, title, content, pendingIntent,
-                FINGERPRINT_ENROLL_CHANNEL, FINGERPRINT_ENROLL_NOTIFICATION_TAG,
-                Notification.VISIBILITY_PUBLIC);
+                Notification.CATEGORY_RECOMMENDATION, FINGERPRINT_ENROLL_CHANNEL,
+                FINGERPRINT_ENROLL_NOTIFICATION_TAG, Notification.VISIBILITY_PUBLIC);
     }
 
     /**
@@ -159,13 +161,13 @@
                 null /* options */, UserHandle.CURRENT);
 
         showNotificationHelper(context, name, title, content, pendingIntent,
-                FINGERPRINT_BAD_CALIBRATION_CHANNEL, BAD_CALIBRATION_NOTIFICATION_TAG,
-                Notification.VISIBILITY_SECRET);
+                Notification.CATEGORY_SYSTEM, FINGERPRINT_BAD_CALIBRATION_CHANNEL,
+                BAD_CALIBRATION_NOTIFICATION_TAG, Notification.VISIBILITY_SECRET);
     }
 
     private static void showNotificationHelper(Context context, String name, String title,
-                String content, PendingIntent pendingIntent, String channelName,
-                String notificationTag, int visibility) {
+                String content, PendingIntent pendingIntent, String category,
+                String channelName, String notificationTag, int visibility) {
         final NotificationManager notificationManager =
                 context.getSystemService(NotificationManager.class);
         final NotificationChannel channel = new NotificationChannel(channelName, name,
@@ -178,7 +180,7 @@
                 .setOnlyAlertOnce(true)
                 .setLocalOnly(true)
                 .setAutoCancel(true)
-                .setCategory(Notification.CATEGORY_SYSTEM)
+                .setCategory(category)
                 .setContentIntent(pendingIntent)
                 .setVisibility(visibility)
                 .build();
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index e490745..a700d32 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -1101,8 +1101,11 @@
                     .allowAlarms(true)
                     .allowMedia(true)
                     .build());
-        } else {
+        } else if (rule.zenPolicy != null) {
             policy.apply(rule.zenPolicy);
+        } else {
+            // active rule with no specified policy inherits the default settings
+            policy.apply(mConfig.toZenPolicy());
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index a988821..b8feb4d 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -20,6 +20,7 @@
 import static android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static android.content.pm.PackageManager.DELETE_KEEP_DATA;
 import static android.content.pm.PackageManager.DELETE_SUCCEEDED;
 import static android.content.pm.PackageManager.MATCH_KNOWN_PACKAGES;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -63,6 +64,7 @@
 import com.android.internal.util.Preconditions;
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
 import com.android.server.pm.pkg.AndroidPackage;
+import com.android.server.pm.pkg.ArchiveState;
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.pkg.PackageUserState;
 import com.android.server.wm.ActivityTaskManagerInternal;
@@ -443,7 +445,7 @@
             // semantics than normal for uninstalling system apps.
             final boolean clearPackageStateAndReturn;
             synchronized (mPm.mLock) {
-                markPackageUninstalledForUserLPw(ps, user);
+                markPackageUninstalledForUserLPw(ps, user, flags);
                 if (!systemApp) {
                     // Do not uninstall the APK if an app should be cached
                     boolean keepUninstalledPackage =
@@ -547,7 +549,7 @@
     }
 
     @GuardedBy("mPm.mLock")
-    private void markPackageUninstalledForUserLPw(PackageSetting ps, UserHandle user) {
+    private void markPackageUninstalledForUserLPw(PackageSetting ps, UserHandle user, int flags) {
         final int[] userIds = (user == null || user.getIdentifier() == UserHandle.USER_ALL)
                 ? mUserManagerInternal.getUserIds()
                 : new int[] {user.getIdentifier()};
@@ -556,6 +558,12 @@
                 Slog.d(TAG, "Marking package:" + ps.getPackageName()
                         + " uninstalled for user:" + nextUserId);
             }
+            // Preserve ArchiveState if this is not a full uninstall
+            ArchiveState archiveState =
+                    (flags & DELETE_KEEP_DATA) == 0
+                            ? null
+                            : ps.getUserStateOrDefault(nextUserId).getArchiveState();
+
             ps.setUserState(nextUserId,
                     ps.getCeDataInode(nextUserId),
                     COMPONENT_ENABLED_STATE_DEFAULT,
@@ -576,7 +584,7 @@
                     null /*splashScreenTheme*/,
                     0 /*firstInstallTime*/,
                     PackageManager.USER_MIN_ASPECT_RATIO_UNSET,
-                    null /*archiveState*/);
+                    archiveState);
         }
         mPm.mSettings.writeKernelMappingLPr(ps);
     }
diff --git a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
index 4180cd2..15a0445 100644
--- a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
@@ -40,8 +40,6 @@
     private static final boolean DEBUG = false;
 
     // Desktop mode feature flags.
-    private static final boolean DESKTOP_MODE_PROTO1_SUPPORTED =
-            SystemProperties.getBoolean("persist.wm.debug.desktop_mode", false);
     private static final boolean DESKTOP_MODE_PROTO2_SUPPORTED =
             SystemProperties.getBoolean("persist.wm.debug.desktop_mode_2", false);
     // Override default freeform task width when desktop mode is enabled. In dips.
@@ -142,6 +140,6 @@
 
     /** Whether desktop mode is supported. */
     static boolean isDesktopModeSupported() {
-        return DESKTOP_MODE_PROTO1_SUPPORTED || DESKTOP_MODE_PROTO2_SUPPORTED;
+        return DESKTOP_MODE_PROTO2_SUPPORTED;
     }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index e540068..e22c104 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -2470,6 +2470,143 @@
         assertEquals(12345, mZenModeEventLogger.getPackageUid(4));
     }
 
+    @Test
+    public void testUpdateConsolidatedPolicy_defaultRulesOnly() {
+        setupZenConfig();
+
+        // When there's one automatic rule active and it doesn't specify a policy, test that the
+        // resulting consolidated policy is one that matches the default rule settings.
+        AutomaticZenRule zenRule = new AutomaticZenRule("name",
+                null,
+                new ComponentName(CUSTOM_PKG_NAME, "ScheduleConditionProvider"),
+                ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+                null,
+                NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+        String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule, "test",
+                Process.SYSTEM_UID, true);
+
+        // enable the rule
+        mZenModeHelper.setAutomaticZenRuleState(id,
+                new Condition(zenRule.getConditionId(), "", STATE_TRUE),
+                Process.SYSTEM_UID, true);
+
+        // inspect the consolidated policy. Based on setupZenConfig() values.
+        assertFalse(mZenModeHelper.mConsolidatedPolicy.allowAlarms());
+        assertFalse(mZenModeHelper.mConsolidatedPolicy.allowMedia());
+        assertFalse(mZenModeHelper.mConsolidatedPolicy.allowSystem());
+        assertTrue(mZenModeHelper.mConsolidatedPolicy.allowReminders());
+        assertTrue(mZenModeHelper.mConsolidatedPolicy.allowCalls());
+        assertEquals(PRIORITY_SENDERS_STARRED, mZenModeHelper.mConsolidatedPolicy.allowCallsFrom());
+        assertTrue(mZenModeHelper.mConsolidatedPolicy.allowMessages());
+        assertTrue(mZenModeHelper.mConsolidatedPolicy.allowConversations());
+        assertTrue(mZenModeHelper.mConsolidatedPolicy.allowRepeatCallers());
+        assertFalse(mZenModeHelper.mConsolidatedPolicy.showBadges());
+    }
+
+    @Test
+    public void testUpdateConsolidatedPolicy_customPolicyOnly() {
+        setupZenConfig();
+
+        // when there's only one automatic rule active and it has a custom policy, make sure that's
+        // what the consolidated policy reflects whether or not it's stricter than what the default
+        // would specify.
+        ZenPolicy customPolicy = new ZenPolicy.Builder()
+                .allowAlarms(true)  // more lenient than default
+                .allowMedia(true)  // more lenient than default
+                .allowRepeatCallers(false)  // more restrictive than default
+                .allowCalls(ZenPolicy.PEOPLE_TYPE_NONE)  // more restrictive than default
+                .showBadges(true)  // more lenient
+                .showPeeking(false)  // more restrictive
+                .build();
+
+        AutomaticZenRule zenRule = new AutomaticZenRule("name",
+                null,
+                new ComponentName(CUSTOM_PKG_NAME, "ScheduleConditionProvider"),
+                ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+                customPolicy,
+                NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+        String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule, "test",
+                Process.SYSTEM_UID, true);
+
+        // enable the rule; this will update the consolidated policy
+        mZenModeHelper.setAutomaticZenRuleState(id,
+                new Condition(zenRule.getConditionId(), "", STATE_TRUE),
+                Process.SYSTEM_UID, true);
+
+        // since this is the only active rule, the consolidated policy should match the custom
+        // policy for every field specified, and take default values for unspecified things
+        assertTrue(mZenModeHelper.mConsolidatedPolicy.allowAlarms());  // custom
+        assertTrue(mZenModeHelper.mConsolidatedPolicy.allowMedia());  // custom
+        assertFalse(mZenModeHelper.mConsolidatedPolicy.allowSystem());  // default
+        assertTrue(mZenModeHelper.mConsolidatedPolicy.allowReminders());  // default
+        assertFalse(mZenModeHelper.mConsolidatedPolicy.allowCalls());  // custom
+        assertTrue(mZenModeHelper.mConsolidatedPolicy.allowMessages()); // default
+        assertTrue(mZenModeHelper.mConsolidatedPolicy.allowConversations());  // default
+        assertFalse(mZenModeHelper.mConsolidatedPolicy.allowRepeatCallers());  // custom
+        assertTrue(mZenModeHelper.mConsolidatedPolicy.showBadges());  // custom
+        assertFalse(mZenModeHelper.mConsolidatedPolicy.showPeeking());  // custom
+    }
+
+    @Test
+    public void testUpdateConsolidatedPolicy_defaultAndCustomActive() {
+        setupZenConfig();
+
+        // when there are two rules active, one inheriting the default policy and one setting its
+        // own custom policy, they should be merged to form the most restrictive combination.
+
+        // rule 1: no custom policy
+        AutomaticZenRule zenRule = new AutomaticZenRule("name",
+                null,
+                new ComponentName(CUSTOM_PKG_NAME, "ScheduleConditionProvider"),
+                ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+                null,
+                NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+        String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule, "test",
+                Process.SYSTEM_UID, true);
+
+        // enable rule 1
+        mZenModeHelper.setAutomaticZenRuleState(id,
+                new Condition(zenRule.getConditionId(), "", STATE_TRUE),
+                Process.SYSTEM_UID, true);
+
+        // custom policy for rule 2
+        ZenPolicy customPolicy = new ZenPolicy.Builder()
+                .allowAlarms(true)  // more lenient than default
+                .allowMedia(true)  // more lenient than default
+                .allowRepeatCallers(false)  // more restrictive than default
+                .allowCalls(ZenPolicy.PEOPLE_TYPE_NONE)  // more restrictive than default
+                .showBadges(true)  // more lenient
+                .showPeeking(false)  // more restrictive
+                .build();
+
+        AutomaticZenRule zenRule2 = new AutomaticZenRule("name2",
+                null,
+                new ComponentName(CUSTOM_PKG_NAME, "ScheduleConditionProvider"),
+                ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+                customPolicy,
+                NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+        String id2 = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule2,
+                "test", Process.SYSTEM_UID, true);
+
+        // enable rule 2; this will update the consolidated policy
+        mZenModeHelper.setAutomaticZenRuleState(id2,
+                new Condition(zenRule2.getConditionId(), "", STATE_TRUE),
+                Process.SYSTEM_UID, true);
+
+        // now both rules should be on, and the consolidated policy should reflect the most
+        // restrictive option of each of the two
+        assertFalse(mZenModeHelper.mConsolidatedPolicy.allowAlarms());  // default stricter
+        assertFalse(mZenModeHelper.mConsolidatedPolicy.allowMedia());  // default stricter
+        assertFalse(mZenModeHelper.mConsolidatedPolicy.allowSystem());  // default, unset in custom
+        assertTrue(mZenModeHelper.mConsolidatedPolicy.allowReminders());  // default
+        assertFalse(mZenModeHelper.mConsolidatedPolicy.allowCalls());  // custom stricter
+        assertTrue(mZenModeHelper.mConsolidatedPolicy.allowMessages()); // default, unset in custom
+        assertTrue(mZenModeHelper.mConsolidatedPolicy.allowConversations());  // default
+        assertFalse(mZenModeHelper.mConsolidatedPolicy.allowRepeatCallers());  // custom stricter
+        assertFalse(mZenModeHelper.mConsolidatedPolicy.showBadges());  // default stricter
+        assertFalse(mZenModeHelper.mConsolidatedPolicy.showPeeking());  // custom stricter
+    }
+
     private void setupZenConfig() {
         mZenModeHelper.mZenMode = Global.ZEN_MODE_OFF;
         mZenModeHelper.mConfig.allowAlarms = false;