summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/util/FeatureFlagUtils.java5
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActionsPanelPlugin.java86
-rw-r--r--packages/SystemUI/res/drawable/global_action_panel_scrim.xml26
-rw-r--r--packages/SystemUI/res/values/dimens.xml3
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java112
5 files changed, 210 insertions, 22 deletions
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index fac699ece642..b99336bb0dbf 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -39,6 +39,8 @@ public class FeatureFlagUtils {
public static final String SAFETY_HUB = "settings_safety_hub";
public static final String SCREENRECORD_LONG_PRESS = "settings_screenrecord_long_press";
public static final String GLOBAL_ACTIONS_GRID_ENABLED = "settings_global_actions_grid_enabled";
+ public static final String GLOBAL_ACTIONS_PANEL_ENABLED =
+ "settings_global_actions_panel_enabled";
private static final Map<String, String> DEFAULT_FLAGS;
@@ -56,7 +58,8 @@ public class FeatureFlagUtils {
DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "false");
DEFAULT_FLAGS.put(SAFETY_HUB, "false");
DEFAULT_FLAGS.put(SCREENRECORD_LONG_PRESS, "false");
- DEFAULT_FLAGS.put(GLOBAL_ACTIONS_GRID_ENABLED, "false");
+ DEFAULT_FLAGS.put(GLOBAL_ACTIONS_GRID_ENABLED, "true");
+ DEFAULT_FLAGS.put(GLOBAL_ACTIONS_PANEL_ENABLED, "true");
}
/**
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActionsPanelPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActionsPanelPlugin.java
new file mode 100644
index 000000000000..7c7268865235
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActionsPanelPlugin.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2019 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.plugins;
+
+import android.view.View;
+
+import com.android.systemui.plugins.annotations.DependsOn;
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
+/**
+ * Plugin which provides a "Panel" {@link View} to be rendered inside of the GlobalActions menu.
+ *
+ * Implementations should construct a new {@link PanelViewController} with the given
+ * {@link Callbacks} instance inside of {@link #onPanelShown(Callbacks)}, and should not hold onto
+ * a reference, instead allowing Global Actions to manage the lifetime of the object.
+ *
+ * Under this assumption, {@link PanelViewController} represents the lifetime of a single invocation
+ * of the Global Actions menu. The {@link View} for the Panel is generated when the
+ * {@link PanelViewController} is constructed, and {@link PanelViewController#getPanelContent()}
+ * serves as a simple getter. When Global Actions is dismissed,
+ * {@link PanelViewController#onDismissed()} can be used to cleanup any resources allocated when
+ * constructed. Global Actions will then release the reference, and the {@link PanelViewController}
+ * will be garbage-collected.
+ */
+@ProvidesInterface(
+ action = GlobalActionsPanelPlugin.ACTION, version = GlobalActionsPanelPlugin.VERSION)
+@DependsOn(target = GlobalActionsPanelPlugin.Callbacks.class)
+@DependsOn(target = GlobalActionsPanelPlugin.PanelViewController.class)
+public interface GlobalActionsPanelPlugin extends Plugin {
+ String ACTION = "com.android.systemui.action.PLUGIN_GLOBAL_ACTIONS_PANEL";
+ int VERSION = 0;
+
+ /**
+ * Invoked when the GlobalActions menu is shown.
+ *
+ * @param callbacks {@link Callbacks} instance that can be used by the Panel to interact with
+ * the Global Actions menu.
+ * @return A {@link PanelViewController} instance used to receive Global Actions events.
+ */
+ PanelViewController onPanelShown(Callbacks callbacks);
+
+ /**
+ * Provides methods to interact with the Global Actions menu.
+ */
+ @ProvidesInterface(version = Callbacks.VERSION)
+ interface Callbacks {
+ int VERSION = 0;
+
+ /** Dismisses the Global Actions menu. */
+ void dismissGlobalActionsMenu();
+ }
+
+ /**
+ * Receives Global Actions events, and provides the Panel {@link View}.
+ */
+ @ProvidesInterface(version = PanelViewController.VERSION)
+ interface PanelViewController {
+ int VERSION = 0;
+
+ /**
+ * Returns the {@link View} for the Panel to be rendered in Global Actions. This View can be
+ * any size, and will be rendered above the Global Actions menu when z-ordered.
+ */
+ View getPanelContent();
+
+ /**
+ * Invoked when the Global Actions menu (containing the View returned from
+ * {@link #getPanelContent()}) is dismissed.
+ */
+ void onDismissed();
+ }
+}
diff --git a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml b/packages/SystemUI/res/drawable/global_action_panel_scrim.xml
new file mode 100644
index 000000000000..177b8d204ac8
--- /dev/null
+++ b/packages/SystemUI/res/drawable/global_action_panel_scrim.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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="rectangle">
+ <gradient
+ android:centerY="0.45"
+ android:startColor="#be3c4043"
+ android:centerColor="#be3c4043"
+ android:endColor="#4d3c4043"
+ android:angle="270" />
+</shape> \ No newline at end of file
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 50cf37beb878..a40a14a47744 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -856,6 +856,9 @@
<!-- Global actions grid layout -->
<dimen name="global_actions_grid_side_margin">4dp</dimen>
+ <!-- Global actions panel -->
+ <dimen name="global_actions_panel_top_margin">85dp</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>
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index c16c91bd4625..8a95cc4910ad 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -67,6 +67,7 @@ import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityEvent;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.BaseAdapter;
+import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.TextView;
@@ -88,8 +89,10 @@ import com.android.systemui.Interpolators;
import com.android.systemui.MultiListLayout;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
-import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.plugins.GlobalActionsPanelPlugin;
import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.ExtensionController;
+import com.android.systemui.statusbar.policy.ExtensionController.Extension;
import com.android.systemui.util.EmergencyDialerConstants;
import com.android.systemui.util.leak.RotationUtils;
import com.android.systemui.volume.SystemUIInterpolators.LogAccelerateInterpolator;
@@ -161,6 +164,8 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
private final ScreenshotHelper mScreenshotHelper;
private final ScreenRecordHelper mScreenRecordHelper;
+ private final Extension<GlobalActionsPanelPlugin> mPanelExtension;
+
/**
* @param context everything needs a context :(
*/
@@ -204,6 +209,11 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
mScreenRecordHelper = new ScreenRecordHelper(context);
Dependency.get(ConfigurationController.class).addCallback(this);
+
+ mPanelExtension = Dependency.get(ExtensionController.class)
+ .newExtension(GlobalActionsPanelPlugin.class)
+ .withPlugin(GlobalActionsPanelPlugin.class)
+ .build();
}
/**
@@ -399,8 +409,16 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
}
return false;
};
+ GlobalActionsPanelPlugin.PanelViewController panelViewController =
+ mPanelExtension.get() != null
+ ? mPanelExtension.get().onPanelShown(() -> {
+ if (mDialog != null) {
+ mDialog.dismiss();
+ }
+ })
+ : null;
ActionsDialog dialog = new ActionsDialog(mContext, this, mAdapter, onItemLongClickListener,
- mSeparatedEmergencyButtonEnabled);
+ mSeparatedEmergencyButtonEnabled, panelViewController);
dialog.setCanceledOnTouchOutside(false); // Handled by the custom class.
dialog.setKeyguardShowing(mKeyguardShowing);
@@ -1470,20 +1488,22 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
private MultiListLayout mGlobalActionsLayout;
private final OnClickListener mClickListener;
private final OnItemLongClickListener mLongClickListener;
- private final GradientDrawable mGradientDrawable;
+ private final Drawable mBackgroundDrawable;
private final ColorExtractor mColorExtractor;
+ private final GlobalActionsPanelPlugin.PanelViewController mPanelController;
private boolean mKeyguardShowing;
private boolean mShouldDisplaySeparatedButton;
private boolean mShowing;
+ private final float mScrimAlpha;
public ActionsDialog(Context context, OnClickListener clickListener, MyAdapter adapter,
- OnItemLongClickListener longClickListener, boolean shouldDisplaySeparatedButton) {
+ OnItemLongClickListener longClickListener, boolean shouldDisplaySeparatedButton,
+ GlobalActionsPanelPlugin.PanelViewController plugin) {
super(context, com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions);
mContext = context;
mAdapter = adapter;
mClickListener = clickListener;
mLongClickListener = longClickListener;
- mGradientDrawable = new GradientDrawable(mContext);
mColorExtractor = Dependency.get(SysuiColorExtractor.class);
mShouldDisplaySeparatedButton = shouldDisplaySeparatedButton;
@@ -1504,12 +1524,46 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
- window.setBackgroundDrawable(mGradientDrawable);
window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
initializeLayout();
setTitle(R.string.global_actions);
+
+ mPanelController = plugin;
+ View panelView = initializePanel();
+ if (panelView == null) {
+ mBackgroundDrawable = new GradientDrawable(context);
+ mScrimAlpha = 0.7f;
+ } else {
+ mBackgroundDrawable = context.getDrawable(
+ com.android.systemui.R.drawable.global_action_panel_scrim);
+ mScrimAlpha = 1f;
+ addContentView(
+ panelView,
+ new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT));
+ }
+ window.setBackgroundDrawable(mBackgroundDrawable);
+ }
+
+ private View initializePanel() {
+ if (isPanelEnabled(mContext) && mPanelController != null) {
+ View panelView = mPanelController.getPanelContent();
+ if (panelView != null) {
+ FrameLayout panelContainer = new FrameLayout(mContext);
+ FrameLayout.LayoutParams panelParams =
+ new FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.MATCH_PARENT,
+ FrameLayout.LayoutParams.WRAP_CONTENT);
+ panelParams.topMargin = mContext.getResources().getDimensionPixelSize(
+ com.android.systemui.R.dimen.global_actions_panel_top_margin);
+ panelContainer.addView(panelView, panelParams);
+ return panelContainer;
+ }
+ }
+ return null;
}
private void initializeLayout() {
@@ -1530,6 +1584,11 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
mGlobalActionsLayout.setRotationListener(this::onRotate);
}
+ private boolean isPanelEnabled(Context context) {
+ return FeatureFlagUtils.isEnabled(
+ context, FeatureFlagUtils.GLOBAL_ACTIONS_PANEL_ENABLED);
+ }
+
private int getGlobalActionsLayoutId(Context context) {
if (isGridEnabled(context)) {
if (RotationUtils.getRotation(context) == RotationUtils.ROTATION_SEASCAPE) {
@@ -1590,13 +1649,18 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
super.onStart();
updateList();
- Point displaySize = new Point();
- mContext.getDisplay().getRealSize(displaySize);
- mColorExtractor.addOnColorsChangedListener(this);
- mGradientDrawable.setScreenSize(displaySize.x, displaySize.y);
- GradientColors colors = mColorExtractor.getColors(mKeyguardShowing ?
- WallpaperManager.FLAG_LOCK : WallpaperManager.FLAG_SYSTEM);
- updateColors(colors, false /* animate */);
+ if (mBackgroundDrawable instanceof GradientDrawable) {
+ Point displaySize = new Point();
+ mContext.getDisplay().getRealSize(displaySize);
+ mColorExtractor.addOnColorsChangedListener(this);
+ ((GradientDrawable) mBackgroundDrawable)
+ .setScreenSize(displaySize.x, displaySize.y);
+ GradientColors colors = mColorExtractor.getColors(
+ mKeyguardShowing
+ ? WallpaperManager.FLAG_LOCK
+ : WallpaperManager.FLAG_SYSTEM);
+ updateColors(colors, false /* animate */);
+ }
}
/**
@@ -1605,11 +1669,14 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
* @param animate Interpolates gradient if true, just sets otherwise.
*/
private void updateColors(GradientColors colors, boolean animate) {
- mGradientDrawable.setColors(colors, animate);
+ if (!(mBackgroundDrawable instanceof GradientDrawable)) {
+ return;
+ }
+ ((GradientDrawable) mBackgroundDrawable).setColors(colors, animate);
View decorView = getWindow().getDecorView();
if (colors.supportsDarkText()) {
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR |
- View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+ View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
} else {
decorView.setSystemUiVisibility(0);
}
@@ -1625,7 +1692,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
public void show() {
super.show();
mShowing = true;
- mGradientDrawable.setAlpha(0);
+ mBackgroundDrawable.setAlpha(0);
mGlobalActionsLayout.setTranslationX(getAnimTranslation());
mGlobalActionsLayout.setAlpha(0);
mGlobalActionsLayout.animate()
@@ -1635,8 +1702,8 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.setUpdateListener(animation -> {
int alpha = (int) ((Float) animation.getAnimatedValue()
- * ScrimController.GRADIENT_SCRIM_ALPHA * 255);
- mGradientDrawable.setAlpha(alpha);
+ * mScrimAlpha * 255);
+ mBackgroundDrawable.setAlpha(alpha);
})
.start();
}
@@ -1653,14 +1720,17 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
.alpha(0)
.translationX(getAnimTranslation())
.setDuration(300)
- .withEndAction(() -> super.dismiss())
+ .withEndAction(super::dismiss)
.setInterpolator(new LogAccelerateInterpolator())
.setUpdateListener(animation -> {
int alpha = (int) ((1f - (Float) animation.getAnimatedValue())
- * ScrimController.GRADIENT_SCRIM_ALPHA * 255);
- mGradientDrawable.setAlpha(alpha);
+ * mScrimAlpha * 255);
+ mBackgroundDrawable.setAlpha(alpha);
})
.start();
+ if (mPanelController != null) {
+ mPanelController.onDismissed();
+ }
}
void dismissImmediately() {