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