• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007-2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 
17 package android.view.inputmethod;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.TestApi;
22 import android.compat.annotation.UnsupportedAppUsage;
23 import android.content.ComponentName;
24 import android.content.Context;
25 import android.content.pm.ActivityInfo;
26 import android.content.pm.ApplicationInfo;
27 import android.content.pm.PackageManager;
28 import android.content.pm.PackageManager.NameNotFoundException;
29 import android.content.pm.ResolveInfo;
30 import android.content.pm.ServiceInfo;
31 import android.content.res.Configuration;
32 import android.content.res.Resources;
33 import android.content.res.Resources.NotFoundException;
34 import android.content.res.TypedArray;
35 import android.content.res.XmlResourceParser;
36 import android.graphics.drawable.Drawable;
37 import android.inputmethodservice.InputMethodService;
38 import android.os.Parcel;
39 import android.os.Parcelable;
40 import android.util.AttributeSet;
41 import android.util.Printer;
42 import android.util.Slog;
43 import android.util.Xml;
44 import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
45 
46 import org.xmlpull.v1.XmlPullParser;
47 import org.xmlpull.v1.XmlPullParserException;
48 
49 import java.io.IOException;
50 import java.util.ArrayList;
51 import java.util.List;
52 
53 /**
54  * This class is used to specify meta information of an input method.
55  *
56  * <p>It should be defined in an XML resource file with an {@code <input-method>} element.
57  * For more information, see the guide to
58  * <a href="{@docRoot}guide/topics/text/creating-input-method.html">
59  * Creating an Input Method</a>.</p>
60  *
61  * @see InputMethodSubtype
62  *
63  * @attr ref android.R.styleable#InputMethod_settingsActivity
64  * @attr ref android.R.styleable#InputMethod_isDefault
65  * @attr ref android.R.styleable#InputMethod_supportsSwitchingToNextInputMethod
66  * @attr ref android.R.styleable#InputMethod_supportsInlineSuggestions
67  * @attr ref android.R.styleable#InputMethod_suppressesSpellChecker
68  * @attr ref android.R.styleable#InputMethod_showInInputMethodPicker
69  * @attr ref android.R.styleable#InputMethod_configChanges
70  */
71 public final class InputMethodInfo implements Parcelable {
72     static final String TAG = "InputMethodInfo";
73 
74     /**
75      * The Service that implements this input method component.
76      */
77     final ResolveInfo mService;
78 
79     /**
80      * IME only supports VR mode.
81      */
82     final boolean mIsVrOnly;
83 
84     /**
85      * The unique string Id to identify the input method.  This is generated
86      * from the input method component.
87      */
88     final String mId;
89 
90     /**
91      * The input method setting activity's name, used by the system settings to
92      * launch the setting activity of this input method.
93      */
94     final String mSettingsActivityName;
95 
96     /**
97      * The resource in the input method's .apk that holds a boolean indicating
98      * whether it should be considered the default input method for this
99      * system.  This is a resource ID instead of the final value so that it
100      * can change based on the configuration (in particular locale).
101      */
102     final int mIsDefaultResId;
103 
104     /**
105      * An array-like container of the subtypes.
106      */
107     @UnsupportedAppUsage
108     private final InputMethodSubtypeArray mSubtypes;
109 
110     private final boolean mIsAuxIme;
111 
112     /**
113      * Caveat: mForceDefault must be false for production. This flag is only for test.
114      */
115     private final boolean mForceDefault;
116 
117     /**
118      * The flag whether this IME supports ways to switch to a next input method (e.g. globe key.)
119      */
120     private final boolean mSupportsSwitchingToNextInputMethod;
121 
122     /**
123      * The flag whether this IME supports inline suggestions.
124      */
125     private final boolean mInlineSuggestionsEnabled;
126 
127     /**
128      * The flag whether this IME suppresses spell checker.
129      */
130     private final boolean mSuppressesSpellChecker;
131 
132     /**
133      * The flag whether this IME should be shown as an option in the IME picker.
134      */
135     private final boolean mShowInInputMethodPicker;
136 
137     /**
138      * The flag for configurations IME assumes the responsibility for handling in
139      * {@link InputMethodService#onConfigurationChanged(Configuration)}}.
140      */
141     private final int mHandledConfigChanges;
142 
143     /**
144      * @param service the {@link ResolveInfo} corresponds in which the IME is implemented.
145      * @return a unique ID to be returned by {@link #getId()}. We have used
146      *         {@link ComponentName#flattenToShortString()} for this purpose (and it is already
147      *         unrealistic to switch to a different scheme as it is already implicitly assumed in
148      *         many places).
149      * @hide
150      */
computeId(@onNull ResolveInfo service)151     public static String computeId(@NonNull ResolveInfo service) {
152         final ServiceInfo si = service.serviceInfo;
153         return new ComponentName(si.packageName, si.name).flattenToShortString();
154     }
155 
156     /**
157      * Constructor.
158      *
159      * @param context The Context in which we are parsing the input method.
160      * @param service The ResolveInfo returned from the package manager about
161      * this input method's component.
162      */
InputMethodInfo(Context context, ResolveInfo service)163     public InputMethodInfo(Context context, ResolveInfo service)
164             throws XmlPullParserException, IOException {
165         this(context, service, null);
166     }
167 
168     /**
169      * Constructor.
170      *
171      * @param context The Context in which we are parsing the input method.
172      * @param service The ResolveInfo returned from the package manager about
173      * this input method's component.
174      * @param additionalSubtypes additional subtypes being added to this InputMethodInfo
175      * @hide
176      */
InputMethodInfo(Context context, ResolveInfo service, List<InputMethodSubtype> additionalSubtypes)177     public InputMethodInfo(Context context, ResolveInfo service,
178             List<InputMethodSubtype> additionalSubtypes)
179             throws XmlPullParserException, IOException {
180         mService = service;
181         ServiceInfo si = service.serviceInfo;
182         mId = computeId(service);
183         boolean isAuxIme = true;
184         boolean supportsSwitchingToNextInputMethod = false; // false as default
185         boolean inlineSuggestionsEnabled = false; // false as default
186         boolean suppressesSpellChecker = false; // false as default
187         boolean showInInputMethodPicker = true; // true as default
188         mForceDefault = false;
189 
190         PackageManager pm = context.getPackageManager();
191         String settingsActivityComponent = null;
192         boolean isVrOnly;
193         int isDefaultResId = 0;
194 
195         XmlResourceParser parser = null;
196         final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
197         try {
198             parser = si.loadXmlMetaData(pm, InputMethod.SERVICE_META_DATA);
199             if (parser == null) {
200                 throw new XmlPullParserException("No "
201                         + InputMethod.SERVICE_META_DATA + " meta-data");
202             }
203 
204             Resources res = pm.getResourcesForApplication(si.applicationInfo);
205 
206             AttributeSet attrs = Xml.asAttributeSet(parser);
207 
208             int type;
209             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
210                     && type != XmlPullParser.START_TAG) {
211             }
212 
213             String nodeName = parser.getName();
214             if (!"input-method".equals(nodeName)) {
215                 throw new XmlPullParserException(
216                         "Meta-data does not start with input-method tag");
217             }
218 
219             TypedArray sa = res.obtainAttributes(attrs,
220                     com.android.internal.R.styleable.InputMethod);
221             settingsActivityComponent = sa.getString(
222                     com.android.internal.R.styleable.InputMethod_settingsActivity);
223             isVrOnly = sa.getBoolean(com.android.internal.R.styleable.InputMethod_isVrOnly, false);
224             isDefaultResId = sa.getResourceId(
225                     com.android.internal.R.styleable.InputMethod_isDefault, 0);
226             supportsSwitchingToNextInputMethod = sa.getBoolean(
227                     com.android.internal.R.styleable.InputMethod_supportsSwitchingToNextInputMethod,
228                     false);
229             inlineSuggestionsEnabled = sa.getBoolean(
230                     com.android.internal.R.styleable.InputMethod_supportsInlineSuggestions, false);
231             suppressesSpellChecker = sa.getBoolean(
232                     com.android.internal.R.styleable.InputMethod_suppressesSpellChecker, false);
233             showInInputMethodPicker = sa.getBoolean(
234                     com.android.internal.R.styleable.InputMethod_showInInputMethodPicker, true);
235             mHandledConfigChanges = sa.getInt(
236                     com.android.internal.R.styleable.InputMethod_configChanges, 0);
237             sa.recycle();
238 
239             final int depth = parser.getDepth();
240             // Parse all subtypes
241             while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
242                     && type != XmlPullParser.END_DOCUMENT) {
243                 if (type == XmlPullParser.START_TAG) {
244                     nodeName = parser.getName();
245                     if (!"subtype".equals(nodeName)) {
246                         throw new XmlPullParserException(
247                                 "Meta-data in input-method does not start with subtype tag");
248                     }
249                     final TypedArray a = res.obtainAttributes(
250                             attrs, com.android.internal.R.styleable.InputMethod_Subtype);
251                     final InputMethodSubtype subtype = new InputMethodSubtypeBuilder()
252                             .setSubtypeNameResId(a.getResourceId(com.android.internal.R.styleable
253                                     .InputMethod_Subtype_label, 0))
254                             .setSubtypeIconResId(a.getResourceId(com.android.internal.R.styleable
255                                     .InputMethod_Subtype_icon, 0))
256                             .setLanguageTag(a.getString(com.android.internal.R.styleable
257                                     .InputMethod_Subtype_languageTag))
258                             .setSubtypeLocale(a.getString(com.android.internal.R.styleable
259                                     .InputMethod_Subtype_imeSubtypeLocale))
260                             .setSubtypeMode(a.getString(com.android.internal.R.styleable
261                                     .InputMethod_Subtype_imeSubtypeMode))
262                             .setSubtypeExtraValue(a.getString(com.android.internal.R.styleable
263                                     .InputMethod_Subtype_imeSubtypeExtraValue))
264                             .setIsAuxiliary(a.getBoolean(com.android.internal.R.styleable
265                                     .InputMethod_Subtype_isAuxiliary, false))
266                             .setOverridesImplicitlyEnabledSubtype(a.getBoolean(
267                                     com.android.internal.R.styleable
268                                     .InputMethod_Subtype_overridesImplicitlyEnabledSubtype, false))
269                             .setSubtypeId(a.getInt(com.android.internal.R.styleable
270                                     .InputMethod_Subtype_subtypeId, 0 /* use Arrays.hashCode */))
271                             .setIsAsciiCapable(a.getBoolean(com.android.internal.R.styleable
272                                     .InputMethod_Subtype_isAsciiCapable, false)).build();
273                     if (!subtype.isAuxiliary()) {
274                         isAuxIme = false;
275                     }
276                     subtypes.add(subtype);
277                 }
278             }
279         } catch (NameNotFoundException | IndexOutOfBoundsException | NumberFormatException e) {
280             throw new XmlPullParserException(
281                     "Unable to create context for: " + si.packageName);
282         } finally {
283             if (parser != null) parser.close();
284         }
285 
286         if (subtypes.size() == 0) {
287             isAuxIme = false;
288         }
289 
290         if (additionalSubtypes != null) {
291             final int N = additionalSubtypes.size();
292             for (int i = 0; i < N; ++i) {
293                 final InputMethodSubtype subtype = additionalSubtypes.get(i);
294                 if (!subtypes.contains(subtype)) {
295                     subtypes.add(subtype);
296                 } else {
297                     Slog.w(TAG, "Duplicated subtype definition found: "
298                             + subtype.getLocale() + ", " + subtype.getMode());
299                 }
300             }
301         }
302         mSubtypes = new InputMethodSubtypeArray(subtypes);
303         mSettingsActivityName = settingsActivityComponent;
304         mIsDefaultResId = isDefaultResId;
305         mIsAuxIme = isAuxIme;
306         mSupportsSwitchingToNextInputMethod = supportsSwitchingToNextInputMethod;
307         mInlineSuggestionsEnabled = inlineSuggestionsEnabled;
308         mSuppressesSpellChecker = suppressesSpellChecker;
309         mShowInInputMethodPicker = showInInputMethodPicker;
310         mIsVrOnly = isVrOnly;
311     }
312 
InputMethodInfo(Parcel source)313     InputMethodInfo(Parcel source) {
314         mId = source.readString();
315         mSettingsActivityName = source.readString();
316         mIsDefaultResId = source.readInt();
317         mIsAuxIme = source.readInt() == 1;
318         mSupportsSwitchingToNextInputMethod = source.readInt() == 1;
319         mInlineSuggestionsEnabled = source.readInt() == 1;
320         mSuppressesSpellChecker = source.readBoolean();
321         mShowInInputMethodPicker = source.readBoolean();
322         mIsVrOnly = source.readBoolean();
323         mService = ResolveInfo.CREATOR.createFromParcel(source);
324         mSubtypes = new InputMethodSubtypeArray(source);
325         mHandledConfigChanges = source.readInt();
326         mForceDefault = false;
327     }
328 
329     /**
330      * Temporary API for creating a built-in input method for test.
331      */
InputMethodInfo(String packageName, String className, CharSequence label, String settingsActivity)332     public InputMethodInfo(String packageName, String className,
333             CharSequence label, String settingsActivity) {
334         this(buildFakeResolveInfo(packageName, className, label), false /* isAuxIme */,
335                 settingsActivity, null /* subtypes */, 0 /* isDefaultResId */,
336                 false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */,
337                 false /* inlineSuggestionsEnabled */, false /* isVrOnly */,
338                 0 /* handledConfigChanges */);
339     }
340 
341     /**
342      * Temporary API for creating a built-in input method for test.
343      * @hide
344      */
345     @TestApi
InputMethodInfo(@onNull String packageName, @NonNull String className, @NonNull CharSequence label, @NonNull String settingsActivity, int handledConfigChanges)346     public InputMethodInfo(@NonNull String packageName, @NonNull String className,
347             @NonNull CharSequence label, @NonNull String settingsActivity,
348             int handledConfigChanges) {
349         this(buildFakeResolveInfo(packageName, className, label), false /* isAuxIme */,
350                 settingsActivity, null /* subtypes */, 0 /* isDefaultResId */,
351                 false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */,
352                 false /* inlineSuggestionsEnabled */, false /* isVrOnly */, handledConfigChanges);
353     }
354 
355     /**
356      * Temporary API for creating a built-in input method for test.
357      * @hide
358      */
InputMethodInfo(ResolveInfo ri, boolean isAuxIme, String settingsActivity, List<InputMethodSubtype> subtypes, int isDefaultResId, boolean forceDefault)359     public InputMethodInfo(ResolveInfo ri, boolean isAuxIme,
360             String settingsActivity, List<InputMethodSubtype> subtypes, int isDefaultResId,
361             boolean forceDefault) {
362         this(ri, isAuxIme, settingsActivity, subtypes, isDefaultResId, forceDefault,
363                 true /* supportsSwitchingToNextInputMethod */, false /* inlineSuggestionsEnabled */,
364                 false /* isVrOnly */, 0 /* handledconfigChanges */);
365     }
366 
367     /**
368      * Temporary API for creating a built-in input method for test.
369      * @hide
370      */
InputMethodInfo(ResolveInfo ri, boolean isAuxIme, String settingsActivity, List<InputMethodSubtype> subtypes, int isDefaultResId, boolean forceDefault, boolean supportsSwitchingToNextInputMethod, boolean isVrOnly)371     public InputMethodInfo(ResolveInfo ri, boolean isAuxIme, String settingsActivity,
372             List<InputMethodSubtype> subtypes, int isDefaultResId, boolean forceDefault,
373             boolean supportsSwitchingToNextInputMethod, boolean isVrOnly) {
374         this(ri, isAuxIme, settingsActivity, subtypes, isDefaultResId, forceDefault,
375                 supportsSwitchingToNextInputMethod, false /* inlineSuggestionsEnabled */, isVrOnly,
376                 0 /* handledConfigChanges */);
377     }
378 
379     /**
380      * Temporary API for creating a built-in input method for test.
381      * @hide
382      */
InputMethodInfo(ResolveInfo ri, boolean isAuxIme, String settingsActivity, List<InputMethodSubtype> subtypes, int isDefaultResId, boolean forceDefault, boolean supportsSwitchingToNextInputMethod, boolean inlineSuggestionsEnabled, boolean isVrOnly, int handledConfigChanges)383     public InputMethodInfo(ResolveInfo ri, boolean isAuxIme, String settingsActivity,
384             List<InputMethodSubtype> subtypes, int isDefaultResId, boolean forceDefault,
385             boolean supportsSwitchingToNextInputMethod, boolean inlineSuggestionsEnabled,
386             boolean isVrOnly, int handledConfigChanges) {
387         final ServiceInfo si = ri.serviceInfo;
388         mService = ri;
389         mId = new ComponentName(si.packageName, si.name).flattenToShortString();
390         mSettingsActivityName = settingsActivity;
391         mIsDefaultResId = isDefaultResId;
392         mIsAuxIme = isAuxIme;
393         mSubtypes = new InputMethodSubtypeArray(subtypes);
394         mForceDefault = forceDefault;
395         mSupportsSwitchingToNextInputMethod = supportsSwitchingToNextInputMethod;
396         mInlineSuggestionsEnabled = inlineSuggestionsEnabled;
397         mSuppressesSpellChecker = false;
398         mShowInInputMethodPicker = true;
399         mIsVrOnly = isVrOnly;
400         mHandledConfigChanges = handledConfigChanges;
401     }
402 
buildFakeResolveInfo(String packageName, String className, CharSequence label)403     private static ResolveInfo buildFakeResolveInfo(String packageName, String className,
404             CharSequence label) {
405         ResolveInfo ri = new ResolveInfo();
406         ServiceInfo si = new ServiceInfo();
407         ApplicationInfo ai = new ApplicationInfo();
408         ai.packageName = packageName;
409         ai.enabled = true;
410         si.applicationInfo = ai;
411         si.enabled = true;
412         si.packageName = packageName;
413         si.name = className;
414         si.exported = true;
415         si.nonLocalizedLabel = label;
416         ri.serviceInfo = si;
417         return ri;
418     }
419 
420     /**
421      * Return a unique ID for this input method.  The ID is generated from
422      * the package and class name implementing the method.
423      */
getId()424     public String getId() {
425         return mId;
426     }
427 
428     /**
429      * Return the .apk package that implements this input method.
430      */
getPackageName()431     public String getPackageName() {
432         return mService.serviceInfo.packageName;
433     }
434 
435     /**
436      * Return the class name of the service component that implements
437      * this input method.
438      */
getServiceName()439     public String getServiceName() {
440         return mService.serviceInfo.name;
441     }
442 
443     /**
444      * Return the raw information about the Service implementing this
445      * input method.  Do not modify the returned object.
446      */
getServiceInfo()447     public ServiceInfo getServiceInfo() {
448         return mService.serviceInfo;
449     }
450 
451     /**
452      * Return the component of the service that implements this input
453      * method.
454      */
getComponent()455     public ComponentName getComponent() {
456         return new ComponentName(mService.serviceInfo.packageName,
457                 mService.serviceInfo.name);
458     }
459 
460     /**
461      * Load the user-displayed label for this input method.
462      *
463      * @param pm Supply a PackageManager used to load the input method's
464      * resources.
465      */
loadLabel(PackageManager pm)466     public CharSequence loadLabel(PackageManager pm) {
467         return mService.loadLabel(pm);
468     }
469 
470     /**
471      * Load the user-displayed icon for this input method.
472      *
473      * @param pm Supply a PackageManager used to load the input method's
474      * resources.
475      */
loadIcon(PackageManager pm)476     public Drawable loadIcon(PackageManager pm) {
477         return mService.loadIcon(pm);
478     }
479 
480     /**
481      * Return the class name of an activity that provides a settings UI for
482      * the input method.  You can launch this activity be starting it with
483      * an {@link android.content.Intent} whose action is MAIN and with an
484      * explicit {@link android.content.ComponentName}
485      * composed of {@link #getPackageName} and the class name returned here.
486      *
487      * <p>A null will be returned if there is no settings activity associated
488      * with the input method.</p>
489      */
getSettingsActivity()490     public String getSettingsActivity() {
491         return mSettingsActivityName;
492     }
493 
494     /**
495      * Returns true if IME supports VR mode only.
496      * @hide
497      */
isVrOnly()498     public boolean isVrOnly() {
499         return mIsVrOnly;
500     }
501 
502     /**
503      * Return the count of the subtypes of Input Method.
504      */
getSubtypeCount()505     public int getSubtypeCount() {
506         return mSubtypes.getCount();
507     }
508 
509     /**
510      * Return the Input Method's subtype at the specified index.
511      *
512      * @param index the index of the subtype to return.
513      */
getSubtypeAt(int index)514     public InputMethodSubtype getSubtypeAt(int index) {
515         return mSubtypes.get(index);
516     }
517 
518     /**
519      * Return the resource identifier of a resource inside of this input
520      * method's .apk that determines whether it should be considered a
521      * default input method for the system.
522      */
getIsDefaultResourceId()523     public int getIsDefaultResourceId() {
524         return mIsDefaultResId;
525     }
526 
527     /**
528      * Return whether or not this ime is a default ime or not.
529      * @hide
530      */
531     @UnsupportedAppUsage
isDefault(Context context)532     public boolean isDefault(Context context) {
533         if (mForceDefault) {
534             return true;
535         }
536         try {
537             if (getIsDefaultResourceId() == 0) {
538                 return false;
539             }
540             final Resources res = context.createPackageContext(getPackageName(), 0).getResources();
541             return res.getBoolean(getIsDefaultResourceId());
542         } catch (NameNotFoundException | NotFoundException e) {
543             return false;
544         }
545     }
546 
547     /**
548      * Returns the bit mask of kinds of configuration changes that this IME
549      * can handle itself (without being restarted by the system).
550      *
551      * @attr ref android.R.styleable#InputMethod_configChanges
552      */
553     @ActivityInfo.Config
getConfigChanges()554     public int getConfigChanges() {
555         return mHandledConfigChanges;
556     }
557 
dump(Printer pw, String prefix)558     public void dump(Printer pw, String prefix) {
559         pw.println(prefix + "mId=" + mId
560                 + " mSettingsActivityName=" + mSettingsActivityName
561                 + " mIsVrOnly=" + mIsVrOnly
562                 + " mSupportsSwitchingToNextInputMethod=" + mSupportsSwitchingToNextInputMethod
563                 + " mInlineSuggestionsEnabled=" + mInlineSuggestionsEnabled
564                 + " mSuppressesSpellChecker=" + mSuppressesSpellChecker
565                 + " mShowInInputMethodPicker=" + mShowInInputMethodPicker);
566         pw.println(prefix + "mIsDefaultResId=0x"
567                 + Integer.toHexString(mIsDefaultResId));
568         pw.println(prefix + "Service:");
569         mService.dump(pw, prefix + "  ");
570     }
571 
572     @Override
toString()573     public String toString() {
574         return "InputMethodInfo{" + mId
575                 + ", settings: "
576                 + mSettingsActivityName + "}";
577     }
578 
579     /**
580      * Used to test whether the given parameter object is an
581      * {@link InputMethodInfo} and its Id is the same to this one.
582      *
583      * @return true if the given parameter object is an
584      *         {@link InputMethodInfo} and its Id is the same to this one.
585      */
586     @Override
equals(@ullable Object o)587     public boolean equals(@Nullable Object o) {
588         if (o == this) return true;
589         if (o == null) return false;
590 
591         if (!(o instanceof InputMethodInfo)) return false;
592 
593         InputMethodInfo obj = (InputMethodInfo) o;
594         return mId.equals(obj.mId);
595     }
596 
597     @Override
hashCode()598     public int hashCode() {
599         return mId.hashCode();
600     }
601 
602     /**
603      * @hide
604      * @return {@code true} if the IME is a trusted system component (e.g. pre-installed)
605      */
isSystem()606     public boolean isSystem() {
607         return (mService.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
608     }
609 
610     /**
611      * @hide
612      */
isAuxiliaryIme()613     public boolean isAuxiliaryIme() {
614         return mIsAuxIme;
615     }
616 
617     /**
618      * @return true if this input method supports ways to switch to a next input method.
619      * @hide
620      */
supportsSwitchingToNextInputMethod()621     public boolean supportsSwitchingToNextInputMethod() {
622         return mSupportsSwitchingToNextInputMethod;
623     }
624 
625     /**
626      * @return true if this input method supports inline suggestions.
627      * @hide
628      */
isInlineSuggestionsEnabled()629     public boolean isInlineSuggestionsEnabled() {
630         return mInlineSuggestionsEnabled;
631     }
632 
633     /**
634      * Return {@code true} if this input method suppresses spell checker.
635      */
suppressesSpellChecker()636     public boolean suppressesSpellChecker() {
637         return mSuppressesSpellChecker;
638     }
639 
640     /**
641      * Returns {@code true} if this input method should be shown in menus for selecting an Input
642      * Method, such as the system Input Method Picker. This is {@code false} if the IME is intended
643      * to be accessed programmatically.
644      */
shouldShowInInputMethodPicker()645     public boolean shouldShowInInputMethodPicker() {
646         return mShowInInputMethodPicker;
647     }
648 
649     /**
650      * Used to package this object into a {@link Parcel}.
651      *
652      * @param dest The {@link Parcel} to be written.
653      * @param flags The flags used for parceling.
654      */
655     @Override
writeToParcel(Parcel dest, int flags)656     public void writeToParcel(Parcel dest, int flags) {
657         dest.writeString(mId);
658         dest.writeString(mSettingsActivityName);
659         dest.writeInt(mIsDefaultResId);
660         dest.writeInt(mIsAuxIme ? 1 : 0);
661         dest.writeInt(mSupportsSwitchingToNextInputMethod ? 1 : 0);
662         dest.writeInt(mInlineSuggestionsEnabled ? 1 : 0);
663         dest.writeBoolean(mSuppressesSpellChecker);
664         dest.writeBoolean(mShowInInputMethodPicker);
665         dest.writeBoolean(mIsVrOnly);
666         mService.writeToParcel(dest, flags);
667         mSubtypes.writeToParcel(dest);
668         dest.writeInt(mHandledConfigChanges);
669     }
670 
671     /**
672      * Used to make this class parcelable.
673      */
674     public static final @android.annotation.NonNull Parcelable.Creator<InputMethodInfo> CREATOR
675             = new Parcelable.Creator<InputMethodInfo>() {
676         @Override
677         public InputMethodInfo createFromParcel(Parcel source) {
678             return new InputMethodInfo(source);
679         }
680 
681         @Override
682         public InputMethodInfo[] newArray(int size) {
683             return new InputMethodInfo[size];
684         }
685     };
686 
687     @Override
describeContents()688     public int describeContents() {
689         return 0;
690     }
691 }
692