diff options
7 files changed, 366 insertions, 34 deletions
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java index 08e30aa37c40..54c2ba565125 100644 --- a/core/java/android/view/inputmethod/InputMethodInfo.java +++ b/core/java/android/view/inputmethod/InputMethodInfo.java @@ -81,6 +81,11 @@ public final class InputMethodInfo implements Parcelable { private boolean mIsAuxIme; /** + * Cavert: mForceDefault must be false for production. This flag is only for test. + */ + private final boolean mForceDefault; + + /** * Constructor. * * @param context The Context in which we are parsing the input method. @@ -108,6 +113,7 @@ public final class InputMethodInfo implements Parcelable { ServiceInfo si = service.serviceInfo; mId = new ComponentName(si.packageName, si.name).flattenToShortString(); mIsAuxIme = true; + mForceDefault = false; PackageManager pm = context.getPackageManager(); String settingsActivityComponent = null; @@ -215,13 +221,39 @@ public final class InputMethodInfo implements Parcelable { mIsAuxIme = source.readInt() == 1; mService = ResolveInfo.CREATOR.createFromParcel(source); source.readTypedList(mSubtypes, InputMethodSubtype.CREATOR); + mForceDefault = false; } /** - * Temporary API for creating a built-in input method. + * Temporary API for creating a built-in input method for test. */ public InputMethodInfo(String packageName, String className, CharSequence label, String settingsActivity) { + this(buildDummyResolveInfo(packageName, className, label), false, settingsActivity, null, + 0, false); + } + + /** + * Temporary API for creating a built-in input method for test. + * @hide + */ + public InputMethodInfo(ResolveInfo ri, boolean isAuxIme, + String settingsActivity, List<InputMethodSubtype> subtypes, int isDefaultResId, + boolean forceDefault) { + final ServiceInfo si = ri.serviceInfo; + mService = ri; + mId = new ComponentName(si.packageName, si.name).flattenToShortString(); + mSettingsActivityName = settingsActivity; + mIsDefaultResId = isDefaultResId; + mIsAuxIme = isAuxIme; + if (subtypes != null) { + mSubtypes.addAll(subtypes); + } + mForceDefault = forceDefault; + } + + private static ResolveInfo buildDummyResolveInfo(String packageName, String className, + CharSequence label) { ResolveInfo ri = new ResolveInfo(); ServiceInfo si = new ServiceInfo(); ApplicationInfo ai = new ApplicationInfo(); @@ -234,11 +266,7 @@ public final class InputMethodInfo implements Parcelable { si.exported = true; si.nonLocalizedLabel = label; ri.serviceInfo = si; - mService = ri; - mId = new ComponentName(si.packageName, si.name).flattenToShortString(); - mSettingsActivityName = settingsActivity; - mIsDefaultResId = 0; - mIsAuxIme = false; + return ri; } /** @@ -340,6 +368,22 @@ public final class InputMethodInfo implements Parcelable { return mIsDefaultResId; } + /** + * Return whether or not this ime is a default ime or not. + * @hide + */ + public boolean isDefault(Context context) { + if (mForceDefault) { + return true; + } + try { + final Resources res = context.createPackageContext(getPackageName(), 0).getResources(); + return res.getBoolean(getIsDefaultResourceId()); + } catch (NameNotFoundException e) { + return false; + } + } + public void dump(Printer pw, String prefix) { pw.println(prefix + "mId=" + mId + " mSettingsActivityName=" + mSettingsActivityName); diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java index 3d7e1ffc1277..655d148548ba 100644 --- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java +++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java @@ -59,11 +59,53 @@ public class InputMethodUtils { & ApplicationInfo.FLAG_SYSTEM) != 0; } - public static boolean isSystemImeThatHasEnglishSubtype(InputMethodInfo imi) { + public static boolean isSystemImeThatHasEnglishKeyboardSubtype(InputMethodInfo imi) { if (!isSystemIme(imi)) { return false; } - return containsSubtypeOf(imi, ENGLISH_LOCALE.getLanguage()); + return containsSubtypeOf(imi, ENGLISH_LOCALE.getLanguage(), SUBTYPE_MODE_KEYBOARD); + } + + private static boolean isSystemAuxilialyImeThatHashAutomaticSubtype(InputMethodInfo imi) { + if (!isSystemIme(imi)) { + return false; + } + if (!imi.isAuxiliaryIme()) { + return false; + } + final int subtypeCount = imi.getSubtypeCount(); + for (int i = 0; i < subtypeCount; ++i) { + final InputMethodSubtype s = imi.getSubtypeAt(i); + if (s.overridesImplicitlyEnabledSubtype()) { + return true; + } + } + return false; + } + + public static ArrayList<InputMethodInfo> getDefaultEnabledImes( + Context context, boolean isSystemReady, ArrayList<InputMethodInfo> imis) { + final ArrayList<InputMethodInfo> retval = new ArrayList<InputMethodInfo>(); + boolean auxilialyImeAdded = false; + for (int i = 0; i < imis.size(); ++i) { + final InputMethodInfo imi = imis.get(i); + if (isDefaultEnabledIme(isSystemReady, imi, context)) { + retval.add(imi); + if (imi.isAuxiliaryIme()) { + auxilialyImeAdded = true; + } + } + } + if (auxilialyImeAdded) { + return retval; + } + for (int i = 0; i < imis.size(); ++i) { + final InputMethodInfo imi = imis.get(i); + if (isSystemAuxilialyImeThatHashAutomaticSubtype(imi)) { + retval.add(imi); + } + } + return retval; } // TODO: Rename isSystemDefaultImeThatHasCurrentLanguageSubtype @@ -77,14 +119,11 @@ public class InputMethodUtils { } if (imi.getIsDefaultResourceId() != 0) { try { - Resources res = context.createPackageContext( - imi.getPackageName(), 0).getResources(); - if (res.getBoolean(imi.getIsDefaultResourceId()) - && containsSubtypeOf(imi, context.getResources().getConfiguration(). - locale.getLanguage())) { + if (imi.isDefault(context) && containsSubtypeOf( + imi, context.getResources().getConfiguration().locale.getLanguage(), + null /* mode */)) { return true; } - } catch (PackageManager.NameNotFoundException ex) { } catch (Resources.NotFoundException ex) { } } @@ -97,15 +136,19 @@ public class InputMethodUtils { public static boolean isDefaultEnabledIme( boolean isSystemReady, InputMethodInfo imi, Context context) { return isValidSystemDefaultIme(isSystemReady, imi, context) - || isSystemImeThatHasEnglishSubtype(imi); + || isSystemImeThatHasEnglishKeyboardSubtype(imi); } - private static boolean containsSubtypeOf(InputMethodInfo imi, String language) { + private static boolean containsSubtypeOf(InputMethodInfo imi, String language, String mode) { final int N = imi.getSubtypeCount(); for (int i = 0; i < N; ++i) { - if (imi.getSubtypeAt(i).getLocale().startsWith(language)) { - return true; + if (!imi.getSubtypeAt(i).getLocale().startsWith(language)) { + continue; + } + if(!TextUtils.isEmpty(mode) && !imi.getSubtypeAt(i).getMode().equalsIgnoreCase(mode)) { + continue; } + return true; } return false; } @@ -141,7 +184,7 @@ public class InputMethodUtils { while (i > 0) { i--; final InputMethodInfo imi = enabledImes.get(i); - if (InputMethodUtils.isSystemImeThatHasEnglishSubtype(imi) + if (InputMethodUtils.isSystemImeThatHasEnglishKeyboardSubtype(imi) && !imi.isAuxiliaryIme()) { return imi; } diff --git a/core/tests/inputmethodtests/Android.mk b/core/tests/inputmethodtests/Android.mk new file mode 100644 index 000000000000..4631e6530214 --- /dev/null +++ b/core/tests/inputmethodtests/Android.mk @@ -0,0 +1,18 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +# We only want this apk build for tests. +LOCAL_MODULE_TAGS := tests + +# Include all test java files. +LOCAL_SRC_FILES := \ + $(call all-java-files-under, src) + +LOCAL_DX_FLAGS := --core-library +LOCAL_STATIC_JAVA_LIBRARIES := core-tests android-common frameworks-core-util-lib +LOCAL_JAVA_LIBRARIES := android.test.runner +LOCAL_PACKAGE_NAME := FrameworksCoreInputMethodTests + +LOCAL_CERTIFICATE := platform + +include $(BUILD_PACKAGE) diff --git a/core/tests/inputmethodtests/AndroidManifest.xml b/core/tests/inputmethodtests/AndroidManifest.xml new file mode 100644 index 000000000000..7f0b1aa27b1c --- /dev/null +++ b/core/tests/inputmethodtests/AndroidManifest.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2013 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. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + android:installLocation="internalOnly" + package="com.android.frameworks.coretests.inputmethod" + android:sharedUserId="android.uid.system"> + + <application> + <uses-library android:name="android.test.runner" /> + </application> + + <instrumentation android:name="android.test.InstrumentationTestRunner" + android:targetPackage="com.android.frameworks.coretests.inputmethod" + android:label="Frameworks InputMethod Core Tests" /> + +</manifest> diff --git a/core/tests/inputmethodtests/run_core_inputmethod_test.sh b/core/tests/inputmethodtests/run_core_inputmethod_test.sh new file mode 100755 index 000000000000..5e123ec20a2f --- /dev/null +++ b/core/tests/inputmethodtests/run_core_inputmethod_test.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +while [[ $# -gt 0 ]]; do + case "$1" in + --rebuild ) echo Rebuild && rebuild=true;; + * ) com_opts+=($1);; + esac + shift +done + +if [[ -z $ANDROID_PRODUCT_OUT && $rebuilld == true ]]; then + echo You must lunch before running this test. + exit 0 +fi + +if [[ $rebuild == true ]]; then + make -j4 FrameworksCoreInputMethodTests + TESTAPP=${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreInputMethodTests.apk + COMMAND="adb install -r $TESTAPP" + echo $COMMAND + $COMMAND +fi + +adb shell am instrument -w -e class android.os.InputMethodTest com.android.frameworks.coretests.inputmethod/android.test.InstrumentationTestRunner diff --git a/core/tests/inputmethodtests/src/android/os/InputMethodTest.java b/core/tests/inputmethodtests/src/android/os/InputMethodTest.java new file mode 100644 index 000000000000..0a2b50cb568e --- /dev/null +++ b/core/tests/inputmethodtests/src/android/os/InputMethodTest.java @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2013 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.os; + +import com.android.internal.inputmethod.InputMethodUtils; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.test.InstrumentationTestCase; +import android.test.suitebuilder.annotation.SmallTest; +import android.view.inputmethod.InputMethodInfo; +import android.view.inputmethod.InputMethodSubtype; + +import java.util.ArrayList; +import java.util.List; + +public class InputMethodTest extends InstrumentationTestCase { + private static final boolean IS_AUX = true; + private static final boolean IS_DEFAULT = true; + private static final boolean IS_AUTO = true; + + @SmallTest + public void testDefaultEnabledImesWithDefaultVoiceIme() throws Exception { + final Context context = getInstrumentation().getTargetContext(); + final ArrayList<InputMethodInfo> imis = new ArrayList<InputMethodInfo>(); + imis.add(createDefaultAutoDummyVoiceIme()); + imis.add(createNonDefaultAutoDummyVoiceIme0()); + imis.add(createNonDefaultAutoDummyVoiceIme1()); + imis.add(createNonDefaultDummyVoiceIme2()); + imis.add(createDefaultDummyEnUSKeyboardIme()); + imis.add(createNonDefaultDummyJaJPKeyboardIme()); + final ArrayList<InputMethodInfo> enabledImis = InputMethodUtils.getDefaultEnabledImes( + context, true, imis); + assertEquals(2, enabledImis.size()); + for (int i = 0; i < enabledImis.size(); ++i) { + final InputMethodInfo imi = enabledImis.get(0); + // "DummyDefaultAutoVoiceIme" and "DummyDefaultEnKeyboardIme" + if (imi.getPackageName().equals("DummyDefaultAutoVoiceIme") + || imi.getPackageName().equals("DummyDefaultEnKeyboardIme")) { + continue; + } else { + fail("Invalid enabled subtype."); + } + } + } + + @SmallTest + public void testDefaultEnabledImesWithOutDefaultVoiceIme() throws Exception { + final Context context = getInstrumentation().getTargetContext(); + final ArrayList<InputMethodInfo> imis = new ArrayList<InputMethodInfo>(); + imis.add(createNonDefaultAutoDummyVoiceIme0()); + imis.add(createNonDefaultAutoDummyVoiceIme1()); + imis.add(createNonDefaultDummyVoiceIme2()); + imis.add(createDefaultDummyEnUSKeyboardIme()); + imis.add(createNonDefaultDummyJaJPKeyboardIme()); + final ArrayList<InputMethodInfo> enabledImis = InputMethodUtils.getDefaultEnabledImes( + context, true, imis); + assertEquals(3, enabledImis.size()); + for (int i = 0; i < enabledImis.size(); ++i) { + final InputMethodInfo imi = enabledImis.get(0); + // "DummyNonDefaultAutoVoiceIme0", "DummyNonDefaultAutoVoiceIme1" and + // "DummyDefaultEnKeyboardIme" + if (imi.getPackageName().equals("DummyNonDefaultAutoVoiceIme0") + || imi.getPackageName().equals("DummyNonDefaultAutoVoiceIme1") + || imi.getPackageName().equals("DummyDefaultEnKeyboardIme")) { + continue; + } else { + fail("Invalid enabled subtype."); + } + } + } + + private static InputMethodInfo createDummyInputMethodInfo(String packageName, String name, + CharSequence label, boolean isAuxIme, boolean isDefault, + List<InputMethodSubtype> subtypes) { + final ResolveInfo ri = new ResolveInfo(); + final ServiceInfo si = new ServiceInfo(); + final ApplicationInfo ai = new ApplicationInfo(); + ai.packageName = packageName; + ai.enabled = true; + ai.flags |= ApplicationInfo.FLAG_SYSTEM; + si.applicationInfo = ai; + si.enabled = true; + si.packageName = packageName; + si.name = name; + si.exported = true; + si.nonLocalizedLabel = label; + ri.serviceInfo = si; + return new InputMethodInfo(ri, isAuxIme, "", subtypes, 1, isDefault); + } + + private static InputMethodSubtype createDummyInputMethodSubtype(String locale, String mode, + boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype) { + return new InputMethodSubtype(0, 0, locale, mode, "", isAuxiliary, + overridesImplicitlyEnabledSubtype); + } + + private static InputMethodInfo createDefaultAutoDummyVoiceIme() { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(createDummyInputMethodSubtype("auto", "voice", IS_AUX, IS_AUTO)); + subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO)); + return createDummyInputMethodInfo("DummyDefaultAutoVoiceIme", "dummy.voice0", + "DummyVoice0", IS_AUX, IS_DEFAULT, subtypes); + } + + private static InputMethodInfo createNonDefaultAutoDummyVoiceIme0() { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(createDummyInputMethodSubtype("auto", "voice", IS_AUX, IS_AUTO)); + subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO)); + return createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme0", "dummy.voice1", + "DummyVoice1", IS_AUX, !IS_DEFAULT, subtypes); + } + + private static InputMethodInfo createNonDefaultAutoDummyVoiceIme1() { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(createDummyInputMethodSubtype("auto", "voice", IS_AUX, IS_AUTO)); + subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO)); + return createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme1", "dummy.voice2", + "DummyVoice2", IS_AUX, !IS_DEFAULT, subtypes); + } + + private static InputMethodInfo createNonDefaultDummyVoiceIme2() { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO)); + return createDummyInputMethodInfo("DummyNonDefaultVoiceIme2", "dummy.voice3", + "DummyVoice3", IS_AUX, !IS_DEFAULT, subtypes); + } + + private static InputMethodInfo createDefaultDummyEnUSKeyboardIme() { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(createDummyInputMethodSubtype("en_US", "keyboard", !IS_AUX, !IS_AUTO)); + return createDummyInputMethodInfo("DummyDefaultEnKeyboardIme", "dummy.keyboard0", + "DummyKeyboard0", !IS_AUX, IS_DEFAULT, subtypes); + } + + private static InputMethodInfo createNonDefaultDummyJaJPKeyboardIme() { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(createDummyInputMethodSubtype("ja_JP", "keyboard", !IS_AUX, !IS_AUTO)); + return createDummyInputMethodInfo("DummyNonDefaultJaJPKeyboardIme", "dummy.keyboard1", + "DummyKeyboard1", !IS_AUX, !IS_DEFAULT, subtypes); + } +} diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index 0f14265e1334..1a8641badfa3 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -511,7 +511,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } - buildInputMethodListLocked(mMethodList, mMethodMap); + buildInputMethodListLocked( + mMethodList, mMethodMap, false /* resetDefaultEnabledIme */); boolean changed = false; @@ -671,9 +672,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // Just checking if defaultImiId is empty or not final String defaultImiId = mSettings.getSelectedInputMethod(); + if (DEBUG) { + Slog.d(TAG, "Initial default ime = " + defaultImiId); + } mImeSelectedOnBoot = !TextUtils.isEmpty(defaultImiId); - buildInputMethodListLocked(mMethodList, mMethodMap); + buildInputMethodListLocked(mMethodList, mMethodMap, + !mImeSelectedOnBoot /* resetDefaultEnabledIme */); mSettings.enableAllIMEsIfThereIsNoEnabledIME(); if (!mImeSelectedOnBoot) { @@ -726,7 +731,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } - private void resetAllInternalStateLocked(boolean updateOnlyWhenLocaleChanged) { + private void resetAllInternalStateLocked(final boolean updateOnlyWhenLocaleChanged) { if (!mSystemReady) { // not system ready return; @@ -744,7 +749,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } // InputMethodAndSubtypeListManager should be reset when the locale is changed. mImListManager = new InputMethodAndSubtypeListManager(mContext, this); - buildInputMethodListLocked(mMethodList, mMethodMap); + buildInputMethodListLocked(mMethodList, mMethodMap, + updateOnlyWhenLocaleChanged /* resetDefaultEnabledIme */); if (!updateOnlyWhenLocaleChanged) { final String selectedImiId = mSettings.getSelectedInputMethod(); if (TextUtils.isEmpty(selectedImiId)) { @@ -814,7 +820,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mWindowManagerService.setOnHardKeyboardStatusChangeListener( mHardKeyboardListener); } - buildInputMethodListLocked(mMethodList, mMethodMap); + buildInputMethodListLocked(mMethodList, mMethodMap, + !mImeSelectedOnBoot /* resetDefaultEnabledIme */); if (!mImeSelectedOnBoot) { Slog.w(TAG, "Reset the default IME as \"Resource\" is ready here."); checkCurrentLocaleChangedLocked(); @@ -2147,7 +2154,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mFileManager.addInputMethodSubtypes(imi, subtypes); final long ident = Binder.clearCallingIdentity(); try { - buildInputMethodListLocked(mMethodList, mMethodMap); + buildInputMethodListLocked(mMethodList, mMethodMap, + false /* resetDefaultEnabledIme */); } finally { Binder.restoreCallingIdentity(ident); } @@ -2397,9 +2405,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } void buildInputMethodListLocked(ArrayList<InputMethodInfo> list, - HashMap<String, InputMethodInfo> map) { + HashMap<String, InputMethodInfo> map, boolean resetDefaultEnabledIme) { if (DEBUG) { - Slog.d(TAG, "--- re-buildInputMethodList " + ", \n ------ \n" + getStackTrace()); + Slog.d(TAG, "--- re-buildInputMethodList reset = " + resetDefaultEnabledIme + + " \n ------ \n" + getStackTrace()); } list.clear(); map.clear(); @@ -2436,14 +2445,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub final String id = p.getId(); map.put(id, p); - // Valid system default IMEs and IMEs that have English subtypes are enabled - // by default - if (InputMethodUtils.isDefaultEnabledIme(mSystemReady, p, mContext)) { - setInputMethodEnabledLocked(id, true); - } - if (DEBUG) { - Slog.d(TAG, "Found a third-party input method " + p); + Slog.d(TAG, "Found an input method " + p); } } catch (XmlPullParserException e) { @@ -2453,6 +2456,18 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } + if (resetDefaultEnabledIme) { + final ArrayList<InputMethodInfo> defaultEnabledIme = + InputMethodUtils.getDefaultEnabledImes(mContext, mSystemReady, list); + for (int i = 0; i < defaultEnabledIme.size(); ++i) { + final InputMethodInfo imi = defaultEnabledIme.get(i); + if (DEBUG) { + Slog.d(TAG, "--- enable ime = " + imi); + } + setInputMethodEnabledLocked(imi.getId(), true); + } + } + final String defaultImiId = mSettings.getSelectedInputMethod(); if (!TextUtils.isEmpty(defaultImiId)) { if (!map.containsKey(defaultImiId)) { |