Color extraction under Power and Volume menus

Bug: 37013646
Test: visual
Change-Id: I29a1734d49e8225f49133424841dfcbfbff59516
diff --git a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/drawable/GradientDrawable.java b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/drawable/GradientDrawable.java
index e75d95a..f6b44c6 100644
--- a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/drawable/GradientDrawable.java
+++ b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/drawable/GradientDrawable.java
@@ -147,7 +147,7 @@
 
     @Override
     public int getOpacity() {
-        return mAlpha == 255 ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT;
+        return PixelFormat.TRANSLUCENT;
     }
 
     public void setScreenSize(int width, int height) {
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 44da876..b046256 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -307,6 +307,8 @@
 
     <style name="Theme.SystemUI.Dialog.Alert" parent="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert" />
 
+    <style name="Theme.SystemUI.Dialog.GlobalActions" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar.Fullscreen" />
+
     <style name="QSBorderlessButton">
         <item name="android:padding">12dp</item>
         <item name="android:background">@drawable/qs_btn_borderless_rect</item>
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 4af21eb..ae6249d 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -14,6 +14,8 @@
 
 package com.android.systemui.globalactions;
 
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+
 import com.android.internal.R;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -21,13 +23,17 @@
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.TelephonyProperties;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.Dependency;
 import com.android.systemui.HardwareUiLayout;
 import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
+import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.volume.VolumeDialogImpl;
 import com.android.systemui.volume.VolumeDialogMotion.LogAccelerateInterpolator;
 import com.android.systemui.volume.VolumeDialogMotion.LogDecelerateInterpolator;
 
 import android.app.ActivityManager;
 import android.app.Dialog;
+import android.app.WallpaperManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -37,6 +43,8 @@
 import android.database.ContentObserver;
 import android.database.DataSetObserver;
 import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.graphics.Point;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.media.AudioManager;
@@ -59,9 +67,12 @@
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
+import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewPropertyAnimator;
+import android.view.Window;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityEvent;
@@ -73,6 +84,10 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import com.google.android.colorextraction.ColorExtractor;
+import com.google.android.colorextraction.ColorExtractor.GradientColors;
+import com.google.android.colorextraction.drawable.GradientDrawable;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -208,8 +223,6 @@
             mDialog.getWindow().setAttributes(attrs);
             mDialog.show();
             mWindowManagerFuncs.onGlobalActionsShown();
-            mDialog.getWindow().getDecorView().setSystemUiVisibility(
-                    View.STATUS_BAR_DISABLE_EXPAND);
         }
     }
 
@@ -332,7 +345,7 @@
         };
         ActionsDialog dialog = new ActionsDialog(mContext, this, mAdapter, onItemLongClickListener);
         dialog.setCanceledOnTouchOutside(false); // Handled by the custom class.
-        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+        dialog.setKeyguardShowing(mKeyguardShowing);
 
         dialog.setOnDismissListener(this);
 
@@ -637,7 +650,6 @@
         refreshSilentMode();
         mAirplaneModeOn.updateState(mAirplaneState);
         mAdapter.notifyDataSetChanged();
-        mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
         if (mShowSilentToggle) {
             IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION);
             mContext.registerReceiver(mRingerModeReceiver, filter);
@@ -1194,7 +1206,8 @@
         }
     }
 
-    private static final class ActionsDialog extends Dialog implements DialogInterface {
+    private static final class ActionsDialog extends Dialog implements DialogInterface,
+            ColorExtractor.OnColorsChangedListener {
 
         private final Context mContext;
         private final MyAdapter mAdapter;
@@ -1202,16 +1215,35 @@
         private final HardwareUiLayout mHardwareLayout;
         private final OnClickListener mClickListener;
         private final OnItemLongClickListener mLongClickListener;
+        private final GradientDrawable mGradientDrawable;
+        private final ColorExtractor mColorExtractor;
+        private boolean mKeyguardShowing;
 
         public ActionsDialog(Context context, OnClickListener clickListener, MyAdapter adapter,
                 OnItemLongClickListener longClickListener) {
-            super(context, android.R.style.Theme_DeviceDefault_Light_NoActionBar_Fullscreen);
+            super(context, com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions);
             mContext = getContext();
             mAdapter = adapter;
             mClickListener = clickListener;
             mLongClickListener = longClickListener;
+            mGradientDrawable = new GradientDrawable(mContext);
+            mColorExtractor = Dependency.get(ColorExtractor.class);
+
+            // Window initialization
+            Window window = getWindow();
+            window.requestFeature(Window.FEATURE_NO_TITLE);
+            window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND
+                    | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
+            window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                    | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                    | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                    | 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);
+
             setContentView(com.android.systemui.R.layout.global_actions_wrapped);
-            getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
             mListView = findViewById(android.R.id.list);
             mHardwareLayout = HardwareUiLayout.get(mListView);
             mHardwareLayout.setOutsideTouchListener(view -> dismiss());
@@ -1234,16 +1266,26 @@
             super.setCanceledOnTouchOutside(true);
             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);
+            mGradientDrawable.setColors(colors, false);
         }
 
         @Override
         protected void onStop() {
             super.onStop();
+            mColorExtractor.removeOnColorsChangedListener(this);
         }
 
         @Override
         public void show() {
             super.show();
+            mGradientDrawable.setAlpha(0);
             mHardwareLayout.setTranslationX(getAnimTranslation());
             mHardwareLayout.setAlpha(0);
             mHardwareLayout.animate()
@@ -1251,6 +1293,11 @@
                     .translationX(0)
                     .setDuration(300)
                     .setInterpolator(new LogDecelerateInterpolator())
+                    .setUpdateListener(animation -> {
+                        int alpha = (int) ((Float) animation.getAnimatedValue()
+                                * ScrimController.GRADIENT_SCRIM_ALPHA * 255);
+                        mGradientDrawable.setAlpha(alpha);
+                    })
                     .start();
         }
 
@@ -1264,6 +1311,11 @@
                     .setDuration(300)
                     .withEndAction(() -> super.dismiss())
                     .setInterpolator(new LogAccelerateInterpolator())
+                    .setUpdateListener(animation -> {
+                        int alpha = (int) ((1f - (Float) animation.getAnimatedValue())
+                                * ScrimController.GRADIENT_SCRIM_ALPHA * 255);
+                        mGradientDrawable.setAlpha(alpha);
+                    })
                     .start();
         }
 
@@ -1285,5 +1337,22 @@
             }
             return super.dispatchPopulateAccessibilityEvent(event);
         }
+
+        @Override
+        public void onColorsChanged(GradientColors colors, int which) {
+            if (mKeyguardShowing) {
+                if ((WallpaperManager.FLAG_LOCK & which) != 0) {
+                    mGradientDrawable.setColors(colors);
+                }
+            } else {
+                if ((WallpaperManager.FLAG_SYSTEM & which) != 0) {
+                    mGradientDrawable.setColors(colors);
+                }
+            }
+        }
+
+        public void setKeyguardShowing(boolean keyguardShowing) {
+            mKeyguardShowing = keyguardShowing;
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 4541d07..01f740f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -57,10 +57,11 @@
             = new PathInterpolator(0f, 0, 0.7f, 1f);
     public static final Interpolator KEYGUARD_FADE_OUT_INTERPOLATOR_LOCKED
             = new PathInterpolator(0.3f, 0f, 0.8f, 1f);
+    public static final float GRADIENT_SCRIM_ALPHA = 0.75f;
     protected static final float SCRIM_BEHIND_ALPHA_KEYGUARD = 0.45f;
     protected static final float SCRIM_BEHIND_ALPHA_UNLOCKING = 0.2f;
-    private static final float SCRIM_IN_FRONT_ALPHA = 0.75f;
-    private static final float SCRIM_IN_FRONT_ALPHA_LOCKED = 0.85f;
+    private static final float SCRIM_IN_FRONT_ALPHA = GRADIENT_SCRIM_ALPHA;
+    private static final float SCRIM_IN_FRONT_ALPHA_LOCKED = GRADIENT_SCRIM_ALPHA;
     private static final int TAG_KEY_ANIM = R.id.scrim;
     private static final int TAG_KEY_ANIM_TARGET = R.id.scrim_target;
     private static final int TAG_START_ALPHA = R.id.scrim_alpha_start;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 1f674e0..9e26c1e 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -26,6 +26,7 @@
 import android.annotation.SuppressLint;
 import android.app.Dialog;
 import android.app.KeyguardManager;
+import android.app.WallpaperManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.ColorStateList;
@@ -33,6 +34,7 @@
 import android.content.res.Resources;
 import android.graphics.Color;
 import android.graphics.PixelFormat;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.graphics.drawable.ColorDrawable;
@@ -82,10 +84,14 @@
 import com.android.systemui.plugins.VolumeDialogController.State;
 import com.android.systemui.plugins.VolumeDialogController.StreamState;
 import com.android.systemui.plugins.VolumeDialog;
+import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.policy.ZenModeController;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerZenModePanel;
 
+import com.google.android.colorextraction.ColorExtractor;
+import com.google.android.colorextraction.drawable.GradientDrawable;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
@@ -97,7 +103,8 @@
  *
  * Methods ending in "H" must be called on the (ui) handler.
  */
-public class VolumeDialogImpl implements VolumeDialog, TunerService.Tunable {
+public class VolumeDialogImpl implements VolumeDialog, TunerService.Tunable,
+        ColorExtractor.OnColorsChangedListener {
     private static final String TAG = Util.logTag(VolumeDialogImpl.class);
 
     public static final String SHOW_FULL_ZEN = "sysui_show_full_zen";
@@ -107,6 +114,8 @@
 
     private final Context mContext;
     private final H mHandler = new H();
+    private final GradientDrawable mGradientDrawable;
+    private final ColorExtractor mColorExtractor;
     private VolumeDialogController mController;
 
     private Window mWindow;
@@ -161,6 +170,9 @@
                 (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
         mActiveSliderTint = ColorStateList.valueOf(Utils.getColorAccent(mContext));
         mInactiveSliderTint = loadColorStateList(R.color.volume_slider_inactive);
+        mGradientDrawable = new GradientDrawable(mContext);
+        mGradientDrawable.setAlpha((int) (ScrimController.GRADIENT_SCRIM_ALPHA * 255));
+        mColorExtractor = Dependency.get(ColorExtractor.class);
     }
 
     public void init(int windowType, Callback callback) {
@@ -182,6 +194,7 @@
     @Override
     public void destroy() {
         mController.removeCallback(mControllerCallbackH);
+        mColorExtractor.removeOnColorsChangedListener(this);
     }
 
     private void initDialog() {
@@ -192,7 +205,7 @@
         mShowing = false;
         mWindow = mDialog.getWindow();
         mWindow.requestFeature(Window.FEATURE_NO_TITLE);
-        mWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
+        mWindow.setBackgroundDrawable(mGradientDrawable);
         mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
         mWindow.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
@@ -200,6 +213,8 @@
                 | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
+        Point displaySize = new Point();
+        mContext.getDisplay().getRealSize(displaySize);
         mDialog.setCanceledOnTouchOutside(true);
         final Resources res = mContext.getResources();
         mWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
@@ -213,6 +228,14 @@
             rescheduleTimeoutH();
             return true;
         });
+
+        mColorExtractor.addOnColorsChangedListener(this);
+        mGradientDrawable.setScreenSize(displaySize.x, displaySize.y);
+        ColorExtractor.GradientColors colors = mColorExtractor.getColors(
+                mKeyguard.isKeyguardLocked() ? WallpaperManager.FLAG_LOCK
+                        : WallpaperManager.FLAG_SYSTEM);
+        mGradientDrawable.setColors(colors, false);
+
         mDialogContentView = mDialog.findViewById(R.id.volume_dialog_content);
         mDialogRowsView = mDialogContentView.findViewById(R.id.volume_dialog_rows);
         mExpanded = false;
@@ -224,7 +247,7 @@
         updateExpandButtonH();
 
         mMotion = new VolumeDialogMotion(mDialog, (View) mDialogView.getParent(),
-                mDialogContentView, mExpandButton, animating -> {
+                mDialogContentView, mExpandButton, mGradientDrawable, animating -> {
                     if (animating) return;
                     if (mPendingStateChanged) {
                         mHandler.sendEmptyMessage(H.STATE_CHANGED);
@@ -1075,6 +1098,19 @@
         }
     };
 
+    @Override
+    public void onColorsChanged(ColorExtractor.GradientColors colors, int which) {
+        if (mKeyguard.isKeyguardLocked()) {
+            if ((WallpaperManager.FLAG_LOCK & which) != 0) {
+                mGradientDrawable.setColors(colors);
+            }
+        } else {
+            if ((WallpaperManager.FLAG_SYSTEM & which) != 0) {
+                mGradientDrawable.setColors(colors);
+            }
+        }
+    }
+
     private final class H extends Handler {
         private static final int SHOW = 1;
         private static final int DISMISS = 2;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogMotion.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogMotion.java
index 8afd91d..2df2227 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogMotion.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogMotion.java
@@ -24,6 +24,7 @@
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnDismissListener;
 import android.content.DialogInterface.OnShowListener;
+import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.util.Log;
 import android.view.View;
@@ -40,8 +41,10 @@
     private final View mDialogView;
     private final ViewGroup mContents;  // volume rows + zen footer
     private final View mChevron;
+    private final Drawable mBackground;
     private final Handler mHandler = new Handler();
     private final Callback mCallback;
+    private final int mBackgroundTargetAlpha;
 
     private boolean mAnimating;  // show or dismiss animation is running
     private boolean mShowing;  // show animation is running
@@ -50,12 +53,14 @@
     private ValueAnimator mContentsPositionAnimator;
 
     public VolumeDialogMotion(Dialog dialog, View dialogView, ViewGroup contents, View chevron,
-            Callback callback) {
+            Drawable background, Callback callback) {
         mDialog = dialog;
         mDialogView = dialogView;
         mContents = contents;
         mChevron = chevron;
         mCallback = callback;
+        mBackground = background;
+        mBackgroundTargetAlpha = mBackground.getAlpha();
         mDialog.setOnDismissListener(new OnDismissListener() {
             @Override
             public void onDismiss(DialogInterface dialog) {
@@ -68,6 +73,7 @@
                 if (D.BUG) Log.d(TAG, "mDialog.onShow");
                 final int w = mDialogView.getWidth() / 4;
                 mDialogView.setTranslationX(w);
+                mBackground.setAlpha(0);
                 startShowAnimation();
             }
         });
@@ -133,18 +139,20 @@
                 .setDuration(scaledDuration(300))
                 .setInterpolator(new LogDecelerateInterpolator())
                 .setListener(null)
-                .setUpdateListener(new AnimatorUpdateListener() {
-                    @Override
-                    public void onAnimationUpdate(ValueAnimator animation) {
+                .setUpdateListener(animation -> {
+                    mBackground.setAlpha(
+                            (int) (animation.getAnimatedFraction() * mBackgroundTargetAlpha));
+                    if (mChevronPositionAnimator != null) {
+                        final float v = (Float) mChevronPositionAnimator.getAnimatedValue();
                         if (mChevronPositionAnimator == null) return;
                         // reposition chevron
-                        final float v = (Float) mChevronPositionAnimator.getAnimatedValue();
                         final int posY = chevronPosY();
                     }
                 })
                 .withEndAction(new Runnable() {
                     @Override
                     public void run() {
+                        mBackground.setAlpha(mBackgroundTargetAlpha);
                         if (mChevronPositionAnimator == null) return;
                         // reposition chevron
                         final int posY = chevronPosY();
@@ -215,6 +223,10 @@
                 .alpha(0)
                 .setDuration(scaledDuration(250))
                 .setInterpolator(new LogAccelerateInterpolator())
+                .setUpdateListener(animation -> {
+                    final float v = 1 - mChevronPositionAnimator.getAnimatedFraction();
+                    mBackground.setAlpha((int) (v * mBackgroundTargetAlpha));
+                })
                 .setListener(new AnimatorListenerAdapter() {
                     private boolean mCancelled;