Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1d76c1cc authored by Evan Severson's avatar Evan Severson
Browse files

Pass a unique identifier for the remote toolbar menu item

The MenuItem itemId is not guaranteed to be unique. For example custom
text processors are assigned Menu.NONE by android.widget.Editor.
Locallay implemented toolbar doesn't need this since it can rely on
using the same reference so we only need this for IPC.

We also fix issues with synchronization of what the local and remote
indend the toolbar to consist of, including process death.

Test: Manual
Bug: 363318732
Flag: android.permission.flags.system_selection_toolbar_enabled
Change-Id: I1bd0f329bef676955747d2df806e57b1b9972fe9
parent 318fcc18
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.service.selectiontoolbar;

import static android.view.selectiontoolbar.ISelectionToolbarCallback.ERROR_DO_NOT_ALLOW_MULTIPLE_TOOL_BAR;
import static android.view.selectiontoolbar.ISelectionToolbarCallback.ERROR_UNKNOWN_WIDGET_TOKEN;
import static android.view.selectiontoolbar.SelectionToolbarManager.NO_TOOLBAR_ID;

import android.util.Pair;
@@ -60,8 +61,9 @@ public final class DefaultSelectionToolbarRenderService extends SelectionToolbar
    public void onShow(int callingUid, ShowInfo showInfo,
            SelectionToolbarRenderService.RemoteCallbackWrapper callbackWrapper) {
        if (isToolbarShown(callingUid, showInfo)) {
            // TODO can we remove this check and just update the widget with dismissing?
            Slog.e(TAG, "Do not allow multiple toolbar for the app.");
            callbackWrapper.onError(ERROR_DO_NOT_ALLOW_MULTIPLE_TOOL_BAR);
            callbackWrapper.onError(ERROR_DO_NOT_ALLOW_MULTIPLE_TOOL_BAR, showInfo.sequenceNumber);
            return;
        }
        long widgetToken = showInfo.widgetToken == NO_TOOLBAR_ID
@@ -80,6 +82,7 @@ public final class DefaultSelectionToolbarRenderService extends SelectionToolbar
            toolbarPair.second.show(showInfo);
        } else {
            Slog.w(TAG, "onShow() for unknown " + widgetToken);
            callbackWrapper.onError(ERROR_UNKNOWN_WIDGET_TOKEN, showInfo.sequenceNumber);
        }
    }

@@ -114,6 +117,16 @@ public final class DefaultSelectionToolbarRenderService extends SelectionToolbar
        }
    }

    @Override
    public void onUidDied(int callingUid) {
        Slog.w(TAG, "onUidDied for callingUid = " + callingUid);
        Pair<Long, RemoteSelectionToolbar> toolbarPair = mToolbarCache.removeReturnOld(callingUid);
        if (toolbarPair != null) {
            RemoteSelectionToolbar remoteToolbar = toolbarPair.second;
            remoteToolbar.dismiss(toolbarPair.first);
        }
    }

    private RemoteSelectionToolbar getRemoteSelectionToolbarByToken(long widgetToken) {
        for (int i = 0; i < mToolbarCache.size(); i++) {
            Pair<Long, RemoteSelectionToolbar> toolbarPair = mToolbarCache.valueAt(i);
+1 −0
Original line number Diff line number Diff line
@@ -29,4 +29,5 @@ oneway interface ISelectionToolbarRenderService {
    void onShow(int callingUid, in ShowInfo showInfo, in ISelectionToolbarCallback callback);
    void onHide(long widgetToken);
    void onDismiss(int callingUid, long widgetToken);
    void onUidDied(int callingUid);
}
+5 −2
Original line number Diff line number Diff line
@@ -125,6 +125,7 @@ final class RemoteSelectionToolbar {
    private int mPopupHeight;
    // Coordinates to show the toolbar relative to the specified view port
    private final Point mRelativeCoordsForToolbar = new Point();
    private int mSequenceNumber;
    private List<ToolbarMenuItem> mMenuItems;
    private SurfaceControlViewHost mSurfaceControlViewHost;
    private SurfaceControlViewHost.SurfacePackage mSurfacePackage;
@@ -245,7 +246,7 @@ final class RemoteSelectionToolbar {
            if (!(tag instanceof ToolbarMenuItem)) {
                return;
            }
            mCallbackWrapper.onMenuItemClicked((ToolbarMenuItem) tag);
            mCallbackWrapper.onMenuItemClicked(((ToolbarMenuItem) tag).itemIndex);
        };
    }

@@ -268,6 +269,7 @@ final class RemoteSelectionToolbar {
                mRelativeCoordsForToolbar.x + mPopupWidth,
                mRelativeCoordsForToolbar.y + mPopupHeight);
        WidgetInfo widgetInfo = new WidgetInfo();
        widgetInfo.sequenceNumber = mSequenceNumber;
        widgetInfo.widgetToken = mSelectionToolbarToken;
        widgetInfo.contentRect = mTempContentRect;
        widgetInfo.surfacePackage = getSurfacePackage();
@@ -313,6 +315,7 @@ final class RemoteSelectionToolbar {
    public void show(ShowInfo showInfo) {
        debugLog("show() for " + showInfo);

        mSequenceNumber = showInfo.sequenceNumber;
        mMenuItems = showInfo.menuItems;
        mViewPortOnScreen.set(showInfo.viewPortOnScreen);

@@ -1090,7 +1093,7 @@ final class RemoteSelectionToolbar {
        overflowPanel.setOnItemClickListener((parent, view, position, id) -> {
            ToolbarMenuItem menuItem =
                    (ToolbarMenuItem) overflowPanel.getAdapter().getItem(position);
            mCallbackWrapper.onMenuItemClicked(menuItem);
            mCallbackWrapper.onMenuItemClicked(menuItem.itemIndex);
        });
        return overflowPanel;
    }
+3 −4
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package android.service.selectiontoolbar;

import android.view.selectiontoolbar.ToolbarMenuItem;
import android.view.selectiontoolbar.WidgetInfo;

/**
@@ -35,9 +34,9 @@ public interface SelectionToolbarRenderCallback {
     */
    void onWidgetUpdated(WidgetInfo info);
    /**
     * The menu item on the selection toolbar has been clicked.
     * The menu item index on the selection toolbar has been clicked.
     */
    void onMenuItemClicked(ToolbarMenuItem item);
    void onMenuItemClicked(int itemIndex);
    /**
     * The toolbar doesn't be dismissed after showing on a given timeout.
     */
@@ -45,5 +44,5 @@ public interface SelectionToolbarRenderCallback {
    /**
     * The error occurred when operating on the selection toolbar.
     */
    void onError(int errorCode);
    void onError(int errorCode, int sequenceNumber);
}
+42 −11
Original line number Diff line number Diff line
@@ -32,7 +32,6 @@ import android.util.Pair;
import android.util.SparseArray;
import android.view.selectiontoolbar.ISelectionToolbarCallback;
import android.view.selectiontoolbar.ShowInfo;
import android.view.selectiontoolbar.ToolbarMenuItem;
import android.view.selectiontoolbar.WidgetInfo;

import java.util.concurrent.TimeUnit;
@@ -80,8 +79,20 @@ public abstract class SelectionToolbarRenderService extends Service {
                public void onShow(int callingUid, ShowInfo showInfo,
                        ISelectionToolbarCallback callback) {
                    if (mCache.indexOfKey(callingUid) < 0) {
                        mCache.put(callingUid, new Pair<>(new RemoteCallbackWrapper(callback),
                        try {
                            DeathRecipient deathRecipient = () -> {
                                mHandler.removeCallbacks(mCache.get(callingUid).second);
                                mCache.remove(callingUid);
                                onUidDied(callingUid);
                            };
                            callback.asBinder().linkToDeath(deathRecipient, 0);
                            mCache.put(callingUid,
                                    new Pair<>(new RemoteCallbackWrapper(callback, deathRecipient),
                                            new CleanCacheRunnable(callingUid)));
                        } catch (RemoteException e) {
                            Log.e(TAG, "ISelectionToolbarCallback has already died");
                            return;
                        }
                    }
                    Pair<RemoteCallbackWrapper, CleanCacheRunnable> toolbarPair = mCache.get(
                            callingUid);
@@ -108,6 +119,7 @@ public abstract class SelectionToolbarRenderService extends Service {
                    if (toolbarPair != null) {
                        mHandler.removeCallbacks(toolbarPair.second);
                        mCache.remove(callingUid);
                        toolbarPair.first.unlinkToDeath();
                    }
                }

@@ -117,6 +129,12 @@ public abstract class SelectionToolbarRenderService extends Service {
                            obtainMessage(SelectionToolbarRenderService::handleOnConnected,
                                    SelectionToolbarRenderService.this, callback));
                }

                @Override
                public void onUidDied(int callingUid) {
                    mHandler.sendMessage(obtainMessage(SelectionToolbarRenderService::onUidDied,
                            SelectionToolbarRenderService.this, callingUid));
                }
            };

    @CallSuper
@@ -174,9 +192,12 @@ public abstract class SelectionToolbarRenderService extends Service {
     * 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
    }
    public abstract void onToolbarShowTimeout(int callingUid);

    /**
     * Called when the client process dies.
     */
    public abstract void onUidDied(int callingUid);

    /**
     * Callback to notify the client toolbar events.
@@ -185,9 +206,17 @@ public abstract class SelectionToolbarRenderService extends Service {

        private final ISelectionToolbarCallback mRemoteCallback;

        RemoteCallbackWrapper(ISelectionToolbarCallback remoteCallback) {
        private final IBinder.DeathRecipient mDeathRecipient;

        RemoteCallbackWrapper(ISelectionToolbarCallback remoteCallback,
                IBinder.DeathRecipient deathRecipient) {
            // TODO(b/215497659): handle if the binder dies.
            mRemoteCallback = remoteCallback;
            mDeathRecipient = deathRecipient;
        }

        private void unlinkToDeath() {
            mRemoteCallback.asBinder().unlinkToDeath(mDeathRecipient, 0);
        }

        @Override
@@ -202,6 +231,7 @@ public abstract class SelectionToolbarRenderService extends Service {
        @Override
        public void onToolbarShowTimeout() {
            try {
                unlinkToDeath();
                mRemoteCallback.onToolbarShowTimeout();
            } catch (RemoteException e) {
                // no-op
@@ -218,18 +248,19 @@ public abstract class SelectionToolbarRenderService extends Service {
        }

        @Override
        public void onMenuItemClicked(ToolbarMenuItem item) {
        public void onMenuItemClicked(int itemIndex) {
            try {
                mRemoteCallback.onMenuItemClicked(item);
                mRemoteCallback.onMenuItemClicked(itemIndex);
            } catch (RemoteException e) {
                // no-op
            }
        }

        @Override
        public void onError(int errorCode) {
        public void onError(int errorCode, int sequenceNumber) {
            try {
                mRemoteCallback.onError(errorCode);
                unlinkToDeath();
                mRemoteCallback.onError(errorCode, sequenceNumber);
            } catch (RemoteException e) {
                // no-op
            }
Loading