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

Commit 10ae385e authored by Guliz Tuncay's avatar Guliz Tuncay
Browse files

Use a separate lock object instead of mSpellCheckerMap

In order to make TSMS multi-user aware, the first step is to get rid of
the use of user-specific mSpellCheckerMap (since there will be one for
each user) in the synchronized blocks, and instead use a separate
object lock.

Bug: 63041121
Test: Manually tested as follows.
      1. Build and flash an OS image.
      2. Complete the setup wizard (if any).
      3. Make sure AOSP Keyboard (com.android.inputmethod.latin)
       is installed.
      4. adb shell settings put secure selected_spell_checker com.android.inputmethod.latin/.spellcheck.AndroidSpellCheckerService
      5. Observe that there are no bindings to the selected spell
       checker service (SCS) by running
       adb shell dumpsys textservices
      6. Observe that there is no connection to selected SCS by running
       adb shell dumpsys activity services com.android.inputmethod.latin
       There should be no ConnectionRecord for
       AndroidSpellCheckerService
      7. Run a test program that has TextView and tap on one of the
       TextViews and type some text.
      8. Repeat steps 5 and 6 to observe there are now bindings and
       connection to the selected SCS.
      9. Kill the app manually. Repeat steps 5 and 6 to see bindings
       and connections are removed again.
      10. adb shell settings put secure selected_spell_checker com.google.android.inputmethod.latin/com.android.inputmethod.latin.spellcheck.AndroidSpellCheckerService
      11. Repeat 7, 8, 9.
      12. Switch to a secondary user account. Repeat 3-11.
Change-Id: Ic8772accb4c6225a1e662fd2fa371b2f4c87e445
parent 692cafde
Loading
Loading
Loading
Loading
+18 −17
Original line number Diff line number Diff line
@@ -85,6 +85,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
    private final TextServicesSettings mSettings;
    @NonNull
    private final UserManager mUserManager;
    private final Object mLock = new Object();

    public static final class Lifecycle extends SystemService {
        private TextServicesManagerService mService;
@@ -124,7 +125,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
    }

    void systemRunning() {
        synchronized (mSpellCheckerMap) {
        synchronized (mLock) {
            if (!mSystemReady) {
                mSystemReady = true;
                resetInternalState(mSettings.getCurrentUserId());
@@ -133,13 +134,13 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
    }

    void onSwitchUser(@UserIdInt int userId) {
        synchronized (mSpellCheckerMap) {
        synchronized (mLock) {
            resetInternalState(userId);
        }
    }

    void onUnlockUser(@UserIdInt int userId) {
        synchronized(mSpellCheckerMap) {
        synchronized (mLock) {
            final int currentUserId = mSettings.getCurrentUserId();
            if (userId != currentUserId) {
                return;
@@ -215,7 +216,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
            if (!isChangingPackagesOfCurrentUser()) {
                return;
            }
            synchronized (mSpellCheckerMap) {
            synchronized (mLock) {
                buildSpellCheckerMapLocked(
                        mContext, mSpellCheckerList, mSpellCheckerMap, mSettings);
                // TODO: Update for each locale
@@ -440,7 +441,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
    }

    private SpellCheckerInfo getCurrentSpellCheckerWithoutVerification() {
        synchronized (mSpellCheckerMap) {
        synchronized (mLock) {
            final String curSpellCheckerId = mSettings.getSelectedSpellChecker();
            if (DBG) {
                Slog.w(TAG, "getCurrentSpellChecker: " + curSpellCheckerId);
@@ -464,7 +465,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
        final int subtypeHashCode;
        final SpellCheckerInfo sci;
        final Locale systemLocale;
        synchronized (mSpellCheckerMap) {
        synchronized (mLock) {
            subtypeHashCode =
                    mSettings.getSelectedSpellCheckerSubtype(SpellCheckerSubtype.SUBTYPE_ID_NONE);
            if (DBG) {
@@ -546,7 +547,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
            Slog.e(TAG, "getSpellCheckerService: Invalid input.");
            return;
        }
        synchronized(mSpellCheckerMap) {
        synchronized (mLock) {
            if (!mSpellCheckerMap.containsKey(sciId)) {
                return;
            }
@@ -578,7 +579,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
        if (!calledFromValidUser()) {
            return false;
        }
        synchronized(mSpellCheckerMap) {
        synchronized (mLock) {
            return isSpellCheckerEnabledLocked();
        }
    }
@@ -628,7 +629,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
        if (DBG) {
            Slog.d(TAG, "FinishSpellCheckerService");
        }
        synchronized(mSpellCheckerMap) {
        synchronized (mLock) {
            final ArrayList<SpellCheckerBindGroup> removeList = new ArrayList<>();
            for (SpellCheckerBindGroup group : mSpellCheckerBindGroups.values()) {
                if (group == null) continue;
@@ -698,7 +699,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;

        synchronized(mSpellCheckerMap) {
        synchronized (mLock) {
            pw.println("Current Text Services Manager state:");
            pw.println("  Spell Checkers:");
            int spellCheckerIndex = 0;
@@ -796,7 +797,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
                Slog.d(TAG, "onServiceConnected");
            }

            synchronized(mSpellCheckerMap) {
            synchronized (mLock) {
                mSpellChecker = spellChecker;
                mConnected = true;
                // Dispatch pending getISpellCheckerSession requests.
@@ -810,7 +811,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
                Slog.d(TAG, "onServiceDisconnected");
            }

            synchronized(mSpellCheckerMap) {
            synchronized (mLock) {
                mSpellChecker = null;
                mConnected = false;
            }
@@ -820,7 +821,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
            if (DBG) {
                Slog.w(TAG, "remove listener: " + listener.hashCode());
            }
            synchronized(mSpellCheckerMap) {
            synchronized (mLock) {
                mListeners.unregister(listener);
                cleanLocked();
            }
@@ -858,7 +859,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {

        public void removeAll() {
            Slog.e(TAG, "Remove the spell checker bind unexpectedly.");
            synchronized(mSpellCheckerMap) {
            synchronized (mLock) {
                final int size = mListeners.getRegisteredCallbackCount();
                for (int i = 0; i < size; ++i) {
                    mListeners.unregister(mListeners.getRegisteredCallbackItem(i));
@@ -898,7 +899,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {

        void onSessionCreated(@Nullable final ISpellCheckerSession newSession,
                @NonNull final SessionRequest request) {
            synchronized (mSpellCheckerMap) {
            synchronized (mLock) {
                if (mUnbindCalled) {
                    return;
                }
@@ -926,7 +927,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            synchronized(mSpellCheckerMap) {
            synchronized (mLock) {
                onServiceConnectedInnerLocked(name, service);
            }
        }
@@ -945,7 +946,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {

        @Override
        public void onServiceDisconnected(ComponentName name) {
            synchronized(mSpellCheckerMap) {
            synchronized (mLock) {
                onServiceDisconnectedInnerLocked(name);
            }
        }