Merge "[DO NOT MERGE] Add animation for Dnd dialog" into sc-v2-dev
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
index a210e90..8b17be1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
@@ -19,7 +19,6 @@
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.AlertDialog;
-import android.app.Dialog;
import android.app.NotificationManager;
import android.content.Context;
import android.content.DialogInterface;
@@ -85,6 +84,7 @@
@VisibleForTesting
protected Context mContext;
+ private final int mThemeResId;
@VisibleForTesting
protected TextView mZenAlarmWarning;
@VisibleForTesting
@@ -97,10 +97,15 @@
protected LayoutInflater mLayoutInflater;
public EnableZenModeDialog(Context context) {
- mContext = context;
+ this(context, 0);
}
- public Dialog createDialog() {
+ public EnableZenModeDialog(Context context, int themeResId) {
+ mContext = context;
+ mThemeResId = themeResId;
+ }
+
+ public AlertDialog createDialog() {
mNotificationManager = (NotificationManager) mContext.
getSystemService(Context.NOTIFICATION_SERVICE);
mForeverId = Condition.newId(mContext).appendPath("forever").build();
@@ -108,7 +113,7 @@
mUserId = mContext.getUserId();
mAttached = false;
- final AlertDialog.Builder builder = new AlertDialog.Builder(mContext)
+ final AlertDialog.Builder builder = new AlertDialog.Builder(mContext, mThemeResId)
.setTitle(R.string.zen_mode_settings_turn_on_dialog_title)
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.zen_mode_enable_dialog_turn_on,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index b1cd68e..3163c5f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -19,6 +19,7 @@
import static android.provider.Settings.Global.ZEN_MODE_ALARMS;
import static android.provider.Settings.Global.ZEN_MODE_OFF;
+import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
@@ -41,7 +42,6 @@
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.ViewGroup;
-import android.view.WindowManager;
import android.widget.Switch;
import android.widget.Toast;
@@ -53,6 +53,7 @@
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.SysUIToast;
+import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -84,6 +85,7 @@
private final DndDetailAdapter mDetailAdapter;
private final SharedPreferences mSharedPreferences;
private final SecureSetting mSettingZenDuration;
+ private final DialogLaunchAnimator mDialogLaunchAnimator;
private boolean mListening;
private boolean mShowingDetail;
@@ -100,7 +102,8 @@
QSLogger qsLogger,
ZenModeController zenModeController,
@Main SharedPreferences sharedPreferences,
- SecureSettings secureSettings
+ SecureSettings secureSettings,
+ DialogLaunchAnimator dialogLaunchAnimator
) {
super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
statusBarStateController, activityStarter, qsLogger);
@@ -108,6 +111,7 @@
mSharedPreferences = sharedPreferences;
mDetailAdapter = new DndDetailAdapter();
mController.observe(getLifecycle(), mZenCallback);
+ mDialogLaunchAnimator = dialogLaunchAnimator;
mSettingZenDuration = new SecureSetting(secureSettings, mUiHandler,
Settings.Secure.ZEN_DURATION, getHost().getUserId()) {
@Override
@@ -117,8 +121,6 @@
};
}
-
-
public static void setVisible(Context context, boolean visible) {
Prefs.putBoolean(context, Prefs.Key.DND_TILE_VISIBLE, visible);
}
@@ -187,14 +189,17 @@
switch (zenDuration) {
case Settings.Secure.ZEN_DURATION_PROMPT:
mUiHandler.post(() -> {
- Dialog mDialog = new EnableZenModeDialog(mContext).createDialog();
- mDialog.getWindow().setType(
- WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- SystemUIDialog.setShowForAllUsers(mDialog, true);
- SystemUIDialog.registerDismissListener(mDialog);
- SystemUIDialog.setWindowOnTop(mDialog);
- mUiHandler.post(() -> mDialog.show());
- mHost.collapsePanels();
+ Dialog dialog = makeZenModeDialog();
+ if (view != null) {
+ final Dialog hostDialog =
+ mDialogLaunchAnimator.showFromView(dialog, view, false);
+ setDialogListeners(dialog, hostDialog);
+ } else {
+ // If we are not launching with animator, register default
+ // dismiss listener
+ SystemUIDialog.registerDismissListener(dialog);
+ dialog.show();
+ }
});
break;
case Settings.Secure.ZEN_DURATION_FOREVER:
@@ -209,6 +214,20 @@
}
}
+ private Dialog makeZenModeDialog() {
+ AlertDialog dialog = new EnableZenModeDialog(mContext, R.style.Theme_SystemUI_Dialog)
+ .createDialog();
+ SystemUIDialog.applyFlags(dialog);
+ SystemUIDialog.setShowForAllUsers(dialog, true);
+ return dialog;
+ }
+
+ private void setDialogListeners(Dialog zenModeDialog, Dialog hostDialog) {
+ // Zen mode dialog is never hidden.
+ SystemUIDialog.registerDismissListener(zenModeDialog, hostDialog::dismiss);
+ zenModeDialog.setOnCancelListener(dialog -> hostDialog.cancel());
+ }
+
@Override
protected void handleSecondaryClick(@Nullable View view) {
if (mController.isVolumeRestricted()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
index 1130ec2..ed52a81 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
@@ -36,6 +36,8 @@
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
+import androidx.annotation.Nullable;
+
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.animation.DialogListener;
@@ -303,13 +305,32 @@
* the screen off / close system dialogs broadcast.
* <p>
* <strong>Note:</strong> Don't call dialog.setOnDismissListener() after
- * calling this because it causes a leak of BroadcastReceiver.
+ * calling this because it causes a leak of BroadcastReceiver. Instead, call the version that
+ * takes an extra Runnable as a parameter.
*
* @param dialog The dialog to be associated with the listener.
*/
public static void registerDismissListener(Dialog dialog) {
+ registerDismissListener(dialog, null);
+ }
+
+
+ /**
+ * Registers a listener that dismisses the given dialog when it receives
+ * the screen off / close system dialogs broadcast.
+ * <p>
+ * <strong>Note:</strong> Don't call dialog.setOnDismissListener() after
+ * calling this because it causes a leak of BroadcastReceiver.
+ *
+ * @param dialog The dialog to be associated with the listener.
+ * @param dismissAction An action to run when the dialog is dismissed.
+ */
+ public static void registerDismissListener(Dialog dialog, @Nullable Runnable dismissAction) {
DismissReceiver dismissReceiver = new DismissReceiver(dialog);
- dialog.setOnDismissListener(d -> dismissReceiver.unregister());
+ dialog.setOnDismissListener(d -> {
+ dismissReceiver.unregister();
+ if (dismissAction != null) dismissAction.run();
+ });
dismissReceiver.register();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
index f99703e..13df04c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
@@ -16,22 +16,28 @@
package com.android.systemui.qs.tiles
+import android.app.Dialog
import android.content.ContextWrapper
import android.content.SharedPreferences
import android.os.Handler
import android.provider.Settings
+import android.provider.Settings.Global.ZEN_MODE_OFF
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
+import android.view.View
import androidx.test.filters.SmallTest
import com.android.internal.logging.MetricsLogger
import com.android.internal.logging.UiEventLogger
import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.DialogLaunchAnimator
import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.qs.QSHost
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.statusbar.policy.ZenModeController
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
import com.android.systemui.util.settings.FakeSettings
import com.android.systemui.util.settings.SecureSettings
import com.google.common.truth.Truth.assertThat
@@ -40,9 +46,12 @@
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
-import org.mockito.Mockito
+import org.mockito.Mockito.anyBoolean
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import java.io.File
+import org.mockito.Mockito.`when` as whenever
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -70,6 +79,10 @@
private lateinit var zenModeController: ZenModeController
@Mock
private lateinit var sharedPreferences: SharedPreferences
+ @Mock
+ private lateinit var dialogLaunchAnimator: DialogLaunchAnimator
+ @Mock
+ private lateinit var hostDialog: Dialog
private lateinit var secureSettings: SecureSettings
private lateinit var testableLooper: TestableLooper
@@ -81,15 +94,17 @@
testableLooper = TestableLooper.get(this)
secureSettings = FakeSettings()
- Mockito.`when`(qsHost.userId).thenReturn(DEFAULT_USER)
- Mockito.`when`(qsHost.uiEventLogger).thenReturn(uiEventLogger)
+ whenever(qsHost.userId).thenReturn(DEFAULT_USER)
+ whenever(qsHost.uiEventLogger).thenReturn(uiEventLogger)
+ whenever(dialogLaunchAnimator.showFromView(any(), any(), anyBoolean()))
+ .thenReturn(hostDialog)
val wrappedContext = object : ContextWrapper(context) {
override fun getSharedPreferences(file: File?, mode: Int): SharedPreferences {
return sharedPreferences
}
}
- Mockito.`when`(qsHost.context).thenReturn(wrappedContext)
+ whenever(qsHost.context).thenReturn(wrappedContext)
tile = DndTile(
qsHost,
@@ -102,7 +117,8 @@
qsLogger,
zenModeController,
sharedPreferences,
- secureSettings
+ secureSettings,
+ dialogLaunchAnimator
)
}
@@ -147,4 +163,32 @@
assertThat(tile.state.forceExpandIcon).isTrue()
}
+
+ @Test
+ fun testLaunchDialogFromViewWhenPrompt() {
+ whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
+
+ secureSettings.putIntForUser(KEY, Settings.Secure.ZEN_DURATION_PROMPT, DEFAULT_USER)
+ testableLooper.processAllMessages()
+
+ val view = View(context)
+ tile.handleClick(view)
+ testableLooper.processAllMessages()
+
+ verify(dialogLaunchAnimator).showFromView(any(), eq(view), anyBoolean())
+ }
+
+ @Test
+ fun testNoLaunchDialogWhenNotPrompt() {
+ whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
+
+ secureSettings.putIntForUser(KEY, 60, DEFAULT_USER)
+ testableLooper.processAllMessages()
+
+ val view = View(context)
+ tile.handleClick(view)
+ testableLooper.processAllMessages()
+
+ verify(dialogLaunchAnimator, never()).showFromView(any(), any(), anyBoolean())
+ }
}
\ No newline at end of file