1 /* 2 * Copyright (C) 2025 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.wm.shell.crashhandling 18 19 import android.app.WindowConfiguration 20 import android.content.Context 21 import android.view.Display.DEFAULT_DISPLAY 22 import android.window.DesktopExperienceFlags 23 import android.window.WindowContainerTransaction 24 import com.android.wm.shell.ShellTaskOrganizer 25 import com.android.wm.shell.common.HomeIntentProvider 26 import com.android.wm.shell.shared.desktopmode.DesktopModeStatus 27 import com.android.wm.shell.sysui.ShellInit 28 29 /** [ShellCrashHandler] for shell to use when it's being initialized. Currently it only restores 30 * the home task to top. 31 **/ 32 class ShellCrashHandler( 33 private val context: Context, 34 private val shellTaskOrganizer: ShellTaskOrganizer, 35 private val homeIntentProvider: HomeIntentProvider, 36 shellInit: ShellInit, 37 ) { 38 init { 39 shellInit.addInitCallback(::onInit, this) 40 } 41 onInitnull42 private fun onInit() { 43 handleCrashIfNeeded() 44 } 45 handleCrashIfNeedednull46 private fun handleCrashIfNeeded() { 47 // For now only handle crashes when desktop mode is enabled on the device. 48 if (DesktopModeStatus.canEnterDesktopMode(context) && 49 !DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { 50 var freeformTaskExists = false 51 // If there are running tasks at init, WMShell has crashed but WMCore is still alive. 52 for (task in shellTaskOrganizer.getRunningTasks()) { 53 if (task.windowingMode == WindowConfiguration.WINDOWING_MODE_FREEFORM) { 54 freeformTaskExists = true 55 } 56 57 if (freeformTaskExists) { 58 shellTaskOrganizer.applyTransaction( 59 addLaunchHomePendingIntent(WindowContainerTransaction(), DEFAULT_DISPLAY) 60 ) 61 break 62 } 63 } 64 } 65 } 66 addLaunchHomePendingIntentnull67 private fun addLaunchHomePendingIntent( 68 wct: WindowContainerTransaction, displayId: Int 69 ): WindowContainerTransaction { 70 // TODO: b/400462917 - Check that crashes are also handled correctly on HSUM devices. We 71 // might need to pass the [userId] here to launch the correct home. 72 homeIntentProvider.addLaunchHomePendingIntent(wct, displayId) 73 return wct 74 } 75 }