summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/service/selectiontoolbar/DefaultSelectionToolbarRenderService.java100
-rw-r--r--core/java/android/service/selectiontoolbar/FloatingToolbarRoot.java61
-rw-r--r--core/java/android/service/selectiontoolbar/ISelectionToolbarRenderService.aidl5
-rw-r--r--core/java/android/service/selectiontoolbar/ISelectionToolbarRenderServiceCallback.aidl (renamed from core/java/android/view/selectiontoolbar/SelectionContext.aidl)12
-rw-r--r--core/java/android/service/selectiontoolbar/RemoteSelectionToolbar.java632
-rw-r--r--core/java/android/service/selectiontoolbar/SelectionToolbarRenderCallback.java12
-rw-r--r--core/java/android/service/selectiontoolbar/SelectionToolbarRenderService.java119
-rw-r--r--core/java/android/view/selectiontoolbar/ISelectionToolbarCallback.aidl3
-rw-r--r--core/java/android/view/selectiontoolbar/SelectionContext.java248
-rw-r--r--core/java/android/view/selectiontoolbar/SelectionToolbarManager.java10
-rw-r--r--core/java/android/view/selectiontoolbar/ShowInfo.java185
-rw-r--r--core/java/android/view/selectiontoolbar/ToolbarMenuItem.java350
-rw-r--r--core/java/android/view/selectiontoolbar/WidgetInfo.java78
13 files changed, 1045 insertions, 770 deletions
diff --git a/core/java/android/service/selectiontoolbar/DefaultSelectionToolbarRenderService.java b/core/java/android/service/selectiontoolbar/DefaultSelectionToolbarRenderService.java
index c452e0615685..08a720555833 100644
--- a/core/java/android/service/selectiontoolbar/DefaultSelectionToolbarRenderService.java
+++ b/core/java/android/service/selectiontoolbar/DefaultSelectionToolbarRenderService.java
@@ -16,12 +16,21 @@
package android.service.selectiontoolbar;
-import android.util.Log;
+import static android.view.selectiontoolbar.SelectionToolbarManager.ERROR_DO_NOT_ALLOW_MULTIPLE_TOOL_BAR;
+import static android.view.selectiontoolbar.SelectionToolbarManager.NO_TOOLBAR_ID;
+
+import android.util.Pair;
+import android.util.Slog;
+import android.util.SparseArray;
import android.view.selectiontoolbar.ShowInfo;
+import java.util.UUID;
+
/**
* The default implementation of {@link SelectionToolbarRenderService}.
*
+ * <p><b>NOTE:<b/> The requests are handled on the service main thread.
+ *
* @hide
*/
// TODO(b/214122495): fix class not found then move to system service folder
@@ -29,22 +38,97 @@ public final class DefaultSelectionToolbarRenderService extends SelectionToolbar
private static final String TAG = "DefaultSelectionToolbarRenderService";
+ // TODO(b/215497659): handle remove if the client process dies.
+ // Only show one toolbar, dismiss the old ones and remove from cache
+ private final SparseArray<Pair<Long, RemoteSelectionToolbar>> mToolbarCache =
+ new SparseArray<>();
+
+ /**
+ * Only allow one package to create one toolbar.
+ */
+ private boolean canShowToolbar(int uid, ShowInfo showInfo) {
+ if (showInfo.getWidgetToken() != NO_TOOLBAR_ID) {
+ return true;
+ }
+ return mToolbarCache.indexOfKey(uid) < 0;
+ }
+
@Override
- public void onShow(ShowInfo showInfo,
+ public void onShow(int callingUid, ShowInfo showInfo,
SelectionToolbarRenderService.RemoteCallbackWrapper callbackWrapper) {
- // TODO: Add implementation
- Log.w(TAG, "onShow()");
+ if (!canShowToolbar(callingUid, showInfo)) {
+ Slog.e(TAG, "Do not allow multiple toolbar for the app.");
+ callbackWrapper.onError(ERROR_DO_NOT_ALLOW_MULTIPLE_TOOL_BAR);
+ return;
+ }
+ long widgetToken = showInfo.getWidgetToken() == NO_TOOLBAR_ID
+ ? UUID.randomUUID().getMostSignificantBits()
+ : showInfo.getWidgetToken();
+
+ if (mToolbarCache.indexOfKey(callingUid) < 0) {
+ RemoteSelectionToolbar toolbar = new RemoteSelectionToolbar(this,
+ widgetToken, showInfo.getHostInputToken(),
+ callbackWrapper, this::transferTouch);
+ mToolbarCache.put(callingUid, new Pair<>(widgetToken, toolbar));
+ }
+ Slog.v(TAG, "onShow() for " + widgetToken);
+ Pair<Long, RemoteSelectionToolbar> toolbarPair = mToolbarCache.get(callingUid);
+ if (toolbarPair.first == widgetToken) {
+ toolbarPair.second.show(showInfo);
+ } else {
+ Slog.w(TAG, "onShow() for unknown " + widgetToken);
+ }
}
@Override
public void onHide(long widgetToken) {
- // TODO: Add implementation
- Log.w(TAG, "onHide()");
+ RemoteSelectionToolbar toolbar = getRemoteSelectionToolbarByTokenLocked(widgetToken);
+ if (toolbar != null) {
+ Slog.v(TAG, "onHide() for " + widgetToken);
+ toolbar.hide(widgetToken);
+ }
}
@Override
public void onDismiss(long widgetToken) {
- // TODO: Add implementation
- Log.w(TAG, "onDismiss()");
+ RemoteSelectionToolbar toolbar = getRemoteSelectionToolbarByTokenLocked(widgetToken);
+ if (toolbar != null) {
+ Slog.v(TAG, "onDismiss() for " + widgetToken);
+ toolbar.dismiss(widgetToken);
+ removeRemoteSelectionToolbarByTokenLocked(widgetToken);
+ }
+ }
+
+ @Override
+ public void onToolbarShowTimeout(int callingUid) {
+ Slog.w(TAG, "onToolbarShowTimeout for callingUid = " + callingUid);
+ Pair<Long, RemoteSelectionToolbar> toolbarPair = mToolbarCache.get(callingUid);
+ if (toolbarPair != null) {
+ RemoteSelectionToolbar remoteToolbar = toolbarPair.second;
+ remoteToolbar.dismiss(toolbarPair.first);
+ remoteToolbar.onToolbarShowTimeout();
+ mToolbarCache.remove(callingUid);
+ }
+ }
+
+ private RemoteSelectionToolbar getRemoteSelectionToolbarByTokenLocked(long widgetToken) {
+ for (int i = 0; i < mToolbarCache.size(); i++) {
+ Pair<Long, RemoteSelectionToolbar> toolbarPair = mToolbarCache.valueAt(i);
+ if (toolbarPair.first == widgetToken) {
+ return toolbarPair.second;
+ }
+ }
+ return null;
+ }
+
+ private void removeRemoteSelectionToolbarByTokenLocked(long widgetToken) {
+ for (int i = 0; i < mToolbarCache.size(); i++) {
+ Pair<Long, RemoteSelectionToolbar> toolbarPair = mToolbarCache.valueAt(i);
+ if (toolbarPair.first == widgetToken) {
+ mToolbarCache.remove(mToolbarCache.keyAt(i));
+ return;
+ }
+ }
}
}
+
diff --git a/core/java/android/service/selectiontoolbar/FloatingToolbarRoot.java b/core/java/android/service/selectiontoolbar/FloatingToolbarRoot.java
new file mode 100644
index 000000000000..5e4262b970eb
--- /dev/null
+++ b/core/java/android/service/selectiontoolbar/FloatingToolbarRoot.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2022 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 android.service.selectiontoolbar;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.os.IBinder;
+import android.view.MotionEvent;
+import android.widget.LinearLayout;
+
+/**
+ * This class is the root view for the selection toolbar. It is responsible for
+ * detecting the click on the item and to also transfer input focus to the application.
+ *
+ * @hide
+ */
+@SuppressLint("ViewConstructor")
+public class FloatingToolbarRoot extends LinearLayout {
+
+ private final IBinder mTargetInputToken;
+ private final SelectionToolbarRenderService.TransferTouchListener mTransferTouchListener;
+ private float mDownX;
+ private float mDownY;
+
+ public FloatingToolbarRoot(Context context, IBinder targetInputToken,
+ SelectionToolbarRenderService.TransferTouchListener transferTouchListener) {
+ super(context);
+ mTargetInputToken = targetInputToken;
+ mTransferTouchListener = transferTouchListener;
+ setFocusable(false);
+ }
+
+ @Override
+ @SuppressLint("ClickableViewAccessibility")
+ public boolean dispatchTouchEvent(MotionEvent event) {
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN: {
+ mDownX = event.getX();
+ mDownY = event.getY();
+ // TODO: Check x, y if we need to transfer touch focus to application
+ //mTransferTouchListener.onTransferTouch(getViewRootImpl().getInputToken(),
+ // mTargetInputToken);
+ }
+ }
+ return super.dispatchTouchEvent(event);
+ }
+}
diff --git a/core/java/android/service/selectiontoolbar/ISelectionToolbarRenderService.aidl b/core/java/android/service/selectiontoolbar/ISelectionToolbarRenderService.aidl
index 2bd99acbf24a..79281b8b361d 100644
--- a/core/java/android/service/selectiontoolbar/ISelectionToolbarRenderService.aidl
+++ b/core/java/android/service/selectiontoolbar/ISelectionToolbarRenderService.aidl
@@ -25,7 +25,8 @@ import android.view.selectiontoolbar.ShowInfo;
* @hide
*/
oneway interface ISelectionToolbarRenderService {
- void onShow(in ShowInfo showInfo, in ISelectionToolbarCallback callback);
+ void onConnected(in IBinder callback);
+ void onShow(int callingUid, in ShowInfo showInfo, in ISelectionToolbarCallback callback);
void onHide(long widgetToken);
- void onDismiss(long widgetToken);
+ void onDismiss(int callingUid, long widgetToken);
}
diff --git a/core/java/android/view/selectiontoolbar/SelectionContext.aidl b/core/java/android/service/selectiontoolbar/ISelectionToolbarRenderServiceCallback.aidl
index 52068312d4a1..f6c47ddf1e00 100644
--- a/core/java/android/view/selectiontoolbar/SelectionContext.aidl
+++ b/core/java/android/service/selectiontoolbar/ISelectionToolbarRenderServiceCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -14,9 +14,15 @@
* limitations under the License.
*/
-package android.view.selectiontoolbar;
+package android.service.selectiontoolbar;
+
+import android.os.IBinder;
/**
+ * The interface from the SelectionToolbarRenderService to the system.
+ *
* @hide
*/
-parcelable SelectionContext;
+oneway interface ISelectionToolbarRenderServiceCallback {
+ void transferTouch(in IBinder source, in IBinder target);
+}
diff --git a/core/java/android/service/selectiontoolbar/RemoteSelectionToolbar.java b/core/java/android/service/selectiontoolbar/RemoteSelectionToolbar.java
index 95ecc4e16446..cbe232b7b39a 100644
--- a/core/java/android/service/selectiontoolbar/RemoteSelectionToolbar.java
+++ b/core/java/android/service/selectiontoolbar/RemoteSelectionToolbar.java
@@ -21,72 +21,63 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
-import android.annotation.Nullable;
import android.content.Context;
import android.content.res.TypedArray;
-import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
-import android.graphics.Region;
import android.graphics.drawable.AnimatedVectorDrawable;
-import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.os.IBinder;
import android.text.TextUtils;
+import android.util.Log;
import android.util.Size;
import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.LayoutInflater;
-import android.view.MenuItem;
import android.view.MotionEvent;
+import android.view.SurfaceControlViewHost;
import android.view.View;
-import android.view.View.MeasureSpec;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
-import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.view.animation.Transformation;
+import android.view.selectiontoolbar.ShowInfo;
+import android.view.selectiontoolbar.ToolbarMenuItem;
+import android.view.selectiontoolbar.WidgetInfo;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
-import android.widget.PopupWindow;
import android.widget.TextView;
import com.android.internal.R;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
-import com.android.internal.widget.floatingtoolbar.FloatingToolbarPopup;
+import com.android.internal.widget.floatingtoolbar.FloatingToolbar;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
import java.util.Objects;
/**
- * A popup window used by the floating toolbar to render menu items in the local app process.
+ * This class is responsible for rendering/animation of the selection toolbar in the remote
+ * system process. It holds 2 panels (i.e. main panel and overflow panel) and an overflow
+ * button to transition between panels.
*
- * This class is responsible for the rendering/animation of the floating toolbar.
- * It holds 2 panels (i.e. main panel and overflow panel) and an overflow button
- * to transition between panels.
+ * @hide
*/
-
-final class RemoteSelectionToolbar implements FloatingToolbarPopup {
+// TODO(b/215497659): share code with LocalFloatingToolbarPopup
+final class RemoteSelectionToolbar {
+ private static final String TAG = "RemoteSelectionToolbar";
/* Minimum and maximum number of items allowed in the overflow. */
private static final int MIN_OVERFLOW_SIZE = 2;
private static final int MAX_OVERFLOW_SIZE = 4;
private final Context mContext;
- private final View mParent; // Parent for the popup window.
- private final PopupWindow mPopupWindow;
/* Margins between the popup window and its content. */
private final int mMarginHorizontal;
@@ -121,23 +112,22 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
private final Animation.AnimationListener mOverflowAnimationListener;
private final Rect mViewPortOnScreen = new Rect(); // portion of screen we can draw in.
- private final Point mCoordsOnWindow = new Point(); // popup window coordinates.
- /* Temporary data holders. Reset values before using. */
- private final int[] mTmpCoords = new int[2];
-
- private final Region mTouchableRegion = new Region();
- private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer =
- info -> {
- info.contentInsets.setEmpty();
- info.visibleInsets.setEmpty();
- info.touchableRegion.set(mTouchableRegion);
- info.setTouchableInsets(
- ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
- };
private final int mLineHeight;
private final int mIconTextSpacing;
+ private final long mSelectionToolbarToken;
+ private IBinder mHostInputToken;
+ private final SelectionToolbarRenderService.RemoteCallbackWrapper mCallbackWrapper;
+ private final SelectionToolbarRenderService.TransferTouchListener mTransferTouchListener;
+ private int mPopupWidth;
+ private int mPopupHeight;
+ // Coordinates to show the toolbar relative to the specified view port
+ private final Point mRelativeCoordsForToolbar = new Point();
+ private List<ToolbarMenuItem> mMenuItems;
+ private SurfaceControlViewHost mSurfaceControlViewHost;
+ private SurfaceControlViewHost.SurfacePackage mSurfacePackage;
+
/**
* @see OverflowPanelViewHelper#preparePopupContent().
*/
@@ -145,7 +135,6 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
@Override
public void run() {
setPanelsStatesAtRestingPosition();
- setContentAreaAsTouchableSurface();
mContentContainer.setAlpha(1);
}
};
@@ -159,26 +148,7 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
private Size mMainPanelSize;
/* Menu items and click listeners */
- private final Map<MenuItemRepr, MenuItem> mMenuItems = new LinkedHashMap<>();
- private MenuItem.OnMenuItemClickListener mOnMenuItemClickListener;
- private final View.OnClickListener mMenuItemButtonOnClickListener =
- new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mOnMenuItemClickListener == null) {
- return;
- }
- final Object tag = v.getTag();
- if (!(tag instanceof MenuItemRepr)) {
- return;
- }
- final MenuItem menuItem = mMenuItems.get((MenuItemRepr) tag);
- if (menuItem == null) {
- return;
- }
- mOnMenuItemClickListener.onMenuItemClick(menuItem);
- }
- };
+ private final View.OnClickListener mMenuItemButtonOnClickListener;
private boolean mOpenOverflowUpwards; // Whether the overflow opens upwards or downwards.
private boolean mIsOverflowOpen;
@@ -186,27 +156,26 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
private int mTransitionDurationScale; // Used to scale the toolbar transition duration.
private final Rect mPreviousContentRect = new Rect();
- private int mSuggestedWidth;
- private boolean mWidthChanged = true;
- /**
- * Initializes a new floating toolbar popup.
- *
- * @param parent A parent view to get the {@link android.view.View#getWindowToken()} token
- * from.
- */
- RemoteSelectionToolbar(Context context, View parent) {
- mParent = Objects.requireNonNull(parent);
+ private final Rect mTempContentRect = new Rect();
+
+ RemoteSelectionToolbar(Context context, long selectionToolbarToken, IBinder hostInputToken,
+ SelectionToolbarRenderService.RemoteCallbackWrapper callbackWrapper,
+ SelectionToolbarRenderService.TransferTouchListener transferTouchListener) {
mContext = applyDefaultTheme(context);
+ mSelectionToolbarToken = selectionToolbarToken;
+ mCallbackWrapper = callbackWrapper;
+ mTransferTouchListener = transferTouchListener;
+ mHostInputToken = hostInputToken;
+
mContentContainer = createContentContainer(mContext);
- mPopupWindow = createPopupWindow(mContentContainer);
- mMarginHorizontal = parent.getResources()
+ mMarginHorizontal = mContext.getResources()
.getDimensionPixelSize(R.dimen.floating_toolbar_horizontal_margin);
- mMarginVertical = parent.getResources()
+ mMarginVertical = mContext.getResources()
.getDimensionPixelSize(R.dimen.floating_toolbar_vertical_margin);
- mLineHeight = context.getResources()
+ mLineHeight = mContext.getResources()
.getDimensionPixelSize(R.dimen.floating_toolbar_height);
- mIconTextSpacing = context.getResources()
+ mIconTextSpacing = mContext.getResources()
.getDimensionPixelSize(R.dimen.floating_toolbar_icon_text_spacing);
// Interpolators
@@ -252,46 +221,54 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- mPopupWindow.dismiss();
+ // TODO(b/215497659): should dismiss window after animation
mContentContainer.removeAllViews();
+ mSurfaceControlViewHost.release();
+ mSurfaceControlViewHost = null;
+ mSurfacePackage = null;
}
});
mHideAnimation = createExitAnimation(
mContentContainer,
0, // startDelay
- new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mPopupWindow.dismiss();
- }
- });
+ null); // TODO(b/215497659): should handle hide after animation
+ mMenuItemButtonOnClickListener = v -> {
+ Object tag = v.getTag();
+ if (!(tag instanceof ToolbarMenuItem)) {
+ return;
+ }
+ mCallbackWrapper.onMenuItemClicked((ToolbarMenuItem) tag);
+ };
}
- @Override
- public boolean setOutsideTouchable(
- boolean outsideTouchable, @Nullable PopupWindow.OnDismissListener onDismiss) {
- boolean ret = false;
- if (mPopupWindow.isOutsideTouchable() ^ outsideTouchable) {
- mPopupWindow.setOutsideTouchable(outsideTouchable);
- mPopupWindow.setFocusable(!outsideTouchable);
- mPopupWindow.update();
- ret = true;
+ private WidgetInfo createWidgetInfo() {
+ mTempContentRect.set(mRelativeCoordsForToolbar.x, mRelativeCoordsForToolbar.y,
+ mRelativeCoordsForToolbar.x + mPopupWidth,
+ mRelativeCoordsForToolbar.y + mPopupHeight);
+ return new WidgetInfo(mSelectionToolbarToken, mTempContentRect, getSurfacePackage());
+ }
+
+ private SurfaceControlViewHost.SurfacePackage getSurfacePackage() {
+ if (mSurfaceControlViewHost == null) {
+ final FloatingToolbarRoot contentHolder = new FloatingToolbarRoot(mContext,
+ mHostInputToken, mTransferTouchListener);
+ contentHolder.addView(mContentContainer);
+ mSurfaceControlViewHost = new SurfaceControlViewHost(mContext, mContext.getDisplay(),
+ mHostInputToken);
+ mSurfaceControlViewHost.setView(contentHolder, mPopupWidth, mPopupHeight);
+ }
+ if (mSurfacePackage == null) {
+ mSurfacePackage = mSurfaceControlViewHost.getSurfacePackage();
}
- mPopupWindow.setOnDismissListener(onDismiss);
- return ret;
+ return mSurfacePackage;
}
- /**
- * Lays out buttons for the specified menu items.
- * Requires a subsequent call to {@link FloatingToolbar#show()} to show the items.
- */
private void layoutMenuItems(
- List<MenuItem> menuItems,
- MenuItem.OnMenuItemClickListener menuItemClickListener,
+ List<ToolbarMenuItem> menuItems,
int suggestedWidth) {
cancelOverflowAnimations();
clearPanels();
- updateMenuItems(menuItems, menuItemClickListener);
+
menuItems = layoutMainPanelItems(menuItems, getAdjustedToolbarWidth(suggestedWidth));
if (!menuItems.isEmpty()) {
// Add remaining items to the overflow.
@@ -300,148 +277,98 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
updatePopupSize();
}
- /**
- * Updates the popup's menu items without rebuilding the widget.
- * Use in place of layoutMenuItems() when the popup's views need not be reconstructed.
- *
- * @see #isLayoutRequired(List<MenuItem>)
- */
- private void updateMenuItems(
- List<MenuItem> menuItems, MenuItem.OnMenuItemClickListener menuItemClickListener) {
- mMenuItems.clear();
- for (MenuItem menuItem : menuItems) {
- mMenuItems.put(MenuItemRepr.of(menuItem), menuItem);
- }
- mOnMenuItemClickListener = menuItemClickListener;
+ public void onToolbarShowTimeout() {
+ mCallbackWrapper.onToolbarShowTimeout();
}
/**
- * Returns true if this popup needs a relayout to properly render the specified menu items.
+ * Show the specified selection toolbar.
*/
- private boolean isLayoutRequired(List<MenuItem> menuItems) {
- return !MenuItemRepr.reprEquals(menuItems, mMenuItems.values());
- }
+ public void show(ShowInfo showInfo) {
+ debugLog("show() for " + showInfo);
- @Override
- public void setWidthChanged(boolean widthChanged) {
- mWidthChanged = widthChanged;
- }
-
- @Override
- public void setSuggestedWidth(int suggestedWidth) {
- // Check if there's been a substantial width spec change.
- int difference = Math.abs(suggestedWidth - mSuggestedWidth);
- mWidthChanged = difference > (mSuggestedWidth * 0.2);
- mSuggestedWidth = suggestedWidth;
- }
+ mMenuItems = showInfo.getMenuItems();
+ mViewPortOnScreen.set(showInfo.getViewPortOnScreen());
- @Override
- public void show(List<MenuItem> menuItems,
- MenuItem.OnMenuItemClickListener menuItemClickListener, Rect contentRect) {
- if (isLayoutRequired(menuItems) || mWidthChanged) {
- dismiss();
- layoutMenuItems(menuItems, menuItemClickListener, mSuggestedWidth);
- } else {
- updateMenuItems(menuItems, menuItemClickListener);
+ debugLog("show(): layoutRequired=" + showInfo.isLayoutRequired());
+ if (showInfo.isLayoutRequired()) {
+ layoutMenuItems(mMenuItems, showInfo.getSuggestedWidth());
}
+ Rect contentRect = showInfo.getContentRect();
if (!isShowing()) {
show(contentRect);
} else if (!mPreviousContentRect.equals(contentRect)) {
updateCoordinates(contentRect);
}
- mWidthChanged = false;
mPreviousContentRect.set(contentRect);
}
private void show(Rect contentRectOnScreen) {
Objects.requireNonNull(contentRectOnScreen);
- if (isShowing()) {
- return;
- }
-
mHidden = false;
mDismissed = false;
cancelDismissAndHideAnimations();
cancelOverflowAnimations();
-
refreshCoordinatesAndOverflowDirection(contentRectOnScreen);
preparePopupContent();
- // We need to specify the position in window coordinates.
- // TODO: Consider to use PopupWindow.setIsLaidOutInScreen(true) so that we can
- // specify the popup position in screen coordinates.
- mPopupWindow.showAtLocation(
- mParent, Gravity.NO_GRAVITY, mCoordsOnWindow.x, mCoordsOnWindow.y);
- setTouchableSurfaceInsetsComputer();
- runShowAnimation();
+ mCallbackWrapper.onShown(createWidgetInfo());
+ // TODO(b/215681595): Use Choreographer to coordinate for show between different thread
+ mShowAnimation.start();
}
- @Override
- public void dismiss() {
+ /**
+ * Dismiss the specified selection toolbar.
+ */
+ public void dismiss(long floatingToolbarToken) {
+ debugLog("dismiss for " + floatingToolbarToken);
if (mDismissed) {
return;
}
-
mHidden = false;
mDismissed = true;
- mHideAnimation.cancel();
- runDismissAnimation();
- setZeroTouchableSurface();
+ mHideAnimation.cancel();
+ mDismissAnimation.start();
}
- @Override
- public void hide() {
+ /**
+ * Hide the specified selection toolbar.
+ */
+ public void hide(long floatingToolbarToken) {
+ debugLog("hide for " + floatingToolbarToken);
if (!isShowing()) {
return;
}
mHidden = true;
- runHideAnimation();
- setZeroTouchableSurface();
+ mHideAnimation.start();
}
- @Override
public boolean isShowing() {
return !mDismissed && !mHidden;
}
- @Override
- public boolean isHidden() {
- return mHidden;
- }
-
- /**
- * Updates the coordinates of this popup.
- * The specified coordinates may be adjusted to make sure the popup is entirely on-screen.
- * This is a no-op if this popup is not showing.
- */
private void updateCoordinates(Rect contentRectOnScreen) {
Objects.requireNonNull(contentRectOnScreen);
- if (!isShowing() || !mPopupWindow.isShowing()) {
+ if (!isShowing()) {
return;
}
-
cancelOverflowAnimations();
refreshCoordinatesAndOverflowDirection(contentRectOnScreen);
preparePopupContent();
- // We need to specify the position in window coordinates.
- // TODO: Consider to use PopupWindow.setIsLaidOutInScreen(true) so that we can
- // specify the popup position in screen coordinates.
- mPopupWindow.update(
- mCoordsOnWindow.x, mCoordsOnWindow.y,
- mPopupWindow.getWidth(), mPopupWindow.getHeight());
+ WidgetInfo widgetInfo = createWidgetInfo();
+ mSurfaceControlViewHost.relayout(mPopupWidth, mPopupHeight);
+ mCallbackWrapper.onWidgetUpdated(widgetInfo);
}
private void refreshCoordinatesAndOverflowDirection(Rect contentRectOnScreen) {
- refreshViewPort();
-
// Initialize x ensuring that the toolbar isn't rendered behind the nav bar in
// landscape.
final int x = Math.min(
- contentRectOnScreen.centerX() - mPopupWindow.getWidth() / 2,
- mViewPortOnScreen.right - mPopupWindow.getWidth());
+ contentRectOnScreen.centerX() - mPopupWidth / 2,
+ mViewPortOnScreen.right - mPopupWidth);
final int y;
@@ -484,7 +411,7 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
// There is enough space at the top of the content rect for the overflow.
// Position above and open upwards.
updateOverflowHeight(availableHeightAboveContent - margin);
- y = contentRectOnScreen.top - mPopupWindow.getHeight();
+ y = contentRectOnScreen.top - mPopupHeight;
mOpenOverflowUpwards = true;
} else if (availableHeightAboveContent >= toolbarHeightWithVerticalMargin
&& availableHeightThroughContentDown >= minimumOverflowHeightWithMargin) {
@@ -507,7 +434,7 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
// Position below but open upwards.
updateOverflowHeight(availableHeightThroughContentUp - margin);
y = contentRectOnScreen.bottom + toolbarHeightWithVerticalMargin
- - mPopupWindow.getHeight();
+ - mPopupHeight;
mOpenOverflowUpwards = true;
} else {
// Not enough space.
@@ -517,45 +444,7 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
mOpenOverflowUpwards = false;
}
}
-
- // We later specify the location of PopupWindow relative to the attached window.
- // The idea here is that 1) we can get the location of a View in both window coordinates
- // and screen coordinates, where the offset between them should be equal to the window
- // origin, and 2) we can use an arbitrary for this calculation while calculating the
- // location of the rootview is supposed to be least expensive.
- // TODO: Consider to use PopupWindow.setIsLaidOutInScreen(true) so that we can avoid
- // the following calculation.
- mParent.getRootView().getLocationOnScreen(mTmpCoords);
- int rootViewLeftOnScreen = mTmpCoords[0];
- int rootViewTopOnScreen = mTmpCoords[1];
- mParent.getRootView().getLocationInWindow(mTmpCoords);
- int rootViewLeftOnWindow = mTmpCoords[0];
- int rootViewTopOnWindow = mTmpCoords[1];
- int windowLeftOnScreen = rootViewLeftOnScreen - rootViewLeftOnWindow;
- int windowTopOnScreen = rootViewTopOnScreen - rootViewTopOnWindow;
- mCoordsOnWindow.set(
- Math.max(0, x - windowLeftOnScreen), Math.max(0, y - windowTopOnScreen));
- }
-
- /**
- * Performs the "show" animation on the floating popup.
- */
- private void runShowAnimation() {
- mShowAnimation.start();
- }
-
- /**
- * Performs the "dismiss" animation on the floating popup.
- */
- private void runDismissAnimation() {
- mDismissAnimation.start();
- }
-
- /**
- * Performs the "hide" animation on the floating popup.
- */
- private void runHideAnimation() {
- mHideAnimation.start();
+ mRelativeCoordsForToolbar.set(x, y);
}
private void cancelDismissAndHideAnimations() {
@@ -628,12 +517,11 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
}
};
widthAnimation.setInterpolator(mLogAccelerateInterpolator);
- widthAnimation.setDuration(getAdjustedDuration(250));
+ widthAnimation.setDuration(getAnimationDuration());
heightAnimation.setInterpolator(mFastOutSlowInInterpolator);
- heightAnimation.setDuration(getAdjustedDuration(250));
+ heightAnimation.setDuration(getAnimationDuration());
overflowButtonAnimation.setInterpolator(mFastOutSlowInInterpolator);
- overflowButtonAnimation.setDuration(getAdjustedDuration(250));
- mOpenOverflowAnimation.getAnimations().clear();
+ overflowButtonAnimation.setDuration(getAnimationDuration());
mOpenOverflowAnimation.getAnimations().clear();
mOpenOverflowAnimation.addAnimation(widthAnimation);
mOpenOverflowAnimation.addAnimation(heightAnimation);
@@ -704,11 +592,11 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
}
};
widthAnimation.setInterpolator(mFastOutSlowInInterpolator);
- widthAnimation.setDuration(getAdjustedDuration(250));
+ widthAnimation.setDuration(getAnimationDuration());
heightAnimation.setInterpolator(mLogAccelerateInterpolator);
- heightAnimation.setDuration(getAdjustedDuration(250));
+ heightAnimation.setDuration(getAnimationDuration());
overflowButtonAnimation.setInterpolator(mFastOutSlowInInterpolator);
- overflowButtonAnimation.setDuration(getAdjustedDuration(250));
+ overflowButtonAnimation.setDuration(getAnimationDuration());
mCloseOverflowAnimation.getAnimations().clear();
mCloseOverflowAnimation.addAnimation(widthAnimation);
mCloseOverflowAnimation.addAnimation(heightAnimation);
@@ -756,7 +644,7 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
mOverflowPanel.setX(0); // align left
} else {
mContentContainer.setX(// align right
- mPopupWindow.getWidth() - containerSize.getWidth() - mMarginHorizontal);
+ mPopupWidth - containerSize.getWidth() - mMarginHorizontal);
mMainPanel.setX(-mContentContainer.getX()); // align right
mOverflowButton.setX(0); // align left
mOverflowPanel.setX(0); // align left
@@ -798,7 +686,7 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
mOverflowPanel.setX(0); // align left
} else {
mContentContainer.setX(// align right
- mPopupWindow.getWidth() - containerSize.getWidth() - mMarginHorizontal);
+ mPopupWidth - containerSize.getWidth() - mMarginHorizontal);
mMainPanel.setX(0); // align left
mOverflowButton.setX(// align right
containerSize.getWidth() - mOverflowButtonSize.getWidth());
@@ -866,70 +754,23 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
width = Math.max(width, mOverflowPanelSize.getWidth());
height = Math.max(height, mOverflowPanelSize.getHeight());
}
- mPopupWindow.setWidth(width + mMarginHorizontal * 2);
- mPopupWindow.setHeight(height + mMarginVertical * 2);
- maybeComputeTransitionDurationScale();
- }
- private void refreshViewPort() {
- mParent.getWindowVisibleDisplayFrame(mViewPortOnScreen);
+ mPopupWidth = width + mMarginHorizontal * 2;
+ mPopupHeight = height + mMarginVertical * 2;
+ maybeComputeTransitionDurationScale();
}
private int getAdjustedToolbarWidth(int suggestedWidth) {
int width = suggestedWidth;
- refreshViewPort();
- int maximumWidth = mViewPortOnScreen.width() - 2 * mParent.getResources()
+ int maximumWidth = mViewPortOnScreen.width() - 2 * mContext.getResources()
.getDimensionPixelSize(R.dimen.floating_toolbar_horizontal_margin);
if (width <= 0) {
- width = mParent.getResources()
+ width = mContext.getResources()
.getDimensionPixelSize(R.dimen.floating_toolbar_preferred_width);
}
return Math.min(width, maximumWidth);
}
- /**
- * Sets the touchable region of this popup to be zero. This means that all touch events on
- * this popup will go through to the surface behind it.
- */
- private void setZeroTouchableSurface() {
- mTouchableRegion.setEmpty();
- }
-
- /**
- * Sets the touchable region of this popup to be the area occupied by its content.
- */
- private void setContentAreaAsTouchableSurface() {
- Objects.requireNonNull(mMainPanelSize);
- final int width;
- final int height;
- if (mIsOverflowOpen) {
- Objects.requireNonNull(mOverflowPanelSize);
- width = mOverflowPanelSize.getWidth();
- height = mOverflowPanelSize.getHeight();
- } else {
- width = mMainPanelSize.getWidth();
- height = mMainPanelSize.getHeight();
- }
- mTouchableRegion.set(
- (int) mContentContainer.getX(),
- (int) mContentContainer.getY(),
- (int) mContentContainer.getX() + width,
- (int) mContentContainer.getY() + height);
- }
-
- /**
- * Make the touchable area of this popup be the area specified by mTouchableRegion.
- * This should be called after the popup window has been dismissed (dismiss/hide)
- * and is probably being re-shown with a new content root view.
- */
- private void setTouchableSurfaceInsetsComputer() {
- ViewTreeObserver viewTreeObserver = mPopupWindow.getContentView()
- .getRootView()
- .getViewTreeObserver();
- viewTreeObserver.removeOnComputeInternalInsetsListener(mInsetsComputer);
- viewTreeObserver.addOnComputeInternalInsetsListener(mInsetsComputer);
- }
-
private boolean isInRTLMode() {
return mContext.getApplicationInfo().hasRtlSupport()
&& mContext.getResources().getConfiguration().getLayoutDirection()
@@ -946,18 +787,14 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
*
* @return The menu items that are not included in this main panel.
*/
- public List<MenuItem> layoutMainPanelItems(
- List<MenuItem> menuItems, final int toolbarWidth) {
- Objects.requireNonNull(menuItems);
-
- int availableWidth = toolbarWidth;
-
- final LinkedList<MenuItem> remainingMenuItems = new LinkedList<>();
+ private List<ToolbarMenuItem> layoutMainPanelItems(List<ToolbarMenuItem> menuItems,
+ int toolbarWidth) {
+ final LinkedList<ToolbarMenuItem> remainingMenuItems = new LinkedList<>();
// add the overflow menu items to the end of the remainingMenuItems list.
- final LinkedList<MenuItem> overflowMenuItems = new LinkedList();
- for (MenuItem menuItem : menuItems) {
+ final LinkedList<ToolbarMenuItem> overflowMenuItems = new LinkedList();
+ for (ToolbarMenuItem menuItem : menuItems) {
if (menuItem.getItemId() != android.R.id.textAssist
- && menuItem.requiresOverflow()) {
+ && menuItem.getPriority() == ToolbarMenuItem.PRIORITY_OVERFLOW) {
overflowMenuItems.add(menuItem);
} else {
remainingMenuItems.add(menuItem);
@@ -968,25 +805,22 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
mMainPanel.removeAllViews();
mMainPanel.setPaddingRelative(0, 0, 0, 0);
- int lastGroupId = -1;
+ int availableWidth = toolbarWidth;
boolean isFirstItem = true;
while (!remainingMenuItems.isEmpty()) {
- final MenuItem menuItem = remainingMenuItems.peek();
-
+ ToolbarMenuItem menuItem = remainingMenuItems.peek();
// if this is the first item, regardless of requiresOverflow(), it should be
// displayed on the main panel. Otherwise all items including this one will be
// overflow items, and should be displayed in overflow panel.
- if (!isFirstItem && menuItem.requiresOverflow()) {
+ if (!isFirstItem && menuItem.getPriority() == ToolbarMenuItem.PRIORITY_OVERFLOW) {
break;
}
-
final boolean showIcon = isFirstItem && menuItem.getItemId() == R.id.textAssist;
final View menuItemButton = createMenuItemButton(
mContext, menuItem, mIconTextSpacing, showIcon);
if (!showIcon && menuItemButton instanceof LinearLayout) {
((LinearLayout) menuItemButton).setGravity(Gravity.CENTER);
}
-
// Adding additional start padding for the first button to even out button spacing.
if (isFirstItem) {
menuItemButton.setPaddingRelative(
@@ -995,7 +829,6 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
menuItemButton.getPaddingEnd(),
menuItemButton.getPaddingBottom());
}
-
// Adding additional end padding for the last button to even out button spacing.
boolean isLastItem = remainingMenuItems.size() == 1;
if (isLastItem) {
@@ -1005,18 +838,17 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
(int) (1.5 * menuItemButton.getPaddingEnd()),
menuItemButton.getPaddingBottom());
}
-
- menuItemButton.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+ menuItemButton.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
final int menuItemButtonWidth = Math.min(
menuItemButton.getMeasuredWidth(), toolbarWidth);
-
// Check if we can fit an item while reserving space for the overflowButton.
final boolean canFitWithOverflow =
menuItemButtonWidth <= availableWidth - mOverflowButtonSize.getWidth();
final boolean canFitNoOverflow =
isLastItem && menuItemButtonWidth <= availableWidth;
if (canFitWithOverflow || canFitNoOverflow) {
- setButtonTagAndClickListener(menuItemButton, menuItem);
+ menuItemButton.setTag(menuItem);
+ menuItemButton.setOnClickListener(mMenuItemButtonOnClickListener);
// Set tooltips for main panel items, but not overflow items (b/35726766).
menuItemButton.setTooltipText(menuItem.getTooltipText());
mMainPanel.addView(menuItemButton);
@@ -1028,22 +860,20 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
} else {
break;
}
- lastGroupId = menuItem.getGroupId();
isFirstItem = false;
}
-
if (!remainingMenuItems.isEmpty()) {
// Reserve space for overflowButton.
mMainPanel.setPaddingRelative(0, 0, mOverflowButtonSize.getWidth(), 0);
}
-
mMainPanelSize = measure(mMainPanel);
+
return remainingMenuItems;
}
- private void layoutOverflowPanelItems(List<MenuItem> menuItems) {
- ArrayAdapter<MenuItem> overflowPanelAdapter =
- (ArrayAdapter<MenuItem>) mOverflowPanel.getAdapter();
+ private void layoutOverflowPanelItems(List<ToolbarMenuItem> menuItems) {
+ ArrayAdapter<ToolbarMenuItem> overflowPanelAdapter =
+ (ArrayAdapter<ToolbarMenuItem>) mOverflowPanel.getAdapter();
overflowPanelAdapter.clear();
final int size = menuItems.size();
for (int i = 0; i < size; i++) {
@@ -1055,7 +885,6 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
} else {
mOverflowPanel.setY(mOverflowButtonSize.getHeight());
}
-
int width = Math.max(getOverflowWidth(), mOverflowButtonSize.getWidth());
int height = calculateOverflowHeight(MAX_OVERFLOW_SIZE);
mOverflowPanelSize = new Size(width, height);
@@ -1067,7 +896,6 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
*/
private void preparePopupContent() {
mContentContainer.removeAllViews();
-
// Add views in the specified order so they stack up as expected.
// Order: overflowPanel, mainPanel, overflowButton.
if (hasOverflow()) {
@@ -1078,7 +906,6 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
mContentContainer.addView(mOverflowButton);
}
setPanelsStatesAtRestingPosition();
- setContentAreaAsTouchableSurface();
// The positioning of contents in RTL is wrong when the view is first rendered.
// Hide the view and post a runnable to recalculate positions and render the view.
@@ -1093,12 +920,12 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
* Clears out the panels and their container. Resets their calculated sizes.
*/
private void clearPanels() {
- mOverflowPanelSize = null;
- mMainPanelSize = null;
mIsOverflowOpen = false;
+ mMainPanelSize = null;
mMainPanel.removeAllViews();
- ArrayAdapter<MenuItem> overflowPanelAdapter =
- (ArrayAdapter<MenuItem>) mOverflowPanel.getAdapter();
+ mOverflowPanelSize = null;
+ ArrayAdapter<ToolbarMenuItem> overflowPanelAdapter =
+ (ArrayAdapter<ToolbarMenuItem>) mOverflowPanel.getAdapter();
overflowPanelAdapter.clear();
mOverflowPanel.setAdapter(overflowPanelAdapter);
mContentContainer.removeAllViews();
@@ -1116,7 +943,7 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
int overflowWidth = 0;
final int count = mOverflowPanel.getAdapter().getCount();
for (int i = 0; i < count; i++) {
- MenuItem menuItem = (MenuItem) mOverflowPanel.getAdapter().getItem(i);
+ ToolbarMenuItem menuItem = (ToolbarMenuItem) mOverflowPanel.getAdapter().getItem(i);
overflowWidth =
Math.max(mOverflowPanelViewHelper.calculateWidth(menuItem), overflowWidth);
}
@@ -1141,29 +968,24 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
+ extension;
}
- private void setButtonTagAndClickListener(View menuItemButton, MenuItem menuItem) {
- menuItemButton.setTag(MenuItemRepr.of(menuItem));
- menuItemButton.setOnClickListener(mMenuItemButtonOnClickListener);
- }
-
/**
* NOTE: Use only in android.view.animation.* animations. Do not use in android.animation.*
* animations. See comment about this in the code.
*/
- private int getAdjustedDuration(int originalDuration) {
+ private int getAnimationDuration() {
if (mTransitionDurationScale < 150) {
// For smaller transition, decrease the time.
- return Math.max(originalDuration - 50, 0);
+ return 200;
} else if (mTransitionDurationScale > 300) {
// For bigger transition, increase the time.
- return originalDuration + 50;
+ return 300;
}
// Scale the animation duration with getDurationScale(). This allows
// android.view.animation.* animations to scale just like android.animation.* animations
// when animator duration scale is adjusted in "Developer Options".
// For this reason, do not use this method for android.animation.* animations.
- return (int) (originalDuration * ValueAnimator.getDurationScale());
+ return (int) (250 * ValueAnimator.getDurationScale());
}
private void maybeComputeTransitionDurationScale() {
@@ -1176,7 +998,7 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
}
private ViewGroup createMainPanel() {
- ViewGroup mainPanel = new LinearLayout(mContext) {
+ return new LinearLayout(mContext) {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (isOverflowAnimating()) {
@@ -1195,7 +1017,6 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
return isOverflowAnimating();
}
};
- return mainPanel;
}
private ImageButton createOverflowButton() {
@@ -1203,6 +1024,12 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
.inflate(R.layout.floating_popup_overflow_button, null);
overflowButton.setImageDrawable(mOverflow);
overflowButton.setOnClickListener(v -> {
+ if (isShowing()) {
+ preparePopupContent();
+ WidgetInfo widgetInfo = createWidgetInfo();
+ mSurfaceControlViewHost.relayout(mPopupWidth, mPopupHeight);
+ mCallbackWrapper.onWidgetUpdated(widgetInfo);
+ }
if (mIsOverflowOpen) {
overflowButton.setImageDrawable(mToOverflow);
mToOverflow.start();
@@ -1224,7 +1051,7 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
overflowPanel.setDividerHeight(0);
final ArrayAdapter adapter =
- new ArrayAdapter<MenuItem>(mContext, 0) {
+ new ArrayAdapter<ToolbarMenuItem>(mContext, 0) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return mOverflowPanelViewHelper.getView(
@@ -1232,14 +1059,11 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
}
};
overflowPanel.setAdapter(adapter);
-
overflowPanel.setOnItemClickListener((parent, view, position, id) -> {
- MenuItem menuItem = (MenuItem) overflowPanel.getAdapter().getItem(position);
- if (mOnMenuItemClickListener != null) {
- mOnMenuItemClickListener.onMenuItemClick(menuItem);
- }
+ ToolbarMenuItem menuItem =
+ (ToolbarMenuItem) overflowPanel.getAdapter().getItem(position);
+ mCallbackWrapper.onMenuItemClicked(menuItem);
});
-
return overflowPanel;
}
@@ -1252,7 +1076,7 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
}
private Animation.AnimationListener createOverflowAnimationListener() {
- Animation.AnimationListener listener = new Animation.AnimationListener() {
+ return new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
// Disable the overflow button while it's animating.
@@ -1270,7 +1094,6 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
// actually ends.
mContentContainer.post(() -> {
setPanelsStatesAtRestingPosition();
- setContentAreaAsTouchableSurface();
});
}
@@ -1278,12 +1101,11 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
public void onAnimationRepeat(Animation animation) {
}
};
- return listener;
}
private static Size measure(View view) {
Preconditions.checkState(view.getParent() == null);
- view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+ view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
return new Size(view.getMeasuredWidth(), view.getMeasuredHeight());
}
@@ -1372,13 +1194,11 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
* A helper for generating views for the overflow panel.
*/
private static final class OverflowPanelViewHelper {
-
+ private final Context mContext;
private final View mCalculator;
private final int mIconTextSpacing;
private final int mSidePadding;
- private final Context mContext;
-
OverflowPanelViewHelper(Context context, int iconTextSpacing) {
mContext = Objects.requireNonNull(context);
mIconTextSpacing = iconTextSpacing;
@@ -1387,7 +1207,7 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
mCalculator = createMenuButton(null);
}
- public View getView(MenuItem menuItem, int minimumWidth, View convertView) {
+ public View getView(ToolbarMenuItem menuItem, int minimumWidth, View convertView) {
Objects.requireNonNull(menuItem);
if (convertView != null) {
updateMenuItemButton(
@@ -1399,7 +1219,7 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
return convertView;
}
- public int calculateWidth(MenuItem menuItem) {
+ public int calculateWidth(ToolbarMenuItem menuItem) {
updateMenuItemButton(
mCalculator, menuItem, mIconTextSpacing, shouldShowIcon(menuItem));
mCalculator.measure(
@@ -1407,18 +1227,18 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
return mCalculator.getMeasuredWidth();
}
- private View createMenuButton(MenuItem menuItem) {
+ private View createMenuButton(ToolbarMenuItem menuItem) {
View button = createMenuItemButton(
mContext, menuItem, mIconTextSpacing, shouldShowIcon(menuItem));
button.setPadding(mSidePadding, 0, mSidePadding, 0);
return button;
}
- private boolean shouldShowIcon(MenuItem menuItem) {
+ private boolean shouldShowIcon(ToolbarMenuItem menuItem) {
if (menuItem != null) {
return menuItem.getGroupId() == android.R.id.textAssist;
}
- return false;
+ return false;
}
}
@@ -1426,7 +1246,7 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
* Creates and returns a menu button for the specified menu item.
*/
private static View createMenuItemButton(
- Context context, MenuItem menuItem, int iconTextSpacing, boolean showIcon) {
+ Context context, ToolbarMenuItem menuItem, int iconTextSpacing, boolean showIcon) {
final View menuItemButton = LayoutInflater.from(context)
.inflate(R.layout.floating_popup_menu_button, null);
if (menuItem != null) {
@@ -1438,8 +1258,8 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
/**
* Updates the specified menu item button with the specified menu item data.
*/
- private static void updateMenuItemButton(
- View menuItemButton, MenuItem menuItem, int iconTextSpacing, boolean showIcon) {
+ private static void updateMenuItemButton(View menuItemButton, ToolbarMenuItem menuItem,
+ int iconTextSpacing, boolean showIcon) {
final TextView buttonText = menuItemButton.findViewById(
R.id.floating_toolbar_menu_item_text);
buttonText.setEllipsize(null);
@@ -1453,15 +1273,12 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
R.id.floating_toolbar_menu_item_image);
if (menuItem.getIcon() == null || !showIcon) {
buttonIcon.setVisibility(View.GONE);
- if (buttonText != null) {
- buttonText.setPaddingRelative(0, 0, 0, 0);
- }
+ buttonText.setPaddingRelative(0, 0, 0, 0);
} else {
buttonIcon.setVisibility(View.VISIBLE);
- buttonIcon.setImageDrawable(menuItem.getIcon());
- if (buttonText != null) {
- buttonText.setPaddingRelative(iconTextSpacing, 0, 0, 0);
- }
+ buttonIcon.setImageDrawable(
+ menuItem.getIcon().loadDrawable(menuItemButton.getContext()));
+ buttonText.setPaddingRelative(iconTextSpacing, 0, 0, 0);
}
final CharSequence contentDescription = menuItem.getContentDescription();
if (TextUtils.isEmpty(contentDescription)) {
@@ -1476,27 +1293,11 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
.inflate(R.layout.floating_popup_container, null);
contentContainer.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
- contentContainer.setTag("floating_toolbar");
+ contentContainer.setTag(FloatingToolbar.FLOATING_TOOLBAR_TAG);
contentContainer.setClipToOutline(true);
return contentContainer;
}
- private static PopupWindow createPopupWindow(ViewGroup content) {
- ViewGroup popupContentHolder = new LinearLayout(content.getContext());
- PopupWindow popupWindow = new PopupWindow(popupContentHolder);
- // TODO: Use .setIsLaidOutInScreen(true) instead of .setClippingEnabled(false)
- // unless FLAG_LAYOUT_IN_SCREEN has any unintentional side-effects.
- popupWindow.setClippingEnabled(false);
- popupWindow.setWindowLayoutType(
- WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL);
- popupWindow.setAnimationStyle(0);
- popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
- content.setLayoutParams(new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
- popupContentHolder.addView(content);
- return popupWindow;
- }
-
/**
* Creates an "appear" animation for the specified view.
*
@@ -1522,7 +1323,9 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
animation.playTogether(
ObjectAnimator.ofFloat(view, View.ALPHA, 1, 0).setDuration(100));
animation.setStartDelay(startDelay);
- animation.addListener(listener);
+ if (listener != null) {
+ animation.addListener(listener);
+ }
return animation;
}
@@ -1538,82 +1341,9 @@ final class RemoteSelectionToolbar implements FloatingToolbarPopup {
return new ContextThemeWrapper(originalContext, themeId);
}
- /**
- * Represents the identity of a MenuItem that is rendered in a FloatingToolbarPopup.
- */
- @VisibleForTesting
- public static final class MenuItemRepr {
-
- public final int itemId;
- public final int groupId;
- @Nullable public final String title;
- @Nullable private final Drawable mIcon;
-
- private MenuItemRepr(
- int itemId, int groupId, @Nullable CharSequence title, @Nullable Drawable icon) {
- this.itemId = itemId;
- this.groupId = groupId;
- this.title = (title == null) ? null : title.toString();
- mIcon = icon;
- }
-
- /**
- * Creates an instance of MenuItemRepr for the specified menu item.
- */
- public static MenuItemRepr of(MenuItem menuItem) {
- return new MenuItemRepr(
- menuItem.getItemId(),
- menuItem.getGroupId(),
- menuItem.getTitle(),
- menuItem.getIcon());
- }
-
- /**
- * Returns this object's hashcode.
- */
- @Override
- public int hashCode() {
- return Objects.hash(itemId, groupId, title, mIcon);
- }
-
- /**
- * Returns true if this object is the same as the specified object.
- */
- @Override
- public boolean equals(Object o) {
- if (o == this) {
- return true;
- }
- if (!(o instanceof MenuItemRepr)) {
- return false;
- }
- final MenuItemRepr other = (MenuItemRepr) o;
- return itemId == other.itemId
- && groupId == other.groupId
- && TextUtils.equals(title, other.title)
- // Many Drawables (icons) do not implement equals(). Using equals() here instead
- // of reference comparisons in case a Drawable subclass implements equals().
- && Objects.equals(mIcon, other.mIcon);
- }
-
- /**
- * Returns true if the two menu item collections are the same based on MenuItemRepr.
- */
- public static boolean reprEquals(
- Collection<MenuItem> menuItems1, Collection<MenuItem> menuItems2) {
- if (menuItems1.size() != menuItems2.size()) {
- return false;
- }
-
- final Iterator<MenuItem> menuItems2Iter = menuItems2.iterator();
- for (MenuItem menuItem1 : menuItems1) {
- final MenuItem menuItem2 = menuItems2Iter.next();
- if (!MenuItemRepr.of(menuItem1).equals(MenuItemRepr.of(menuItem2))) {
- return false;
- }
- }
-
- return true;
+ private static void debugLog(String message) {
+ if (Log.isLoggable(FloatingToolbar.FLOATING_TOOLBAR_TAG, Log.DEBUG)) {
+ Log.v(TAG, message);
}
}
}
diff --git a/core/java/android/service/selectiontoolbar/SelectionToolbarRenderCallback.java b/core/java/android/service/selectiontoolbar/SelectionToolbarRenderCallback.java
index 6468183880f4..a10b6a8ac8cb 100644
--- a/core/java/android/service/selectiontoolbar/SelectionToolbarRenderCallback.java
+++ b/core/java/android/service/selectiontoolbar/SelectionToolbarRenderCallback.java
@@ -31,14 +31,6 @@ public interface SelectionToolbarRenderCallback {
*/
void onShown(WidgetInfo widgetInfo);
/**
- * The selection toolbar is hidden.
- */
- void onHidden(long widgetToken);
- /**
- * The selection toolbar is dismissed.
- */
- void onDismissed(long widgetToken);
- /**
* The selection toolbar has changed.
*/
void onWidgetUpdated(WidgetInfo info);
@@ -47,6 +39,10 @@ public interface SelectionToolbarRenderCallback {
*/
void onMenuItemClicked(ToolbarMenuItem item);
/**
+ * The toolbar doesn't be dismissed after showing on a given timeout.
+ */
+ void onToolbarShowTimeout();
+ /**
* The error occurred when operating on the selection toolbar.
*/
void onError(int errorCode);
diff --git a/core/java/android/service/selectiontoolbar/SelectionToolbarRenderService.java b/core/java/android/service/selectiontoolbar/SelectionToolbarRenderService.java
index 6f66c9f1ed3a..f33feaec6dde 100644
--- a/core/java/android/service/selectiontoolbar/SelectionToolbarRenderService.java
+++ b/core/java/android/service/selectiontoolbar/SelectionToolbarRenderService.java
@@ -28,6 +28,8 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;
+import android.util.Pair;
+import android.util.SparseArray;
import android.view.selectiontoolbar.ISelectionToolbarCallback;
import android.view.selectiontoolbar.ShowInfo;
import android.view.selectiontoolbar.ToolbarMenuItem;
@@ -42,6 +44,10 @@ public abstract class SelectionToolbarRenderService extends Service {
private static final String TAG = "SelectionToolbarRenderService";
+ // TODO(b/215497659): read from DeviceConfig
+ // The timeout to clean the cache if the client forgot to call dismiss()
+ private static final int CACHE_CLEAN_AFTER_SHOW_TIMEOUT_IN_MS = 10 * 60 * 1000; // 10 minutes
+
/**
* The {@link Intent} that must be declared as handled by the service.
*
@@ -53,6 +59,10 @@ public abstract class SelectionToolbarRenderService extends Service {
"android.service.selectiontoolbar.SelectionToolbarRenderService";
private Handler mHandler;
+ private ISelectionToolbarRenderServiceCallback mServiceCallback;
+
+ private final SparseArray<Pair<RemoteCallbackWrapper, CleanCacheRunnable>> mCache =
+ new SparseArray<>();
/**
* Binder to receive calls from system server.
@@ -61,10 +71,18 @@ public abstract class SelectionToolbarRenderService extends Service {
new ISelectionToolbarRenderService.Stub() {
@Override
- public void onShow(ShowInfo showInfo, ISelectionToolbarCallback callback) {
+ public void onShow(int callingUid, ShowInfo showInfo, ISelectionToolbarCallback callback) {
+ if (mCache.indexOfKey(callingUid) < 0) {
+ mCache.put(callingUid, new Pair<>(new RemoteCallbackWrapper(callback),
+ new CleanCacheRunnable(callingUid)));
+ }
+ Pair<RemoteCallbackWrapper, CleanCacheRunnable> toolbarPair = mCache.get(callingUid);
+ CleanCacheRunnable cleanRunnable = toolbarPair.second;
+ mHandler.removeCallbacks(cleanRunnable);
mHandler.sendMessage(obtainMessage(SelectionToolbarRenderService::onShow,
- SelectionToolbarRenderService.this, showInfo,
- new RemoteCallbackWrapper(callback)));
+ SelectionToolbarRenderService.this, callingUid, showInfo,
+ toolbarPair.first));
+ mHandler.postDelayed(cleanRunnable, CACHE_CLEAN_AFTER_SHOW_TIMEOUT_IN_MS);
}
@Override
@@ -74,9 +92,20 @@ public abstract class SelectionToolbarRenderService extends Service {
}
@Override
- public void onDismiss(long widgetToken) {
+ public void onDismiss(int callingUid, long widgetToken) {
mHandler.sendMessage(obtainMessage(SelectionToolbarRenderService::onDismiss,
SelectionToolbarRenderService.this, widgetToken));
+ Pair<RemoteCallbackWrapper, CleanCacheRunnable> toolbarPair = mCache.get(callingUid);
+ if (toolbarPair != null) {
+ mHandler.removeCallbacks(toolbarPair.second);
+ mCache.remove(callingUid);
+ }
+ }
+
+ @Override
+ public void onConnected(IBinder callback) {
+ mHandler.sendMessage(obtainMessage(SelectionToolbarRenderService::handleOnConnected,
+ SelectionToolbarRenderService.this, callback));
}
};
@@ -97,11 +126,28 @@ public abstract class SelectionToolbarRenderService extends Service {
return null;
}
+ private void handleOnConnected(@NonNull IBinder callback) {
+ mServiceCallback = ISelectionToolbarRenderServiceCallback.Stub.asInterface(callback);
+ }
+
+ protected void transferTouch(@NonNull IBinder source, @NonNull IBinder target) {
+ final ISelectionToolbarRenderServiceCallback callback = mServiceCallback;
+ if (callback == null) {
+ Log.e(TAG, "transferTouch(): no server callback");
+ return;
+ }
+ try {
+ callback.transferTouch(source, target);
+ } catch (RemoteException e) {
+ // no-op
+ }
+ }
/**
* Called when showing the selection toolbar.
*/
- public abstract void onShow(ShowInfo showInfo, RemoteCallbackWrapper callbackWrapper);
+ public abstract void onShow(int callingUid, ShowInfo showInfo,
+ RemoteCallbackWrapper callbackWrapper);
/**
* Called when hiding the selection toolbar.
@@ -115,13 +161,22 @@ public abstract class SelectionToolbarRenderService extends Service {
public abstract void onDismiss(long widgetToken);
/**
- * Add avadoc.
+ * Called when showing the selection toolbar for a specific timeout. This avoids the client
+ * forgot to call dismiss to clean the state.
+ */
+ public void onToolbarShowTimeout(int callingUid) {
+ // no-op
+ }
+
+ /**
+ * Callback to notify the client toolbar events.
*/
public static final class RemoteCallbackWrapper implements SelectionToolbarRenderCallback {
private final ISelectionToolbarCallback mRemoteCallback;
RemoteCallbackWrapper(ISelectionToolbarCallback remoteCallback) {
+ // TODO(b/215497659): handle if the binder dies.
mRemoteCallback = remoteCallback;
}
@@ -130,25 +185,16 @@ public abstract class SelectionToolbarRenderService extends Service {
try {
mRemoteCallback.onShown(widgetInfo);
} catch (RemoteException e) {
- e.rethrowAsRuntimeException();
+ // no-op
}
}
@Override
- public void onHidden(long widgetToken) {
+ public void onToolbarShowTimeout() {
try {
- mRemoteCallback.onHidden(widgetToken);
+ mRemoteCallback.onToolbarShowTimeout();
} catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
- }
-
- @Override
- public void onDismissed(long widgetToken) {
- try {
- mRemoteCallback.onDismissed(widgetToken);
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
+ // no-op
}
}
@@ -157,7 +203,7 @@ public abstract class SelectionToolbarRenderService extends Service {
try {
mRemoteCallback.onWidgetUpdated(widgetInfo);
} catch (RemoteException e) {
- e.rethrowAsRuntimeException();
+ // no-op
}
}
@@ -166,7 +212,7 @@ public abstract class SelectionToolbarRenderService extends Service {
try {
mRemoteCallback.onMenuItemClicked(item);
} catch (RemoteException e) {
- e.rethrowAsRuntimeException();
+ // no-op
}
}
@@ -175,8 +221,37 @@ public abstract class SelectionToolbarRenderService extends Service {
try {
mRemoteCallback.onError(errorCode);
} catch (RemoteException e) {
- e.rethrowAsRuntimeException();
+ // no-op
}
}
}
+
+ private class CleanCacheRunnable implements Runnable {
+
+ int mCleanUid;
+
+ CleanCacheRunnable(int cleanUid) {
+ mCleanUid = cleanUid;
+ }
+
+ @Override
+ public void run() {
+ Pair<RemoteCallbackWrapper, CleanCacheRunnable> toolbarPair = mCache.get(mCleanUid);
+ if (toolbarPair != null) {
+ Log.w(TAG, "CleanCacheRunnable: remove " + mCleanUid + " from cache.");
+ mCache.remove(mCleanUid);
+ onToolbarShowTimeout(mCleanUid);
+ }
+ }
+ }
+
+ /**
+ * A listener to notify the service to the transfer touch focus.
+ */
+ public interface TransferTouchListener {
+ /**
+ * Notify the service to transfer the touch focus.
+ */
+ void onTransferTouch(IBinder source, IBinder target);
+ }
}
diff --git a/core/java/android/view/selectiontoolbar/ISelectionToolbarCallback.aidl b/core/java/android/view/selectiontoolbar/ISelectionToolbarCallback.aidl
index 48af7b96b195..aaeb12012f68 100644
--- a/core/java/android/view/selectiontoolbar/ISelectionToolbarCallback.aidl
+++ b/core/java/android/view/selectiontoolbar/ISelectionToolbarCallback.aidl
@@ -25,9 +25,8 @@ import android.view.selectiontoolbar.WidgetInfo;
*/
oneway interface ISelectionToolbarCallback {
void onShown(in WidgetInfo info);
- void onHidden(long widgetToken);
- void onDismissed(long widgetToken);
void onWidgetUpdated(in WidgetInfo info);
+ void onToolbarShowTimeout();
void onMenuItemClicked(in ToolbarMenuItem item);
void onError(int errorCode);
}
diff --git a/core/java/android/view/selectiontoolbar/SelectionContext.java b/core/java/android/view/selectiontoolbar/SelectionContext.java
deleted file mode 100644
index 21b8d8f11d25..000000000000
--- a/core/java/android/view/selectiontoolbar/SelectionContext.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * 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 android.view.selectiontoolbar;
-
-import android.annotation.NonNull;
-import android.os.Parcelable;
-
-import com.android.internal.util.DataClass;
-
-/**
- * The class holds information for a selection.
- *
- * @hide
- */
-@DataClass(genBuilder = true, genToString = true, genEqualsHashCode = true)
-public final class SelectionContext implements Parcelable {
-
- /**
- * The start index of a selection.
- */
- private final int mStartIndex;
-
- /**
- * The end index of a selection.
- */
- private final int mEndIndex;
-
-
-
- // Code below generated by codegen v1.0.23.
- //
- // DO NOT MODIFY!
- // CHECKSTYLE:OFF Generated code
- //
- // To regenerate run:
- // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/selectiontoolbar/SelectionContext.java
- //
- // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
- // Settings > Editor > Code Style > Formatter Control
- //@formatter:off
-
-
- @DataClass.Generated.Member
- /* package-private */ SelectionContext(
- int startIndex,
- int endIndex) {
- this.mStartIndex = startIndex;
- this.mEndIndex = endIndex;
-
- // onConstructed(); // You can define this method to get a callback
- }
-
- /**
- * The start index of a selection.
- */
- @DataClass.Generated.Member
- public int getStartIndex() {
- return mStartIndex;
- }
-
- /**
- * The end index of a selection.
- */
- @DataClass.Generated.Member
- public int getEndIndex() {
- return mEndIndex;
- }
-
- @Override
- @DataClass.Generated.Member
- public String toString() {
- // You can override field toString logic by defining methods like:
- // String fieldNameToString() { ... }
-
- return "SelectionContext { " +
- "startIndex = " + mStartIndex + ", " +
- "endIndex = " + mEndIndex +
- " }";
- }
-
- @Override
- @DataClass.Generated.Member
- public boolean equals(@android.annotation.Nullable Object o) {
- // You can override field equality logic by defining either of the methods like:
- // boolean fieldNameEquals(SelectionContext other) { ... }
- // boolean fieldNameEquals(FieldType otherValue) { ... }
-
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- @SuppressWarnings("unchecked")
- SelectionContext that = (SelectionContext) o;
- //noinspection PointlessBooleanExpression
- return true
- && mStartIndex == that.mStartIndex
- && mEndIndex == that.mEndIndex;
- }
-
- @Override
- @DataClass.Generated.Member
- public int hashCode() {
- // You can override field hashCode logic by defining methods like:
- // int fieldNameHashCode() { ... }
-
- int _hash = 1;
- _hash = 31 * _hash + mStartIndex;
- _hash = 31 * _hash + mEndIndex;
- return _hash;
- }
-
- @Override
- @DataClass.Generated.Member
- public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
- // You can override field parcelling by defining methods like:
- // void parcelFieldName(Parcel dest, int flags) { ... }
-
- dest.writeInt(mStartIndex);
- dest.writeInt(mEndIndex);
- }
-
- @Override
- @DataClass.Generated.Member
- public int describeContents() { return 0; }
-
- /** @hide */
- @SuppressWarnings({"unchecked", "RedundantCast"})
- @DataClass.Generated.Member
- /* package-private */ SelectionContext(@NonNull android.os.Parcel in) {
- // You can override field unparcelling by defining methods like:
- // static FieldType unparcelFieldName(Parcel in) { ... }
-
- int startIndex = in.readInt();
- int endIndex = in.readInt();
-
- this.mStartIndex = startIndex;
- this.mEndIndex = endIndex;
-
- // onConstructed(); // You can define this method to get a callback
- }
-
- @DataClass.Generated.Member
- public static final @NonNull Parcelable.Creator<SelectionContext> CREATOR
- = new Parcelable.Creator<SelectionContext>() {
- @Override
- public SelectionContext[] newArray(int size) {
- return new SelectionContext[size];
- }
-
- @Override
- public SelectionContext createFromParcel(@NonNull android.os.Parcel in) {
- return new SelectionContext(in);
- }
- };
-
- /**
- * A builder for {@link SelectionContext}
- */
- @SuppressWarnings("WeakerAccess")
- @DataClass.Generated.Member
- public static final class Builder {
-
- private int mStartIndex;
- private int mEndIndex;
-
- private long mBuilderFieldsSet = 0L;
-
- /**
- * Creates a new Builder.
- *
- * @param startIndex
- * The start index of a selection.
- * @param endIndex
- * The end index of a selection.
- */
- public Builder(
- int startIndex,
- int endIndex) {
- mStartIndex = startIndex;
- mEndIndex = endIndex;
- }
-
- /**
- * The start index of a selection.
- */
- @DataClass.Generated.Member
- public @NonNull Builder setStartIndex(int value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x1;
- mStartIndex = value;
- return this;
- }
-
- /**
- * The end index of a selection.
- */
- @DataClass.Generated.Member
- public @NonNull Builder setEndIndex(int value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x2;
- mEndIndex = value;
- return this;
- }
-
- /** Builds the instance. This builder should not be touched after calling this! */
- public @NonNull SelectionContext build() {
- checkNotUsed();
- mBuilderFieldsSet |= 0x4; // Mark builder used
-
- SelectionContext o = new SelectionContext(
- mStartIndex,
- mEndIndex);
- return o;
- }
-
- private void checkNotUsed() {
- if ((mBuilderFieldsSet & 0x4) != 0) {
- throw new IllegalStateException(
- "This Builder should not be reused. Use a new Builder instance instead");
- }
- }
- }
-
- @DataClass.Generated(
- time = 1639488292248L,
- codegenVersion = "1.0.23",
- sourceFile = "frameworks/base/core/java/android/view/selectiontoolbar/SelectionContext.java",
- inputSignatures = "private final int mStartIndex\nprivate final int mEndIndex\nclass SelectionContext extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genToString=true, genEqualsHashCode=true)")
- @Deprecated
- private void __metadata() {}
-
-
- //@formatter:on
- // End of generated code
-
-}
diff --git a/core/java/android/view/selectiontoolbar/SelectionToolbarManager.java b/core/java/android/view/selectiontoolbar/SelectionToolbarManager.java
index ba45b85e08a3..6de031628768 100644
--- a/core/java/android/view/selectiontoolbar/SelectionToolbarManager.java
+++ b/core/java/android/view/selectiontoolbar/SelectionToolbarManager.java
@@ -47,6 +47,16 @@ public final class SelectionToolbarManager {
private static final String REMOTE_SELECTION_TOOLBAR_ENABLED =
"remote_selection_toolbar_enabled";
+ /**
+ * Used to mark a toolbar that has no toolbar token id.
+ */
+ public static final long NO_TOOLBAR_ID = 0;
+
+ /**
+ * The error code that do not allow to create multiple toolbar.
+ */
+ public static final int ERROR_DO_NOT_ALLOW_MULTIPLE_TOOL_BAR = 1;
+
@NonNull
private final Context mContext;
private final ISelectionToolbarManager mService;
diff --git a/core/java/android/view/selectiontoolbar/ShowInfo.java b/core/java/android/view/selectiontoolbar/ShowInfo.java
index bbbd5c0df0b4..594b6bc7400a 100644
--- a/core/java/android/view/selectiontoolbar/ShowInfo.java
+++ b/core/java/android/view/selectiontoolbar/ShowInfo.java
@@ -17,10 +17,14 @@
package android.view.selectiontoolbar;
import android.annotation.NonNull;
+import android.graphics.Rect;
+import android.os.IBinder;
import android.os.Parcelable;
import com.android.internal.util.DataClass;
+import java.util.List;
+
/**
* The class holds menu information for render service to render the selection toolbar.
@@ -29,14 +33,47 @@ import com.android.internal.util.DataClass;
*/
@DataClass(genToString = true, genEqualsHashCode = true)
public final class ShowInfo implements Parcelable {
+
/**
* The token that is used to identify the selection toolbar. This is initially set to 0
* until a selection toolbar has been created for the showToolbar request.
*/
private final long mWidgetToken;
- // TODO: add members when the code really uses it
+ /**
+ * If the toolbar menu items need to be re-layout.
+ */
+ private final boolean mLayoutRequired;
+ /**
+ * The menu items to be rendered in the selection toolbar.
+ */
+ @NonNull
+ private final List<ToolbarMenuItem> mMenuItems;
+
+ /**
+ * A rect specifying where the selection toolbar on the screen.
+ */
+ @NonNull
+ private final Rect mContentRect;
+
+ /**
+ * A recommended maximum suggested width of the selection toolbar.
+ */
+ private final int mSuggestedWidth;
+
+ /**
+ * The portion of the screen that is available to the selection toolbar.
+ */
+ @NonNull
+ private final Rect mViewPortOnScreen;
+
+ /**
+ * The host application's input token, this allows the remote render service to transfer
+ * the touch focus to the host application.
+ */
+ @NonNull
+ private final IBinder mHostInputToken;
@@ -57,24 +94,108 @@ public final class ShowInfo implements Parcelable {
* Creates a new ShowInfo.
*
* @param widgetToken
- * The token that is used to identify the selection toolbar.
+ * The token that is used to identify the selection toolbar. This is initially set to 0
+ * until a selection toolbar has been created for the showToolbar request.
+ * @param layoutRequired
+ * If the toolbar menu items need to be re-layout.
+ * @param menuItems
+ * The menu items to be rendered in the selection toolbar.
+ * @param contentRect
+ * A rect specifying where the selection toolbar on the screen.
+ * @param suggestedWidth
+ * A recommended maximum suggested width of the selection toolbar.
+ * @param viewPortOnScreen
+ * The portion of the screen that is available to the selection toolbar.
+ * @param hostInputToken
+ * The host application's input token, this allows the remote render service to transfer
+ * the touch focus to the host application.
*/
@DataClass.Generated.Member
public ShowInfo(
- long widgetToken) {
+ long widgetToken,
+ boolean layoutRequired,
+ @NonNull List<ToolbarMenuItem> menuItems,
+ @NonNull Rect contentRect,
+ int suggestedWidth,
+ @NonNull Rect viewPortOnScreen,
+ @NonNull IBinder hostInputToken) {
this.mWidgetToken = widgetToken;
+ this.mLayoutRequired = layoutRequired;
+ this.mMenuItems = menuItems;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mMenuItems);
+ this.mContentRect = contentRect;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mContentRect);
+ this.mSuggestedWidth = suggestedWidth;
+ this.mViewPortOnScreen = viewPortOnScreen;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mViewPortOnScreen);
+ this.mHostInputToken = hostInputToken;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mHostInputToken);
// onConstructed(); // You can define this method to get a callback
}
/**
- * The token that is used to identify the selection toolbar.
+ * The token that is used to identify the selection toolbar. This is initially set to 0
+ * until a selection toolbar has been created for the showToolbar request.
*/
@DataClass.Generated.Member
public long getWidgetToken() {
return mWidgetToken;
}
+ /**
+ * If the toolbar menu items need to be re-layout.
+ */
+ @DataClass.Generated.Member
+ public boolean isLayoutRequired() {
+ return mLayoutRequired;
+ }
+
+ /**
+ * The menu items to be rendered in the selection toolbar.
+ */
+ @DataClass.Generated.Member
+ public @NonNull List<ToolbarMenuItem> getMenuItems() {
+ return mMenuItems;
+ }
+
+ /**
+ * A rect specifying where the selection toolbar on the screen.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Rect getContentRect() {
+ return mContentRect;
+ }
+
+ /**
+ * A recommended maximum suggested width of the selection toolbar.
+ */
+ @DataClass.Generated.Member
+ public int getSuggestedWidth() {
+ return mSuggestedWidth;
+ }
+
+ /**
+ * The portion of the screen that is available to the selection toolbar.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Rect getViewPortOnScreen() {
+ return mViewPortOnScreen;
+ }
+
+ /**
+ * The host application's input token, this allows the remote render service to transfer
+ * the touch focus to the host application.
+ */
+ @DataClass.Generated.Member
+ public @NonNull IBinder getHostInputToken() {
+ return mHostInputToken;
+ }
+
@Override
@DataClass.Generated.Member
public String toString() {
@@ -82,7 +203,13 @@ public final class ShowInfo implements Parcelable {
// String fieldNameToString() { ... }
return "ShowInfo { " +
- "widgetToken = " + mWidgetToken +
+ "widgetToken = " + mWidgetToken + ", " +
+ "layoutRequired = " + mLayoutRequired + ", " +
+ "menuItems = " + mMenuItems + ", " +
+ "contentRect = " + mContentRect + ", " +
+ "suggestedWidth = " + mSuggestedWidth + ", " +
+ "viewPortOnScreen = " + mViewPortOnScreen + ", " +
+ "hostInputToken = " + mHostInputToken +
" }";
}
@@ -99,7 +226,13 @@ public final class ShowInfo implements Parcelable {
ShowInfo that = (ShowInfo) o;
//noinspection PointlessBooleanExpression
return true
- && mWidgetToken == that.mWidgetToken;
+ && mWidgetToken == that.mWidgetToken
+ && mLayoutRequired == that.mLayoutRequired
+ && java.util.Objects.equals(mMenuItems, that.mMenuItems)
+ && java.util.Objects.equals(mContentRect, that.mContentRect)
+ && mSuggestedWidth == that.mSuggestedWidth
+ && java.util.Objects.equals(mViewPortOnScreen, that.mViewPortOnScreen)
+ && java.util.Objects.equals(mHostInputToken, that.mHostInputToken);
}
@Override
@@ -110,6 +243,12 @@ public final class ShowInfo implements Parcelable {
int _hash = 1;
_hash = 31 * _hash + Long.hashCode(mWidgetToken);
+ _hash = 31 * _hash + Boolean.hashCode(mLayoutRequired);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mMenuItems);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mContentRect);
+ _hash = 31 * _hash + mSuggestedWidth;
+ _hash = 31 * _hash + java.util.Objects.hashCode(mViewPortOnScreen);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mHostInputToken);
return _hash;
}
@@ -119,7 +258,15 @@ public final class ShowInfo implements Parcelable {
// You can override field parcelling by defining methods like:
// void parcelFieldName(Parcel dest, int flags) { ... }
+ byte flg = 0;
+ if (mLayoutRequired) flg |= 0x2;
+ dest.writeByte(flg);
dest.writeLong(mWidgetToken);
+ dest.writeParcelableList(mMenuItems, flags);
+ dest.writeTypedObject(mContentRect, flags);
+ dest.writeInt(mSuggestedWidth);
+ dest.writeTypedObject(mViewPortOnScreen, flags);
+ dest.writeStrongBinder(mHostInputToken);
}
@Override
@@ -133,9 +280,31 @@ public final class ShowInfo implements Parcelable {
// You can override field unparcelling by defining methods like:
// static FieldType unparcelFieldName(Parcel in) { ... }
+ byte flg = in.readByte();
+ boolean layoutRequired = (flg & 0x2) != 0;
long widgetToken = in.readLong();
+ List<ToolbarMenuItem> menuItems = new java.util.ArrayList<>();
+ in.readParcelableList(menuItems, ToolbarMenuItem.class.getClassLoader());
+ Rect contentRect = (Rect) in.readTypedObject(Rect.CREATOR);
+ int suggestedWidth = in.readInt();
+ Rect viewPortOnScreen = (Rect) in.readTypedObject(Rect.CREATOR);
+ IBinder hostInputToken = (IBinder) in.readStrongBinder();
this.mWidgetToken = widgetToken;
+ this.mLayoutRequired = layoutRequired;
+ this.mMenuItems = menuItems;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mMenuItems);
+ this.mContentRect = contentRect;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mContentRect);
+ this.mSuggestedWidth = suggestedWidth;
+ this.mViewPortOnScreen = viewPortOnScreen;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mViewPortOnScreen);
+ this.mHostInputToken = hostInputToken;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mHostInputToken);
// onConstructed(); // You can define this method to get a callback
}
@@ -155,10 +324,10 @@ public final class ShowInfo implements Parcelable {
};
@DataClass.Generated(
- time = 1639488262761L,
+ time = 1643186262604L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/view/selectiontoolbar/ShowInfo.java",
- inputSignatures = "private final long mWidgetToken\nclass ShowInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genEqualsHashCode=true)")
+ inputSignatures = "private final long mWidgetToken\nprivate final boolean mLayoutRequired\nprivate final @android.annotation.NonNull java.util.List<android.view.selectiontoolbar.ToolbarMenuItem> mMenuItems\nprivate final @android.annotation.NonNull android.graphics.Rect mContentRect\nprivate final int mSuggestedWidth\nprivate final @android.annotation.NonNull android.graphics.Rect mViewPortOnScreen\nprivate final @android.annotation.NonNull android.os.IBinder mHostInputToken\nclass ShowInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genEqualsHashCode=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/view/selectiontoolbar/ToolbarMenuItem.java b/core/java/android/view/selectiontoolbar/ToolbarMenuItem.java
index 5af232c7a34d..89347c613310 100644
--- a/core/java/android/view/selectiontoolbar/ToolbarMenuItem.java
+++ b/core/java/android/view/selectiontoolbar/ToolbarMenuItem.java
@@ -18,7 +18,9 @@ package android.view.selectiontoolbar;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.graphics.drawable.Icon;
import android.os.Parcelable;
+import android.view.MenuItem;
import com.android.internal.util.DataClass;
@@ -31,10 +33,84 @@ import com.android.internal.util.DataClass;
public final class ToolbarMenuItem implements Parcelable {
/**
+ * The priority of menu item is unknown.
+ */
+ public static final int PRIORITY_UNKNOWN = 0;
+
+ /**
+ * The priority of menu item is shown in primary selection toolbar.
+ */
+ public static final int PRIORITY_PRIMARY = 1;
+
+ /**
+ * The priority of menu item is shown in overflow selection toolbar.
+ */
+ public static final int PRIORITY_OVERFLOW = 2;
+
+ /**
* The id of the menu item.
+ *
+ * @see MenuItem#getItemId()
*/
private final int mItemId;
+ /**
+ * The title of the menu item.
+ *
+ * @see MenuItem#getTitle()
+ */
+ @NonNull
+ private final CharSequence mTitle;
+
+ /**
+ * The content description of the menu item.
+ *
+ * @see MenuItem#getContentDescription()
+ */
+ @Nullable
+ private final CharSequence mContentDescription;
+
+ /**
+ * The group id of the menu item.
+ *
+ * @see MenuItem#getGroupId()
+ */
+ private final int mGroupId;
+
+ /**
+ * The icon id of the menu item.
+ *
+ * @see MenuItem#getIcon()
+ */
+ @Nullable
+ private final Icon mIcon;
+
+ /**
+ * The tooltip text of the menu item.
+ *
+ * @see MenuItem#getTooltipText()
+ */
+ @Nullable
+ private final CharSequence mTooltipText;
+
+ /**
+ * The priority of the menu item used to display the order of the menu item.
+ */
+ private final int mPriority;
+
+ /**
+ * Returns the priority from a given {@link MenuItem}.
+ */
+ public static int getPriorityFromMenuItem(MenuItem menuItem) {
+ if (menuItem.requiresActionButton()) {
+ return PRIORITY_PRIMARY;
+ } else if (menuItem.requiresOverflow()) {
+ return PRIORITY_OVERFLOW;
+ }
+ return PRIORITY_UNKNOWN;
+ }
+
+
// Code below generated by codegen v1.0.23.
@@ -50,22 +126,118 @@ public final class ToolbarMenuItem implements Parcelable {
//@formatter:off
+ @android.annotation.IntDef(prefix = "PRIORITY_", value = {
+ PRIORITY_UNKNOWN,
+ PRIORITY_PRIMARY,
+ PRIORITY_OVERFLOW
+ })
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
+ @DataClass.Generated.Member
+ public @interface Priority {}
+
+ @DataClass.Generated.Member
+ public static String priorityToString(@Priority int value) {
+ switch (value) {
+ case PRIORITY_UNKNOWN:
+ return "PRIORITY_UNKNOWN";
+ case PRIORITY_PRIMARY:
+ return "PRIORITY_PRIMARY";
+ case PRIORITY_OVERFLOW:
+ return "PRIORITY_OVERFLOW";
+ default: return Integer.toHexString(value);
+ }
+ }
+
@DataClass.Generated.Member
/* package-private */ ToolbarMenuItem(
- int itemId) {
+ int itemId,
+ @NonNull CharSequence title,
+ @Nullable CharSequence contentDescription,
+ int groupId,
+ @Nullable Icon icon,
+ @Nullable CharSequence tooltipText,
+ int priority) {
this.mItemId = itemId;
+ this.mTitle = title;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mTitle);
+ this.mContentDescription = contentDescription;
+ this.mGroupId = groupId;
+ this.mIcon = icon;
+ this.mTooltipText = tooltipText;
+ this.mPriority = priority;
// onConstructed(); // You can define this method to get a callback
}
/**
* The id of the menu item.
+ *
+ * @see MenuItem#getItemId()
*/
@DataClass.Generated.Member
public int getItemId() {
return mItemId;
}
+ /**
+ * The title of the menu item.
+ *
+ * @see MenuItem#getTitle()
+ */
+ @DataClass.Generated.Member
+ public @NonNull CharSequence getTitle() {
+ return mTitle;
+ }
+
+ /**
+ * The content description of the menu item.
+ *
+ * @see MenuItem#getContentDescription()
+ */
+ @DataClass.Generated.Member
+ public @Nullable CharSequence getContentDescription() {
+ return mContentDescription;
+ }
+
+ /**
+ * The group id of the menu item.
+ *
+ * @see MenuItem#getGroupId()
+ */
+ @DataClass.Generated.Member
+ public int getGroupId() {
+ return mGroupId;
+ }
+
+ /**
+ * The icon id of the menu item.
+ *
+ * @see MenuItem#getIcon()
+ */
+ @DataClass.Generated.Member
+ public @Nullable Icon getIcon() {
+ return mIcon;
+ }
+
+ /**
+ * The tooltip text of the menu item.
+ *
+ * @see MenuItem#getTooltipText()
+ */
+ @DataClass.Generated.Member
+ public @Nullable CharSequence getTooltipText() {
+ return mTooltipText;
+ }
+
+ /**
+ * The priority of the menu item used to display the order of the menu item.
+ */
+ @DataClass.Generated.Member
+ public int getPriority() {
+ return mPriority;
+ }
+
@Override
@DataClass.Generated.Member
public String toString() {
@@ -73,7 +245,13 @@ public final class ToolbarMenuItem implements Parcelable {
// String fieldNameToString() { ... }
return "ToolbarMenuItem { " +
- "itemId = " + mItemId +
+ "itemId = " + mItemId + ", " +
+ "title = " + mTitle + ", " +
+ "contentDescription = " + mContentDescription + ", " +
+ "groupId = " + mGroupId + ", " +
+ "icon = " + mIcon + ", " +
+ "tooltipText = " + mTooltipText + ", " +
+ "priority = " + mPriority +
" }";
}
@@ -90,7 +268,13 @@ public final class ToolbarMenuItem implements Parcelable {
ToolbarMenuItem that = (ToolbarMenuItem) o;
//noinspection PointlessBooleanExpression
return true
- && mItemId == that.mItemId;
+ && mItemId == that.mItemId
+ && java.util.Objects.equals(mTitle, that.mTitle)
+ && java.util.Objects.equals(mContentDescription, that.mContentDescription)
+ && mGroupId == that.mGroupId
+ && java.util.Objects.equals(mIcon, that.mIcon)
+ && java.util.Objects.equals(mTooltipText, that.mTooltipText)
+ && mPriority == that.mPriority;
}
@Override
@@ -101,6 +285,12 @@ public final class ToolbarMenuItem implements Parcelable {
int _hash = 1;
_hash = 31 * _hash + mItemId;
+ _hash = 31 * _hash + java.util.Objects.hashCode(mTitle);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mContentDescription);
+ _hash = 31 * _hash + mGroupId;
+ _hash = 31 * _hash + java.util.Objects.hashCode(mIcon);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mTooltipText);
+ _hash = 31 * _hash + mPriority;
return _hash;
}
@@ -110,7 +300,18 @@ public final class ToolbarMenuItem implements Parcelable {
// You can override field parcelling by defining methods like:
// void parcelFieldName(Parcel dest, int flags) { ... }
+ byte flg = 0;
+ if (mContentDescription != null) flg |= 0x4;
+ if (mIcon != null) flg |= 0x10;
+ if (mTooltipText != null) flg |= 0x20;
+ dest.writeByte(flg);
dest.writeInt(mItemId);
+ dest.writeCharSequence(mTitle);
+ if (mContentDescription != null) dest.writeCharSequence(mContentDescription);
+ dest.writeInt(mGroupId);
+ if (mIcon != null) dest.writeTypedObject(mIcon, flags);
+ if (mTooltipText != null) dest.writeCharSequence(mTooltipText);
+ dest.writeInt(mPriority);
}
@Override
@@ -124,9 +325,24 @@ public final class ToolbarMenuItem implements Parcelable {
// You can override field unparcelling by defining methods like:
// static FieldType unparcelFieldName(Parcel in) { ... }
+ byte flg = in.readByte();
int itemId = in.readInt();
+ CharSequence title = (CharSequence) in.readCharSequence();
+ CharSequence contentDescription = (flg & 0x4) == 0 ? null : (CharSequence) in.readCharSequence();
+ int groupId = in.readInt();
+ Icon icon = (flg & 0x10) == 0 ? null : (Icon) in.readTypedObject(Icon.CREATOR);
+ CharSequence tooltipText = (flg & 0x20) == 0 ? null : (CharSequence) in.readCharSequence();
+ int priority = in.readInt();
this.mItemId = itemId;
+ this.mTitle = title;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mTitle);
+ this.mContentDescription = contentDescription;
+ this.mGroupId = groupId;
+ this.mIcon = icon;
+ this.mTooltipText = tooltipText;
+ this.mPriority = priority;
// onConstructed(); // You can define this method to get a callback
}
@@ -153,6 +369,12 @@ public final class ToolbarMenuItem implements Parcelable {
public static final class Builder {
private int mItemId;
+ private @NonNull CharSequence mTitle;
+ private @Nullable CharSequence mContentDescription;
+ private int mGroupId;
+ private @Nullable Icon mIcon;
+ private @Nullable CharSequence mTooltipText;
+ private int mPriority;
private long mBuilderFieldsSet = 0L;
@@ -161,14 +383,42 @@ public final class ToolbarMenuItem implements Parcelable {
*
* @param itemId
* The id of the menu item.
+ * @param title
+ * The title of the menu item.
+ * @param contentDescription
+ * The content description of the menu item.
+ * @param groupId
+ * The group id of the menu item.
+ * @param icon
+ * The icon id of the menu item.
+ * @param tooltipText
+ * The tooltip text of the menu item.
+ * @param priority
+ * The priority of the menu item used to display the order of the menu item.
*/
public Builder(
- int itemId) {
+ int itemId,
+ @NonNull CharSequence title,
+ @Nullable CharSequence contentDescription,
+ int groupId,
+ @Nullable Icon icon,
+ @Nullable CharSequence tooltipText,
+ int priority) {
mItemId = itemId;
+ mTitle = title;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mTitle);
+ mContentDescription = contentDescription;
+ mGroupId = groupId;
+ mIcon = icon;
+ mTooltipText = tooltipText;
+ mPriority = priority;
}
/**
* The id of the menu item.
+ *
+ * @see MenuItem#getItemId()
*/
@DataClass.Generated.Member
public @NonNull Builder setItemId(int value) {
@@ -178,18 +428,100 @@ public final class ToolbarMenuItem implements Parcelable {
return this;
}
+ /**
+ * The title of the menu item.
+ *
+ * @see MenuItem#getTitle()
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setTitle(@NonNull CharSequence value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x2;
+ mTitle = value;
+ return this;
+ }
+
+ /**
+ * The content description of the menu item.
+ *
+ * @see MenuItem#getContentDescription()
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setContentDescription(@NonNull CharSequence value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x4;
+ mContentDescription = value;
+ return this;
+ }
+
+ /**
+ * The group id of the menu item.
+ *
+ * @see MenuItem#getGroupId()
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setGroupId(int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x8;
+ mGroupId = value;
+ return this;
+ }
+
+ /**
+ * The icon id of the menu item.
+ *
+ * @see MenuItem#getIcon()
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setIcon(@NonNull Icon value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x10;
+ mIcon = value;
+ return this;
+ }
+
+ /**
+ * The tooltip text of the menu item.
+ *
+ * @see MenuItem#getTooltipText()
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setTooltipText(@NonNull CharSequence value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x20;
+ mTooltipText = value;
+ return this;
+ }
+
+ /**
+ * The priority of the menu item used to display the order of the menu item.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setPriority(int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x40;
+ mPriority = value;
+ return this;
+ }
+
/** Builds the instance. This builder should not be touched after calling this! */
public @NonNull ToolbarMenuItem build() {
checkNotUsed();
- mBuilderFieldsSet |= 0x2; // Mark builder used
+ mBuilderFieldsSet |= 0x80; // Mark builder used
ToolbarMenuItem o = new ToolbarMenuItem(
- mItemId);
+ mItemId,
+ mTitle,
+ mContentDescription,
+ mGroupId,
+ mIcon,
+ mTooltipText,
+ mPriority);
return o;
}
private void checkNotUsed() {
- if ((mBuilderFieldsSet & 0x2) != 0) {
+ if ((mBuilderFieldsSet & 0x80) != 0) {
throw new IllegalStateException(
"This Builder should not be reused. Use a new Builder instance instead");
}
@@ -197,10 +529,10 @@ public final class ToolbarMenuItem implements Parcelable {
}
@DataClass.Generated(
- time = 1639488328542L,
+ time = 1643200806234L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/view/selectiontoolbar/ToolbarMenuItem.java",
- inputSignatures = "private final int mItemId\nclass ToolbarMenuItem extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genToString=true, genEqualsHashCode=true)")
+ inputSignatures = "public static final int PRIORITY_UNKNOWN\npublic static final int PRIORITY_PRIMARY\npublic static final int PRIORITY_OVERFLOW\nprivate final int mItemId\nprivate final @android.annotation.NonNull java.lang.CharSequence mTitle\nprivate final @android.annotation.Nullable java.lang.CharSequence mContentDescription\nprivate final int mGroupId\nprivate final @android.annotation.Nullable android.graphics.drawable.Icon mIcon\nprivate final @android.annotation.Nullable java.lang.CharSequence mTooltipText\nprivate final int mPriority\npublic static int getPriorityFromMenuItem(android.view.MenuItem)\nclass ToolbarMenuItem extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genToString=true, genEqualsHashCode=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/view/selectiontoolbar/WidgetInfo.java b/core/java/android/view/selectiontoolbar/WidgetInfo.java
index 961d8ac8e5e0..5d0fd473c914 100644
--- a/core/java/android/view/selectiontoolbar/WidgetInfo.java
+++ b/core/java/android/view/selectiontoolbar/WidgetInfo.java
@@ -17,7 +17,10 @@
package android.view.selectiontoolbar;
import android.annotation.NonNull;
+import android.graphics.Rect;
+import android.os.Parcel;
import android.os.Parcelable;
+import android.view.SurfaceControlViewHost;
import com.android.internal.util.DataClass;
@@ -35,7 +38,18 @@ public final class WidgetInfo implements Parcelable {
*/
private final long mWidgetToken;
- // TODO: add members when the code really uses it
+ /**
+ * A Rect that defines the size and positioning of the remote view with respect to
+ * its host window.
+ */
+ @NonNull
+ private final Rect mContentRect;
+
+ /**
+ * The SurfacePackage pointing to the remote view.
+ */
+ @NonNull
+ private final SurfaceControlViewHost.SurfacePackage mSurfacePackage;
@@ -57,11 +71,24 @@ public final class WidgetInfo implements Parcelable {
*
* @param widgetToken
* The token that is used to identify the selection toolbar.
+ * @param contentRect
+ * A Rect that defines the size and positioning of the remote view with respect to
+ * its host window.
+ * @param surfacePackage
+ * The SurfacePackage pointing to the remote view.
*/
@DataClass.Generated.Member
public WidgetInfo(
- long widgetToken) {
+ long widgetToken,
+ @NonNull Rect contentRect,
+ @NonNull SurfaceControlViewHost.SurfacePackage surfacePackage) {
this.mWidgetToken = widgetToken;
+ this.mContentRect = contentRect;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mContentRect);
+ this.mSurfacePackage = surfacePackage;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mSurfacePackage);
// onConstructed(); // You can define this method to get a callback
}
@@ -74,6 +101,23 @@ public final class WidgetInfo implements Parcelable {
return mWidgetToken;
}
+ /**
+ * A Rect that defines the size and positioning of the remote view with respect to
+ * its host window.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Rect getContentRect() {
+ return mContentRect;
+ }
+
+ /**
+ * The SurfacePackage pointing to the remote view.
+ */
+ @DataClass.Generated.Member
+ public @NonNull SurfaceControlViewHost.SurfacePackage getSurfacePackage() {
+ return mSurfacePackage;
+ }
+
@Override
@DataClass.Generated.Member
public String toString() {
@@ -81,7 +125,9 @@ public final class WidgetInfo implements Parcelable {
// String fieldNameToString() { ... }
return "WidgetInfo { " +
- "widgetToken = " + mWidgetToken +
+ "widgetToken = " + mWidgetToken + ", " +
+ "contentRect = " + mContentRect + ", " +
+ "surfacePackage = " + mSurfacePackage +
" }";
}
@@ -98,7 +144,9 @@ public final class WidgetInfo implements Parcelable {
WidgetInfo that = (WidgetInfo) o;
//noinspection PointlessBooleanExpression
return true
- && mWidgetToken == that.mWidgetToken;
+ && mWidgetToken == that.mWidgetToken
+ && java.util.Objects.equals(mContentRect, that.mContentRect)
+ && java.util.Objects.equals(mSurfacePackage, that.mSurfacePackage);
}
@Override
@@ -109,16 +157,20 @@ public final class WidgetInfo implements Parcelable {
int _hash = 1;
_hash = 31 * _hash + Long.hashCode(mWidgetToken);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mContentRect);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mSurfacePackage);
return _hash;
}
@Override
@DataClass.Generated.Member
- public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
// You can override field parcelling by defining methods like:
// void parcelFieldName(Parcel dest, int flags) { ... }
dest.writeLong(mWidgetToken);
+ dest.writeTypedObject(mContentRect, flags);
+ dest.writeTypedObject(mSurfacePackage, flags);
}
@Override
@@ -128,13 +180,21 @@ public final class WidgetInfo implements Parcelable {
/** @hide */
@SuppressWarnings({"unchecked", "RedundantCast"})
@DataClass.Generated.Member
- /* package-private */ WidgetInfo(@NonNull android.os.Parcel in) {
+ /* package-private */ WidgetInfo(@NonNull Parcel in) {
// You can override field unparcelling by defining methods like:
// static FieldType unparcelFieldName(Parcel in) { ... }
long widgetToken = in.readLong();
+ Rect contentRect = (Rect) in.readTypedObject(Rect.CREATOR);
+ SurfaceControlViewHost.SurfacePackage surfacePackage = (SurfaceControlViewHost.SurfacePackage) in.readTypedObject(SurfaceControlViewHost.SurfacePackage.CREATOR);
this.mWidgetToken = widgetToken;
+ this.mContentRect = contentRect;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mContentRect);
+ this.mSurfacePackage = surfacePackage;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mSurfacePackage);
// onConstructed(); // You can define this method to get a callback
}
@@ -148,16 +208,16 @@ public final class WidgetInfo implements Parcelable {
}
@Override
- public WidgetInfo createFromParcel(@NonNull android.os.Parcel in) {
+ public WidgetInfo createFromParcel(@NonNull Parcel in) {
return new WidgetInfo(in);
}
};
@DataClass.Generated(
- time = 1639488254020L,
+ time = 1643281495056L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/view/selectiontoolbar/WidgetInfo.java",
- inputSignatures = "private final long mWidgetToken\nclass WidgetInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genEqualsHashCode=true)")
+ inputSignatures = "private final long mWidgetToken\nprivate final @android.annotation.NonNull android.graphics.Rect mContentRect\nprivate final @android.annotation.NonNull android.view.SurfaceControlViewHost.SurfacePackage mSurfacePackage\nclass WidgetInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genEqualsHashCode=true)")
@Deprecated
private void __metadata() {}