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

Commit c12e4bcb authored by Joanne Chung's avatar Joanne Chung Committed by Android (Google) Code Review
Browse files

Merge "Remove selection toolbar code from build time" into main

parents 0be13007 cc8461dd
Loading
Loading
Loading
Loading
+0 −13
Original line number Diff line number Diff line
@@ -237,8 +237,6 @@ import android.view.contentcapture.ContentCaptureManager;
import android.view.contentcapture.IContentCaptureManager;
import android.view.displayhash.DisplayHashManager;
import android.view.inputmethod.InputMethodManager;
import android.view.selectiontoolbar.ISelectionToolbarManager;
import android.view.selectiontoolbar.SelectionToolbarManager;
import android.view.textclassifier.TextClassificationManager;
import android.view.textservice.TextServicesManager;
import android.view.translation.ITranslationManager;
@@ -379,17 +377,6 @@ public final class SystemServiceRegistry {
                return new TextClassificationManager(ctx);
            }});

        registerService(Context.SELECTION_TOOLBAR_SERVICE, SelectionToolbarManager.class,
                new CachedServiceFetcher<SelectionToolbarManager>() {
                    @Override
                    public SelectionToolbarManager createService(ContextImpl ctx)
                            throws ServiceNotFoundException {
                        IBinder b = ServiceManager.getServiceOrThrow(
                                Context.SELECTION_TOOLBAR_SERVICE);
                        return new SelectionToolbarManager(ctx.getOuterContext(),
                                ISelectionToolbarManager.Stub.asInterface(b));
                    }});

        registerService(Context.FONT_SERVICE, FontManager.class,
                new CachedServiceFetcher<FontManager>() {
            @Override
+0 −153
Original line number Diff line number Diff line
/*
 * 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.service.selectiontoolbar;

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.io.FileDescriptor;
import java.io.PrintWriter;
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
public final class DefaultSelectionToolbarRenderService extends SelectionToolbarRenderService {

    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(int callingUid, ShowInfo showInfo,
            SelectionToolbarRenderService.RemoteCallbackWrapper callbackWrapper) {
        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,
                    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) {
        RemoteSelectionToolbar toolbar = getRemoteSelectionToolbarByTokenLocked(widgetToken);
        if (toolbar != null) {
            Slog.v(TAG, "onHide() for " + widgetToken);
            toolbar.hide(widgetToken);
        }
    }

    @Override
    public void onDismiss(long widgetToken) {
        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;
            }
        }
    }

    @Override
    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        int size = mToolbarCache.size();
        pw.print("number selectionToolbar: "); pw.println(size);
        String pfx = "  ";
        for (int i = 0; i < size; i++) {
            pw.print("#"); pw.println(i);
            int callingUid = mToolbarCache.keyAt(i);
            pw.print(pfx); pw.print("callingUid: "); pw.println(callingUid);
            Pair<Long, RemoteSelectionToolbar> toolbarPair = mToolbarCache.valueAt(i);
            RemoteSelectionToolbar selectionToolbar = toolbarPair.second;
            pw.print(pfx); pw.print("selectionToolbar: ");
            selectionToolbar.dump(pfx, pw);
            pw.println();
        }
    }
}
+0 −89
Original line number Diff line number Diff line
/*
 * 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.graphics.Rect;
import android.os.IBinder;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;

import java.io.PrintWriter;

/**
 * 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 static final boolean DEBUG = false;
    private static final String TAG = "FloatingToolbarRoot";

    private final IBinder mTargetInputToken;
    private final SelectionToolbarRenderService.TransferTouchListener mTransferTouchListener;
    private final Rect mContentRect = new Rect();

    private int mLastDownX = -1;
    private int mLastDownY = -1;

    public FloatingToolbarRoot(Context context, IBinder targetInputToken,
            SelectionToolbarRenderService.TransferTouchListener transferTouchListener) {
        super(context);
        mTargetInputToken = targetInputToken;
        mTransferTouchListener = transferTouchListener;
        setFocusable(false);
    }

    /**
     * Sets the Rect that shows the selection toolbar content.
     */
    public void setContentRect(Rect contentRect) {
        mContentRect.set(contentRect);
    }

    @Override
    @SuppressLint("ClickableViewAccessibility")
    public boolean dispatchTouchEvent(MotionEvent event) {
        if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
            mLastDownX = (int) event.getX();
            mLastDownY = (int) event.getY();
            if (DEBUG) {
                Log.d(TAG, "downX=" + mLastDownX + " downY=" + mLastDownY);
            }
            // TODO(b/215497659): Check FLAG_WINDOW_IS_PARTIALLY_OBSCURED
            if (!mContentRect.contains(mLastDownX, mLastDownY)) {
                if (DEBUG) {
                    Log.d(TAG, "Transfer touch focus to application.");
                }
                mTransferTouchListener.onTransferTouch(getViewRootImpl().getInputToken(),
                        mTargetInputToken);
            }
        }
        return super.dispatchTouchEvent(event);
    }

    void dump(String prefix, PrintWriter pw) {
        pw.print(prefix); pw.println("FloatingToolbarRoot:");
        pw.print(prefix + "  "); pw.print("last down X: "); pw.println(mLastDownX);
        pw.print(prefix + "  "); pw.print("last down Y: "); pw.println(mLastDownY);
    }
}
+0 −32
Original line number Diff line number Diff line
/*
 * 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.service.selectiontoolbar;

import android.view.selectiontoolbar.ISelectionToolbarCallback;
import android.view.selectiontoolbar.ShowInfo;

/**
 * The service to render the selection toolbar menus.
 *
 * @hide
 */
oneway interface ISelectionToolbarRenderService {
    void onConnected(in IBinder callback);
    void onShow(int callingUid, in ShowInfo showInfo, in ISelectionToolbarCallback callback);
    void onHide(long widgetToken);
    void onDismiss(int callingUid, long widgetToken);
}
+0 −28
Original line number Diff line number Diff line
/*
 * 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.os.IBinder;

/**
 * The interface from the SelectionToolbarRenderService to the system.
 *
 * @hide
 */
oneway interface ISelectionToolbarRenderServiceCallback {
    void transferTouch(in IBinder source, in IBinder target);
}
Loading