Adrian Roos | 5005244 | 2014-07-17 23:35:18 +0200 | [diff] [blame] | 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 | |
Adrian Roos | 5005244 | 2014-07-17 23:35:18 +0200 | [diff] [blame] | 19 | import android.app.AlertDialog; |
Jason Monk | 9ca1848 | 2017-08-01 10:38:02 -0400 | [diff] [blame] | 20 | import android.app.Dialog; |
| 21 | import android.content.BroadcastReceiver; |
Adrian Roos | 5005244 | 2014-07-17 23:35:18 +0200 | [diff] [blame] | 22 | import android.content.Context; |
Jason Monk | 9ca1848 | 2017-08-01 10:38:02 -0400 | [diff] [blame] | 23 | import android.content.Intent; |
| 24 | import android.content.IntentFilter; |
| 25 | import android.os.UserHandle; |
Tiger Huang | 4a7835f | 2019-11-06 00:07:56 +0800 | [diff] [blame] | 26 | import android.view.Window; |
| 27 | import android.view.WindowInsets.Type; |
Adrian Roos | 5005244 | 2014-07-17 23:35:18 +0200 | [diff] [blame] | 28 | import android.view.WindowManager; |
Jason Monk | 9ca1848 | 2017-08-01 10:38:02 -0400 | [diff] [blame] | 29 | import android.view.WindowManager.LayoutParams; |
Adrian Roos | 5005244 | 2014-07-17 23:35:18 +0200 | [diff] [blame] | 30 | |
Jason Monk | 9ca1848 | 2017-08-01 10:38:02 -0400 | [diff] [blame] | 31 | import com.android.systemui.Dependency; |
Winson | c0d7058 | 2016-01-29 10:24:39 -0800 | [diff] [blame] | 32 | import com.android.systemui.R; |
Fabian Kozynski | ff5e91f | 2019-09-24 15:38:08 -0400 | [diff] [blame] | 33 | import com.android.systemui.broadcast.BroadcastDispatcher; |
Lucas Dupin | c8f16e8 | 2019-09-17 18:24:50 -0400 | [diff] [blame] | 34 | import com.android.systemui.statusbar.policy.KeyguardStateController; |
Winson | c0d7058 | 2016-01-29 10:24:39 -0800 | [diff] [blame] | 35 | |
Amin Shaikh | 6be5368 | 2018-05-02 15:59:44 -0400 | [diff] [blame] | 36 | |
Adrian Roos | 5005244 | 2014-07-17 23:35:18 +0200 | [diff] [blame] | 37 | /** |
| 38 | * Base class for dialogs that should appear over panels and keyguard. |
Satoshi Sanno | 3756b09 | 2019-05-29 16:39:50 +0900 | [diff] [blame] | 39 | * The SystemUIDialog registers a listener for the screen off / close system dialogs broadcast, |
| 40 | * and dismisses itself when it receives the broadcast. |
Adrian Roos | 5005244 | 2014-07-17 23:35:18 +0200 | [diff] [blame] | 41 | */ |
| 42 | public class SystemUIDialog extends AlertDialog { |
| 43 | |
John Spurlock | 1bb480a | 2014-08-02 17:12:43 -0400 | [diff] [blame] | 44 | private final Context mContext; |
Satoshi Sanno | 3756b09 | 2019-05-29 16:39:50 +0900 | [diff] [blame] | 45 | private final DismissReceiver mDismissReceiver; |
John Spurlock | 1bb480a | 2014-08-02 17:12:43 -0400 | [diff] [blame] | 46 | |
Adrian Roos | 5005244 | 2014-07-17 23:35:18 +0200 | [diff] [blame] | 47 | public SystemUIDialog(Context context) { |
Jason Monk | 5db8a41 | 2015-10-21 15:16:23 -0700 | [diff] [blame] | 48 | this(context, R.style.Theme_SystemUI_Dialog); |
| 49 | } |
| 50 | |
| 51 | public SystemUIDialog(Context context, int theme) { |
| 52 | super(context, theme); |
John Spurlock | 1bb480a | 2014-08-02 17:12:43 -0400 | [diff] [blame] | 53 | mContext = context; |
| 54 | |
Jason Monk | 39c98e6 | 2016-03-16 09:18:35 -0400 | [diff] [blame] | 55 | applyFlags(this); |
Adrian Roos | 5005244 | 2014-07-17 23:35:18 +0200 | [diff] [blame] | 56 | WindowManager.LayoutParams attrs = getWindow().getAttributes(); |
John Spurlock | 3513460 | 2014-07-24 18:10:48 -0400 | [diff] [blame] | 57 | attrs.setTitle(getClass().getSimpleName()); |
Adrian Roos | 5005244 | 2014-07-17 23:35:18 +0200 | [diff] [blame] | 58 | getWindow().setAttributes(attrs); |
phweiss | 679dc24 | 2017-07-05 18:54:54 +0200 | [diff] [blame] | 59 | |
Satoshi Sanno | 3756b09 | 2019-05-29 16:39:50 +0900 | [diff] [blame] | 60 | mDismissReceiver = new DismissReceiver(this); |
| 61 | } |
| 62 | |
| 63 | @Override |
| 64 | protected void onStart() { |
| 65 | super.onStart(); |
| 66 | mDismissReceiver.register(); |
| 67 | } |
| 68 | |
| 69 | @Override |
| 70 | protected void onStop() { |
| 71 | super.onStop(); |
| 72 | mDismissReceiver.unregister(); |
Adrian Roos | 5005244 | 2014-07-17 23:35:18 +0200 | [diff] [blame] | 73 | } |
John Spurlock | 1bb480a | 2014-08-02 17:12:43 -0400 | [diff] [blame] | 74 | |
| 75 | public void setShowForAllUsers(boolean show) { |
Jason Monk | 39c98e6 | 2016-03-16 09:18:35 -0400 | [diff] [blame] | 76 | setShowForAllUsers(this, show); |
John Spurlock | 1bb480a | 2014-08-02 17:12:43 -0400 | [diff] [blame] | 77 | } |
| 78 | |
| 79 | public void setMessage(int resId) { |
| 80 | setMessage(mContext.getString(resId)); |
| 81 | } |
| 82 | |
| 83 | public void setPositiveButton(int resId, OnClickListener onClick) { |
| 84 | setButton(BUTTON_POSITIVE, mContext.getString(resId), onClick); |
| 85 | } |
| 86 | |
| 87 | public void setNegativeButton(int resId, OnClickListener onClick) { |
| 88 | setButton(BUTTON_NEGATIVE, mContext.getString(resId), onClick); |
| 89 | } |
Jason Monk | 39c98e6 | 2016-03-16 09:18:35 -0400 | [diff] [blame] | 90 | |
Makoto Onuki | 41d5ccf | 2018-04-03 11:46:02 -0700 | [diff] [blame] | 91 | public void setNeutralButton(int resId, OnClickListener onClick) { |
| 92 | setButton(BUTTON_NEUTRAL, mContext.getString(resId), onClick); |
| 93 | } |
| 94 | |
Jason Monk | 9ca1848 | 2017-08-01 10:38:02 -0400 | [diff] [blame] | 95 | public static void setShowForAllUsers(Dialog dialog, boolean show) { |
Jason Monk | 39c98e6 | 2016-03-16 09:18:35 -0400 | [diff] [blame] | 96 | if (show) { |
| 97 | dialog.getWindow().getAttributes().privateFlags |= |
Roshan Pius | a3f89c6 | 2019-10-11 08:50:53 -0700 | [diff] [blame] | 98 | WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS; |
Jason Monk | 39c98e6 | 2016-03-16 09:18:35 -0400 | [diff] [blame] | 99 | } else { |
| 100 | dialog.getWindow().getAttributes().privateFlags &= |
Roshan Pius | a3f89c6 | 2019-10-11 08:50:53 -0700 | [diff] [blame] | 101 | ~WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS; |
Jason Monk | 39c98e6 | 2016-03-16 09:18:35 -0400 | [diff] [blame] | 102 | } |
| 103 | } |
| 104 | |
Jason Monk | 9ca1848 | 2017-08-01 10:38:02 -0400 | [diff] [blame] | 105 | public static void setWindowOnTop(Dialog dialog) { |
Lucas Dupin | c8f16e8 | 2019-09-17 18:24:50 -0400 | [diff] [blame] | 106 | if (Dependency.get(KeyguardStateController.class).isShowing()) { |
Tiger Huang | 4a7835f | 2019-11-06 00:07:56 +0800 | [diff] [blame] | 107 | final Window window = dialog.getWindow(); |
| 108 | window.setType(LayoutParams.TYPE_STATUS_BAR_PANEL); |
Tiger Huang | 5272444 | 2020-01-20 21:38:42 +0800 | [diff] [blame] | 109 | window.getAttributes().setFitInsetsTypes( |
| 110 | window.getAttributes().getFitInsetsTypes() & ~Type.statusBars()); |
Jason Monk | 9ca1848 | 2017-08-01 10:38:02 -0400 | [diff] [blame] | 111 | } else { |
| 112 | dialog.getWindow().setType(LayoutParams.TYPE_STATUS_BAR_SUB_PANEL); |
| 113 | } |
| 114 | } |
| 115 | |
Jason Monk | 54ff0ef | 2017-07-25 14:44:28 -0400 | [diff] [blame] | 116 | public static AlertDialog applyFlags(AlertDialog dialog) { |
Tiger Huang | 4a7835f | 2019-11-06 00:07:56 +0800 | [diff] [blame] | 117 | final Window window = dialog.getWindow(); |
| 118 | window.setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL); |
| 119 | window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM |
Jason Monk | 39c98e6 | 2016-03-16 09:18:35 -0400 | [diff] [blame] | 120 | | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); |
Tiger Huang | 5272444 | 2020-01-20 21:38:42 +0800 | [diff] [blame] | 121 | window.getAttributes().setFitInsetsTypes( |
| 122 | window.getAttributes().getFitInsetsTypes() & ~Type.statusBars()); |
Jason Monk | 54ff0ef | 2017-07-25 14:44:28 -0400 | [diff] [blame] | 123 | return dialog; |
Jason Monk | 39c98e6 | 2016-03-16 09:18:35 -0400 | [diff] [blame] | 124 | } |
Jason Monk | 9ca1848 | 2017-08-01 10:38:02 -0400 | [diff] [blame] | 125 | |
Satoshi Sanno | 3756b09 | 2019-05-29 16:39:50 +0900 | [diff] [blame] | 126 | /** |
| 127 | * Registers a listener that dismisses the given dialog when it receives |
| 128 | * the screen off / close system dialogs broadcast. |
| 129 | * <p> |
| 130 | * <strong>Note:</strong> Don't call dialog.setOnDismissListener() after |
| 131 | * calling this because it causes a leak of BroadcastReceiver. |
| 132 | * |
| 133 | * @param dialog The dialog to be associated with the listener. |
| 134 | */ |
Jason Monk | 9ca1848 | 2017-08-01 10:38:02 -0400 | [diff] [blame] | 135 | public static void registerDismissListener(Dialog dialog) { |
Amin Shaikh | 6be5368 | 2018-05-02 15:59:44 -0400 | [diff] [blame] | 136 | DismissReceiver dismissReceiver = new DismissReceiver(dialog); |
Satoshi Sanno | 3756b09 | 2019-05-29 16:39:50 +0900 | [diff] [blame] | 137 | dialog.setOnDismissListener(d -> dismissReceiver.unregister()); |
Amin Shaikh | 6be5368 | 2018-05-02 15:59:44 -0400 | [diff] [blame] | 138 | dismissReceiver.register(); |
Jason Monk | 9ca1848 | 2017-08-01 10:38:02 -0400 | [diff] [blame] | 139 | } |
Amin Shaikh | 6be5368 | 2018-05-02 15:59:44 -0400 | [diff] [blame] | 140 | |
Satoshi Sanno | 3756b09 | 2019-05-29 16:39:50 +0900 | [diff] [blame] | 141 | private static class DismissReceiver extends BroadcastReceiver { |
Amin Shaikh | 6be5368 | 2018-05-02 15:59:44 -0400 | [diff] [blame] | 142 | private static final IntentFilter INTENT_FILTER = new IntentFilter(); |
| 143 | static { |
| 144 | INTENT_FILTER.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); |
| 145 | INTENT_FILTER.addAction(Intent.ACTION_SCREEN_OFF); |
| 146 | } |
| 147 | |
| 148 | private final Dialog mDialog; |
| 149 | private boolean mRegistered; |
Fabian Kozynski | ff5e91f | 2019-09-24 15:38:08 -0400 | [diff] [blame] | 150 | private final BroadcastDispatcher mBroadcastDispatcher; |
Amin Shaikh | 6be5368 | 2018-05-02 15:59:44 -0400 | [diff] [blame] | 151 | |
| 152 | DismissReceiver(Dialog dialog) { |
| 153 | mDialog = dialog; |
Fabian Kozynski | ff5e91f | 2019-09-24 15:38:08 -0400 | [diff] [blame] | 154 | mBroadcastDispatcher = Dependency.get(BroadcastDispatcher.class); |
Amin Shaikh | 6be5368 | 2018-05-02 15:59:44 -0400 | [diff] [blame] | 155 | } |
| 156 | |
| 157 | void register() { |
Fabian Kozynski | ff5e91f | 2019-09-24 15:38:08 -0400 | [diff] [blame] | 158 | mBroadcastDispatcher.registerReceiver(this, INTENT_FILTER, null, UserHandle.CURRENT); |
Amin Shaikh | 6be5368 | 2018-05-02 15:59:44 -0400 | [diff] [blame] | 159 | mRegistered = true; |
| 160 | } |
| 161 | |
Satoshi Sanno | 3756b09 | 2019-05-29 16:39:50 +0900 | [diff] [blame] | 162 | void unregister() { |
Amin Shaikh | 6be5368 | 2018-05-02 15:59:44 -0400 | [diff] [blame] | 163 | if (mRegistered) { |
Fabian Kozynski | ff5e91f | 2019-09-24 15:38:08 -0400 | [diff] [blame] | 164 | mBroadcastDispatcher.unregisterReceiver(this); |
Amin Shaikh | 6be5368 | 2018-05-02 15:59:44 -0400 | [diff] [blame] | 165 | mRegistered = false; |
| 166 | } |
| 167 | } |
Satoshi Sanno | 3756b09 | 2019-05-29 16:39:50 +0900 | [diff] [blame] | 168 | |
| 169 | @Override |
| 170 | public void onReceive(Context context, Intent intent) { |
| 171 | mDialog.dismiss(); |
| 172 | } |
| 173 | } |
| 174 | } |