diff options
Diffstat (limited to 'libs')
20 files changed, 356 insertions, 118 deletions
diff --git a/libs/WindowManager/Shell/OWNERS b/libs/WindowManager/Shell/OWNERS index e346b51a4f19..0c4fd140780e 100644 --- a/libs/WindowManager/Shell/OWNERS +++ b/libs/WindowManager/Shell/OWNERS @@ -2,3 +2,4 @@ xutan@google.com # Give submodule owners in shell resource approval per-file res*/*/*.xml = atsjenk@google.com, hwwang@google.com, jorgegil@google.com, lbill@google.com, madym@google.com, nmusgrave@google.com, pbdr@google.com, tkachenkoi@google.com +per-file res*/*/tv_*.xml = bronger@google.com diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.java index 160f922dd928..55982dca79b3 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.java @@ -310,12 +310,16 @@ public class CrossActivityBackAnimation extends ShellBackAnimation { float top = mapRange(progress, mEnteringStartRect.top, mStartTaskRect.top); float width = mapRange(progress, mEnteringStartRect.width(), mStartTaskRect.width()); float height = mapRange(progress, mEnteringStartRect.height(), mStartTaskRect.height()); - float alpha = mapRange(progress, mEnteringProgress, 1.0f); - + float alpha = mapRange(progress, getPreCommitEnteringAlpha(), 1.0f); mEnteringRect.set(left, top, left + width, top + height); applyTransform(mEnteringTarget.leash, mEnteringRect, alpha); } + private float getPreCommitEnteringAlpha() { + return Math.max(smoothstep(ENTER_ALPHA_THRESHOLD, 0.7f, mEnteringProgress), + MIN_WINDOW_ALPHA); + } + private float getEnteringProgress() { return mEnteringProgress * SCALE_FACTOR; } @@ -325,9 +329,7 @@ public class CrossActivityBackAnimation extends ShellBackAnimation { if (mEnteringTarget != null && mEnteringTarget.leash != null) { transformWithProgress( mEnteringProgress, - Math.max( - smoothstep(ENTER_ALPHA_THRESHOLD, 0.7f, mEnteringProgress), - MIN_WINDOW_ALPHA), /* alpha */ + getPreCommitEnteringAlpha(), mEnteringTarget.leash, mEnteringRect, -mWindowXShift, @@ -336,6 +338,11 @@ public class CrossActivityBackAnimation extends ShellBackAnimation { } } + private float getPreCommitLeavingAlpha() { + return Math.max(1 - smoothstep(0, ENTER_ALPHA_THRESHOLD, mLeavingProgress), + MIN_WINDOW_ALPHA); + } + private float getLeavingProgress() { return mLeavingProgress * SCALE_FACTOR; } @@ -345,9 +352,7 @@ public class CrossActivityBackAnimation extends ShellBackAnimation { if (mClosingTarget != null && mClosingTarget.leash != null) { transformWithProgress( mLeavingProgress, - Math.max( - 1 - smoothstep(0, ENTER_ALPHA_THRESHOLD, mLeavingProgress), - MIN_WINDOW_ALPHA), + getPreCommitLeavingAlpha(), mClosingTarget.leash, mClosingRect, 0, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java index 7a4ad0a56022..da530d740d48 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java @@ -53,8 +53,6 @@ import com.android.launcher3.icons.BubbleIconFactory; import com.android.wm.shell.bubbles.bar.BubbleBarExpandedView; import com.android.wm.shell.bubbles.bar.BubbleBarLayerView; import com.android.wm.shell.common.bubbles.BubbleInfo; -import com.android.wm.shell.taskview.TaskView; -import com.android.wm.shell.taskview.TaskViewTaskController; import java.io.PrintWriter; import java.util.List; @@ -403,13 +401,9 @@ public class Bubble implements BubbleViewProvider { * Returns the existing {@link #mBubbleTaskView} if it's not {@code null}. Otherwise a new * instance of {@link BubbleTaskView} is created. */ - public BubbleTaskView getOrCreateBubbleTaskView(Context context, BubbleController controller) { + public BubbleTaskView getOrCreateBubbleTaskView(BubbleTaskViewFactory taskViewFactory) { if (mBubbleTaskView == null) { - TaskViewTaskController taskViewTaskController = new TaskViewTaskController(context, - controller.getTaskOrganizer(), - controller.getTaskViewTransitions(), controller.getSyncTransactionQueue()); - TaskView taskView = new TaskView(context, taskViewTaskController); - mBubbleTaskView = new BubbleTaskView(taskView, controller.getMainExecutor()); + mBubbleTaskView = taskViewFactory.create(); } return mBubbleTaskView; } @@ -514,14 +508,18 @@ public class Bubble implements BubbleViewProvider { * * @param callback the callback to notify one the bubble is ready to be displayed. * @param context the context for the bubble. - * @param controller the bubble controller. + * @param expandedViewManager the bubble expanded view manager. + * @param taskViewFactory the task view factory used to create the task view for the bubble. + * @param positioner the bubble positioner. * @param stackView the view the bubble is added to, iff showing as floating. * @param layerView the layer the bubble is added to, iff showing in the bubble bar. - * @param iconFactory the icon factory use to create images for the bubble. + * @param iconFactory the icon factory used to create images for the bubble. */ void inflate(BubbleViewInfoTask.Callback callback, Context context, - BubbleController controller, + BubbleExpandedViewManager expandedViewManager, + BubbleTaskViewFactory taskViewFactory, + BubblePositioner positioner, @Nullable BubbleStackView stackView, @Nullable BubbleBarLayerView layerView, BubbleIconFactory iconFactory, @@ -531,7 +529,9 @@ public class Bubble implements BubbleViewProvider { } mInflationTask = new BubbleViewInfoTask(this, context, - controller, + expandedViewManager, + taskViewFactory, + positioner, stackView, layerView, iconFactory, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java index 0aa89598cd10..5c6f73f0a4a2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java @@ -113,6 +113,7 @@ import com.android.wm.shell.sysui.ShellCommandHandler; import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.taskview.TaskView; +import com.android.wm.shell.taskview.TaskViewTaskController; import com.android.wm.shell.taskview.TaskViewTransitions; import com.android.wm.shell.transition.Transitions; @@ -190,6 +191,8 @@ public class BubbleController implements ConfigurationChangeListener, private final ShellCommandHandler mShellCommandHandler; private final IWindowManager mWmService; private final BubbleProperties mBubbleProperties; + private final BubbleTaskViewFactory mBubbleTaskViewFactory; + private final BubbleExpandedViewManager mExpandedViewManager; // Used to post to main UI thread private final ShellExecutor mMainExecutor; @@ -333,6 +336,16 @@ public class BubbleController implements ConfigurationChangeListener, mWmService = wmService; mBubbleProperties = bubbleProperties; shellInit.addInitCallback(this::onInit, this); + mBubbleTaskViewFactory = new BubbleTaskViewFactory() { + @Override + public BubbleTaskView create() { + TaskViewTaskController taskViewTaskController = new TaskViewTaskController( + context, organizer, taskViewTransitions, syncQueue); + TaskView taskView = new TaskView(context, taskViewTaskController); + return new BubbleTaskView(taskView, mainExecutor); + } + }; + mExpandedViewManager = BubbleExpandedViewManager.fromBubbleController(this); } private void registerOneHandedState(OneHandedController oneHanded) { @@ -802,7 +815,13 @@ public class BubbleController implements ConfigurationChangeListener, try { mAddedToWindowManager = true; registerBroadcastReceiver(); - mBubbleData.getOverflow().initialize(this, isShowingAsBubbleBar()); + if (isShowingAsBubbleBar()) { + mBubbleData.getOverflow().initializeForBubbleBar( + mExpandedViewManager, mBubblePositioner); + } else { + mBubbleData.getOverflow().initialize( + mExpandedViewManager, mStackView, mBubblePositioner); + } // (TODO: b/273314541) some duplication in the inset listener if (isShowingAsBubbleBar()) { mWindowManager.addView(mLayerView, mWmLayoutParams); @@ -984,7 +1003,9 @@ public class BubbleController implements ConfigurationChangeListener, for (Bubble b : mBubbleData.getBubbles()) { b.inflate(null /* callback */, mContext, - this, + mExpandedViewManager, + mBubbleTaskViewFactory, + mBubblePositioner, mStackView, mLayerView, mBubbleIconFactory, @@ -993,7 +1014,9 @@ public class BubbleController implements ConfigurationChangeListener, for (Bubble b : mBubbleData.getOverflowBubbles()) { b.inflate(null /* callback */, mContext, - this, + mExpandedViewManager, + mBubbleTaskViewFactory, + mBubblePositioner, mStackView, mLayerView, mBubbleIconFactory, @@ -1377,7 +1400,9 @@ public class BubbleController implements ConfigurationChangeListener, bubble.inflate( (b) -> mBubbleData.overflowBubble(Bubbles.DISMISS_RELOAD_FROM_DISK, bubble), mContext, - this, + mExpandedViewManager, + mBubbleTaskViewFactory, + mBubblePositioner, mStackView, mLayerView, mBubbleIconFactory, @@ -1431,7 +1456,9 @@ public class BubbleController implements ConfigurationChangeListener, Bubble bubble = mBubbleData.getBubbles().get(i); bubble.inflate(callback, mContext, - this, + mExpandedViewManager, + mBubbleTaskViewFactory, + mBubblePositioner, mStackView, mLayerView, mBubbleIconFactory, @@ -1506,8 +1533,14 @@ public class BubbleController implements ConfigurationChangeListener, // Lazy init stack view when a bubble is created ensureBubbleViewsAndWindowCreated(); bubble.setInflateSynchronously(mInflateSynchronously); - bubble.inflate(b -> mBubbleData.notificationEntryUpdated(b, suppressFlyout, showInShade), - mContext, this, mStackView, mLayerView, + bubble.inflate( + b -> mBubbleData.notificationEntryUpdated(b, suppressFlyout, showInShade), + mContext, + mExpandedViewManager, + mBubbleTaskViewFactory, + mBubblePositioner, + mStackView, + mLayerView, mBubbleIconFactory, false /* skipInflation */); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java index 6d3f0c32bcbb..6c2f925119f3 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java @@ -37,10 +37,8 @@ import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.FrameworkStatsLog; -import com.android.launcher3.icons.BubbleIconFactory; import com.android.wm.shell.R; import com.android.wm.shell.bubbles.Bubbles.DismissReason; -import com.android.wm.shell.bubbles.bar.BubbleBarLayerView; import com.android.wm.shell.common.bubbles.BubbleBarUpdate; import com.android.wm.shell.common.bubbles.RemovedBubble; @@ -180,7 +178,7 @@ public class BubbleData { * This interface reports changes to the state and appearance of bubbles which should be applied * as necessary to the UI. */ - interface Listener { + public interface Listener { /** Reports changes have have occurred as a result of the most recent operation. */ void applyUpdate(Update update); } @@ -419,8 +417,10 @@ public class BubbleData { /** * When this method is called it is expected that all info in the bubble has completed loading. - * @see Bubble#inflate(BubbleViewInfoTask.Callback, Context, BubbleController, BubbleStackView, - * BubbleBarLayerView, BubbleIconFactory, boolean) + * @see Bubble#inflate(BubbleViewInfoTask.Callback, Context, BubbleExpandedViewManager, + * BubbleTaskViewFactory, BubblePositioner, BubbleStackView, + * com.android.wm.shell.bubbles.bar.BubbleBarLayerView, + * com.android.launcher3.icons.BubbleIconFactory, boolean) */ void notificationEntryUpdated(Bubble bubble, boolean suppressFlyout, boolean showInShade) { mPendingBubbles.remove(bubble.getKey()); // No longer pending once we're here diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java index 088660e4e8dc..df9ba63b4cc2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java @@ -184,7 +184,7 @@ public class BubbleExpandedView extends LinearLayout { private boolean mIsOverflow; private boolean mIsClipping; - private BubbleController mController; + private BubbleExpandedViewManager mManager; private BubbleStackView mStackView; private BubblePositioner mPositioner; @@ -261,7 +261,7 @@ public class BubbleExpandedView extends LinearLayout { // the bubble again so we'll just remove it. Log.w(TAG, "Exception while displaying bubble: " + getBubbleKey() + ", " + e.getMessage() + "; removing bubble"); - mController.removeBubble(getBubbleKey(), Bubbles.DISMISS_INVALID_INTENT); + mManager.removeBubble(getBubbleKey(), Bubbles.DISMISS_INVALID_INTENT); } }); mInitialized = true; @@ -281,7 +281,7 @@ public class BubbleExpandedView extends LinearLayout { if (mBubble != null && mBubble.isAppBubble()) { // Let the controller know sooner what the taskId is. - mController.setAppBubbleTaskId(mBubble.getKey(), mTaskId); + mManager.setAppBubbleTaskId(mBubble.getKey(), mTaskId); } // With the task org, the taskAppeared callback will only happen once the task has @@ -301,7 +301,7 @@ public class BubbleExpandedView extends LinearLayout { ProtoLog.d(WM_SHELL_BUBBLES, "onTaskRemovalStarted: taskId=%d bubble=%s", taskId, getBubbleKey()); if (mBubble != null) { - mController.removeBubble(mBubble.getKey(), Bubbles.DISMISS_TASK_FINISHED); + mManager.removeBubble(mBubble.getKey(), Bubbles.DISMISS_TASK_FINISHED); } if (mTaskView != null) { // Release the surface @@ -421,17 +421,20 @@ public class BubbleExpandedView extends LinearLayout { * Initialize {@link BubbleController} and {@link BubbleStackView} here, this method must need * to be called after view inflate. */ - void initialize(BubbleController controller, BubbleStackView stackView, boolean isOverflow, + void initialize(BubbleExpandedViewManager expandedViewManager, + BubbleStackView stackView, + BubblePositioner positioner, + boolean isOverflow, @Nullable BubbleTaskView bubbleTaskView) { - mController = controller; + mManager = expandedViewManager; mStackView = stackView; mIsOverflow = isOverflow; - mPositioner = mController.getPositioner(); + mPositioner = positioner; if (mIsOverflow) { mOverflowView = (BubbleOverflowContainerView) LayoutInflater.from(getContext()).inflate( R.layout.bubble_overflow_container, null /* root */); - mOverflowView.setBubbleController(mController); + mOverflowView.initialize(expandedViewManager, positioner); FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT); mExpandedViewContainer.addView(mOverflowView, lp); mExpandedViewContainer.setLayoutParams( diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedViewManager.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedViewManager.kt new file mode 100644 index 000000000000..b0d3cc4a5d5c --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedViewManager.kt @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2024 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.wm.shell.bubbles + +/** Manager interface for bubble expanded views. */ +interface BubbleExpandedViewManager { + + val overflowBubbles: List<Bubble> + fun setOverflowListener(listener: BubbleData.Listener) + fun collapseStack() + fun updateWindowFlagsForBackpress(intercept: Boolean) + fun promoteBubbleFromOverflow(bubble: Bubble) + fun removeBubble(key: String, reason: Int) + fun dismissBubble(bubble: Bubble, reason: Int) + fun setAppBubbleTaskId(key: String, taskId: Int) + fun isStackExpanded(): Boolean + fun isShowingAsBubbleBar(): Boolean + + companion object { + /** + * Convenience function for creating a [BubbleExpandedViewManager] that delegates to the + * given `controller`. + */ + @JvmStatic + fun fromBubbleController(controller: BubbleController): BubbleExpandedViewManager { + return object : BubbleExpandedViewManager { + + override val overflowBubbles: List<Bubble> + get() = controller.overflowBubbles + + override fun setOverflowListener(listener: BubbleData.Listener) { + controller.setOverflowListener(listener) + } + + override fun collapseStack() { + controller.collapseStack() + } + + override fun updateWindowFlagsForBackpress(intercept: Boolean) { + controller.updateWindowFlagsForBackpress(intercept) + } + + override fun promoteBubbleFromOverflow(bubble: Bubble) { + controller.promoteBubbleFromOverflow(bubble) + } + + override fun removeBubble(key: String, reason: Int) { + controller.removeBubble(key, reason) + } + + override fun dismissBubble(bubble: Bubble, reason: Int) { + controller.dismissBubble(bubble, reason) + } + + override fun setAppBubbleTaskId(key: String, taskId: Int) { + controller.setAppBubbleTaskId(key, taskId) + } + + override fun isStackExpanded(): Boolean = controller.isStackExpanded + + override fun isShowingAsBubbleBar(): Boolean = controller.isShowingAsBubbleBar + } + } + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt index e5d9acedc903..f32974e1765d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt @@ -56,19 +56,32 @@ class BubbleOverflow(private val context: Context, private val positioner: Bubbl } /** Call before use and again if cleanUpExpandedState was called. */ - fun initialize(controller: BubbleController, forBubbleBar: Boolean) { - if (forBubbleBar) { - createBubbleBarExpandedView() - .initialize(controller, /* isOverflow= */ true, /* bubbleTaskView= */ null) - } else { - createExpandedView() + fun initialize( + expandedViewManager: BubbleExpandedViewManager, + stackView: BubbleStackView, + positioner: BubblePositioner + ) { + createExpandedView() .initialize( - controller, - controller.stackView, + expandedViewManager, + stackView, + positioner, /* isOverflow= */ true, /* bubbleTaskView= */ null ) - } + } + + fun initializeForBubbleBar( + expandedViewManager: BubbleExpandedViewManager, + positioner: BubblePositioner + ) { + createBubbleBarExpandedView() + .initialize( + expandedViewManager, + positioner, + /* isOverflow= */ true, + /* bubbleTaskView= */ null + ) } fun cleanUpExpandedState() { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java index 70cdc82c47ad..b06de4f4002c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java @@ -62,7 +62,8 @@ public class BubbleOverflowContainerView extends LinearLayout { private ImageView mEmptyStateImage; private int mHorizontalMargin; private int mVerticalMargin; - private BubbleController mController; + private BubbleExpandedViewManager mExpandedViewManager; + private BubblePositioner mPositioner; private BubbleOverflowAdapter mAdapter; private RecyclerView mRecyclerView; private List<Bubble> mOverflowBubbles = new ArrayList<>(); @@ -70,7 +71,7 @@ public class BubbleOverflowContainerView extends LinearLayout { private View.OnKeyListener mKeyListener = (view, i, keyEvent) -> { if (keyEvent.getAction() == KeyEvent.ACTION_UP && keyEvent.getKeyCode() == KeyEvent.KEYCODE_BACK) { - mController.collapseStack(); + mExpandedViewManager.collapseStack(); return true; } return false; @@ -126,8 +127,11 @@ public class BubbleOverflowContainerView extends LinearLayout { setFocusableInTouchMode(true); } - public void setBubbleController(BubbleController controller) { - mController = controller; + /** Initializes the view. Must be called after creation. */ + public void initialize(BubbleExpandedViewManager expandedViewManager, + BubblePositioner positioner) { + mExpandedViewManager = expandedViewManager; + mPositioner = positioner; } public void show() { @@ -149,9 +153,9 @@ public class BubbleOverflowContainerView extends LinearLayout { @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - if (mController != null) { + if (mExpandedViewManager != null) { // For the overflow to get key events (e.g. back press) we need to adjust the flags - mController.updateWindowFlagsForBackpress(true); + mExpandedViewManager.updateWindowFlagsForBackpress(true); } setOnKeyListener(mKeyListener); } @@ -159,8 +163,8 @@ public class BubbleOverflowContainerView extends LinearLayout { @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - if (mController != null) { - mController.updateWindowFlagsForBackpress(false); + if (mExpandedViewManager != null) { + mExpandedViewManager.updateWindowFlagsForBackpress(false); } setOnKeyListener(null); } @@ -177,15 +181,15 @@ public class BubbleOverflowContainerView extends LinearLayout { mRecyclerView.addItemDecoration(new OverflowItemDecoration()); } mAdapter = new BubbleOverflowAdapter(getContext(), mOverflowBubbles, - mController::promoteBubbleFromOverflow, - mController.getPositioner()); + mExpandedViewManager::promoteBubbleFromOverflow, + mPositioner); mRecyclerView.setAdapter(mAdapter); mOverflowBubbles.clear(); - mOverflowBubbles.addAll(mController.getOverflowBubbles()); + mOverflowBubbles.addAll(mExpandedViewManager.getOverflowBubbles()); mAdapter.notifyDataSetChanged(); - mController.setOverflowListener(mDataListener); + mExpandedViewManager.setOverflowListener(mDataListener); updateEmptyStateVisibility(); updateTheme(); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewFactory.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewFactory.kt new file mode 100644 index 000000000000..230626f49c51 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewFactory.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2024 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.wm.shell.bubbles + +/** Factory for creating [BubbleTaskView]s. */ +fun interface BubbleTaskViewFactory { + /** Creates a new instance of [BubbleTaskView]. */ + fun create(): BubbleTaskView +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java index 530ec5a6c9fe..21b70b8e32da 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java @@ -62,7 +62,7 @@ public class BubbleTaskViewHelper { } private final Context mContext; - private final BubbleController mController; + private final BubbleExpandedViewManager mExpandedViewManager; private final BubbleTaskViewHelper.Listener mListener; private final View mParentView; @@ -142,7 +142,8 @@ public class BubbleTaskViewHelper { // the bubble again so we'll just remove it. Log.w(TAG, "Exception while displaying bubble: " + getBubbleKey() + ", " + e.getMessage() + "; removing bubble"); - mController.removeBubble(getBubbleKey(), Bubbles.DISMISS_INVALID_INTENT); + mExpandedViewManager.removeBubble( + getBubbleKey(), Bubbles.DISMISS_INVALID_INTENT); } mInitialized = true; }); @@ -175,7 +176,7 @@ public class BubbleTaskViewHelper { ProtoLog.d(WM_SHELL_BUBBLES, "onTaskRemovalStarted: taskId=%d bubble=%s", taskId, getBubbleKey()); if (mBubble != null) { - mController.removeBubble(mBubble.getKey(), Bubbles.DISMISS_TASK_FINISHED); + mExpandedViewManager.removeBubble(mBubble.getKey(), Bubbles.DISMISS_TASK_FINISHED); } if (mTaskView != null) { mTaskView.release(); @@ -186,19 +187,19 @@ public class BubbleTaskViewHelper { @Override public void onBackPressedOnTaskRoot(int taskId) { - if (mTaskId == taskId && mController.isStackExpanded()) { + if (mTaskId == taskId && mExpandedViewManager.isStackExpanded()) { mListener.onBackPressed(); } } }; public BubbleTaskViewHelper(Context context, - BubbleController controller, + BubbleExpandedViewManager expandedViewManager, BubbleTaskViewHelper.Listener listener, BubbleTaskView bubbleTaskView, View parent) { mContext = context; - mController = controller; + mExpandedViewManager = expandedViewManager; mListener = listener; mParentView = parent; mTaskView = bubbleTaskView.getTaskView(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java index 5fc10a9f6b69..69119cf4338e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java @@ -70,7 +70,9 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask private Bubble mBubble; private WeakReference<Context> mContext; - private WeakReference<BubbleController> mController; + private WeakReference<BubbleExpandedViewManager> mExpandedViewManager; + private WeakReference<BubbleTaskViewFactory> mTaskViewFactory; + private WeakReference<BubblePositioner> mPositioner; private WeakReference<BubbleStackView> mStackView; private WeakReference<BubbleBarLayerView> mLayerView; private BubbleIconFactory mIconFactory; @@ -84,7 +86,9 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask */ BubbleViewInfoTask(Bubble b, Context context, - BubbleController controller, + BubbleExpandedViewManager expandedViewManager, + BubbleTaskViewFactory taskViewFactory, + BubblePositioner positioner, @Nullable BubbleStackView stackView, @Nullable BubbleBarLayerView layerView, BubbleIconFactory factory, @@ -93,7 +97,9 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask Executor mainExecutor) { mBubble = b; mContext = new WeakReference<>(context); - mController = new WeakReference<>(controller); + mExpandedViewManager = new WeakReference<>(expandedViewManager); + mTaskViewFactory = new WeakReference<>(taskViewFactory); + mPositioner = new WeakReference<>(positioner); mStackView = new WeakReference<>(stackView); mLayerView = new WeakReference<>(layerView); mIconFactory = factory; @@ -109,11 +115,13 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask return null; } if (mLayerView.get() != null) { - return BubbleViewInfo.populateForBubbleBar(mContext.get(), mController.get(), - mLayerView.get(), mIconFactory, mBubble, mSkipInflation); + return BubbleViewInfo.populateForBubbleBar(mContext.get(), mExpandedViewManager.get(), + mTaskViewFactory.get(), mPositioner.get(), mLayerView.get(), mIconFactory, + mBubble, mSkipInflation); } else { - return BubbleViewInfo.populate(mContext.get(), mController.get(), mStackView.get(), - mIconFactory, mBubble, mSkipInflation); + return BubbleViewInfo.populate(mContext.get(), mExpandedViewManager.get(), + mTaskViewFactory.get(), mPositioner.get(), mStackView.get(), mIconFactory, + mBubble, mSkipInflation); } } @@ -135,7 +143,7 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask } private boolean verifyState() { - if (mController.get().isShowingAsBubbleBar()) { + if (mExpandedViewManager.get().isShowingAsBubbleBar()) { return mLayerView.get() != null; } else { return mStackView.get() != null; @@ -167,18 +175,23 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask Bitmap badgeBitmap; @Nullable - public static BubbleViewInfo populateForBubbleBar(Context c, BubbleController controller, - BubbleBarLayerView layerView, BubbleIconFactory iconFactory, Bubble b, + public static BubbleViewInfo populateForBubbleBar(Context c, + BubbleExpandedViewManager expandedViewManager, + BubbleTaskViewFactory taskViewFactory, + BubblePositioner positioner, + BubbleBarLayerView layerView, + BubbleIconFactory iconFactory, + Bubble b, boolean skipInflation) { BubbleViewInfo info = new BubbleViewInfo(); if (!skipInflation && !b.isInflated()) { - BubbleTaskView bubbleTaskView = b.getOrCreateBubbleTaskView(c, controller); + BubbleTaskView bubbleTaskView = b.getOrCreateBubbleTaskView(taskViewFactory); LayoutInflater inflater = LayoutInflater.from(c); info.bubbleBarExpandedView = (BubbleBarExpandedView) inflater.inflate( R.layout.bubble_bar_expanded_view, layerView, false /* attachToRoot */); info.bubbleBarExpandedView.initialize( - controller, false /* isOverflow */, bubbleTaskView); + expandedViewManager, positioner, false /* isOverflow */, bubbleTaskView); } if (!populateCommonInfo(info, c, b, iconFactory)) { @@ -191,8 +204,13 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask @VisibleForTesting @Nullable - public static BubbleViewInfo populate(Context c, BubbleController controller, - BubbleStackView stackView, BubbleIconFactory iconFactory, Bubble b, + public static BubbleViewInfo populate(Context c, + BubbleExpandedViewManager expandedViewManager, + BubbleTaskViewFactory taskViewFactory, + BubblePositioner positioner, + BubbleStackView stackView, + BubbleIconFactory iconFactory, + Bubble b, boolean skipInflation) { BubbleViewInfo info = new BubbleViewInfo(); @@ -201,13 +219,14 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask LayoutInflater inflater = LayoutInflater.from(c); info.imageView = (BadgedImageView) inflater.inflate( R.layout.bubble_view, stackView, false /* attachToRoot */); - info.imageView.initialize(controller.getPositioner()); + info.imageView.initialize(positioner); - BubbleTaskView bubbleTaskView = b.getOrCreateBubbleTaskView(c, controller); + BubbleTaskView bubbleTaskView = b.getOrCreateBubbleTaskView(taskViewFactory); info.expandedView = (BubbleExpandedView) inflater.inflate( R.layout.bubble_expanded_view, stackView, false /* attachToRoot */); info.expandedView.initialize( - controller, stackView, false /* isOverflow */, bubbleTaskView); + expandedViewManager, stackView, positioner, false /* isOverflow */, + bubbleTaskView); } if (!populateCommonInfo(info, c, b, iconFactory)) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java index 73a9cf456a6e..ebb8e3e2d207 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java @@ -36,8 +36,9 @@ import android.widget.FrameLayout; import com.android.internal.policy.ScreenDecorationsUtils; import com.android.wm.shell.R; import com.android.wm.shell.bubbles.Bubble; -import com.android.wm.shell.bubbles.BubbleController; +import com.android.wm.shell.bubbles.BubbleExpandedViewManager; import com.android.wm.shell.bubbles.BubbleOverflowContainerView; +import com.android.wm.shell.bubbles.BubblePositioner; import com.android.wm.shell.bubbles.BubbleTaskView; import com.android.wm.shell.bubbles.BubbleTaskViewHelper; import com.android.wm.shell.bubbles.Bubbles; @@ -45,11 +46,7 @@ import com.android.wm.shell.taskview.TaskView; import java.util.function.Supplier; -/** - * Expanded view of a bubble when it's part of the bubble bar. - * - * {@link BubbleController#isShowingAsBubbleBar()} - */ +/** Expanded view of a bubble when it's part of the bubble bar. */ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskViewHelper.Listener { /** * The expanded view listener notifying the {@link BubbleBarLayerView} about the internal @@ -67,7 +64,7 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView private static final String TAG = BubbleBarExpandedView.class.getSimpleName(); private static final int INVALID_TASK_ID = -1; - private BubbleController mController; + private BubbleExpandedViewManager mManager; private boolean mIsOverflow; private BubbleTaskViewHelper mBubbleTaskViewHelper; private BubbleBarMenuViewController mMenuViewController; @@ -133,20 +130,22 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView mMenuViewController.hideMenu(false /* animated */); } - /** Set the BubbleController on the view, must be called before doing anything else. */ - public void initialize(BubbleController controller, boolean isOverflow, + /** Initializes the view, must be called before doing anything else. */ + public void initialize(BubbleExpandedViewManager expandedViewManager, + BubblePositioner positioner, + boolean isOverflow, @Nullable BubbleTaskView bubbleTaskView) { - mController = controller; + mManager = expandedViewManager; mIsOverflow = isOverflow; if (mIsOverflow) { mOverflowView = (BubbleOverflowContainerView) LayoutInflater.from(getContext()).inflate( R.layout.bubble_overflow_container, null /* root */); - mOverflowView.setBubbleController(mController); + mOverflowView.initialize(expandedViewManager, positioner); addView(mOverflowView); } else { mTaskView = bubbleTaskView.getTaskView(); - mBubbleTaskViewHelper = new BubbleTaskViewHelper(mContext, mController, + mBubbleTaskViewHelper = new BubbleTaskViewHelper(mContext, expandedViewManager, /* listener= */ this, bubbleTaskView, /* viewParent= */ this); if (mTaskView.getParent() != null) { @@ -178,13 +177,13 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView @Override public void onOpenAppSettings(Bubble bubble) { - mController.collapseStack(); + mManager.collapseStack(); mContext.startActivityAsUser(bubble.getSettingsIntent(mContext), bubble.getUser()); } @Override public void onDismissBubble(Bubble bubble) { - mController.dismissBubble(bubble, Bubbles.DISMISS_USER_REMOVED); + mManager.dismissBubble(bubble, Bubbles.DISMISS_USER_REMOVED); } }); mHandleView.setOnClickListener(view -> { @@ -279,7 +278,7 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView if (mMenuViewController.isMenuVisible()) { mMenuViewController.hideMenu(/* animated = */ true); } else { - mController.collapseStack(); + mManager.collapseStack(); } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleOverflowTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleOverflowTest.java index f5b0174642d1..094af9652ea3 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleOverflowTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleOverflowTest.java @@ -18,7 +18,6 @@ package com.android.wm.shell.bubbles; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.testing.AndroidTestingRunner; @@ -45,18 +44,22 @@ public class BubbleOverflowTest extends ShellTestCase { private TestableBubblePositioner mPositioner; private BubbleOverflow mOverflow; + private BubbleExpandedViewManager mExpandedViewManager; @Mock private BubbleController mBubbleController; + @Mock + private BubbleStackView mBubbleStackView; @Before - public void setUp() throws Exception { + public void setUp() { MockitoAnnotations.initMocks(this); + mExpandedViewManager = BubbleExpandedViewManager.fromBubbleController(mBubbleController); mPositioner = new TestableBubblePositioner(mContext, mContext.getSystemService(WindowManager.class)); when(mBubbleController.getPositioner()).thenReturn(mPositioner); - when(mBubbleController.getStackView()).thenReturn(mock(BubbleStackView.class)); + when(mBubbleController.getStackView()).thenReturn(mBubbleStackView); mOverflow = new BubbleOverflow(mContext, mPositioner); } @@ -65,7 +68,7 @@ public class BubbleOverflowTest extends ShellTestCase { public void test_initialize_forStack() { assertThat(mOverflow.getExpandedView()).isNull(); - mOverflow.initialize(mBubbleController, /* forBubbleBar= */ false); + mOverflow.initialize(mExpandedViewManager, mBubbleStackView, mPositioner); assertThat(mOverflow.getExpandedView()).isNotNull(); assertThat(mOverflow.getExpandedView().getBubbleKey()).isEqualTo(BubbleOverflow.KEY); @@ -74,7 +77,7 @@ public class BubbleOverflowTest extends ShellTestCase { @Test public void test_initialize_forBubbleBar() { - mOverflow.initialize(mBubbleController, /* forBubbleBar= */ true); + mOverflow.initializeForBubbleBar(mExpandedViewManager, mPositioner); assertThat(mOverflow.getBubbleBarExpandedView()).isNotNull(); assertThat(mOverflow.getExpandedView()).isNull(); @@ -82,11 +85,10 @@ public class BubbleOverflowTest extends ShellTestCase { @Test public void test_cleanUpExpandedState() { - mOverflow.initialize(mBubbleController, /* forBubbleBar= */ false); + mOverflow.initialize(mExpandedViewManager, mBubbleStackView, mPositioner); assertThat(mOverflow.getExpandedView()).isNotNull(); mOverflow.cleanUpExpandedState(); assertThat(mOverflow.getExpandedView()).isNull(); } - } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt index 1668e3712462..ae39fbcb4eed 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt @@ -44,6 +44,7 @@ import com.android.wm.shell.common.TaskStackListenerImpl import com.android.wm.shell.sysui.ShellCommandHandler import com.android.wm.shell.sysui.ShellController import com.android.wm.shell.sysui.ShellInit +import com.android.wm.shell.taskview.TaskView import com.android.wm.shell.taskview.TaskViewTransitions import com.android.wm.shell.transition.Transitions import com.google.common.truth.Truth.assertThat @@ -55,6 +56,7 @@ import org.mockito.kotlin.doThrow import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.whenever +import java.util.concurrent.Executor /** Tests for loading / inflating views & icons for a bubble. */ @SmallTest @@ -65,11 +67,16 @@ class BubbleViewInfoTest : ShellTestCase() { private lateinit var metadataFlagListener: Bubbles.BubbleMetadataFlagListener private lateinit var iconFactory: BubbleIconFactory private lateinit var bubble: Bubble - private lateinit var bubbleController: BubbleController private lateinit var mainExecutor: ShellExecutor private lateinit var bubbleStackView: BubbleStackView private lateinit var bubbleBarLayerView: BubbleBarLayerView + private lateinit var bubblePositioner: BubblePositioner + private lateinit var expandedViewManager: BubbleExpandedViewManager + + private val bubbleTaskViewFactory = BubbleTaskViewFactory { + BubbleTaskView(mock<TaskView>(), mock<Executor>()) + } @Before fun setup() { @@ -88,7 +95,7 @@ class BubbleViewInfoTest : ShellTestCase() { val shellInit = ShellInit(mainExecutor) val shellCommandHandler = ShellCommandHandler() val shellController = ShellController(context, shellInit, shellCommandHandler, mainExecutor) - val bubblePositioner = BubblePositioner(context, windowManager) + bubblePositioner = BubblePositioner(context, windowManager) val bubbleData = BubbleData( context, @@ -143,6 +150,7 @@ class BubbleViewInfoTest : ShellTestCase() { bubbleController, mainExecutor ) + expandedViewManager = BubbleExpandedViewManager.fromBubbleController(bubbleController) bubbleBarLayerView = BubbleBarLayerView(context, bubbleController, bubbleData) } @@ -152,7 +160,9 @@ class BubbleViewInfoTest : ShellTestCase() { val info = BubbleViewInfoTask.BubbleViewInfo.populate( context, - bubbleController, + expandedViewManager, + bubbleTaskViewFactory, + bubblePositioner, bubbleStackView, iconFactory, bubble, @@ -178,7 +188,9 @@ class BubbleViewInfoTest : ShellTestCase() { val info = BubbleViewInfoTask.BubbleViewInfo.populateForBubbleBar( context, - bubbleController, + expandedViewManager, + bubbleTaskViewFactory, + bubblePositioner, bubbleBarLayerView, iconFactory, bubble, @@ -212,7 +224,9 @@ class BubbleViewInfoTest : ShellTestCase() { val info = BubbleViewInfoTask.BubbleViewInfo.populateForBubbleBar( context, - bubbleController, + expandedViewManager, + bubbleTaskViewFactory, + bubblePositioner, bubbleBarLayerView, iconFactory, bubble, diff --git a/libs/hwui/apex/android_paint.cpp b/libs/hwui/apex/android_paint.cpp index cc79cba5e19c..5e73e7628568 100644 --- a/libs/hwui/apex/android_paint.cpp +++ b/libs/hwui/apex/android_paint.cpp @@ -14,12 +14,13 @@ * limitations under the License. */ -#include "android/graphics/paint.h" +#include <SkBlendMode.h> +#include <SkImageFilter.h> +#include <hwui/Paint.h> #include "TypeCast.h" - -#include <hwui/Paint.h> -#include <SkBlendMode.h> +#include "android/graphics/paint.h" +#include "include/effects/SkImageFilters.h" using namespace android; @@ -43,6 +44,22 @@ static SkBlendMode convertBlendMode(ABlendMode blendMode) { } } +static sk_sp<SkImageFilter> convertImageFilter(AImageFilter imageFilter) { + switch (imageFilter) { + case AIMAGE_FILTER_DROP_SHADOW_FOR_POINTER_ICON: + // Material Elevation Level 1 Drop Shadow. + sk_sp<SkImageFilter> key_shadow = SkImageFilters::DropShadow( + 0.0f, 1.0f, 2.0f, 2.0f, SkColorSetARGB(0x4D, 0x00, 0x00, 0x00), nullptr); + sk_sp<SkImageFilter> ambient_shadow = SkImageFilters::DropShadow( + 0.0f, 1.0f, 3.0f, 3.0f, SkColorSetARGB(0x26, 0x00, 0x00, 0x00), nullptr); + return SkImageFilters::Compose(ambient_shadow, key_shadow); + } +} + void APaint_setBlendMode(APaint* paint, ABlendMode blendMode) { TypeCast::toPaint(paint)->setBlendMode(convertBlendMode(blendMode)); } + +void APaint_setImageFilter(APaint* paint, AImageFilter imageFilter) { + TypeCast::toPaint(paint)->setImageFilter(convertImageFilter(imageFilter)); +} diff --git a/libs/hwui/apex/include/android/graphics/paint.h b/libs/hwui/apex/include/android/graphics/paint.h index 058db8d37619..36b7575d585d 100644 --- a/libs/hwui/apex/include/android/graphics/paint.h +++ b/libs/hwui/apex/include/android/graphics/paint.h @@ -26,6 +26,14 @@ __BEGIN_DECLS */ typedef struct APaint APaint; +/** + * Predefined Image filter type. + */ +enum AImageFilter { + /** Drop shadow image filter for PointerIcons. */ + AIMAGE_FILTER_DROP_SHADOW_FOR_POINTER_ICON = 0, +}; + /** Bitmap pixel format. */ enum ABlendMode { /** replaces destination with zero: fully transparent */ @@ -42,6 +50,8 @@ ANDROID_API void APaint_destroyPaint(APaint* paint); ANDROID_API void APaint_setBlendMode(APaint* paint, ABlendMode blendMode); +ANDROID_API void APaint_setImageFilter(APaint* paint, AImageFilter imageFilter); + __END_DECLS #ifdef __cplusplus @@ -54,6 +64,10 @@ namespace graphics { void setBlendMode(ABlendMode blendMode) { APaint_setBlendMode(mPaint, blendMode); } + void setImageFilter(AImageFilter imageFilter) { + APaint_setImageFilter(mPaint, imageFilter); + } + const APaint& get() const { return *mPaint; } private: diff --git a/libs/hwui/libhwui.map.txt b/libs/hwui/libhwui.map.txt index fdb237387098..d03ceb471d6c 100644 --- a/libs/hwui/libhwui.map.txt +++ b/libs/hwui/libhwui.map.txt @@ -32,6 +32,7 @@ LIBHWUI { # platform-only /* HWUI isn't current a module, so all of these are st APaint_createPaint; APaint_destroyPaint; APaint_setBlendMode; + APaint_setImageFilter; ARegionIterator_acquireIterator; ARegionIterator_releaseIterator; ARegionIterator_isComplex; diff --git a/libs/input/SpriteIcon.cpp b/libs/input/SpriteIcon.cpp index b7e51e22a214..59e36e4b0d1e 100644 --- a/libs/input/SpriteIcon.cpp +++ b/libs/input/SpriteIcon.cpp @@ -34,6 +34,9 @@ bool SpriteIcon::draw(sp<Surface> surface) const { graphics::Paint paint; paint.setBlendMode(ABLEND_MODE_SRC); + if (drawNativeDropShadow) { + paint.setImageFilter(AIMAGE_FILTER_DROP_SHADOW_FOR_POINTER_ICON); + } graphics::Canvas canvas(outBuffer, (int32_t)surface->getBuffersDataSpace()); canvas.drawBitmap(bitmap, 0, 0, &paint); diff --git a/libs/input/SpriteIcon.h b/libs/input/SpriteIcon.h index 5f085bbd2374..9e6cc81f0bb4 100644 --- a/libs/input/SpriteIcon.h +++ b/libs/input/SpriteIcon.h @@ -29,16 +29,22 @@ namespace android { struct SpriteIcon { inline SpriteIcon() : style(PointerIconStyle::TYPE_NULL), hotSpotX(0), hotSpotY(0) {} inline SpriteIcon(const graphics::Bitmap& bitmap, PointerIconStyle style, float hotSpotX, - float hotSpotY) - : bitmap(bitmap), style(style), hotSpotX(hotSpotX), hotSpotY(hotSpotY) {} + float hotSpotY, bool drawNativeDropShadow) + : bitmap(bitmap), + style(style), + hotSpotX(hotSpotX), + hotSpotY(hotSpotY), + drawNativeDropShadow(drawNativeDropShadow) {} graphics::Bitmap bitmap; PointerIconStyle style; float hotSpotX; float hotSpotY; + bool drawNativeDropShadow; inline SpriteIcon copy() const { - return SpriteIcon(bitmap.copy(ANDROID_BITMAP_FORMAT_RGBA_8888), style, hotSpotX, hotSpotY); + return SpriteIcon(bitmap.copy(ANDROID_BITMAP_FORMAT_RGBA_8888), style, hotSpotX, hotSpotY, + drawNativeDropShadow); } inline void reset() { @@ -46,6 +52,7 @@ struct SpriteIcon { style = PointerIconStyle::TYPE_NULL; hotSpotX = 0; hotSpotY = 0; + drawNativeDropShadow = false; } inline bool isValid() const { return bitmap.isValid() && !bitmap.isEmpty(); } |