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

Commit 73d1ca18 authored by Cosmin Băieș's avatar Cosmin Băieș
Browse files

Revert "Introduce per-user InputMethodSettings cache"

This reverts commit 90622cfc.

This fixes a lock contention that added a regression in boot time.

Fix: 329414077
Bug: 309837937
Test: n/a
Change-Id: I1e6caa541620523ffdd611042c80a3b2562ae0be
parent 84c61c45
Loading
Loading
Loading
Loading
+3 −13
Original line number Diff line number Diff line
@@ -19,13 +19,11 @@ package com.android.server.inputmethod;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.Context;
import android.content.pm.UserInfo;
import android.os.Handler;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.inputmethod.DirectBootAwareness;
import com.android.server.LocalServices;
import com.android.server.pm.UserManagerInternal;

@@ -69,7 +67,7 @@ final class AdditionalSubtypeMapRepository {
        AdditionalSubtypeUtils.save(map, inputMethodMap, userId);
    }

    static void initialize(@NonNull Handler handler, @NonNull Context context) {
    static void initialize(@NonNull Handler handler) {
        final UserManagerInternal userManagerInternal =
                LocalServices.getService(UserManagerInternal.class);
        handler.post(() -> {
@@ -81,16 +79,8 @@ final class AdditionalSubtypeMapRepository {
                            handler.post(() -> {
                                synchronized (ImfLock.class) {
                                    if (!sPerUserMap.contains(userId)) {
                                        final AdditionalSubtypeMap additionalSubtypeMap =
                                                AdditionalSubtypeUtils.load(userId);
                                        sPerUserMap.put(userId, additionalSubtypeMap);
                                        final InputMethodSettings settings =
                                                InputMethodManagerService
                                                        .queryInputMethodServicesInternal(context,
                                                                userId,
                                                                additionalSubtypeMap,
                                                                DirectBootAwareness.AUTO);
                                        InputMethodSettingsRepository.put(userId, settings);
                                        sPerUserMap.put(userId,
                                                AdditionalSubtypeUtils.load(userId));
                                    }
                                }
                            });
+31 −46
Original line number Diff line number Diff line
@@ -870,17 +870,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
            if (!mSystemReady) {
                return;
            }
            for (int userId : mUserManagerInternal.getUserIds()) {
                final InputMethodSettings settings = queryInputMethodServicesInternal(
                                mContext,
                                userId,
                                AdditionalSubtypeMapRepository.get(userId),
            mSettings = queryInputMethodServicesInternal(mContext, mSettings.getUserId(),
                    AdditionalSubtypeMapRepository.get(mSettings.getUserId()),
                    DirectBootAwareness.AUTO);
                InputMethodSettingsRepository.put(userId, settings);
                if (userId == mSettings.getUserId()) {
                    mSettings = settings;
                }
            }
            postInputMethodSettingUpdatedLocked(true /* resetDefaultEnabledIme */);
            // If the locale is changed, needs to reset the default ime
            resetDefaultImeLocked(mContext);
@@ -1127,15 +1119,12 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
                    AdditionalSubtypeMapRepository.putAndSave(userId, newAdditionalSubtypeMap,
                            settings.getMethodMap());
                }
                if (isCurrentUser
                        && !(additionalSubtypeChanged || shouldRebuildInputMethodListLocked())) {

                if (!isCurrentUser) {
                    return;
                }

                final InputMethodSettings newSettings = queryInputMethodServicesInternal(mContext,
                        userId, newAdditionalSubtypeMap, DirectBootAwareness.AUTO);
                InputMethodSettingsRepository.put(userId, newSettings);
                if (!isCurrentUser) {
                if (!(additionalSubtypeChanged || shouldRebuildInputMethodListLocked())) {
                    return;
                }
                mSettings = queryInputMethodServicesInternal(mContext, userId,
@@ -1300,24 +1289,23 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub

    void onUnlockUser(@UserIdInt int userId) {
        synchronized (ImfLock.class) {
            final int currentUserId = mSettings.getUserId();
            if (DEBUG) {
                Slog.d(TAG, "onUnlockUser: userId=" + userId + " curUserId="
                        + mSettings.getUserId());
                Slog.d(TAG, "onUnlockUser: userId=" + userId + " curUserId=" + currentUserId);
            }
            if (userId != currentUserId) {
                return;
            }
            if (!mSystemReady) {
                return;
            }
            final InputMethodSettings newSettings = queryInputMethodServicesInternal(mContext,
                    userId, AdditionalSubtypeMapRepository.get(userId), DirectBootAwareness.AUTO);
            InputMethodSettingsRepository.put(userId, newSettings);
            if (mSettings.getUserId() == userId) {
                mSettings = newSettings;
            mSettings = queryInputMethodServicesInternal(mContext, userId,
                    AdditionalSubtypeMapRepository.get(userId), DirectBootAwareness.AUTO);
            // We need to rebuild IMEs.
            postInputMethodSettingUpdatedLocked(false /* resetDefaultEnabledIme */);
            updateInputMethodsFromSettingsLocked(true /* enabledChanged */);
        }
    }
    }

    @GuardedBy("ImfLock.class")
    void scheduleSwitchUserTaskLocked(@UserIdInt int userId,
@@ -1379,13 +1367,12 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub

        mShowOngoingImeSwitcherForPhones = false;

        // InputMethodSettingsRepository should be initialized before buildInputMethodListLocked
        InputMethodSettingsRepository.initialize(mHandler, mContext);
        AdditionalSubtypeMapRepository.initialize(mHandler, mContext);
        AdditionalSubtypeMapRepository.initialize(mHandler);

        final int userId = mActivityManagerInternal.getCurrentUserId();

        mSettings = InputMethodSettingsRepository.get(userId);
        // mSettings should be created before buildInputMethodListLocked
        mSettings = InputMethodSettings.createEmptyMap(userId);

        mSwitchingController =
                InputMethodSubtypeSwitchingController.createInstanceLocked(context,
@@ -1549,10 +1536,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
        // and user switch would not happen at that time.
        resetCurrentMethodAndClientLocked(UnbindReason.SWITCH_USER);

        final InputMethodSettings newSettings = queryInputMethodServicesInternal(mContext,
                newUserId, AdditionalSubtypeMapRepository.get(newUserId), DirectBootAwareness.AUTO);
        InputMethodSettingsRepository.put(newUserId, newSettings);
        mSettings = newSettings;
        mSettings = queryInputMethodServicesInternal(mContext, newUserId,
                AdditionalSubtypeMapRepository.get(newUserId), DirectBootAwareness.AUTO);
        postInputMethodSettingUpdatedLocked(initialUserSwitch /* resetDefaultEnabledIme */);
        if (TextUtils.isEmpty(mSettings.getSelectedInputMethod())) {
            // This is the first time of the user switch and
@@ -1634,11 +1619,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub

                final String defaultImiId = mSettings.getSelectedInputMethod();
                final boolean imeSelectedOnBoot = !TextUtils.isEmpty(defaultImiId);
                final InputMethodSettings newSettings = queryInputMethodServicesInternal(mContext,
                        currentUserId, AdditionalSubtypeMapRepository.get(currentUserId),
                mSettings = queryInputMethodServicesInternal(mContext, currentUserId,
                        AdditionalSubtypeMapRepository.get(mSettings.getUserId()),
                        DirectBootAwareness.AUTO);
                InputMethodSettingsRepository.put(currentUserId, newSettings);
                mSettings = newSettings;
                postInputMethodSettingUpdatedLocked(
                        !imeSelectedOnBoot /* resetDefaultEnabledIme */);
                updateFromSettingsLocked(true);
@@ -4078,20 +4061,22 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub

            final var additionalSubtypeMap = AdditionalSubtypeMapRepository.get(userId);
            final boolean isCurrentUser = (mSettings.getUserId() == userId);
            final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
            final InputMethodSettings settings = isCurrentUser
                    ? mSettings
                    : queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap,
                            DirectBootAwareness.AUTO);
            final var newAdditionalSubtypeMap = settings.getNewAdditionalSubtypeMap(
                    imiId, toBeAdded, additionalSubtypeMap, mPackageManagerInternal, callingUid);
            if (additionalSubtypeMap != newAdditionalSubtypeMap) {
                AdditionalSubtypeMapRepository.putAndSave(userId, newAdditionalSubtypeMap,
                        settings.getMethodMap());
                final InputMethodSettings newSettings = queryInputMethodServicesInternal(mContext,
                        userId, AdditionalSubtypeMapRepository.get(userId),
                        DirectBootAwareness.AUTO);
                InputMethodSettingsRepository.put(userId, newSettings);
                if (isCurrentUser) {
                    final long ident = Binder.clearCallingIdentity();
                    try {
                        mSettings = newSettings;
                        mSettings = queryInputMethodServicesInternal(mContext,
                                mSettings.getUserId(),
                                AdditionalSubtypeMapRepository.get(mSettings.getUserId()),
                                DirectBootAwareness.AUTO);
                        postInputMethodSettingUpdatedLocked(false /* resetDefaultEnabledIme */);
                    } finally {
                        Binder.restoreCallingIdentity(ident);
+0 −86
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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 com.android.server.inputmethod;

import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.content.Context;
import android.content.pm.UserInfo;
import android.os.Handler;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.inputmethod.DirectBootAwareness;
import com.android.server.LocalServices;
import com.android.server.pm.UserManagerInternal;

final class InputMethodSettingsRepository {
    @GuardedBy("ImfLock.class")
    @NonNull
    private static final SparseArray<InputMethodSettings> sPerUserMap = new SparseArray<>();

    /**
     * Not intended to be instantiated.
     */
    private InputMethodSettingsRepository() {
    }

    @NonNull
    @GuardedBy("ImfLock.class")
    static InputMethodSettings get(@UserIdInt int userId) {
        final InputMethodSettings obj = sPerUserMap.get(userId);
        if (obj != null) {
            return obj;
        }
        return InputMethodSettings.createEmptyMap(userId);
    }

    @GuardedBy("ImfLock.class")
    static void put(@UserIdInt int userId, @NonNull InputMethodSettings obj) {
        sPerUserMap.put(userId, obj);
    }

    static void initialize(@NonNull Handler handler, @NonNull Context context) {
        final UserManagerInternal userManagerInternal =
                LocalServices.getService(UserManagerInternal.class);
        handler.post(() -> {
            userManagerInternal.addUserLifecycleListener(
                    new UserManagerInternal.UserLifecycleListener() {
                        @Override
                        public void onUserRemoved(UserInfo user) {
                            final int userId = user.id;
                            handler.post(() -> {
                                synchronized (ImfLock.class) {
                                    sPerUserMap.remove(userId);
                                }
                            });
                        }
                    });
            synchronized (ImfLock.class) {
                for (int userId : userManagerInternal.getUserIds()) {
                    final InputMethodSettings settings =
                            InputMethodManagerService.queryInputMethodServicesInternal(
                                    context,
                                    userId,
                                    AdditionalSubtypeMapRepository.get(userId),
                                    DirectBootAwareness.AUTO);
                    sPerUserMap.put(userId, settings);
                }
            }
        });
    }
}