Catch IllegalArgumentException from PackageManager in InputMethodUtils

PackageManager APIs sometimes throw IllegalArgumentException.  Failure
to catch them in InputMethodManagerService may result in crash looping
at an early boot stage.

This CL makes sure that InputMethodUtils can gracefully catch
IllegalArgumentException from PackageManagerService without causing
crash of system_server.

For normal situations, there should be no behavior change in this CL.

Fix: 218385726
Test: Manually verified as follows.
 1. Build aosp_coral-userdebug and flash it w/ wiping the user data.
 2. Build coral-userdebug and flash it w/o wiping user the data.
 3. Make sure that the device still boots.
Change-Id: I58af03ec96103b60e20758558a92dd9408baab2f
This commit is contained in:
Yohei Yukawa
2022-03-08 10:34:19 -08:00
parent 54d7eb4497
commit 4654609a7e
2 changed files with 39 additions and 29 deletions

View File

@@ -1757,6 +1757,15 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
}
@NonNull
private static PackageManager getPackageManagerForUser(@NonNull Context context,
@UserIdInt int userId) {
return context.getUserId() == userId
? context.getPackageManager()
: context.createContextAsUser(UserHandle.of(userId), 0 /* flags */)
.getPackageManager();
}
@GuardedBy("ImfLock.class")
private void switchUserOnHandlerLocked(@UserIdInt int newUserId,
IInputMethodClient clientToBeReset) {
@@ -1801,9 +1810,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
updateFromSettingsLocked(true);
if (initialUserSwitch) {
InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(mIPackageManager,
mSettings.getEnabledInputMethodListLocked(), newUserId,
mContext.getBasePackageName());
InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(
getPackageManagerForUser(mContext, newUserId),
mSettings.getEnabledInputMethodListLocked());
}
if (DEBUG) Slog.d(TAG, "Switching user stage 3/3. newUserId=" + newUserId
@@ -1892,9 +1901,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
final boolean imeSelectedOnBoot = !TextUtils.isEmpty(defaultImiId);
buildInputMethodListLocked(!imeSelectedOnBoot /* resetDefaultEnabledIme */);
updateFromSettingsLocked(true);
InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(mIPackageManager,
mSettings.getEnabledInputMethodListLocked(), currentUserId,
mContext.getBasePackageName());
InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(
getPackageManagerForUser(mContext, currentUserId),
mSettings.getEnabledInputMethodListLocked());
}
}
}
@@ -6122,10 +6131,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
setInputMethodEnabledLocked(imi.getId(), true);
}
updateInputMethodsFromSettingsLocked(true /* enabledMayChange */);
InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(mIPackageManager,
mSettings.getEnabledInputMethodListLocked(),
mSettings.getCurrentUserId(),
mContext.getBasePackageName());
InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(
getPackageManagerForUser(mContext, mSettings.getCurrentUserId()),
mSettings.getEnabledInputMethodListLocked());
nextIme = mSettings.getSelectedInputMethod();
nextEnabledImes = mSettings.getEnabledInputMethodListLocked();
} else {

View File

@@ -18,17 +18,16 @@ package com.android.server.inputmethod;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserHandleAware;
import android.annotation.UserIdInt;
import android.app.AppOpsManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Build;
import android.os.LocaleList;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
@@ -663,8 +662,9 @@ final class InputMethodUtils {
return !subtype.isAuxiliary();
}
static void setNonSelectedSystemImesDisabledUntilUsed(IPackageManager packageManager,
List<InputMethodInfo> enabledImis, @UserIdInt int userId, String callingPackage) {
@UserHandleAware
static void setNonSelectedSystemImesDisabledUntilUsed(PackageManager packageManagerForUser,
List<InputMethodInfo> enabledImis) {
if (DEBUG) {
Slog.d(TAG, "setNonSelectedSystemImesDisabledUntilUsed");
}
@@ -675,7 +675,8 @@ final class InputMethodUtils {
}
// Only the current spell checker should be treated as an enabled one.
final SpellCheckerInfo currentSpellChecker =
TextServicesManagerInternal.get().getCurrentSpellCheckerForUser(userId);
TextServicesManagerInternal.get().getCurrentSpellCheckerForUser(
packageManagerForUser.getUserId());
for (final String packageName : systemImesDisabledUntilUsed) {
if (DEBUG) {
Slog.d(TAG, "check " + packageName);
@@ -702,11 +703,12 @@ final class InputMethodUtils {
}
ApplicationInfo ai = null;
try {
ai = packageManager.getApplicationInfo(packageName,
PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, userId);
} catch (RemoteException e) {
ai = packageManagerForUser.getApplicationInfo(packageName,
PackageManager.ApplicationInfoFlags.of(
PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS));
} catch (PackageManager.NameNotFoundException e) {
Slog.w(TAG, "getApplicationInfo failed. packageName=" + packageName
+ " userId=" + userId, e);
+ " userId=" + packageManagerForUser.getUserId(), e);
continue;
}
if (ai == null) {
@@ -717,18 +719,18 @@ final class InputMethodUtils {
if (!isSystemPackage) {
continue;
}
setDisabledUntilUsed(packageManager, packageName, userId, callingPackage);
setDisabledUntilUsed(packageManagerForUser, packageName);
}
}
private static void setDisabledUntilUsed(IPackageManager packageManager, String packageName,
int userId, String callingPackage) {
private static void setDisabledUntilUsed(PackageManager packageManagerForUser,
String packageName) {
final int state;
try {
state = packageManager.getApplicationEnabledSetting(packageName, userId);
} catch (RemoteException e) {
state = packageManagerForUser.getApplicationEnabledSetting(packageName);
} catch (IllegalArgumentException e) {
Slog.w(TAG, "getApplicationEnabledSetting failed. packageName=" + packageName
+ " userId=" + userId, e);
+ " userId=" + packageManagerForUser.getUserId(), e);
return;
}
if (state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
@@ -737,12 +739,12 @@ final class InputMethodUtils {
Slog.d(TAG, "Update state(" + packageName + "): DISABLED_UNTIL_USED");
}
try {
packageManager.setApplicationEnabledSetting(packageName,
packageManagerForUser.setApplicationEnabledSetting(packageName,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED,
0 /* newState */, userId, callingPackage);
} catch (RemoteException e) {
0 /* newState */);
} catch (IllegalArgumentException e) {
Slog.w(TAG, "setApplicationEnabledSetting failed. packageName=" + packageName
+ " userId=" + userId + " callingPackage=" + callingPackage, e);
+ " userId=" + packageManagerForUser.getUserId(), e);
return;
}
} else {