Merge changes from topics "delegate-imf", "delegate-view" into udc-dev
* changes: Revert "Revert "Support handwriting delegation across different ..." Revert "Revert "Fix handwriting support on fake editors using de..."
This commit is contained in:
@@ -50382,12 +50382,6 @@ 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
|
||||
@@ -51985,6 +51979,8 @@ 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();
|
||||
@@ -52040,7 +52036,7 @@ package android.view {
|
||||
method public float getHandwritingBoundsOffsetLeft();
|
||||
method public float getHandwritingBoundsOffsetRight();
|
||||
method public float getHandwritingBoundsOffsetTop();
|
||||
method @Nullable public android.view.HandwritingDelegateConfiguration getHandwritingDelegateConfiguration();
|
||||
method @Nullable public Runnable getHandwritingDelegatorCallback();
|
||||
method public final boolean getHasOverlappingRendering();
|
||||
method public final int getHeight();
|
||||
method public void getHitRect(android.graphics.Rect);
|
||||
@@ -52196,6 +52192,7 @@ 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();
|
||||
@@ -52366,6 +52363,8 @@ 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);
|
||||
@@ -52408,7 +52407,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 setHandwritingDelegateConfiguration(@Nullable android.view.HandwritingDelegateConfiguration);
|
||||
method public void setHandwritingDelegatorCallback(@Nullable Runnable);
|
||||
method public void setHapticFeedbackEnabled(boolean);
|
||||
method public void setHasTransientState(boolean);
|
||||
method public void setHorizontalFadingEdgeEnabled(boolean);
|
||||
@@ -52421,6 +52420,7 @@ 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);
|
||||
@@ -55619,6 +55619,8 @@ package android.view.inputmethod {
|
||||
}
|
||||
|
||||
public final class InputMethodManager {
|
||||
method public boolean acceptStylusHandwritingDelegation(@NonNull android.view.View);
|
||||
method public boolean acceptStylusHandwritingDelegation(@NonNull android.view.View, @NonNull String);
|
||||
method public void dispatchKeyEventFromInputMethod(@Nullable android.view.View, @NonNull android.view.KeyEvent);
|
||||
method public void displayCompletions(android.view.View, android.view.inputmethod.CompletionInfo[]);
|
||||
method @Nullable public android.view.inputmethod.InputMethodInfo getCurrentInputMethodInfo();
|
||||
@@ -55640,6 +55642,8 @@ package android.view.inputmethod {
|
||||
method public boolean isInputMethodSuppressingSpellChecker();
|
||||
method public boolean isStylusHandwritingAvailable();
|
||||
method @Deprecated public boolean isWatchingCursor(android.view.View);
|
||||
method public void prepareStylusHandwritingDelegation(@NonNull android.view.View);
|
||||
method public void prepareStylusHandwritingDelegation(@NonNull android.view.View, @NonNull String);
|
||||
method public void restartInput(android.view.View);
|
||||
method public void sendAppPrivateCommand(android.view.View, String, android.os.Bundle);
|
||||
method @Deprecated public void setAdditionalInputMethodSubtypes(@NonNull String, @NonNull android.view.inputmethod.InputMethodSubtype[]);
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package android.view;
|
||||
|
||||
import android.annotation.IdRes;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
@@ -172,15 +171,11 @@ public class HandwritingInitiator {
|
||||
if (candidateView != null) {
|
||||
if (candidateView == getConnectedView()) {
|
||||
startHandwriting(candidateView);
|
||||
} else if (candidateView.getHandwritingDelegateConfiguration() != null) {
|
||||
mState.mDelegatorViewId =
|
||||
candidateView
|
||||
.getHandwritingDelegateConfiguration()
|
||||
.getDelegatorViewId();
|
||||
candidateView
|
||||
.getHandwritingDelegateConfiguration()
|
||||
.getInitiationCallback()
|
||||
.run();
|
||||
} else if (candidateView.getHandwritingDelegatorCallback() != null) {
|
||||
mImm.prepareStylusHandwritingDelegation(
|
||||
candidateView,
|
||||
candidateView.getAllowedHandwritingDelegatePackageName());
|
||||
candidateView.getHandwritingDelegatorCallback().run();
|
||||
} else {
|
||||
if (candidateView.getRevealOnFocusHint()) {
|
||||
candidateView.setRevealOnFocusHint(false);
|
||||
@@ -227,6 +222,9 @@ public class HandwritingInitiator {
|
||||
} else {
|
||||
mConnectedView = new WeakReference<>(view);
|
||||
mConnectionCount = 1;
|
||||
if (view.isHandwritingDelegate() && tryAcceptStylusHandwritingDelegation(view)) {
|
||||
return;
|
||||
}
|
||||
if (mState != null && mState.mShouldInitHandwriting) {
|
||||
tryStartHandwriting();
|
||||
}
|
||||
@@ -279,17 +277,15 @@ public class HandwritingInitiator {
|
||||
}
|
||||
|
||||
final Rect handwritingArea = getViewHandwritingArea(connectedView);
|
||||
if ((mState.mDelegatorViewId != View.NO_ID
|
||||
&& mState.mDelegatorViewId == connectedView.getId())
|
||||
|| isInHandwritingArea(
|
||||
handwritingArea, mState.mStylusDownX, mState.mStylusDownY, connectedView)) {
|
||||
if (isInHandwritingArea(
|
||||
handwritingArea, mState.mStylusDownX, mState.mStylusDownY, connectedView)) {
|
||||
startHandwriting(connectedView);
|
||||
} else {
|
||||
mState.mShouldInitHandwriting = false;
|
||||
}
|
||||
}
|
||||
|
||||
/** For test only. */
|
||||
/** Starts a stylus handwriting session for the view. */
|
||||
@VisibleForTesting
|
||||
public void startHandwriting(@NonNull View view) {
|
||||
mImm.startStylusHandwriting(view);
|
||||
@@ -297,6 +293,23 @@ 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.
|
||||
@@ -542,13 +555,6 @@ 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;
|
||||
|
||||
@@ -5101,12 +5101,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
||||
*/
|
||||
private boolean mHoveringTouchDelegate = false;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
// 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;
|
||||
|
||||
/**
|
||||
* Solid color to use as a background when creating the drawing cache. Enables
|
||||
@@ -12410,27 +12411,168 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* <p>If {@code null} is passed, this view will no longer act as a handwriting initiation
|
||||
* delegate.
|
||||
* delegator.
|
||||
*
|
||||
* @param callback a callback which should be called when a stylus {@link MotionEvent} occurs
|
||||
* within this view's bounds
|
||||
*/
|
||||
public void setHandwritingDelegateConfiguration(
|
||||
@Nullable HandwritingDelegateConfiguration configuration) {
|
||||
mHandwritingDelegateConfiguration = configuration;
|
||||
if (configuration != null) {
|
||||
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();
|
||||
setHandwritingArea(new Rect(0, 0, getWidth(), getHeight()));
|
||||
} else {
|
||||
mAllowedHandwritingDelegatePackageName = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If this view has been configured as a handwriting initiation delegate, returns the delegate
|
||||
* configuration.
|
||||
* 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.
|
||||
*/
|
||||
@Nullable
|
||||
public HandwritingDelegateConfiguration getHandwritingDelegateConfiguration() {
|
||||
return mHandwritingDelegateConfiguration;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -24474,7 +24616,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
||||
}
|
||||
}
|
||||
rebuildOutline();
|
||||
if (onCheckIsTextEditor() || mHandwritingDelegateConfiguration != null) {
|
||||
if (onCheckIsTextEditor() || mHandwritingDelegatorCallback != null) {
|
||||
setHandwritingArea(new Rect(0, 0, newWidth, newHeight));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -504,6 +504,40 @@ final class IInputMethodManagerGlobalInvoker {
|
||||
}
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
static void prepareStylusHandwritingDelegation(
|
||||
@NonNull IInputMethodClient client,
|
||||
@NonNull String delegatePackageName,
|
||||
@NonNull String delegatorPackageName) {
|
||||
final IInputMethodManager service = getService();
|
||||
if (service == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
service.prepareStylusHandwritingDelegation(
|
||||
client, delegatePackageName, delegatorPackageName);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
static boolean acceptStylusHandwritingDelegation(
|
||||
@NonNull IInputMethodClient client,
|
||||
@NonNull String delegatePackageName,
|
||||
@NonNull String delegatorPackageName) {
|
||||
final IInputMethodManager service = getService();
|
||||
if (service == null) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return service.acceptStylusHandwritingDelegation(
|
||||
client, delegatePackageName, delegatorPackageName);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
@RequiresPermission(value = Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true)
|
||||
static boolean isStylusHandwritingAvailableAsUser(@UserIdInt int userId) {
|
||||
|
||||
@@ -99,6 +99,7 @@ import android.view.WindowManager;
|
||||
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
|
||||
import android.view.autofill.AutofillId;
|
||||
import android.view.autofill.AutofillManager;
|
||||
import android.widget.Editor;
|
||||
import android.window.ImeOnBackInvokedDispatcher;
|
||||
import android.window.WindowOnBackInvokedDispatcher;
|
||||
|
||||
@@ -1552,11 +1553,7 @@ public final class InputMethodManager {
|
||||
if (fallbackContext == null) {
|
||||
return false;
|
||||
}
|
||||
if (Settings.Global.getInt(fallbackContext.getContentResolver(),
|
||||
Settings.Global.STYLUS_HANDWRITING_ENABLED, 0) == 0) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Stylus handwriting is not enabled in settings.");
|
||||
}
|
||||
if (!isStylusHandwritingEnabled(fallbackContext)) {
|
||||
return false;
|
||||
}
|
||||
return IInputMethodManagerGlobalInvoker.isStylusHandwritingAvailableAsUser(userId);
|
||||
@@ -2233,37 +2230,175 @@ public final class InputMethodManager {
|
||||
* @see #isStylusHandwritingAvailable()
|
||||
*/
|
||||
public void startStylusHandwriting(@NonNull View view) {
|
||||
startStylusHandwritingInternal(view, null /* delegatorPackageName */);
|
||||
}
|
||||
|
||||
private boolean startStylusHandwritingInternal(
|
||||
@NonNull View view, @Nullable String delegatorPackageName) {
|
||||
Objects.requireNonNull(view);
|
||||
|
||||
// Re-dispatch if there is a context mismatch.
|
||||
final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
|
||||
if (fallbackImm != null) {
|
||||
fallbackImm.startStylusHandwriting(view);
|
||||
fallbackImm.startStylusHandwritingInternal(view, delegatorPackageName);
|
||||
}
|
||||
Objects.requireNonNull(view);
|
||||
|
||||
if (Settings.Global.getInt(view.getContext().getContentResolver(),
|
||||
Settings.Global.STYLUS_HANDWRITING_ENABLED, 0) == 0) {
|
||||
Log.d(TAG, "Ignoring startStylusHandwriting(view) as stylus handwriting is disabled");
|
||||
return;
|
||||
boolean useDelegation = !TextUtils.isEmpty(delegatorPackageName);
|
||||
if (!isStylusHandwritingEnabled(view.getContext())) {
|
||||
Log.w(TAG, "Stylus handwriting pref is disabled. "
|
||||
+ "Ignoring calls to start stylus handwriting.");
|
||||
return false;
|
||||
}
|
||||
|
||||
checkFocus();
|
||||
synchronized (mH) {
|
||||
if (!hasServedByInputMethodLocked(view)) {
|
||||
Log.w(TAG,
|
||||
"Ignoring startStylusHandwriting() as view=" + view + " is not served.");
|
||||
return;
|
||||
"Ignoring startStylusHandwriting as view=" + view + " is not served.");
|
||||
return false;
|
||||
}
|
||||
if (view.getViewRootImpl() != mCurRootView) {
|
||||
Log.w(TAG, "Ignoring startStylusHandwriting: View's window does not have focus.");
|
||||
return;
|
||||
Log.w(TAG,
|
||||
"Ignoring startStylusHandwriting: View's window does not have focus.");
|
||||
return false;
|
||||
}
|
||||
|
||||
IInputMethodManagerGlobalInvoker.startStylusHandwriting(mClient);
|
||||
// TODO(b/210039666): do we need any extra work for supporting non-native
|
||||
// UI toolkits?
|
||||
if (useDelegation) {
|
||||
return IInputMethodManagerGlobalInvoker.acceptStylusHandwritingDelegation(
|
||||
mClient, view.getContext().getOpPackageName(), delegatorPackageName);
|
||||
} else {
|
||||
IInputMethodManagerGlobalInvoker.startStylusHandwriting(mClient);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isStylusHandwritingEnabled(@NonNull Context context) {
|
||||
if (Settings.Global.getInt(context.getContentResolver(),
|
||||
Settings.Global.STYLUS_HANDWRITING_ENABLED, 0) == 0) {
|
||||
Log.d(TAG, "Stylus handwriting pref is disabled.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares delegation of starting stylus handwriting session to a different editor in same
|
||||
* or different window than the view on which initial handwriting stroke was detected.
|
||||
*
|
||||
* Delegation can be used to start stylus handwriting session before the {@link Editor} view or
|
||||
* its {@link InputConnection} is started. Calling this method starts buffering of stylus
|
||||
* motion events until {@link #acceptStylusHandwritingDelegation(View)} is called, at which
|
||||
* point the handwriting session can be started and the buffered stylus motion events will be
|
||||
* delivered to the IME.
|
||||
* e.g. Delegation can be used when initial handwriting stroke is
|
||||
* on a pseudo {@link Editor} like widget (with no {@link InputConnection}) but actual
|
||||
* {@link Editor} is on a different window.
|
||||
*
|
||||
* <p> Note: If an actual {@link Editor} capable of {@link InputConnection} is being scribbled
|
||||
* upon using stylus, use {@link #startStylusHandwriting(View)} instead.</p>
|
||||
*
|
||||
* @param delegatorView the view that receives initial stylus stroke and delegates it to the
|
||||
* actual editor. Its window must {@link View#hasWindowFocus have focus}.
|
||||
* @see #prepareStylusHandwritingDelegation(View, String)
|
||||
* @see #acceptStylusHandwritingDelegation(View)
|
||||
* @see #startStylusHandwriting(View)
|
||||
*/
|
||||
public void prepareStylusHandwritingDelegation(@NonNull View delegatorView) {
|
||||
prepareStylusHandwritingDelegation(
|
||||
delegatorView, delegatorView.getContext().getOpPackageName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares delegation of starting stylus handwriting session to a different editor in same or a
|
||||
* different window in a different package than the view on which initial handwriting stroke
|
||||
* was detected.
|
||||
*
|
||||
* Delegation can be used to start stylus handwriting session before the {@link Editor} view or
|
||||
* its {@link InputConnection} is started. Calling this method starts buffering of stylus
|
||||
* motion events until {@link #acceptStylusHandwritingDelegation(View, String)} is called, at
|
||||
* which point the handwriting session can be started and the buffered stylus motion events will
|
||||
* be delivered to the IME.
|
||||
* e.g. Delegation can be used when initial handwriting stroke is
|
||||
* on a pseudo {@link Editor} like widget (with no {@link InputConnection}) but actual
|
||||
* {@link Editor} is on a different window in the given package.
|
||||
*
|
||||
* <p>Note: If delegator and delegate are in same package use
|
||||
* {@link #prepareStylusHandwritingDelegation(View)} instead.</p>
|
||||
*
|
||||
* @param delegatorView the view that receives initial stylus stroke and delegates it to the
|
||||
* actual editor. Its window must {@link View#hasWindowFocus have focus}.
|
||||
* @param delegatePackageName package name that contains actual {@link Editor} which should
|
||||
* start stylus handwriting session by calling {@link #acceptStylusHandwritingDelegation}.
|
||||
* @see #prepareStylusHandwritingDelegation(View)
|
||||
* @see #acceptStylusHandwritingDelegation(View, String)
|
||||
*/
|
||||
public void prepareStylusHandwritingDelegation(
|
||||
@NonNull View delegatorView, @NonNull String delegatePackageName) {
|
||||
Objects.requireNonNull(delegatorView);
|
||||
Objects.requireNonNull(delegatePackageName);
|
||||
|
||||
// Re-dispatch if there is a context mismatch.
|
||||
final InputMethodManager fallbackImm =
|
||||
getFallbackInputMethodManagerIfNecessary(delegatorView);
|
||||
if (fallbackImm != null) {
|
||||
fallbackImm.prepareStylusHandwritingDelegation(delegatorView, delegatePackageName);
|
||||
}
|
||||
|
||||
if (!isStylusHandwritingEnabled(delegatorView.getContext())) {
|
||||
Log.w(TAG, "Stylus handwriting pref is disabled. "
|
||||
+ "Ignoring prepareStylusHandwritingDelegation().");
|
||||
return;
|
||||
}
|
||||
IInputMethodManagerGlobalInvoker.prepareStylusHandwritingDelegation(
|
||||
mClient,
|
||||
delegatePackageName,
|
||||
delegatorView.getContext().getOpPackageName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts and starts a stylus handwriting session on the delegate view, if handwriting
|
||||
* initiation delegation was previously requested using
|
||||
* {@link #prepareStylusHandwritingDelegation(View)} from the delegator.
|
||||
*
|
||||
* <p>Note: If delegator and delegate are in different application packages, use
|
||||
* {@link #acceptStylusHandwritingDelegation(View, String)} instead.</p>
|
||||
*
|
||||
* @param delegateView delegate view capable of receiving input via {@link InputConnection}
|
||||
* on which {@link #startStylusHandwriting(View)} will be called.
|
||||
* @return {@code true} if view belongs to same application package as used in
|
||||
* {@link #prepareStylusHandwritingDelegation(View)} and handwriting session can start.
|
||||
* @see #acceptStylusHandwritingDelegation(View, String)
|
||||
* @see #prepareStylusHandwritingDelegation(View)
|
||||
*/
|
||||
public boolean acceptStylusHandwritingDelegation(@NonNull View delegateView) {
|
||||
return startStylusHandwritingInternal(
|
||||
delegateView, delegateView.getContext().getOpPackageName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts and starts a stylus handwriting session on the delegate view, if handwriting
|
||||
* initiation delegation was previously requested using
|
||||
* {@link #prepareStylusHandwritingDelegation(View, String)} from te delegator and the view
|
||||
* belongs to a specified delegate package.
|
||||
*
|
||||
* <p>Note: If delegator and delegate are in same application package use
|
||||
* {@link #acceptStylusHandwritingDelegation(View)} instead.</p>
|
||||
*
|
||||
* @param delegateView delegate view capable of receiving input via {@link InputConnection}
|
||||
* on which {@link #startStylusHandwriting(View)} will be called.
|
||||
* @param delegatorPackageName package name of the delegator that handled initial stylus stroke.
|
||||
* @return {@code true} if view belongs to allowed delegate package declared in
|
||||
* {@link #prepareStylusHandwritingDelegation(View, String)} and handwriting session can start.
|
||||
* @see #prepareStylusHandwritingDelegation(View, String)
|
||||
* @see #acceptStylusHandwritingDelegation(View)
|
||||
*/
|
||||
public boolean acceptStylusHandwritingDelegation(
|
||||
@NonNull View delegateView, @NonNull String delegatorPackageName) {
|
||||
Objects.requireNonNull(delegatorPackageName);
|
||||
|
||||
return startStylusHandwritingInternal(delegateView, delegatorPackageName);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method toggles the input method window display.
|
||||
* If the input window is already displayed, it gets hidden.
|
||||
|
||||
@@ -148,6 +148,15 @@ interface IInputMethodManager {
|
||||
/** Start Stylus handwriting session **/
|
||||
void startStylusHandwriting(in IInputMethodClient client);
|
||||
|
||||
/** Prepares delegation of starting stylus handwriting session to a different editor **/
|
||||
void prepareStylusHandwritingDelegation(in IInputMethodClient client,
|
||||
in String delegatePackageName,
|
||||
in String delegatorPackageName);
|
||||
|
||||
/** Accepts and starts a stylus handwriting session for the delegate view **/
|
||||
boolean acceptStylusHandwritingDelegation(in IInputMethodClient client,
|
||||
in String delegatePackageName, in String delegatorPackageName);
|
||||
|
||||
/** Returns {@code true} if currently selected IME supports Stylus handwriting. */
|
||||
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
|
||||
+ "android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true)")
|
||||
|
||||
@@ -32,7 +32,6 @@ 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;
|
||||
@@ -210,14 +209,11 @@ public class HandwritingInitiatorTest {
|
||||
|
||||
@Test
|
||||
public void onTouchEvent_startHandwriting_delegate() {
|
||||
int delegatorViewId = 234;
|
||||
View delegatorView = new View(mContext);
|
||||
delegatorView.setId(delegatorViewId);
|
||||
View delegateView = new View(mContext);
|
||||
delegateView.setIsHandwritingDelegate(true);
|
||||
|
||||
mTestView.setHandwritingDelegateConfiguration(
|
||||
new HandwritingDelegateConfiguration(
|
||||
delegatorViewId,
|
||||
() -> mHandwritingInitiator.onInputConnectionCreated(delegatorView)));
|
||||
mTestView.setHandwritingDelegatorCallback(
|
||||
() -> mHandwritingInitiator.onInputConnectionCreated(delegateView));
|
||||
|
||||
final int x1 = (sHwArea.left + sHwArea.right) / 2;
|
||||
final int y1 = (sHwArea.top + sHwArea.bottom) / 2;
|
||||
@@ -229,7 +225,7 @@ public class HandwritingInitiatorTest {
|
||||
MotionEvent stylusEvent2 = createStylusEvent(ACTION_MOVE, x2, y2, 0);
|
||||
mHandwritingInitiator.onTouchEvent(stylusEvent2);
|
||||
|
||||
verify(mHandwritingInitiator, times(1)).startHandwriting(delegatorView);
|
||||
verify(mHandwritingInitiator, times(1)).tryAcceptStylusHandwritingDelegation(delegateView);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -20,12 +20,14 @@ import static android.view.InputDevice.SOURCE_STYLUS;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.AnyThread;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.annotation.UiThread;
|
||||
import android.hardware.input.InputManager;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Slog;
|
||||
import android.view.BatchedInputEventReceiver;
|
||||
import android.view.Choreographer;
|
||||
@@ -35,6 +37,8 @@ import android.view.InputEvent;
|
||||
import android.view.InputEventReceiver;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.input.InputManagerInternal;
|
||||
@@ -52,6 +56,9 @@ final class HandwritingModeController {
|
||||
// TODO(b/210039666): flip the flag.
|
||||
static final boolean DEBUG = true;
|
||||
private static final int EVENT_BUFFER_SIZE = 100;
|
||||
// A longer event buffer used for handwriting delegation
|
||||
// TODO(b/210039666): make this device touch sampling rate dependent.
|
||||
private static final int LONG_EVENT_BUFFER = EVENT_BUFFER_SIZE * 20;
|
||||
|
||||
// This must be the looper for the UiThread.
|
||||
private final Looper mLooper;
|
||||
@@ -63,6 +70,9 @@ final class HandwritingModeController {
|
||||
private Runnable mInkWindowInitRunnable;
|
||||
private boolean mRecordingGesture;
|
||||
private int mCurrentDisplayId;
|
||||
// when set, package names are used for handwriting delegation.
|
||||
private @Nullable String mDelegatePackageName;
|
||||
private @Nullable String mDelegatorPackageName;
|
||||
|
||||
private HandwritingEventReceiverSurface mHandwritingSurface;
|
||||
|
||||
@@ -137,6 +147,41 @@ final class HandwritingModeController {
|
||||
return mRecordingGesture;
|
||||
}
|
||||
|
||||
boolean hasOngoingStylusHandwritingSession() {
|
||||
return mHandwritingSurface != null && mHandwritingSurface.isIntercepting();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare delegation of stylus handwriting to a different editor
|
||||
* @see InputMethodManager#prepareStylusHandwritingDelegation(View, String)
|
||||
*/
|
||||
void prepareStylusHandwritingDelegation(
|
||||
@NonNull String delegatePackageName, @NonNull String delegatorPackageName) {
|
||||
mDelegatePackageName = delegatePackageName;
|
||||
mDelegatorPackageName = delegatorPackageName;
|
||||
((ArrayList) mHandwritingBuffer).ensureCapacity(LONG_EVENT_BUFFER);
|
||||
// TODO(b/210039666): cancel delegation after a timeout or next input method client binding.
|
||||
}
|
||||
|
||||
@Nullable String getDelegatePackageName() {
|
||||
return mDelegatePackageName;
|
||||
}
|
||||
|
||||
@Nullable String getDelegatorPackageName() {
|
||||
return mDelegatorPackageName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear any pending handwriting delegation info.
|
||||
*/
|
||||
void clearPendingHandwritingDelegation() {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "clearPendingHandwritingDelegation");
|
||||
}
|
||||
mDelegatorPackageName = null;
|
||||
mDelegatePackageName = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a {@link HandwritingSession} to transfer to the IME.
|
||||
*
|
||||
@@ -223,6 +268,7 @@ final class HandwritingModeController {
|
||||
}
|
||||
}
|
||||
|
||||
clearPendingHandwritingDelegation();
|
||||
mRecordingGesture = false;
|
||||
}
|
||||
|
||||
@@ -259,7 +305,10 @@ final class HandwritingModeController {
|
||||
mInkWindowInitRunnable = null;
|
||||
}
|
||||
|
||||
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
|
||||
// If handwriting delegation is ongoing, don't clear the buffer so that multiple strokes
|
||||
// can be buffered across windows.
|
||||
if (TextUtils.isEmpty(mDelegatePackageName)
|
||||
&& (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL)) {
|
||||
mRecordingGesture = false;
|
||||
mHandwritingBuffer.clear();
|
||||
return;
|
||||
|
||||
@@ -236,6 +236,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
private static final int MSG_FINISH_HANDWRITING = 1110;
|
||||
private static final int MSG_REMOVE_HANDWRITING_WINDOW = 1120;
|
||||
|
||||
private static final int MSG_PREPARE_HANDWRITING_DELEGATION = 1130;
|
||||
|
||||
private static final int MSG_SET_INTERACTIVE = 3030;
|
||||
|
||||
private static final int MSG_HARD_KEYBOARD_SWITCH_CHANGED = 4000;
|
||||
@@ -2688,6 +2690,14 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
mHandler.obtainMessage(MSG_RESET_HANDWRITING).sendToTarget();
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
void schedulePrepareStylusHandwritingDelegation(
|
||||
@NonNull String delegatePackageName, @NonNull String delegatorPackageName) {
|
||||
mHandler.obtainMessage(
|
||||
MSG_PREPARE_HANDWRITING_DELEGATION,
|
||||
new Pair<>(delegatePackageName, delegatorPackageName)).sendToTarget();
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
void scheduleRemoveStylusHandwritingWindow() {
|
||||
mHandler.obtainMessage(MSG_REMOVE_HANDWRITING_WINDOW).sendToTarget();
|
||||
@@ -3304,6 +3314,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
"InputMethodManagerService#startStylusHandwriting");
|
||||
int uid = Binder.getCallingUid();
|
||||
synchronized (ImfLock.class) {
|
||||
mHwController.clearPendingHandwritingDelegation();
|
||||
if (!canInteractWithImeLocked(uid, client, "startStylusHandwriting",
|
||||
null /* statsToken */)) {
|
||||
return;
|
||||
@@ -3331,6 +3342,13 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
"There is no ongoing stylus gesture to start stylus handwriting.");
|
||||
return;
|
||||
}
|
||||
if (mHwController.hasOngoingStylusHandwritingSession()) {
|
||||
// prevent duplicate calls to startStylusHandwriting().
|
||||
Slog.e(TAG,
|
||||
"Stylus handwriting session is already ongoing."
|
||||
+ " Ignoring startStylusHandwriting().");
|
||||
return;
|
||||
}
|
||||
if (DEBUG) Slog.v(TAG, "Client requesting Stylus Handwriting to be started");
|
||||
final IInputMethodInvoker curMethod = getCurMethodLocked();
|
||||
if (curMethod != null) {
|
||||
@@ -3345,6 +3363,68 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareStylusHandwritingDelegation(
|
||||
@NonNull IInputMethodClient client,
|
||||
@NonNull String delegatePackageName,
|
||||
@NonNull String delegatorPackageName) {
|
||||
if (!verifyClientAndPackageMatch(client, delegatorPackageName)) {
|
||||
Slog.w(TAG, "prepareStylusHandwritingDelegation() fail");
|
||||
throw new IllegalArgumentException("Delegator doesn't match Uid");
|
||||
}
|
||||
schedulePrepareStylusHandwritingDelegation(delegatePackageName, delegatorPackageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptStylusHandwritingDelegation(
|
||||
@NonNull IInputMethodClient client,
|
||||
@NonNull String delegatePackageName,
|
||||
@NonNull String delegatorPackageName) {
|
||||
if (!verifyDelegator(client, delegatePackageName, delegatorPackageName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
startStylusHandwriting(client);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean verifyClientAndPackageMatch(
|
||||
@NonNull IInputMethodClient client, @NonNull String packageName) {
|
||||
ClientState cs;
|
||||
synchronized (ImfLock.class) {
|
||||
cs = mClients.get(client.asBinder());
|
||||
}
|
||||
if (cs == null) {
|
||||
throw new IllegalArgumentException("unknown client " + client.asBinder());
|
||||
}
|
||||
return InputMethodUtils.checkIfPackageBelongsToUid(
|
||||
mPackageManagerInternal, cs.mUid, packageName);
|
||||
}
|
||||
|
||||
private boolean verifyDelegator(
|
||||
@NonNull IInputMethodClient client,
|
||||
@NonNull String delegatePackageName,
|
||||
@NonNull String delegatorPackageName) {
|
||||
if (!verifyClientAndPackageMatch(client, delegatePackageName)) {
|
||||
Slog.w(TAG, "Delegate package does not belong to the same user. Ignoring"
|
||||
+ " startStylusHandwriting");
|
||||
return false;
|
||||
}
|
||||
synchronized (ImfLock.class) {
|
||||
if (!delegatorPackageName.equals(mHwController.getDelegatorPackageName())) {
|
||||
Slog.w(TAG,
|
||||
"Delegator package does not match. Ignoring startStylusHandwriting");
|
||||
return false;
|
||||
}
|
||||
if (!delegatePackageName.equals(mHwController.getDelegatePackageName())) {
|
||||
Slog.w(TAG,
|
||||
"Delegate package does not match. Ignoring startStylusHandwriting");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@BinderThread
|
||||
@Override
|
||||
public void reportPerceptibleAsync(IBinder windowToken, boolean perceptible) {
|
||||
@@ -4852,6 +4932,13 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case MSG_PREPARE_HANDWRITING_DELEGATION:
|
||||
synchronized (ImfLock.class) {
|
||||
String delegate = (String) ((Pair) msg.obj).first;
|
||||
String delegator = (String) ((Pair) msg.obj).second;
|
||||
mHwController.prepareStylusHandwritingDelegation(delegate, delegator);
|
||||
}
|
||||
return true;
|
||||
case MSG_START_HANDWRITING:
|
||||
synchronized (ImfLock.class) {
|
||||
IInputMethodInvoker curMethod = getCurMethodLocked();
|
||||
|
||||
Reference in New Issue
Block a user