1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11  * KIND, either express or implied. See the License for the specific language governing
12  * permissions and limitations under the License.
13  */
14 
15 package com.android.systemui.globalactions;
16 
17 import static android.app.StatusBarManager.DISABLE2_GLOBAL_ACTIONS;
18 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
19 
20 import android.annotation.Nullable;
21 import android.annotation.StringRes;
22 import android.app.Dialog;
23 import android.content.Context;
24 import android.os.PowerManager;
25 import android.view.View;
26 import android.view.ViewGroup;
27 import android.view.Window;
28 import android.view.WindowManager;
29 import android.widget.ProgressBar;
30 import android.widget.TextView;
31 
32 import com.android.internal.R;
33 import com.android.settingslib.Utils;
34 import com.android.systemui.plugins.GlobalActions;
35 import com.android.systemui.scrim.ScrimDrawable;
36 import com.android.systemui.statusbar.BlurUtils;
37 import com.android.systemui.statusbar.CommandQueue;
38 import com.android.systemui.statusbar.phone.ScrimController;
39 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
40 import com.android.systemui.statusbar.policy.KeyguardStateController;
41 
42 import javax.inject.Inject;
43 
44 import dagger.Lazy;
45 
46 public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks {
47 
48     private final Context mContext;
49     private final Lazy<GlobalActionsDialogLite> mGlobalActionsDialogLazy;
50     private final KeyguardStateController mKeyguardStateController;
51     private final DeviceProvisionedController mDeviceProvisionedController;
52     private final BlurUtils mBlurUtils;
53     private final CommandQueue mCommandQueue;
54     private GlobalActionsDialogLite mGlobalActionsDialog;
55     private boolean mDisabled;
56 
57     @Inject
GlobalActionsImpl(Context context, CommandQueue commandQueue, Lazy<GlobalActionsDialogLite> globalActionsDialogLazy, BlurUtils blurUtils, KeyguardStateController keyguardStateController, DeviceProvisionedController deviceProvisionedController)58     public GlobalActionsImpl(Context context, CommandQueue commandQueue,
59             Lazy<GlobalActionsDialogLite> globalActionsDialogLazy, BlurUtils blurUtils,
60             KeyguardStateController keyguardStateController,
61             DeviceProvisionedController deviceProvisionedController) {
62         mContext = context;
63         mGlobalActionsDialogLazy = globalActionsDialogLazy;
64         mKeyguardStateController = keyguardStateController;
65         mDeviceProvisionedController = deviceProvisionedController;
66         mCommandQueue = commandQueue;
67         mBlurUtils = blurUtils;
68         mCommandQueue.addCallback(this);
69     }
70 
71     @Override
destroy()72     public void destroy() {
73         mCommandQueue.removeCallback(this);
74         if (mGlobalActionsDialog != null) {
75             mGlobalActionsDialog.destroy();
76             mGlobalActionsDialog = null;
77         }
78     }
79 
80     @Override
showGlobalActions(GlobalActionsManager manager)81     public void showGlobalActions(GlobalActionsManager manager) {
82         if (mDisabled) return;
83         mGlobalActionsDialog = mGlobalActionsDialogLazy.get();
84         mGlobalActionsDialog.showOrHideDialog(mKeyguardStateController.isShowing(),
85                 mDeviceProvisionedController.isDeviceProvisioned(), null /* view */);
86     }
87 
88     @Override
showShutdownUi(boolean isReboot, String reason)89     public void showShutdownUi(boolean isReboot, String reason) {
90         ScrimDrawable background = new ScrimDrawable();
91 
92         final Dialog d = new Dialog(mContext,
93                 com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions);
94 
95         d.setOnShowListener(dialog -> {
96             if (mBlurUtils.supportsBlursOnWindows()) {
97                 int backgroundAlpha = (int) (ScrimController.BUSY_SCRIM_ALPHA * 255);
98                 background.setAlpha(backgroundAlpha);
99                 mBlurUtils.applyBlur(d.getWindow().getDecorView().getViewRootImpl(),
100                         (int) mBlurUtils.blurRadiusOfRatio(1), backgroundAlpha == 255);
101             } else {
102                 float backgroundAlpha = mContext.getResources().getFloat(
103                         com.android.systemui.R.dimen.shutdown_scrim_behind_alpha);
104                 background.setAlpha((int) (backgroundAlpha * 255));
105             }
106         });
107 
108         // Window initialization
109         Window window = d.getWindow();
110         window.requestFeature(Window.FEATURE_NO_TITLE);
111         window.getAttributes().systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
112                 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
113                 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
114         // Inflate the decor view, so the attributes below are not overwritten by the theme.
115         window.getDecorView();
116         window.getAttributes().width = ViewGroup.LayoutParams.MATCH_PARENT;
117         window.getAttributes().height = ViewGroup.LayoutParams.MATCH_PARENT;
118         window.getAttributes().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
119         window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
120         window.getAttributes().setFitInsetsTypes(0 /* types */);
121         window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
122         window.addFlags(
123                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
124                         | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
125                         | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
126                         | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
127                         | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
128                         | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
129         window.setBackgroundDrawable(background);
130         window.setWindowAnimations(com.android.systemui.R.style.Animation_ShutdownUi);
131 
132         d.setContentView(R.layout.shutdown_dialog);
133         d.setCancelable(false);
134 
135         int color;
136         if (mBlurUtils.supportsBlursOnWindows()) {
137             color = Utils.getColorAttrDefaultColor(mContext,
138                     com.android.systemui.R.attr.wallpaperTextColor);
139         } else {
140             color = mContext.getResources().getColor(
141                     com.android.systemui.R.color.global_actions_shutdown_ui_text);
142         }
143 
144         ProgressBar bar = d.findViewById(R.id.progress);
145         bar.getIndeterminateDrawable().setTint(color);
146 
147         TextView reasonView = d.findViewById(R.id.text1);
148         TextView messageView = d.findViewById(R.id.text2);
149 
150         reasonView.setTextColor(color);
151         messageView.setTextColor(color);
152 
153         messageView.setText(getRebootMessage(isReboot, reason));
154         String rebootReasonMessage = getReasonMessage(reason);
155         if (rebootReasonMessage != null) {
156             reasonView.setVisibility(View.VISIBLE);
157             reasonView.setText(rebootReasonMessage);
158         }
159 
160         d.show();
161     }
162 
163     @StringRes
getRebootMessage(boolean isReboot, @Nullable String reason)164     private int getRebootMessage(boolean isReboot, @Nullable String reason) {
165         if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) {
166             return R.string.reboot_to_update_reboot;
167         } else if (reason != null && reason.equals(PowerManager.REBOOT_RECOVERY)) {
168             return R.string.reboot_to_reset_message;
169         } else if (isReboot) {
170             return R.string.reboot_to_reset_message;
171         } else {
172             return R.string.shutdown_progress;
173         }
174     }
175 
176     @Nullable
getReasonMessage(@ullable String reason)177     private String getReasonMessage(@Nullable String reason) {
178         if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) {
179             return mContext.getString(R.string.reboot_to_update_title);
180         } else if (reason != null && reason.equals(PowerManager.REBOOT_RECOVERY)) {
181             return mContext.getString(R.string.reboot_to_reset_title);
182         } else {
183             return null;
184         }
185     }
186 
187     @Override
disable(int displayId, int state1, int state2, boolean animate)188     public void disable(int displayId, int state1, int state2, boolean animate) {
189         final boolean disabled = (state2 & DISABLE2_GLOBAL_ACTIONS) != 0;
190         if (displayId != mContext.getDisplayId() || disabled == mDisabled) return;
191         mDisabled = disabled;
192         if (disabled && mGlobalActionsDialog != null) {
193             mGlobalActionsDialog.dismissDialog();
194         }
195     }
196 }
197