1 /* 2 * Copyright (C) 2023 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.systemui.globalactions; 18 19 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; 20 21 import android.annotation.Nullable; 22 import android.annotation.StringRes; 23 import android.app.Dialog; 24 import android.content.Context; 25 import android.os.PowerManager; 26 import android.view.View; 27 import android.view.ViewGroup; 28 import android.view.Window; 29 import android.view.WindowManager; 30 import android.widget.ProgressBar; 31 import android.widget.TextView; 32 33 import androidx.annotation.VisibleForTesting; 34 35 import com.android.internal.R; 36 import com.android.settingslib.Utils; 37 import com.android.systemui.scrim.ScrimDrawable; 38 import com.android.systemui.statusbar.BlurUtils; 39 import com.android.systemui.statusbar.phone.ScrimController; 40 41 /** 42 * Provides the UI shown during system shutdown. 43 */ 44 public class ShutdownUi { 45 46 private Context mContext; 47 private BlurUtils mBlurUtils; ShutdownUi(Context context, BlurUtils blurUtils)48 public ShutdownUi(Context context, BlurUtils blurUtils) { 49 mContext = context; 50 mBlurUtils = blurUtils; 51 } 52 53 /** 54 * Display the shutdown UI. 55 * @param isReboot Whether the device will be rebooting after this shutdown. 56 * @param reason Cause for the shutdown. 57 */ showShutdownUi(boolean isReboot, String reason)58 public void showShutdownUi(boolean isReboot, String reason) { 59 ScrimDrawable background = new ScrimDrawable(); 60 61 final Dialog d = new Dialog(mContext, 62 com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions); 63 64 d.setOnShowListener(dialog -> { 65 if (mBlurUtils.supportsBlursOnWindows()) { 66 int backgroundAlpha = (int) (ScrimController.BUSY_SCRIM_ALPHA * 255); 67 background.setAlpha(backgroundAlpha); 68 mBlurUtils.applyBlur(d.getWindow().getDecorView().getViewRootImpl(), 69 (int) mBlurUtils.blurRadiusOfRatio(1), backgroundAlpha == 255); 70 } else { 71 float backgroundAlpha = mContext.getResources().getFloat( 72 com.android.systemui.R.dimen.shutdown_scrim_behind_alpha); 73 background.setAlpha((int) (backgroundAlpha * 255)); 74 } 75 }); 76 77 // Window initialization 78 Window window = d.getWindow(); 79 window.requestFeature(Window.FEATURE_NO_TITLE); 80 window.getAttributes().systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 81 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE 82 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; 83 // Inflate the decor view, so the attributes below are not overwritten by the theme. 84 window.getDecorView(); 85 window.getAttributes().width = ViewGroup.LayoutParams.MATCH_PARENT; 86 window.getAttributes().height = ViewGroup.LayoutParams.MATCH_PARENT; 87 window.getAttributes().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; 88 window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY); 89 window.getAttributes().setFitInsetsTypes(0 /* types */); 90 window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); 91 window.addFlags( 92 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN 93 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL 94 | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR 95 | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED 96 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH 97 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); 98 window.setBackgroundDrawable(background); 99 window.setWindowAnimations(com.android.systemui.R.style.Animation_ShutdownUi); 100 101 d.setContentView(getShutdownDialogContent(isReboot)); 102 d.setCancelable(false); 103 104 int color; 105 if (mBlurUtils.supportsBlursOnWindows()) { 106 color = Utils.getColorAttrDefaultColor(mContext, 107 com.android.systemui.R.attr.wallpaperTextColor); 108 } else { 109 color = mContext.getResources().getColor( 110 com.android.systemui.R.color.global_actions_shutdown_ui_text); 111 } 112 113 ProgressBar bar = d.findViewById(R.id.progress); 114 bar.getIndeterminateDrawable().setTint(color); 115 116 TextView reasonView = d.findViewById(R.id.text1); 117 TextView messageView = d.findViewById(R.id.text2); 118 119 reasonView.setTextColor(color); 120 messageView.setTextColor(color); 121 122 messageView.setText(getRebootMessage(isReboot, reason)); 123 String rebootReasonMessage = getReasonMessage(reason); 124 if (rebootReasonMessage != null) { 125 reasonView.setVisibility(View.VISIBLE); 126 reasonView.setText(rebootReasonMessage); 127 } 128 129 d.show(); 130 } 131 132 /** 133 * Returns the layout resource to use for UI while shutting down. 134 * @param isReboot Whether this is a reboot or a shutdown. 135 * @return 136 */ getShutdownDialogContent(boolean isReboot)137 public int getShutdownDialogContent(boolean isReboot) { 138 return R.layout.shutdown_dialog; 139 } 140 141 @StringRes getRebootMessage(boolean isReboot, @Nullable String reason)142 @VisibleForTesting int getRebootMessage(boolean isReboot, @Nullable String reason) { 143 if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) { 144 return R.string.reboot_to_update_reboot; 145 } else if (reason != null && reason.equals(PowerManager.REBOOT_RECOVERY)) { 146 return R.string.reboot_to_reset_message; 147 } else if (isReboot) { 148 return R.string.reboot_to_reset_message; 149 } else { 150 return R.string.shutdown_progress; 151 } 152 } 153 154 @Nullable getReasonMessage(@ullable String reason)155 @VisibleForTesting String getReasonMessage(@Nullable String reason) { 156 if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) { 157 return mContext.getString(R.string.reboot_to_update_title); 158 } else if (reason != null && reason.equals(PowerManager.REBOOT_RECOVERY)) { 159 return mContext.getString(R.string.reboot_to_reset_title); 160 } else { 161 return null; 162 } 163 } 164 } 165