Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9ac796de authored by Fabian Kozynski's avatar Fabian Kozynski
Browse files

[DO NOT MERGE] Add animation for Dnd dialog

Also, use SystemUI dialog theme.

Test: manual
Test: atest DndTileTest
Fixes: 206454318
Fixes: 206730944
Change-Id: I599935e28ab6d6f6ad1fa497f4eeea652b74dad6
parent b17c10f6
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package com.android.settingslib.notification;
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 @@ public class EnableZenModeDialog {

    @VisibleForTesting
    protected Context mContext;
    private final int mThemeResId;
    @VisibleForTesting
    protected TextView mZenAlarmWarning;
    @VisibleForTesting
@@ -97,10 +97,15 @@ public class EnableZenModeDialog {
    protected LayoutInflater mLayoutInflater;

    public EnableZenModeDialog(Context context) {
        this(context, 0);
    }

    public EnableZenModeDialog(Context context, int themeResId) {
        mContext = context;
        mThemeResId = themeResId;
    }

    public Dialog createDialog() {
    public AlertDialog createDialog() {
        mNotificationManager = (NotificationManager) mContext.
                getSystemService(Context.NOTIFICATION_SERVICE);
        mForeverId =  Condition.newId(mContext).appendPath("forever").build();
@@ -108,7 +113,7 @@ public class EnableZenModeDialog {
        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,
+31 −12
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.systemui.qs.tiles;
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.LayoutInflater;
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.settingslib.notification.EnableZenModeDialog;
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 @@ public class DndTile extends QSTileImpl<BooleanState> {
    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 @@ public class DndTile extends QSTileImpl<BooleanState> {
            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 @@ public class DndTile extends QSTileImpl<BooleanState> {
        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 class DndTile extends QSTileImpl<BooleanState> {
        };
    }



    public static void setVisible(Context context, boolean visible) {
        Prefs.putBoolean(context, Prefs.Key.DND_TILE_VISIBLE, visible);
    }
@@ -187,14 +189,17 @@ public class DndTile extends QSTileImpl<BooleanState> {
            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 @@ public class DndTile extends QSTileImpl<BooleanState> {
        }
    }

    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()) {
+23 −2
Original line number Diff line number Diff line
@@ -36,6 +36,8 @@ import android.view.WindowInsets.Type;
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 @@ public class SystemUIDialog extends AlertDialog implements ListenableDialog,
     * 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();
    }

+49 −5
Original line number Diff line number Diff line
@@ -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.Before
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 @@ class DndTileTest : SysuiTestCase() {
    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 @@ class DndTileTest : SysuiTestCase() {
        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 @@ class DndTileTest : SysuiTestCase() {
            qsLogger,
            zenModeController,
            sharedPreferences,
            secureSettings
            secureSettings,
            dialogLaunchAnimator
        )
    }

@@ -147,4 +163,32 @@ class DndTileTest : SysuiTestCase() {

        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