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

Commit b667b12f authored by Iavor-Valentin Iftime's avatar Iavor-Valentin Iftime Committed by Automerger Merge Worker
Browse files

Merge changes from topic...

Merge changes from topic "revert-21476203-cherrypick-delegate-yv7lsnf9lu-WDFXBNMFFU" into udc-dev am: 17028b3d

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21540945



Change-Id: If098b318d419519f32d1f4458ab5bc099604ac49
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 90f50b7a 17028b3d
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -50382,6 +50382,12 @@ package android.view {
    field public static final int VERTICAL_GRAVITY_MASK = 112; // 0x70
  }
  public class HandwritingDelegateConfiguration {
    ctor public HandwritingDelegateConfiguration(@IdRes int, @NonNull Runnable);
    method public int getDelegatorViewId();
    method @NonNull public Runnable getInitiationCallback();
  }
  public class HapticFeedbackConstants {
    field public static final int CLOCK_TICK = 4; // 0x4
    field public static final int CONFIRM = 16; // 0x10
@@ -51979,8 +51985,6 @@ package android.view {
    method @Nullable public CharSequence getAccessibilityPaneTitle();
    method @IdRes public int getAccessibilityTraversalAfter();
    method @IdRes public int getAccessibilityTraversalBefore();
    method @NonNull public String getAllowedHandwritingDelegatePackageName();
    method @NonNull public String getAllowedHandwritingDelegatorPackageName();
    method public float getAlpha();
    method public android.view.animation.Animation getAnimation();
    method @Nullable public android.graphics.Matrix getAnimationMatrix();
@@ -52036,7 +52040,7 @@ package android.view {
    method public float getHandwritingBoundsOffsetLeft();
    method public float getHandwritingBoundsOffsetRight();
    method public float getHandwritingBoundsOffsetTop();
    method @Nullable public Runnable getHandwritingDelegatorCallback();
    method @Nullable public android.view.HandwritingDelegateConfiguration getHandwritingDelegateConfiguration();
    method public final boolean getHasOverlappingRendering();
    method public final int getHeight();
    method public void getHitRect(android.graphics.Rect);
@@ -52192,7 +52196,6 @@ package android.view {
    method public boolean isFocused();
    method public final boolean isFocusedByDefault();
    method public boolean isForceDarkAllowed();
    method public boolean isHandwritingDelegate();
    method public boolean isHapticFeedbackEnabled();
    method public boolean isHardwareAccelerated();
    method public boolean isHorizontalFadingEdgeEnabled();
@@ -52363,8 +52366,6 @@ package android.view {
    method public void setAccessibilityTraversalBefore(@IdRes int);
    method public void setActivated(boolean);
    method public void setAllowClickWhenDisabled(boolean);
    method public void setAllowedHandwritingDelegatePackage(@NonNull String);
    method public void setAllowedHandwritingDelegatorPackage(@NonNull String);
    method public void setAlpha(@FloatRange(from=0.0, to=1.0) float);
    method public void setAnimation(android.view.animation.Animation);
    method public void setAnimationMatrix(@Nullable android.graphics.Matrix);
@@ -52407,7 +52408,7 @@ package android.view {
    method public void setForegroundTintList(@Nullable android.content.res.ColorStateList);
    method public void setForegroundTintMode(@Nullable android.graphics.PorterDuff.Mode);
    method public void setHandwritingBoundsOffsets(float, float, float, float);
    method public void setHandwritingDelegatorCallback(@Nullable Runnable);
    method public void setHandwritingDelegateConfiguration(@Nullable android.view.HandwritingDelegateConfiguration);
    method public void setHapticFeedbackEnabled(boolean);
    method public void setHasTransientState(boolean);
    method public void setHorizontalFadingEdgeEnabled(boolean);
@@ -52420,7 +52421,6 @@ package android.view {
    method public void setImportantForAutofill(int);
    method public void setImportantForContentCapture(int);
    method public void setIsCredential(boolean);
    method public void setIsHandwritingDelegate(boolean);
    method public void setKeepScreenOn(boolean);
    method public void setKeyboardNavigationCluster(boolean);
    method public void setLabelFor(@IdRes int);
+74 −0
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.view;

import android.annotation.IdRes;
import android.annotation.NonNull;

/**
 * Configuration for a view to act as a handwriting initiation delegate. This allows handwriting
 * mode for a delegator editor view to be initiated by stylus movement on the delegate view.
 *
 * <p>If a stylus {@link MotionEvent} occurs within the delegate view's bounds, the callback
 * returned by {@link #getInitiationCallback()} will be called. The callback implementation is
 * expected to show and focus the delegator editor view. If a view with identifier matching {@link
 * #getDelegatorViewId()} creates an input connection while the same stylus {@link MotionEvent}
 * sequence is ongoing, handwriting mode will be initiated for that view.
 *
 * <p>A common use case is a custom view which looks like a text editor but does not actually
 * support text editing itself, and clicking on the custom view causes an EditText to be shown. To
 * support handwriting initiation in this case, {@link View#setHandwritingDelegateConfiguration} can
 * be called on the custom view to configure it as a delegate, and set the EditText as the delegator
 * by passing the EditText's identifier as the {@code delegatorViewId}. The {@code
 * initiationCallback} implementation is typically the same as the click listener implementation
 * which shows the EditText.
 */
public class HandwritingDelegateConfiguration {
    @IdRes private final int mDelegatorViewId;
    @NonNull private final Runnable mInitiationCallback;

    /**
     * Constructs a HandwritingDelegateConfiguration instance.
     *
     * @param delegatorViewId identifier of the delegator editor view for which handwriting mode
     *     should be initiated
     * @param initiationCallback callback called when a stylus {@link MotionEvent} occurs within
     *     this view's bounds. This will be called from the UI thread.
     */
    public HandwritingDelegateConfiguration(
            @IdRes int delegatorViewId, @NonNull Runnable initiationCallback) {
        mDelegatorViewId = delegatorViewId;
        mInitiationCallback = initiationCallback;
    }

    /**
     * Returns the identifier of the delegator editor view for which handwriting mode should be
     * initiated.
     */
    public int getDelegatorViewId() {
        return mDelegatorViewId;
    }

    /**
     * Returns the callback which should be called when a stylus {@link MotionEvent} occurs within
     * the delegate view's bounds. The callback should only be called from the UI thread.
     */
    @NonNull
    public Runnable getInitiationCallback() {
        return mInitiationCallback;
    }
}
+22 −28
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.view;

import android.annotation.IdRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -171,11 +172,15 @@ public class HandwritingInitiator {
                    if (candidateView != null) {
                        if (candidateView == getConnectedView()) {
                            startHandwriting(candidateView);
                        } else if (candidateView.getHandwritingDelegatorCallback() != null) {
                            mImm.prepareStylusHandwritingDelegation(
                                    candidateView,
                                    candidateView.getAllowedHandwritingDelegatePackageName());
                            candidateView.getHandwritingDelegatorCallback().run();
                        } else if (candidateView.getHandwritingDelegateConfiguration() != null) {
                            mState.mDelegatorViewId =
                                    candidateView
                                            .getHandwritingDelegateConfiguration()
                                            .getDelegatorViewId();
                            candidateView
                                    .getHandwritingDelegateConfiguration()
                                    .getInitiationCallback()
                                    .run();
                        } else {
                            if (candidateView.getRevealOnFocusHint()) {
                                candidateView.setRevealOnFocusHint(false);
@@ -222,9 +227,6 @@ public class HandwritingInitiator {
        } else {
            mConnectedView = new WeakReference<>(view);
            mConnectionCount = 1;
            if (view.isHandwritingDelegate() && tryAcceptStylusHandwritingDelegation(view)) {
                return;
            }
            if (mState != null && mState.mShouldInitHandwriting) {
                tryStartHandwriting();
            }
@@ -277,7 +279,9 @@ public class HandwritingInitiator {
        }

        final Rect handwritingArea = getViewHandwritingArea(connectedView);
        if (isInHandwritingArea(
        if ((mState.mDelegatorViewId != View.NO_ID
                        && mState.mDelegatorViewId == connectedView.getId())
                || isInHandwritingArea(
                        handwritingArea, mState.mStylusDownX, mState.mStylusDownY, connectedView)) {
            startHandwriting(connectedView);
        } else {
@@ -285,7 +289,7 @@ public class HandwritingInitiator {
        }
    }

    /** Starts a stylus handwriting session for the view. */
    /** For test only. */
    @VisibleForTesting
    public void startHandwriting(@NonNull View view) {
        mImm.startStylusHandwriting(view);
@@ -293,23 +297,6 @@ public class HandwritingInitiator {
        mState.mShouldInitHandwriting = false;
    }

    /**
     * Starts a stylus handwriting session for the delegate view, if {@link
     * InputMethodManager#prepareStylusHandwritingDelegation} was previously called.
     */
    @VisibleForTesting
    public boolean tryAcceptStylusHandwritingDelegation(@NonNull View view) {
        if (mImm.acceptStylusHandwritingDelegation(
                view, view.getAllowedHandwritingDelegatorPackageName())) {
            if (mState != null) {
                mState.mHasInitiatedHandwriting = true;
                mState.mShouldInitHandwriting = false;
            }
            return true;
        }
        return false;
    }

    /**
     * Notify that the handwriting area for the given view might be updated.
     * @param view the view whose handwriting area might be updated.
@@ -555,6 +542,13 @@ public class HandwritingInitiator {
         * built InputConnection.
         */
        private boolean mExceedHandwritingSlop;
        /**
         * If the current ongoing stylus MotionEvent sequence started over a handwriting initiation
         * delegate view, then this is the view identifier of the corresponding delegator view. If
         * the delegator view creates an input connection while the MotionEvent sequence is still
         * ongoing, then handwriting mode will be initiated for the delegator view.
         */
        @IdRes private int mDelegatorViewId = View.NO_ID;

        /** The pointer id of the stylus pointer that is being tracked. */
        private final int mStylusPointerId;
+18 −160
Original line number Diff line number Diff line
@@ -5101,13 +5101,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    private boolean mHoveringTouchDelegate = false;
    // These two fields are set if the view is a handwriting delegator.
    private Runnable mHandwritingDelegatorCallback;
    private String mAllowedHandwritingDelegatePackageName;
    // These two fields are set if the view is a handwriting delegate.
    private boolean mIsHandwritingDelegate;
    private String mAllowedHandwritingDelegatorPackageName;
    /**
     * Configuration for this view to act as a handwriting initiation delegate. This allows
     * handwriting mode for a delegator editor view to be initiated by stylus movement on this
     * delegate view.
     */
    private HandwritingDelegateConfiguration mHandwritingDelegateConfiguration;
    /**
     * Solid color to use as a background when creating the drawing cache. Enables
@@ -12411,168 +12410,27 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    }
    /**
     * Sets a callback which should be called when a stylus {@link MotionEvent} occurs within this
     * view's bounds. The callback will be called from the UI thread.
     *
     * <p>Setting a callback allows this view to act as a handwriting delegator, so that handwriting
     * mode for a delegate editor view can be initiated by stylus movement on this delegator view.
     * The callback implementation is expected to show and focus the delegate editor view. If a view
     * which returns {@code true} for {@link #isHandwritingDelegate()} creates an input connection
     * while the same stylus {@link MotionEvent} sequence is ongoing, handwriting mode will be
     * initiated for that view.
     *
     * <p>A common use case is a custom view which looks like a text editor but does not actually
     * support text editing itself, and clicking on the custom view causes an EditText to be shown.
     * To support handwriting initiation in this case, this method can be called on the custom view
     * to configure it as a delegator. The EditText should call {@link #setIsHandwritingDelegate} to
     * set it as a delegate. The {@code callback} implementation is typically the same as the click
     * listener implementation which shows the EditText.
     * Configures this view to act as a handwriting initiation delegate. This allows handwriting
     * mode for a delegator editor view to be initiated by stylus movement on this delegate view.
     *
     * <p>If {@code null} is passed, this view will no longer act as a handwriting initiation
     * delegator.
     *
     * @param callback a callback which should be called when a stylus {@link MotionEvent} occurs
     *     within this view's bounds
     * delegate.
     */
    public void setHandwritingDelegatorCallback(@Nullable Runnable callback) {
        mHandwritingDelegatorCallback = callback;
        if (callback != null) {
            // By default, the delegate must be from the same package as the delegator view.
            mAllowedHandwritingDelegatePackageName = mContext.getOpPackageName();
    public void setHandwritingDelegateConfiguration(
            @Nullable HandwritingDelegateConfiguration configuration) {
        mHandwritingDelegateConfiguration = configuration;
        if (configuration != null) {
            setHandwritingArea(new Rect(0, 0, getWidth(), getHeight()));
        } else {
            mAllowedHandwritingDelegatePackageName = null;
        }
    }
    /**
     * Returns the callback set by {@link #setHandwritingDelegatorCallback} which should be called
     * when a stylus {@link MotionEvent} occurs within this view's bounds. The callback should only
     * be called from the UI thread.
     * If this view has been configured as a handwriting initiation delegate, returns the delegate
     * configuration.
     */
    @Nullable
    public Runnable getHandwritingDelegatorCallback() {
        return mHandwritingDelegatorCallback;
    }
    /**
     * Specifies that this view may act as a handwriting initiation delegator for a delegate editor
     * view from the specified package. If this method is not called, delegators may only be used to
     * initiate handwriting mode for a delegate editor view from the same package as the delegator
     * view. This method allows specifying a different trusted package which may contain a delegate
     * editor view linked to this delegator view. This should be called after {@link
     * #setHandwritingDelegatorCallback}.
     *
     * <p>If this method is called on the delegator view, then {@link
     * #setAllowedHandwritingDelegatorPackage} should also be called on the delegate editor view.
     *
     * <p>For example, to configure a delegator view in package 1:
     *
     * <pre>
     * delegatorView.setHandwritingDelegatorCallback(callback);
     * delegatorView.setAllowedHandwritingDelegatePackage(package2);</pre>
     *
     * Then to configure the corresponding delegate editor view in package 2:
     *
     * <pre>
     * delegateEditorView.setIsHandwritingDelegate(true);
     * delegateEditorView.setAllowedHandwritingDelegatorPackage(package1);</pre>
     *
     * @param allowedPackageName the package name of a delegate editor view linked to this delegator
     *     view
     * @throws IllegalStateException If the view has not been configured as a handwriting delegator
     *     using {@link #setHandwritingDelegatorCallback}.
     */
    public void setAllowedHandwritingDelegatePackage(@NonNull String allowedPackageName) {
        if (mHandwritingDelegatorCallback == null) {
            throw new IllegalStateException("This view is not a handwriting delegator.");
        }
        mAllowedHandwritingDelegatePackageName = allowedPackageName;
    }
    /**
     * Returns the allowed package for delegate editor views for which this view may act as a
     * handwriting delegator. If {@link #setAllowedHandwritingDelegatePackage} has not been called,
     * this will return this view's package name, since by default delegators may only be used to
     * initiate handwriting mode for a delegate editor view from the same package as the delegator
     * view. This will return a different allowed package if set by {@link
     * #setAllowedHandwritingDelegatePackage}.
     *
     * @throws IllegalStateException If the view has not been configured as a handwriting delegator
     *     using {@link #setHandwritingDelegatorCallback}.
     */
    @NonNull
    public String getAllowedHandwritingDelegatePackageName() {
        if (mHandwritingDelegatorCallback == null) {
            throw new IllegalStateException("This view is not a handwriting delegator.");
        }
        return mAllowedHandwritingDelegatePackageName;
    }
    /**
     * Sets this view to be a handwriting delegate. If a delegate view creates an input connection
     * while a stylus {@link MotionEvent} sequence from a delegator view is ongoing, handwriting
     * mode will be initiated for the delegate view.
     *
     * @param isHandwritingDelegate whether this view is a handwriting initiation delegate
     * @see #setHandwritingDelegatorCallback(Runnable)
     */
    public void setIsHandwritingDelegate(boolean isHandwritingDelegate) {
        mIsHandwritingDelegate = isHandwritingDelegate;
        if (mIsHandwritingDelegate) {
            // By default, the delegator must be from the same package as the delegate view.
            mAllowedHandwritingDelegatorPackageName = mContext.getOpPackageName();
        } else {
            mAllowedHandwritingDelegatePackageName = null;
        }
    }
    /**
     * Returns whether this view has been set as a handwriting delegate by {@link
     * #setIsHandwritingDelegate}.
     */
    public boolean isHandwritingDelegate() {
        return mIsHandwritingDelegate;
    }
    /**
     * Specifies that a view from the specified package may act as a handwriting delegator for this
     * delegate editor view. If this method is not called, only views from the same package as the
     * delegate editor view may act as a handwriting delegator. This method allows specifying a
     * different trusted package which may contain a delegator view linked to this delegate editor
     * view. This should be called after {@link #setIsHandwritingDelegate}.
     *
     * <p>If this method is called on the delegate editor view, then {@link
     * #setAllowedHandwritingDelegatePackage} should also be called on the delegator view.
     *
     * @param allowedPackageName the package name of a delegator view linked to this delegate editor
     *     view
     * @throws IllegalStateException If the view has not been configured as a handwriting delegate
     *     using {@link #setIsHandwritingDelegate}.
     */
    public void setAllowedHandwritingDelegatorPackage(@NonNull String allowedPackageName) {
        if (!mIsHandwritingDelegate) {
            throw new IllegalStateException("This view is not a handwriting delegate.");
        }
        mAllowedHandwritingDelegatorPackageName = allowedPackageName;
    }
    /**
     * Returns the allowed package for views which may act as a handwriting delegator for this
     * delegate editor view. If {@link #setAllowedHandwritingDelegatorPackage} has not been called,
     * this will return this view's package name, since by default only views from the same package
     * as the delegator editor view may act as a handwriting delegator. This will return a different
     * allowed package if set by {@link #setAllowedHandwritingDelegatorPackage}.
     *
     * @throws IllegalStateException If the view has not been configured as a handwriting delegate
     *     using {@link #setIsHandwritingDelegate}.
     */
    @NonNull
    public String getAllowedHandwritingDelegatorPackageName() {
        if (!mIsHandwritingDelegate) {
            throw new IllegalStateException("This view is not a handwriting delegate.");
        }
        return mAllowedHandwritingDelegatorPackageName;
    public HandwritingDelegateConfiguration getHandwritingDelegateConfiguration() {
        return mHandwritingDelegateConfiguration;
    }
    /**
@@ -24616,7 +24474,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            }
        }
        rebuildOutline();
        if (onCheckIsTextEditor() || mHandwritingDelegatorCallback != null) {
        if (onCheckIsTextEditor() || mHandwritingDelegateConfiguration != null) {
            setHandwritingArea(new Rect(0, 0, newWidth, newHeight));
        }
    }
+9 −5
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.app.Instrumentation;
import android.content.Context;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.view.HandwritingDelegateConfiguration;
import android.view.HandwritingInitiator;
import android.view.InputDevice;
import android.view.MotionEvent;
@@ -209,11 +210,14 @@ public class HandwritingInitiatorTest {

    @Test
    public void onTouchEvent_startHandwriting_delegate() {
        View delegateView = new View(mContext);
        delegateView.setIsHandwritingDelegate(true);
        int delegatorViewId = 234;
        View delegatorView = new View(mContext);
        delegatorView.setId(delegatorViewId);

        mTestView.setHandwritingDelegatorCallback(
                () -> mHandwritingInitiator.onInputConnectionCreated(delegateView));
        mTestView.setHandwritingDelegateConfiguration(
                new HandwritingDelegateConfiguration(
                        delegatorViewId,
                        () -> mHandwritingInitiator.onInputConnectionCreated(delegatorView)));

        final int x1 = (sHwArea.left + sHwArea.right) / 2;
        final int y1 = (sHwArea.top + sHwArea.bottom) / 2;
@@ -225,7 +229,7 @@ public class HandwritingInitiatorTest {
        MotionEvent stylusEvent2 = createStylusEvent(ACTION_MOVE, x2, y2, 0);
        mHandwritingInitiator.onTouchEvent(stylusEvent2);

        verify(mHandwritingInitiator, times(1)).tryAcceptStylusHandwritingDelegation(delegateView);
        verify(mHandwritingInitiator, times(1)).startHandwriting(delegatorView);
    }

    @Test