Add power menu lite

Refactored existing long-press power menu so common elements could be
reused. This power menu only includes the standard buttons and can
rotate, with different "grid" size based on number of buttons available

Bug: 179674461
Test: atest com.android.systemui.globalactions
Test: manual, verify layout looks correct with different buttons and rotations

Change-Id: I2b61bc0ac2c9a15c4acc639770e4a3799a26c21a
This commit is contained in:
Beth Thibodeau
2021-03-17 13:36:11 -04:00
parent df7f14b885
commit 65c210b191
15 changed files with 3107 additions and 2093 deletions

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* Copyright 2021, 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.
*/
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/global_actions_lite_background"/>
<corners android:radius="@dimen/global_actions_corner_radius" />
</shape>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* Copyright 2021, 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.
*/
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/global_actions_lite_button_background"/>
</shape>

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 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.
-->
<com.android.systemui.globalactions.GlobalActionsItem
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_gravity="center"
android:orientation="vertical"
android:stateListAnimator="@anim/control_state_list_animator">
<ImageView
android:id="@*android:id/icon"
android:layout_width="@dimen/global_actions_button_size"
android:layout_height="@dimen/global_actions_button_size"
android:layout_marginBottom="@dimen/global_actions_grid_container_bottom_margin"
android:padding="@dimen/global_actions_button_padding"
android:scaleType="centerInside"
android:tint="@color/global_actions_lite_text"
android:background="@drawable/global_actions_lite_button"/>
<TextView
android:id="@*android:id/message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:marqueeRepeatLimit="marquee_forever"
android:maxLines="2"
android:textSize="12sp"
android:gravity="center"
android:textColor="@color/global_actions_lite_text"
android:breakStrategy="high_quality"
android:hyphenationFrequency="full"
android:textAppearance="?android:attr/textAppearanceSmall" />
</com.android.systemui.globalactions.GlobalActionsItem>

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/global_actions_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:layout_gravity="center">
<com.android.systemui.globalactions.GlobalActionsLayoutLite
android:id="@id/global_actions_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:clipChildren="false"
android:clipToPadding="false"
android:background="@drawable/global_actions_lite_background"
android:padding="@dimen/global_actions_lite_padding">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@android:id/list"
android:gravity="center"
android:translationZ="@dimen/global_actions_translate"
android:orientation="horizontal"
android:layoutDirection="ltr">
<androidx.constraintlayout.helper.widget.Flow
android:id="@+id/list_flow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:flow_wrapMode="chain"
app:flow_maxElementsWrap="2"
app:flow_horizontalGap="@dimen/global_actions_lite_padding"
app:flow_verticalGap="@dimen/global_actions_lite_padding"
app:flow_horizontalStyle="packed"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.android.systemui.globalactions.GlobalActionsLayoutLite>
</LinearLayout>

View File

@@ -54,6 +54,13 @@
<color name="global_actions_emergency_background">@color/GM2_red_400</color>
<color name="global_actions_emergency_text">@color/GM2_grey_100</color>
<!-- Colors for Power Menu Lite -->
<color name="global_actions_lite_background">#191C18</color>
<color name="global_actions_lite_button_background">#303030</color>
<color name="global_actions_lite_text">#F0F0F0</color>
<color name="global_actions_lite_emergency_background">#F85D4D</color>
<color name="global_actions_lite_emergency_icon">@color/GM2_grey_900</color>
<color name="global_actions_shutdown_ui_text">@color/control_primary_text</color>
<!-- Tint color for the content on the notification overflow card. -->

View File

@@ -553,6 +553,10 @@
<!-- Max number of columns for power menu -->
<integer name="power_menu_max_columns">3</integer>
<!-- Max number of columns for power menu lite -->
<integer name="power_menu_lite_max_columns">2</integer>
<!-- Max number of rows for power menu lite -->
<integer name="power_menu_lite_max_rows">4</integer>
<!-- If the dp width of the available space is <= this value, potentially adjust the number
of columns-->

View File

@@ -1063,6 +1063,12 @@
<dimen name="global_actions_power_dialog_item_width">255dp</dimen>
<dimen name="global_actions_power_dialog_item_bottom_margin">45dp</dimen>
<!-- Power Menu Lite -->
<dimen name="global_actions_button_size">96dp</dimen>
<dimen name="global_actions_button_padding">38dp</dimen>
<dimen name="global_actions_corner_radius">28dp</dimen>
<dimen name="global_actions_lite_padding">24dp</dimen>
<!-- The maximum offset in either direction that elements are moved horizontally to prevent
burn-in on AOD. -->
<dimen name="burn_in_prevention_offset_x">8dp</dimen>

View File

@@ -395,6 +395,13 @@
<item name="android:windowIsFloating">true</item>
</style>
<style name="Theme.SystemUI.Dialog.GlobalActionsLite" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar.Fullscreen">
<item name="android:windowIsFloating">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="android:windowCloseOnTouchOutside">true</item>
</style>
<style name="Theme.SystemUI.Dialog.MediaOutput">
<item name="android:windowBackground">@drawable/media_output_dialog_background</item>
</style>

View File

@@ -0,0 +1,133 @@
/*
* Copyright (C) 2021 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 com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import androidx.constraintlayout.helper.widget.Flow;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.HardwareBgDrawable;
import com.android.systemui.R;
/**
* ConstraintLayout implementation of the button layout created by the global actions dialog.
*/
public class GlobalActionsLayoutLite extends GlobalActionsLayout {
private final int mMaxColumns;
private final int mMaxRows;
public GlobalActionsLayoutLite(Context context, AttributeSet attrs) {
super(context, attrs);
mMaxColumns = getResources().getInteger(
com.android.systemui.R.integer.power_menu_lite_max_columns);
mMaxRows = getResources().getInteger(
com.android.systemui.R.integer.power_menu_lite_max_rows);
}
@VisibleForTesting
@Override
protected boolean shouldReverseListItems() {
// Handled in XML
return false;
}
@Override
protected HardwareBgDrawable getBackgroundDrawable(int backgroundColor) {
return null;
}
@Override
public void onUpdateList() {
super.onUpdateList();
int nElementsWrap = (getCurrentRotation() == ROTATION_NONE) ? mMaxColumns : mMaxRows;
int nChildren = getListView().getChildCount() - 1; // don't count flow element
if (getCurrentRotation() != ROTATION_NONE && nChildren > mMaxRows) {
// up to 4 elements can fit in a row in landscape, otherwise limit for balance
nElementsWrap -= 1;
}
Flow flow = findViewById(R.id.list_flow);
flow.setMaxElementsWrap(nElementsWrap);
}
@Override
protected void addToListView(View v, boolean reverse) {
super.addToListView(v, reverse);
Flow flow = findViewById(R.id.list_flow);
flow.addView(v);
}
@Override
protected void removeAllListViews() {
View flow = findViewById(R.id.list_flow);
super.removeAllListViews();
// Add flow element back after clearing the list view
super.addToListView(flow, false);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
boolean anyTruncated = false;
ViewGroup listView = getListView();
// Check to see if any of the GlobalActionsItems have had their messages truncated
for (int i = 0; i < listView.getChildCount(); i++) {
View child = listView.getChildAt(i);
if (child instanceof GlobalActionsItem) {
GlobalActionsItem item = (GlobalActionsItem) child;
anyTruncated = anyTruncated || item.isTruncated();
}
}
// If any of the items have been truncated, set the all to single-line marquee
if (anyTruncated) {
for (int i = 0; i < listView.getChildCount(); i++) {
View child = listView.getChildAt(i);
if (child instanceof GlobalActionsItem) {
GlobalActionsItem item = (GlobalActionsItem) child;
item.setMarquee(true);
}
}
}
}
@VisibleForTesting
protected float getGridItemSize() {
return getContext().getResources().getDimension(R.dimen.global_actions_grid_item_height);
}
@VisibleForTesting
protected float getAnimationDistance() {
return getGridItemSize() / 2;
}
@Override
public float getAnimationOffsetX() {
return getAnimationDistance();
}
@Override
public float getAnimationOffsetY() {
return 0f;
}
}

View File

@@ -32,6 +32,7 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
import com.android.systemui.globalactions.GlobalActionsDialogLite;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.qs.dagger.QSScope;
import com.android.systemui.settings.UserTracker;
@@ -68,6 +69,7 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
private final PageIndicator mPageIndicator;
private final View mPowerMenuLite;
private final boolean mShowPMLiteButton;
private GlobalActionsDialogLite mGlobalActionsDialog;
private final UserInfoController.OnUserInfoChangedListener mOnUserInfoChangedListener =
new UserInfoController.OnUserInfoChangedListener() {
@@ -115,6 +117,8 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
} else {
startSettingsActivity();
}
} else if (v == mPowerMenuLite) {
mGlobalActionsDialog.showOrHideDialog(false, true);
}
}
};
@@ -129,7 +133,8 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
QSPanelController qsPanelController, QSDetailDisplayer qsDetailDisplayer,
QuickQSPanelController quickQSPanelController,
TunerService tunerService, MetricsLogger metricsLogger,
@Named(PM_LITE_ENABLED) boolean showPMLiteButton) {
@Named(PM_LITE_ENABLED) boolean showPMLiteButton,
GlobalActionsDialogLite globalActionsDialog) {
super(view);
mUserManager = userManager;
mUserInfoController = userInfoController;
@@ -149,11 +154,15 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
mPageIndicator = mView.findViewById(R.id.footer_page_indicator);
mPowerMenuLite = mView.findViewById(R.id.pm_lite);
mShowPMLiteButton = showPMLiteButton;
mGlobalActionsDialog = globalActionsDialog;
}
@Override
protected void onViewAttached() {
if (!mShowPMLiteButton) {
if (mShowPMLiteButton) {
mPowerMenuLite.setVisibility(View.VISIBLE);
mPowerMenuLite.setOnClickListener(mSettingsOnClickListener);
} else {
mPowerMenuLite.setVisibility(View.GONE);
}
mView.addOnLayoutChangeListener(

View File

@@ -0,0 +1,289 @@
/*
* Copyright (C) 2020 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 com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.IActivityManager;
import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
import android.content.res.Resources;
import android.graphics.Color;
import android.media.AudioManager;
import android.os.Handler;
import android.os.UserManager;
import android.service.dreams.IDreamManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.IWindowManager;
import android.view.WindowManagerPolicyConstants;
import androidx.test.filters.SmallTest;
import com.android.internal.colorextraction.ColorExtractor;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.GlobalActions;
import com.android.systemui.settings.UserContextProvider;
import com.android.systemui.statusbar.NotificationShadeDepthController;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.telephony.TelephonyListenerManager;
import com.android.systemui.util.RingerModeLiveData;
import com.android.systemui.util.RingerModeTracker;
import com.android.systemui.util.settings.GlobalSettings;
import com.android.systemui.util.settings.SecureSettings;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.List;
import java.util.concurrent.Executor;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class GlobalActionsDialogLiteTest extends SysuiTestCase {
private GlobalActionsDialogLite mGlobalActionsDialogLite;
@Mock private GlobalActions.GlobalActionsManager mWindowManagerFuncs;
@Mock private AudioManager mAudioManager;
@Mock private IDreamManager mDreamManager;
@Mock private DevicePolicyManager mDevicePolicyManager;
@Mock private LockPatternUtils mLockPatternUtils;
@Mock private BroadcastDispatcher mBroadcastDispatcher;
@Mock private TelephonyListenerManager mTelephonyListenerManager;
@Mock private GlobalSettings mGlobalSettings;
@Mock private SecureSettings mSecureSettings;
@Mock private Resources mResources;
@Mock private ConfigurationController mConfigurationController;
@Mock private KeyguardStateController mKeyguardStateController;
@Mock private UserManager mUserManager;
@Mock private TrustManager mTrustManager;
@Mock private IActivityManager mActivityManager;
@Mock private MetricsLogger mMetricsLogger;
@Mock private NotificationShadeDepthController mDepthController;
@Mock private SysuiColorExtractor mColorExtractor;
@Mock private IStatusBarService mStatusBarService;
@Mock private NotificationShadeWindowController mNotificationShadeWindowController;
@Mock private IWindowManager mWindowManager;
@Mock private Executor mBackgroundExecutor;
@Mock private UiEventLogger mUiEventLogger;
@Mock private RingerModeTracker mRingerModeTracker;
@Mock private RingerModeLiveData mRingerModeLiveData;
@Mock private SysUiState mSysUiState;
@Mock private Handler mHandler;
@Mock private UserContextProvider mUserContextProvider;
private TestableLooper mTestableLooper;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mTestableLooper = TestableLooper.get(this);
allowTestableLooperAsMainThread();
when(mRingerModeTracker.getRingerMode()).thenReturn(mRingerModeLiveData);
when(mUserContextProvider.getUserContext()).thenReturn(mContext);
mGlobalActionsDialogLite = new GlobalActionsDialogLite(mContext,
mWindowManagerFuncs,
mAudioManager,
mDreamManager,
mDevicePolicyManager,
mLockPatternUtils,
mBroadcastDispatcher,
mTelephonyListenerManager,
mGlobalSettings,
mSecureSettings,
null,
mResources,
mConfigurationController,
mKeyguardStateController,
mUserManager,
mTrustManager,
mActivityManager,
null,
mMetricsLogger,
mDepthController,
mColorExtractor,
mStatusBarService,
mNotificationShadeWindowController,
mWindowManager,
mBackgroundExecutor,
mUiEventLogger,
mRingerModeTracker,
mSysUiState,
mHandler
);
mGlobalActionsDialogLite.setZeroDialogPressDelayForTesting();
ColorExtractor.GradientColors backdropColors = new ColorExtractor.GradientColors();
backdropColors.setMainColor(Color.BLACK);
when(mColorExtractor.getNeutralColors()).thenReturn(backdropColors);
when(mSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mSysUiState);
}
@Test
public void testShouldLogShow() {
mGlobalActionsDialogLite.onShow(null);
mTestableLooper.processAllMessages();
verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_POWER_MENU_OPEN);
}
@Test
public void testShouldLogDismiss() {
mGlobalActionsDialogLite.onDismiss(mGlobalActionsDialogLite.mDialog);
mTestableLooper.processAllMessages();
verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_POWER_MENU_CLOSE);
}
@Test
public void testShouldLogBugreportPress() throws InterruptedException {
GlobalActionsDialog.BugReportAction bugReportAction =
mGlobalActionsDialogLite.makeBugReportActionForTesting();
bugReportAction.onPress();
verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_BUGREPORT_PRESS);
}
@Test
public void testShouldLogBugreportLongPress() {
GlobalActionsDialog.BugReportAction bugReportAction =
mGlobalActionsDialogLite.makeBugReportActionForTesting();
bugReportAction.onLongPress();
verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_BUGREPORT_LONG_PRESS);
}
@Test
public void testShouldLogEmergencyDialerPress() {
GlobalActionsDialog.EmergencyDialerAction emergencyDialerAction =
mGlobalActionsDialogLite.makeEmergencyDialerActionForTesting();
emergencyDialerAction.onPress();
verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_EMERGENCY_DIALER_PRESS);
}
@Test
public void testShouldLogScreenshotPress() {
GlobalActionsDialog.ScreenshotAction screenshotAction =
mGlobalActionsDialogLite.makeScreenshotActionForTesting();
screenshotAction.onPress();
verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_SCREENSHOT_PRESS);
}
@Test
public void testShouldShowScreenshot() {
mContext.getOrCreateTestableResources().addOverride(
com.android.internal.R.integer.config_navBarInteractionMode,
WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON);
GlobalActionsDialog.ScreenshotAction screenshotAction =
mGlobalActionsDialogLite.makeScreenshotActionForTesting();
assertThat(screenshotAction.shouldShow()).isTrue();
}
@Test
public void testShouldNotShowScreenshot() {
mContext.getOrCreateTestableResources().addOverride(
com.android.internal.R.integer.config_navBarInteractionMode,
WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON);
GlobalActionsDialog.ScreenshotAction screenshotAction =
mGlobalActionsDialogLite.makeScreenshotActionForTesting();
assertThat(screenshotAction.shouldShow()).isFalse();
}
private void verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent event) {
mTestableLooper.processAllMessages();
verify(mUiEventLogger, times(1))
.log(event);
}
@SafeVarargs
private static <T> void assertItemsOfType(List<T> stuff, Class<? extends T>... classes) {
assertThat(stuff).hasSize(classes.length);
for (int i = 0; i < stuff.size(); i++) {
assertThat(stuff.get(i)).isInstanceOf(classes[i]);
}
}
@Test
public void testCreateActionItems_lockdownEnabled_doesShowLockdown() {
mGlobalActionsDialogLite = spy(mGlobalActionsDialogLite);
doReturn(4).when(mGlobalActionsDialogLite).getMaxShownPowerItems();
doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayLockdown(any());
doReturn(true).when(mGlobalActionsDialogLite).shouldShowAction(any());
String[] actions = {
GlobalActionsDialog.GLOBAL_ACTION_KEY_EMERGENCY,
GlobalActionsDialog.GLOBAL_ACTION_KEY_LOCKDOWN,
GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER,
GlobalActionsDialog.GLOBAL_ACTION_KEY_RESTART,
};
doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions();
mGlobalActionsDialogLite.createActionItems();
assertItemsOfType(mGlobalActionsDialogLite.mItems,
GlobalActionsDialog.EmergencyAction.class,
GlobalActionsDialog.LockDownAction.class,
GlobalActionsDialog.ShutDownAction.class,
GlobalActionsDialog.RestartAction.class);
assertThat(mGlobalActionsDialogLite.mOverflowItems).isEmpty();
assertThat(mGlobalActionsDialogLite.mPowerItems).isEmpty();
}
@Test
public void testCreateActionItems_lockdownDisabled_doesNotShowLockdown() {
mGlobalActionsDialogLite = spy(mGlobalActionsDialogLite);
doReturn(4).when(mGlobalActionsDialogLite).getMaxShownPowerItems();
// make sure lockdown action will NOT be shown
doReturn(false).when(mGlobalActionsDialogLite).shouldDisplayLockdown(any());
String[] actions = {
GlobalActionsDialog.GLOBAL_ACTION_KEY_EMERGENCY,
// lockdown action not allowed
GlobalActionsDialog.GLOBAL_ACTION_KEY_LOCKDOWN,
GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER,
GlobalActionsDialog.GLOBAL_ACTION_KEY_RESTART,
};
doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions();
mGlobalActionsDialogLite.createActionItems();
assertItemsOfType(mGlobalActionsDialogLite.mItems,
GlobalActionsDialog.EmergencyAction.class,
GlobalActionsDialog.ShutDownAction.class,
GlobalActionsDialog.RestartAction.class);
assertThat(mGlobalActionsDialogLite.mOverflowItems).isEmpty();
assertThat(mGlobalActionsDialogLite.mPowerItems).isEmpty();
}
}

View File

@@ -33,12 +33,10 @@ import static org.mockito.Mockito.when;
import android.app.IActivityManager;
import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
import android.content.ContentResolver;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Color;
import android.media.AudioManager;
import android.net.ConnectivityManager;
import android.os.Handler;
import android.os.RemoteException;
import android.os.UserManager;
@@ -77,6 +75,7 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.telephony.TelephonyListenerManager;
import com.android.systemui.util.RingerModeLiveData;
import com.android.systemui.util.RingerModeTracker;
import com.android.systemui.util.settings.GlobalSettings;
import com.android.systemui.util.settings.SecureSettings;
import org.junit.Before;
@@ -105,9 +104,8 @@ public class GlobalActionsDialogTest extends SysuiTestCase {
@Mock private DevicePolicyManager mDevicePolicyManager;
@Mock private LockPatternUtils mLockPatternUtils;
@Mock private BroadcastDispatcher mBroadcastDispatcher;
@Mock private ConnectivityManager mConnectivityManager;
@Mock private TelephonyListenerManager mTelephonyListenerManager;
@Mock private ContentResolver mContentResolver;
@Mock private GlobalSettings mGlobalSettings;
@Mock private Resources mResources;
@Mock private ConfigurationController mConfigurationController;
@Mock private ActivityStarter mActivityStarter;
@@ -166,9 +164,9 @@ public class GlobalActionsDialogTest extends SysuiTestCase {
mDevicePolicyManager,
mLockPatternUtils,
mBroadcastDispatcher,
mConnectivityManager,
mTelephonyListenerManager,
mContentResolver,
mGlobalSettings,
mSecureSettings,
null,
mResources,
mConfigurationController,
@@ -520,7 +518,8 @@ public class GlobalActionsDialogTest extends SysuiTestCase {
mGlobalActionsDialog.showOrHideDialog(false, true, mWalletPlugin);
GlobalActionsDialog.ActionsDialog dialog = mGlobalActionsDialog.mDialog;
GlobalActionsDialog.ActionsDialog dialog =
(GlobalActionsDialog.ActionsDialog) mGlobalActionsDialog.mDialog;
assertThat(dialog).isNotNull();
assertThat(dialog.mLockMessageContainer.getVisibility()).isEqualTo(View.VISIBLE);
@@ -543,7 +542,8 @@ public class GlobalActionsDialogTest extends SysuiTestCase {
mGlobalActionsDialog.showOrHideDialog(false, true, mWalletPlugin);
GlobalActionsDialog.ActionsDialog dialog = mGlobalActionsDialog.mDialog;
GlobalActionsDialog.ActionsDialog dialog =
(GlobalActionsDialog.ActionsDialog) mGlobalActionsDialog.mDialog;
assertThat(dialog).isNotNull();
assertThat(dialog.mLockMessageContainer.getVisibility()).isEqualTo(View.GONE);
@@ -568,7 +568,8 @@ public class GlobalActionsDialogTest extends SysuiTestCase {
mGlobalActionsDialog.showOrHideDialog(false, true, mWalletPlugin);
GlobalActionsDialog.ActionsDialog dialog = mGlobalActionsDialog.mDialog;
GlobalActionsDialog.ActionsDialog dialog =
(GlobalActionsDialog.ActionsDialog) mGlobalActionsDialog.mDialog;
assertThat(dialog).isNotNull();
assertThat(dialog.mLockMessageContainer.getVisibility()).isEqualTo(View.GONE);

View File

@@ -38,6 +38,7 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.testing.FakeMetricsLogger;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.globalactions.GlobalActionsDialogLite;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.MultiUserSwitch;
@@ -91,6 +92,8 @@ public class QSFooterViewControllerTest extends LeakCheckedTest {
private MultiUserSwitch mMultiUserSwitch;
@Mock
private View mPowerMenuLiteView;
@Mock
private GlobalActionsDialogLite mGlobalActionsDialog;
private QSFooterViewController mController;
@@ -118,7 +121,7 @@ public class QSFooterViewControllerTest extends LeakCheckedTest {
mController = new QSFooterViewController(mView, mUserManager, mUserInfoController,
mActivityStarter, mDeviceProvisionedController, mUserTracker, mQSPanelController,
new QSDetailDisplayer(), mQuickQSPanelController, mFakeTunerService,
mMetricsLogger, false);
mMetricsLogger, false, mGlobalActionsDialog);
mController.init();
}