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

Commit a72c6717 authored by Justin Ghan's avatar Justin Ghan
Browse files

Add connectionless handwriting support to input method info

Adds APIs for input methods to declare support for connectionless
handwriting sessions, and APIs to query support.

Bug: 300979854
Bug: 293898187
Test: atest InputMethodInfoTest
Test: atest StylusHandwritingTest
Change-Id: I16ff508187c9b08146f56801bf3a83fbc2aade73
parent c1e1505e
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1603,6 +1603,7 @@ package android {
    field public static final int supportedTypes = 16844369; // 0x1010651
    field public static final int supportsAssist = 16844016; // 0x10104f0
    field public static final int supportsBatteryGameMode = 16844374; // 0x1010656
    field @FlaggedApi("android.view.inputmethod.connectionless_handwriting") public static final int supportsConnectionlessStylusHandwriting;
    field public static final int supportsInlineSuggestions = 16844301; // 0x101060d
    field public static final int supportsInlineSuggestionsWithTouchExploration = 16844397; // 0x101066d
    field public static final int supportsLaunchVoiceAssistFromKeyguard = 16844017; // 0x10104f1
@@ -56105,6 +56106,7 @@ package android.view.inputmethod {
    method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
    method public CharSequence loadLabel(android.content.pm.PackageManager);
    method public boolean shouldShowInInputMethodPicker();
    method @FlaggedApi("android.view.inputmethod.connectionless_handwriting") public boolean supportsConnectionlessStylusHandwriting();
    method public boolean supportsStylusHandwriting();
    method public boolean suppressesSpellChecker();
    method public void writeToParcel(android.os.Parcel, int);
@@ -56134,6 +56136,7 @@ package android.view.inputmethod {
    method public boolean isAcceptingText();
    method public boolean isActive(android.view.View);
    method public boolean isActive();
    method @FlaggedApi("android.view.inputmethod.connectionless_handwriting") public boolean isConnectionlessStylusHandwritingAvailable();
    method public boolean isFullscreenMode();
    method public boolean isInputMethodSuppressingSpellChecker();
    method public boolean isStylusHandwritingAvailable();
+1 −1
Original line number Diff line number Diff line
@@ -3901,7 +3901,7 @@ package android.view.inputmethod {
  }

  public final class InputMethodInfo implements android.os.Parcelable {
    ctor public InputMethodInfo(@NonNull String, @NonNull String, @NonNull CharSequence, @NonNull String, @NonNull String, boolean, @NonNull String);
    ctor @FlaggedApi("android.view.inputmethod.connectionless_handwriting") public InputMethodInfo(@NonNull String, @NonNull String, @NonNull CharSequence, @NonNull String, @NonNull String, boolean, boolean, @NonNull String);
    ctor public InputMethodInfo(@NonNull String, @NonNull String, @NonNull CharSequence, @NonNull String, int);
    field public static final int COMPONENT_NAME_MAX_LENGTH = 1000; // 0x3e8
    field public static final int MAX_IMES_PER_PACKAGE = 20; // 0x14
+3 −2
Original line number Diff line number Diff line
@@ -530,13 +530,14 @@ final class IInputMethodManagerGlobalInvoker {

    @AnyThread
    @RequiresPermission(value = Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true)
    static boolean isStylusHandwritingAvailableAsUser(@UserIdInt int userId) {
    static boolean isStylusHandwritingAvailableAsUser(
            @UserIdInt int userId, boolean connectionless) {
        final IInputMethodManager service = getService();
        if (service == null) {
            return false;
        }
        try {
            return service.isStylusHandwritingAvailableAsUser(userId);
            return service.isStylusHandwritingAvailableAsUser(userId, connectionless);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
+32 −3
Original line number Diff line number Diff line
@@ -204,6 +204,9 @@ public final class InputMethodInfo implements Parcelable {
     */
    private final boolean mSupportsStylusHandwriting;

    /** The flag whether this IME supports connectionless stylus handwriting sessions. */
    private final boolean mSupportsConnectionlessStylusHandwriting;

    /**
     * The stylus handwriting setting activity's name, used by the system settings to
     * launch the stylus handwriting specific setting activity of this input method.
@@ -330,6 +333,9 @@ public final class InputMethodInfo implements Parcelable {
                    com.android.internal.R.styleable.InputMethod_configChanges, 0);
            mSupportsStylusHandwriting = sa.getBoolean(
                    com.android.internal.R.styleable.InputMethod_supportsStylusHandwriting, false);
            mSupportsConnectionlessStylusHandwriting = sa.getBoolean(
                    com.android.internal.R.styleable
                            .InputMethod_supportsConnectionlessStylusHandwriting, false);
            stylusHandwritingSettingsActivity = sa.getString(
                    com.android.internal.R.styleable.InputMethod_stylusHandwritingSettingsActivity);
            sa.recycle();
@@ -442,6 +448,7 @@ public final class InputMethodInfo implements Parcelable {
        mSubtypes = source.mSubtypes;
        mHandledConfigChanges = source.mHandledConfigChanges;
        mSupportsStylusHandwriting = source.mSupportsStylusHandwriting;
        mSupportsConnectionlessStylusHandwriting = source.mSupportsConnectionlessStylusHandwriting;
        mForceDefault = source.mForceDefault;
        mStylusHandwritingSettingsActivityAttr = source.mStylusHandwritingSettingsActivityAttr;
    }
@@ -463,6 +470,7 @@ public final class InputMethodInfo implements Parcelable {
        mSubtypes = new InputMethodSubtypeArray(source);
        mHandledConfigChanges = source.readInt();
        mSupportsStylusHandwriting = source.readBoolean();
        mSupportsConnectionlessStylusHandwriting = source.readBoolean();
        mStylusHandwritingSettingsActivityAttr = source.readString8();
        mForceDefault = false;
    }
@@ -479,6 +487,7 @@ public final class InputMethodInfo implements Parcelable {
                false /* inlineSuggestionsEnabled */, false /* isVrOnly */,
                false /* isVirtualDeviceOnly */, 0 /* handledConfigChanges */,
                false /* supportsStylusHandwriting */,
                false /* supportConnectionlessStylusHandwriting */,
                null /* stylusHandwritingSettingsActivityAttr */,
                false /* inlineSuggestionsEnabled */);
    }
@@ -488,9 +497,11 @@ public final class InputMethodInfo implements Parcelable {
     * @hide
     */
    @TestApi
    @FlaggedApi(Flags.FLAG_CONNECTIONLESS_HANDWRITING)
    public InputMethodInfo(@NonNull String packageName, @NonNull String className,
            @NonNull CharSequence label, @NonNull String settingsActivity,
            @NonNull String languageSettingsActivity, boolean supportStylusHandwriting,
            boolean supportConnectionlessStylusHandwriting,
            @NonNull String stylusHandwritingSettingsActivityAttr) {
        this(buildFakeResolveInfo(packageName, className, label), false /* isAuxIme */,
                settingsActivity, languageSettingsActivity, null /* subtypes */,
@@ -498,8 +509,8 @@ public final class InputMethodInfo implements Parcelable {
                true /* supportsSwitchingToNextInputMethod */,
                false /* inlineSuggestionsEnabled */, false /* isVrOnly */,
                false /* isVirtualDeviceOnly */, 0 /* handledConfigChanges */,
                supportStylusHandwriting, stylusHandwritingSettingsActivityAttr,
                false /* inlineSuggestionsEnabled */);
                supportStylusHandwriting, supportConnectionlessStylusHandwriting,
                stylusHandwritingSettingsActivityAttr, false /* inlineSuggestionsEnabled */);
    }

    /**
@@ -517,6 +528,7 @@ public final class InputMethodInfo implements Parcelable {
                false /* inlineSuggestionsEnabled */, false /* isVrOnly */,
                false /* isVirtualDeviceOnly */, handledConfigChanges,
                false /* supportsStylusHandwriting */,
                false /* supportConnectionlessStylusHandwriting */,
                null /* stylusHandwritingSettingsActivityAttr */,
                false /* inlineSuggestionsEnabled */);
    }
@@ -533,6 +545,7 @@ public final class InputMethodInfo implements Parcelable {
                true /* supportsSwitchingToNextInputMethod */, false /* inlineSuggestionsEnabled */,
                false /* isVrOnly */, false /* isVirtualDeviceOnly */, 0 /* handledconfigChanges */,
                false /* supportsStylusHandwriting */,
                false /* supportConnectionlessStylusHandwriting */,
                null /* stylusHandwritingSettingsActivityAttr */,
                false /* inlineSuggestionsEnabled */);
    }
@@ -549,6 +562,7 @@ public final class InputMethodInfo implements Parcelable {
                supportsSwitchingToNextInputMethod, false /* inlineSuggestionsEnabled */, isVrOnly,
                false /* isVirtualDeviceOnly */,
                0 /* handledConfigChanges */, false /* supportsStylusHandwriting */,
                false /* supportConnectionlessStylusHandwriting */,
                null /* stylusHandwritingSettingsActivityAttr */,
                false /* inlineSuggestionsEnabled */);
    }
@@ -562,7 +576,8 @@ public final class InputMethodInfo implements Parcelable {
            int isDefaultResId, boolean forceDefault,
            boolean supportsSwitchingToNextInputMethod, boolean inlineSuggestionsEnabled,
            boolean isVrOnly, boolean isVirtualDeviceOnly, int handledConfigChanges,
            boolean supportsStylusHandwriting, String stylusHandwritingSettingsActivityAttr,
            boolean supportsStylusHandwriting, boolean supportsConnectionlessStylusHandwriting,
            String stylusHandwritingSettingsActivityAttr,
            boolean supportsInlineSuggestionsWithTouchExploration) {
        final ServiceInfo si = ri.serviceInfo;
        mService = ri;
@@ -583,6 +598,7 @@ public final class InputMethodInfo implements Parcelable {
        mIsVirtualDeviceOnly = isVirtualDeviceOnly;
        mHandledConfigChanges = handledConfigChanges;
        mSupportsStylusHandwriting = supportsStylusHandwriting;
        mSupportsConnectionlessStylusHandwriting = supportsConnectionlessStylusHandwriting;
        mStylusHandwritingSettingsActivityAttr = stylusHandwritingSettingsActivityAttr;
    }

@@ -762,6 +778,16 @@ public final class InputMethodInfo implements Parcelable {
        return mSupportsStylusHandwriting;
    }

    /**
     * Returns whether the IME supports connectionless stylus handwriting sessions.
     *
     * @attr ref android.R.styleable#InputMethod_supportsConnectionlessStylusHandwriting
     */
    @FlaggedApi(Flags.FLAG_CONNECTIONLESS_HANDWRITING)
    public boolean supportsConnectionlessStylusHandwriting() {
        return mSupportsConnectionlessStylusHandwriting;
    }

    /**
     * Returns {@link Intent} for stylus handwriting settings activity with
     * {@link Intent#getAction() Intent action} {@link #ACTION_STYLUS_HANDWRITING_SETTINGS}
@@ -828,6 +854,8 @@ public final class InputMethodInfo implements Parcelable {
                + " mSuppressesSpellChecker=" + mSuppressesSpellChecker
                + " mShowInInputMethodPicker=" + mShowInInputMethodPicker
                + " mSupportsStylusHandwriting=" + mSupportsStylusHandwriting
                + " mSupportsConnectionlessStylusHandwriting="
                + mSupportsConnectionlessStylusHandwriting
                + " mStylusHandwritingSettingsActivityAttr="
                        + mStylusHandwritingSettingsActivityAttr);
        pw.println(prefix + "mIsDefaultResId=0x"
@@ -947,6 +975,7 @@ public final class InputMethodInfo implements Parcelable {
        mSubtypes.writeToParcel(dest);
        dest.writeInt(mHandledConfigChanges);
        dest.writeBoolean(mSupportsStylusHandwriting);
        dest.writeBoolean(mSupportsConnectionlessStylusHandwriting);
        dest.writeString8(mStylusHandwritingSettingsActivityAttr);
    }

+43 −1
Original line number Diff line number Diff line
@@ -566,8 +566,15 @@ public final class InputMethodManager {
    @GuardedBy("mH")
    private PropertyInvalidatedCache<Integer, Boolean> mStylusHandwritingAvailableCache;

    /** Cached value for {@link #isConnectionlessStylusHandwritingAvailable} for userId. */
    @GuardedBy("mH")
    private PropertyInvalidatedCache<Integer, Boolean>
            mConnectionlessStylusHandwritingAvailableCache;

    private static final String CACHE_KEY_STYLUS_HANDWRITING_PROPERTY =
            "cache_key.system_server.stylus_handwriting";
    private static final String CACHE_KEY_CONNECTIONLESS_STYLUS_HANDWRITING_PROPERTY =
            "cache_key.system_server.connectionless_stylus_handwriting";

    @GuardedBy("mH")
    private int mCursorSelStart;
@@ -691,6 +698,17 @@ public final class InputMethodManager {
        PropertyInvalidatedCache.invalidateCache(CACHE_KEY_STYLUS_HANDWRITING_PROPERTY);
    }

    /**
     * Calling this will invalidate the local connectionless stylus handwriting availability cache,
     * which forces the next query in any process to recompute the cache.
     *
     * @hide
     */
    public static void invalidateLocalConnectionlessStylusHandwritingAvailabilityCaches() {
        PropertyInvalidatedCache.invalidateCache(
                CACHE_KEY_CONNECTIONLESS_STYLUS_HANDWRITING_PROPERTY);
    }

    private static boolean isAutofillUIShowing(View servedView) {
        AutofillManager afm = servedView.getContext().getSystemService(AutofillManager.class);
        return afm != null && afm.isAutofillUiShowing();
@@ -1584,7 +1602,7 @@ public final class InputMethodManager {
                    @Override
                    public Boolean recompute(Integer userId) {
                        return IInputMethodManagerGlobalInvoker.isStylusHandwritingAvailableAsUser(
                                userId);
                                userId, /* connectionless= */ false);
                    }
                };
            }
@@ -1593,6 +1611,30 @@ public final class InputMethodManager {
        return isAvailable;
    }

    /**
     * Returns {@code true} if the currently selected IME supports connectionless stylus handwriting
     * sessions and is enabled.
     */
    @FlaggedApi(Flags.FLAG_CONNECTIONLESS_HANDWRITING)
    public boolean isConnectionlessStylusHandwritingAvailable() {
        if (ActivityThread.currentApplication() == null) {
            return false;
        }
        synchronized (mH) {
            if (mConnectionlessStylusHandwritingAvailableCache == null) {
                mConnectionlessStylusHandwritingAvailableCache = new PropertyInvalidatedCache<>(
                        /* maxEntries= */ 4, CACHE_KEY_CONNECTIONLESS_STYLUS_HANDWRITING_PROPERTY) {
                    @Override
                    public Boolean recompute(@NonNull Integer userId) {
                        return IInputMethodManagerGlobalInvoker.isStylusHandwritingAvailableAsUser(
                                userId, /* connectionless= */ true);
                    }
                };
            }
            return mConnectionlessStylusHandwritingAvailableCache.query(UserHandle.myUserId());
        }
    }

    /**
     * Returns the list of installed input methods for the specified user.
     *
Loading