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

Commit f1816eb3 authored by Alison Cichowlas's avatar Alison Cichowlas
Browse files

GlobalActions: Create a separate module for ShutdownUI.

Existing GlobalActionsImpl will delegate to ShutdownUi, which is
currently exactly the same implementation.

This allows us to override ShutdownUi behavior elsewhere, although in
this CL we use the same implementation in all SysUIs.

Bug: 246980844
Test: builds, boots; no user visible change to shutdown

Change-Id: Icbf04b5f98b891ca43041ae6e8637a1e03020ec0
parent b55bce2a
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import com.android.systemui.dreams.dagger.DreamModule;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.FlagsModule;
import com.android.systemui.globalactions.ShutdownUiModule;
import com.android.systemui.keyboard.KeyboardModule;
import com.android.systemui.keyguard.data.BouncerViewModule;
import com.android.systemui.log.dagger.LogModule;
@@ -187,6 +188,7 @@ import javax.inject.Named;
            ScreenRecordModule.class,
            SettingsUtilModule.class,
            ShadeModule.class,
            ShutdownUiModule.class,
            SmartRepliesInflationModule.class,
            SmartspaceModule.class,
            StatusBarPipelineModule.class,
+5 −112
Original line number Diff line number Diff line
@@ -15,27 +15,12 @@
package com.android.systemui.globalactions;

import static android.app.StatusBarManager.DISABLE2_GLOBAL_ACTIONS;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;

import android.annotation.Nullable;
import android.annotation.StringRes;
import android.app.Dialog;
import android.content.Context;
import android.os.PowerManager;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.android.internal.R;
import com.android.settingslib.Utils;
import com.android.systemui.plugins.GlobalActions;
import com.android.systemui.scrim.ScrimDrawable;
import com.android.systemui.statusbar.BlurUtils;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardStateController;

@@ -50,12 +35,14 @@ public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks
    private final CommandQueue mCommandQueue;
    private final GlobalActionsDialogLite mGlobalActionsDialog;
    private boolean mDisabled;
    private ShutdownUi mShutdownUi;

    @Inject
    public GlobalActionsImpl(Context context, CommandQueue commandQueue,
            GlobalActionsDialogLite globalActionsDialog, BlurUtils blurUtils,
            KeyguardStateController keyguardStateController,
            DeviceProvisionedController deviceProvisionedController) {
            DeviceProvisionedController deviceProvisionedController,
            ShutdownUi shutdownUi) {
        mContext = context;
        mGlobalActionsDialog = globalActionsDialog;
        mKeyguardStateController = keyguardStateController;
@@ -63,6 +50,7 @@ public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks
        mCommandQueue = commandQueue;
        mBlurUtils = blurUtils;
        mCommandQueue.addCallback(this);
        mShutdownUi = shutdownUi;
    }

    @Override
@@ -80,103 +68,8 @@ public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks

    @Override
    public void showShutdownUi(boolean isReboot, String reason) {
        ScrimDrawable background = new ScrimDrawable();

        final Dialog d = new Dialog(mContext,
                com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions);

        d.setOnShowListener(dialog -> {
            if (mBlurUtils.supportsBlursOnWindows()) {
                int backgroundAlpha = (int) (ScrimController.BUSY_SCRIM_ALPHA * 255);
                background.setAlpha(backgroundAlpha);
                mBlurUtils.applyBlur(d.getWindow().getDecorView().getViewRootImpl(),
                        (int) mBlurUtils.blurRadiusOfRatio(1), backgroundAlpha == 255);
            } else {
                float backgroundAlpha = mContext.getResources().getFloat(
                        com.android.systemui.R.dimen.shutdown_scrim_behind_alpha);
                background.setAlpha((int) (backgroundAlpha * 255));
            }
        });

        // Window initialization
        Window window = d.getWindow();
        window.requestFeature(Window.FEATURE_NO_TITLE);
        window.getAttributes().systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
        // Inflate the decor view, so the attributes below are not overwritten by the theme.
        window.getDecorView();
        window.getAttributes().width = ViewGroup.LayoutParams.MATCH_PARENT;
        window.getAttributes().height = ViewGroup.LayoutParams.MATCH_PARENT;
        window.getAttributes().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
        window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
        window.getAttributes().setFitInsetsTypes(0 /* types */);
        window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
        window.addFlags(
                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                        | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
                        | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                        | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
        window.setBackgroundDrawable(background);
        window.setWindowAnimations(com.android.systemui.R.style.Animation_ShutdownUi);

        d.setContentView(R.layout.shutdown_dialog);
        d.setCancelable(false);

        int color;
        if (mBlurUtils.supportsBlursOnWindows()) {
            color = Utils.getColorAttrDefaultColor(mContext,
                    com.android.systemui.R.attr.wallpaperTextColor);
        } else {
            color = mContext.getResources().getColor(
                    com.android.systemui.R.color.global_actions_shutdown_ui_text);
        }

        ProgressBar bar = d.findViewById(R.id.progress);
        bar.getIndeterminateDrawable().setTint(color);

        TextView reasonView = d.findViewById(R.id.text1);
        TextView messageView = d.findViewById(R.id.text2);

        reasonView.setTextColor(color);
        messageView.setTextColor(color);

        messageView.setText(getRebootMessage(isReboot, reason));
        String rebootReasonMessage = getReasonMessage(reason);
        if (rebootReasonMessage != null) {
            reasonView.setVisibility(View.VISIBLE);
            reasonView.setText(rebootReasonMessage);
        }

        d.show();
    }

    @StringRes
    private int getRebootMessage(boolean isReboot, @Nullable String reason) {
        if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) {
            return R.string.reboot_to_update_reboot;
        } else if (reason != null && reason.equals(PowerManager.REBOOT_RECOVERY)) {
            return R.string.reboot_to_reset_message;
        } else if (isReboot) {
            return R.string.reboot_to_reset_message;
        } else {
            return R.string.shutdown_progress;
        mShutdownUi.showShutdownUi(isReboot, reason);
    }
    }

    @Nullable
    private String getReasonMessage(@Nullable String reason) {
        if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) {
            return mContext.getString(R.string.reboot_to_update_title);
        } else if (reason != null && reason.equals(PowerManager.REBOOT_RECOVERY)) {
            return mContext.getString(R.string.reboot_to_reset_title);
        } else {
            return null;
        }
    }

    @Override
    public void disable(int displayId, int state1, int state2, boolean animate) {
        final boolean disabled = (state2 & DISABLE2_GLOBAL_ACTIONS) != 0;
+155 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.globalactions;

import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;

import android.annotation.Nullable;
import android.annotation.StringRes;
import android.app.Dialog;
import android.content.Context;
import android.os.PowerManager;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ProgressBar;
import android.widget.TextView;

import androidx.annotation.VisibleForTesting;

import com.android.internal.R;
import com.android.settingslib.Utils;
import com.android.systemui.scrim.ScrimDrawable;
import com.android.systemui.statusbar.BlurUtils;
import com.android.systemui.statusbar.phone.ScrimController;

/**
 * Provides the UI shown during system shutdown.
 */
public class ShutdownUi {

    private Context mContext;
    private BlurUtils mBlurUtils;
    public ShutdownUi(Context context, BlurUtils blurUtils) {
        mContext = context;
        mBlurUtils = blurUtils;
    }

    /**
     * Display the shutdown UI.
     * @param isReboot Whether the device will be rebooting after this shutdown.
     * @param reason Cause for the shutdown.
     */
    public void showShutdownUi(boolean isReboot, String reason) {
        ScrimDrawable background = new ScrimDrawable();

        final Dialog d = new Dialog(mContext,
                com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions);

        d.setOnShowListener(dialog -> {
            if (mBlurUtils.supportsBlursOnWindows()) {
                int backgroundAlpha = (int) (ScrimController.BUSY_SCRIM_ALPHA * 255);
                background.setAlpha(backgroundAlpha);
                mBlurUtils.applyBlur(d.getWindow().getDecorView().getViewRootImpl(),
                        (int) mBlurUtils.blurRadiusOfRatio(1), backgroundAlpha == 255);
            } else {
                float backgroundAlpha = mContext.getResources().getFloat(
                        com.android.systemui.R.dimen.shutdown_scrim_behind_alpha);
                background.setAlpha((int) (backgroundAlpha * 255));
            }
        });

        // Window initialization
        Window window = d.getWindow();
        window.requestFeature(Window.FEATURE_NO_TITLE);
        window.getAttributes().systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
        // Inflate the decor view, so the attributes below are not overwritten by the theme.
        window.getDecorView();
        window.getAttributes().width = ViewGroup.LayoutParams.MATCH_PARENT;
        window.getAttributes().height = ViewGroup.LayoutParams.MATCH_PARENT;
        window.getAttributes().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
        window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
        window.getAttributes().setFitInsetsTypes(0 /* types */);
        window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
        window.addFlags(
                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                        | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
                        | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                        | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
        window.setBackgroundDrawable(background);
        window.setWindowAnimations(com.android.systemui.R.style.Animation_ShutdownUi);

        d.setContentView(R.layout.shutdown_dialog);
        d.setCancelable(false);

        int color;
        if (mBlurUtils.supportsBlursOnWindows()) {
            color = Utils.getColorAttrDefaultColor(mContext,
                    com.android.systemui.R.attr.wallpaperTextColor);
        } else {
            color = mContext.getResources().getColor(
                    com.android.systemui.R.color.global_actions_shutdown_ui_text);
        }

        ProgressBar bar = d.findViewById(R.id.progress);
        bar.getIndeterminateDrawable().setTint(color);

        TextView reasonView = d.findViewById(R.id.text1);
        TextView messageView = d.findViewById(R.id.text2);

        reasonView.setTextColor(color);
        messageView.setTextColor(color);

        messageView.setText(getRebootMessage(isReboot, reason));
        String rebootReasonMessage = getReasonMessage(reason);
        if (rebootReasonMessage != null) {
            reasonView.setVisibility(View.VISIBLE);
            reasonView.setText(rebootReasonMessage);
        }

        d.show();
    }

    @StringRes
    @VisibleForTesting int getRebootMessage(boolean isReboot, @Nullable String reason) {
        if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) {
            return R.string.reboot_to_update_reboot;
        } else if (reason != null && reason.equals(PowerManager.REBOOT_RECOVERY)) {
            return R.string.reboot_to_reset_message;
        } else if (isReboot) {
            return R.string.reboot_to_reset_message;
        } else {
            return R.string.shutdown_progress;
        }
    }

    @Nullable
    @VisibleForTesting String getReasonMessage(@Nullable String reason) {
        if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) {
            return mContext.getString(R.string.reboot_to_update_title);
        } else if (reason != null && reason.equals(PowerManager.REBOOT_RECOVERY)) {
            return mContext.getString(R.string.reboot_to_reset_title);
        } else {
            return null;
        }
    }
}
+31 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.systemui.globalactions

import android.content.Context
import com.android.systemui.statusbar.BlurUtils
import dagger.Module
import dagger.Provides

/** Provides the UI shown during system shutdown. */
@Module
class ShutdownUiModule {
    /** Shutdown UI provider. */
    @Provides
    fun provideShutdownUi(context: Context?, blurUtils: BlurUtils?): ShutdownUi {
        return ShutdownUi(context, blurUtils)
    }
}
+87 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.globalactions;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNull;

import android.os.PowerManager;
import android.testing.AndroidTestingRunner;

import androidx.test.filters.SmallTest;

import com.android.internal.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.BlurUtils;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;

/**
 * Tests for {@link ListGridLayout}.
 */
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class ShutdownUiTest extends SysuiTestCase {

    ShutdownUi mShutdownUi;
    @Mock
    BlurUtils mBlurUtils;

    @Before
    public void setUp() throws Exception {
        mShutdownUi = new ShutdownUi(getContext(), mBlurUtils);
    }

    @Test
    public void getRebootMessage_update() {
        int messageId = mShutdownUi.getRebootMessage(true, PowerManager.REBOOT_RECOVERY_UPDATE);
        assertEquals(messageId, R.string.reboot_to_update_reboot);
    }

    @Test
    public void getRebootMessage_rebootDefault() {
        int messageId = mShutdownUi.getRebootMessage(true, "anything-else");
        assertEquals(messageId, R.string.reboot_to_reset_message);
    }

    @Test
    public void getRebootMessage_shutdown() {
        int messageId = mShutdownUi.getRebootMessage(false, "anything-else");
        assertEquals(messageId, R.string.shutdown_progress);
    }

    @Test
    public void getReasonMessage_update() {
        String message = mShutdownUi.getReasonMessage(PowerManager.REBOOT_RECOVERY_UPDATE);
        assertEquals(message, mContext.getString(R.string.reboot_to_update_title));
    }

    @Test
    public void getReasonMessage_rebootDefault() {
        String message = mShutdownUi.getReasonMessage(PowerManager.REBOOT_RECOVERY);
        assertEquals(message, mContext.getString(R.string.reboot_to_reset_title));
    }

    @Test
    public void getRebootMessage_defaultToNone() {
        String message = mShutdownUi.getReasonMessage("anything-else");
        assertNull(message);
    }
}