• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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.statusbar.phone;
18 
19 import android.app.AlertDialog;
20 import android.app.Dialog;
21 import android.content.BroadcastReceiver;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.IntentFilter;
25 import android.os.UserHandle;
26 import android.view.Window;
27 import android.view.WindowInsets.Type;
28 import android.view.WindowManager;
29 import android.view.WindowManager.LayoutParams;
30 
31 import com.android.systemui.Dependency;
32 import com.android.systemui.R;
33 import com.android.systemui.broadcast.BroadcastDispatcher;
34 import com.android.systemui.statusbar.policy.KeyguardStateController;
35 
36 
37 /**
38  * Base class for dialogs that should appear over panels and keyguard.
39  * The SystemUIDialog registers a listener for the screen off / close system dialogs broadcast,
40  * and dismisses itself when it receives the broadcast.
41  */
42 public class SystemUIDialog extends AlertDialog {
43 
44     private final Context mContext;
45     private final DismissReceiver mDismissReceiver;
46 
SystemUIDialog(Context context)47     public SystemUIDialog(Context context) {
48         this(context, R.style.Theme_SystemUI_Dialog);
49     }
50 
SystemUIDialog(Context context, int theme)51     public SystemUIDialog(Context context, int theme) {
52         super(context, theme);
53         mContext = context;
54 
55         applyFlags(this);
56         WindowManager.LayoutParams attrs = getWindow().getAttributes();
57         attrs.setTitle(getClass().getSimpleName());
58         getWindow().setAttributes(attrs);
59 
60         mDismissReceiver = new DismissReceiver(this);
61     }
62 
63     @Override
onStart()64     protected void onStart() {
65         super.onStart();
66         mDismissReceiver.register();
67     }
68 
69     @Override
onStop()70     protected void onStop() {
71         super.onStop();
72         mDismissReceiver.unregister();
73     }
74 
setShowForAllUsers(boolean show)75     public void setShowForAllUsers(boolean show) {
76         setShowForAllUsers(this, show);
77     }
78 
setMessage(int resId)79     public void setMessage(int resId) {
80         setMessage(mContext.getString(resId));
81     }
82 
setPositiveButton(int resId, OnClickListener onClick)83     public void setPositiveButton(int resId, OnClickListener onClick) {
84         setButton(BUTTON_POSITIVE, mContext.getString(resId), onClick);
85     }
86 
setNegativeButton(int resId, OnClickListener onClick)87     public void setNegativeButton(int resId, OnClickListener onClick) {
88         setButton(BUTTON_NEGATIVE, mContext.getString(resId), onClick);
89     }
90 
setNeutralButton(int resId, OnClickListener onClick)91     public void setNeutralButton(int resId, OnClickListener onClick) {
92         setButton(BUTTON_NEUTRAL, mContext.getString(resId), onClick);
93     }
94 
setShowForAllUsers(Dialog dialog, boolean show)95     public static void setShowForAllUsers(Dialog dialog, boolean show) {
96         if (show) {
97             dialog.getWindow().getAttributes().privateFlags |=
98                     WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
99         } else {
100             dialog.getWindow().getAttributes().privateFlags &=
101                     ~WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
102         }
103     }
104 
setWindowOnTop(Dialog dialog)105     public static void setWindowOnTop(Dialog dialog) {
106         final Window window = dialog.getWindow();
107         window.setType(LayoutParams.TYPE_STATUS_BAR_SUB_PANEL);
108         if (Dependency.get(KeyguardStateController.class).isShowing()) {
109             window.getAttributes().setFitInsetsTypes(
110                     window.getAttributes().getFitInsetsTypes() & ~Type.statusBars());
111         }
112     }
113 
applyFlags(AlertDialog dialog)114     public static AlertDialog applyFlags(AlertDialog dialog) {
115         final Window window = dialog.getWindow();
116         window.setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL);
117         window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
118                 | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
119         window.getAttributes().setFitInsetsTypes(
120                 window.getAttributes().getFitInsetsTypes() & ~Type.statusBars());
121         return dialog;
122     }
123 
124     /**
125      * Registers a listener that dismisses the given dialog when it receives
126      * the screen off / close system dialogs broadcast.
127      * <p>
128      * <strong>Note:</strong> Don't call dialog.setOnDismissListener() after
129      * calling this because it causes a leak of BroadcastReceiver.
130      *
131      * @param dialog The dialog to be associated with the listener.
132      */
registerDismissListener(Dialog dialog)133     public static void registerDismissListener(Dialog dialog) {
134         DismissReceiver dismissReceiver = new DismissReceiver(dialog);
135         dialog.setOnDismissListener(d -> dismissReceiver.unregister());
136         dismissReceiver.register();
137     }
138 
139     private static class DismissReceiver extends BroadcastReceiver {
140         private static final IntentFilter INTENT_FILTER = new IntentFilter();
141         static {
142             INTENT_FILTER.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
143             INTENT_FILTER.addAction(Intent.ACTION_SCREEN_OFF);
144         }
145 
146         private final Dialog mDialog;
147         private boolean mRegistered;
148         private final BroadcastDispatcher mBroadcastDispatcher;
149 
DismissReceiver(Dialog dialog)150         DismissReceiver(Dialog dialog) {
151             mDialog = dialog;
152             mBroadcastDispatcher = Dependency.get(BroadcastDispatcher.class);
153         }
154 
register()155         void register() {
156             mBroadcastDispatcher.registerReceiver(this, INTENT_FILTER, null, UserHandle.CURRENT);
157             mRegistered = true;
158         }
159 
unregister()160         void unregister() {
161             if (mRegistered) {
162                 mBroadcastDispatcher.unregisterReceiver(this);
163                 mRegistered = false;
164             }
165         }
166 
167         @Override
onReceive(Context context, Intent intent)168         public void onReceive(Context context, Intent intent) {
169             mDialog.dismiss();
170         }
171     }
172 }
173