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

Commit f0f16806 authored by Yohei Yukawa's avatar Yohei Yukawa
Browse files

Reset TSMS when the device is unlocked.

This ports my previous CL for InputMethodManagerService [1] to
TextServicesSettings (TSMS).

With File-Based Encryption (FBE), now we have yet another runteime event
to reset TSMS state in order to keep the list of available spell
checkers updated.

See my previous commit message [1] for details about the idea.

Rebuild spell checker list when the system becomes ready.

  [1]: Ifa2225070bf8223f8964cf063c86889e312c5e9a
       0e367d08aab2c1cb2d0fb9cbf1e8a6d09d1ac523

Bug: 27456430
Change-Id: I2b5a6989a99fd18b3bf109f5cda6270ccadaaf6d
parent 49ed1401
Loading
Loading
Loading
Loading
+35 −10
Original line number Original line Diff line number Diff line
@@ -27,6 +27,7 @@ import com.android.internal.textservice.ITextServicesSessionListener;


import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserException;


import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.annotation.UserIdInt;
import android.app.ActivityManagerNative;
import android.app.ActivityManagerNative;
import android.app.AppGlobals;
import android.app.AppGlobals;
@@ -80,6 +81,8 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
    private final ArrayList<SpellCheckerInfo> mSpellCheckerList = new ArrayList<>();
    private final ArrayList<SpellCheckerInfo> mSpellCheckerList = new ArrayList<>();
    private final HashMap<String, SpellCheckerBindGroup> mSpellCheckerBindGroups = new HashMap<>();
    private final HashMap<String, SpellCheckerBindGroup> mSpellCheckerBindGroups = new HashMap<>();
    private final TextServicesSettings mSettings;
    private final TextServicesSettings mSettings;
    @NonNull
    private final UserManager mUserManager;


    public static final class Lifecycle extends SystemService {
    public static final class Lifecycle extends SystemService {
        private TextServicesManagerService mService;
        private TextServicesManagerService mService;
@@ -109,20 +112,37 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
                mService.systemRunning();
                mService.systemRunning();
            }
            }
        }
        }

        @Override
        public void onUnlockUser(@UserIdInt int userHandle) {
            // Called on the system server's main looper thread.
            // TODO: Dispatch this to a worker thread as needed.
            mService.onUnlockUser(userHandle);
        }
    }
    }


    void systemRunning() {
    void systemRunning() {
        synchronized (mSpellCheckerMap) {
        synchronized (mSpellCheckerMap) {
            if (!mSystemReady) {
            if (!mSystemReady) {
                mSystemReady = true;
                mSystemReady = true;
                switchUserLocked(mSettings.getCurrentUserId());
                resetInternalState(mSettings.getCurrentUserId());
            }
            }
        }
        }
    }
    }


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

    void onUnlockUser(@UserIdInt int userId) {
        synchronized(mSpellCheckerMap) {
            final int currentUserId = mSettings.getCurrentUserId();
            if (userId != currentUserId) {
                return;
            }
            resetInternalState(currentUserId);
        }
        }
    }
    }


@@ -130,6 +150,8 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
        mSystemReady = false;
        mSystemReady = false;
        mContext = context;
        mContext = context;


        mUserManager = mContext.getSystemService(UserManager.class);

        final IntentFilter broadcastFilter = new IntentFilter();
        final IntentFilter broadcastFilter = new IntentFilter();
        broadcastFilter.addAction(Intent.ACTION_USER_ADDED);
        broadcastFilter.addAction(Intent.ACTION_USER_ADDED);
        broadcastFilter.addAction(Intent.ACTION_USER_REMOVED);
        broadcastFilter.addAction(Intent.ACTION_USER_REMOVED);
@@ -143,17 +165,18 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
        }
        }
        mMonitor = new TextServicesMonitor();
        mMonitor = new TextServicesMonitor();
        mMonitor.register(context, null, true);
        mMonitor.register(context, null, true);
        // If the system is not ready, then we use copy-on-write settings.
        final boolean useCopyOnWriteSettings =
        final boolean useCopyOnWriteSettings = !mSystemReady;
                !mSystemReady || !mUserManager.isUserUnlocked(userId);
        mSettings = new TextServicesSettings(context.getContentResolver(), userId,
        mSettings = new TextServicesSettings(context.getContentResolver(), userId,
                useCopyOnWriteSettings);
                useCopyOnWriteSettings);


        // "switchUserLocked" initializes the states for the foreground user
        // "resetInternalState" initializes the states for the foreground user
        switchUserLocked(userId);
        resetInternalState(userId);
    }
    }


    private void switchUserLocked(@UserIdInt int userId) {
    private void resetInternalState(@UserIdInt int userId) {
        final boolean useCopyOnWriteSettings = !mSystemReady;
        final boolean useCopyOnWriteSettings =
                !mSystemReady || !mUserManager.isUserUnlocked(userId);
        mSettings.switchCurrentUser(userId, useCopyOnWriteSettings);
        mSettings.switchCurrentUser(userId, useCopyOnWriteSettings);
        updateCurrentProfileIds();
        updateCurrentProfileIds();
        unbindServiceLocked();
        unbindServiceLocked();
@@ -171,8 +194,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
    }
    }


    void updateCurrentProfileIds() {
    void updateCurrentProfileIds() {
        List<UserInfo> profiles =
        final List<UserInfo> profiles = mUserManager.getProfiles(mSettings.getCurrentUserId());
                UserManager.get(mContext).getProfiles(mSettings.getCurrentUserId());
        int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
        int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
        for (int i = 0; i < currentProfileIds.length; i++) {
        for (int i = 0; i < currentProfileIds.length; i++) {
            currentProfileIds[i] = profiles.get(i).id;
            currentProfileIds[i] = profiles.get(i).id;
@@ -237,6 +259,9 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
        list.clear();
        list.clear();
        map.clear();
        map.clear();
        final PackageManager pm = context.getPackageManager();
        final PackageManager pm = context.getPackageManager();
        // Note: We do not specify PackageManager.MATCH_ENCRYPTION_* flags here because the default
        // behavior of PackageManager is exactly what we want.  It by default picks up appropriate
        // services depending on the unlock state for the specified user.
        final List<ResolveInfo> services = pm.queryIntentServicesAsUser(
        final List<ResolveInfo> services = pm.queryIntentServicesAsUser(
                new Intent(SpellCheckerService.SERVICE_INTERFACE), PackageManager.GET_META_DATA,
                new Intent(SpellCheckerService.SERVICE_INTERFACE), PackageManager.GET_META_DATA,
                settings.getCurrentUserId());
                settings.getCurrentUserId());