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

Commit b1f56430 authored by Yohei Yukawa's avatar Yohei Yukawa Committed by Android Git Automerger
Browse files

am 22cbf54c: Merge "Conditionally allow non-primay profiles to use TextServices" into lmp-mr1-dev

* commit '22cbf54c':
  Conditionally allow non-primay profiles to use TextServices
parents 4f5b8a6b 22cbf54c
Loading
Loading
Loading
Loading
+94 −4
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.PackageMonitor;
import com.android.internal.textservice.ISpellCheckerService;
import com.android.internal.textservice.ISpellCheckerSession;
@@ -28,14 +29,18 @@ import org.xmlpull.v1.XmlPullParserException;
import android.app.ActivityManagerNative;
import android.app.AppGlobals;
import android.app.IUserSwitchObserver;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
@@ -43,6 +48,7 @@ import android.os.IRemoteCallback;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.service.textservice.SpellCheckerService;
import android.text.TextUtils;
@@ -84,6 +90,12 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
    public TextServicesManagerService(Context context) {
        mSystemReady = false;
        mContext = context;

        final IntentFilter broadcastFilter = new IntentFilter();
        broadcastFilter.addAction(Intent.ACTION_USER_ADDED);
        broadcastFilter.addAction(Intent.ACTION_USER_REMOVED);
        mContext.registerReceiver(new TextServicesBroadcastReceiver(), broadcastFilter);

        int userId = UserHandle.USER_OWNER;
        try {
            ActivityManagerNative.getDefault().registerUserSwitchObserver(
@@ -119,6 +131,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {

    private void switchUserLocked(int userId) {
        mSettings.setCurrentUserId(userId);
        updateCurrentProfileIds();
        unbindServiceLocked();
        buildSpellCheckerMapLocked(mContext, mSpellCheckerList, mSpellCheckerMap, mSettings);
        SpellCheckerInfo sci = getCurrentSpellChecker(null);
@@ -133,6 +146,16 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
        }
    }

    void updateCurrentProfileIds() {
        List<UserInfo> profiles =
                UserManager.get(mContext).getProfiles(mSettings.getCurrentUserId());
        int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
        for (int i = 0; i < currentProfileIds.length; i++) {
            currentProfileIds[i] = profiles.get(i).id;
        }
        mSettings.setCurrentProfileIds(currentProfileIds);
    }

    private class TextServicesMonitor extends PackageMonitor {
        private boolean isChangingPackagesOfCurrentUser() {
            final int userId = getChangingUserId();
@@ -171,6 +194,19 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
        }
    }

    class TextServicesBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (Intent.ACTION_USER_ADDED.equals(action)
                    || Intent.ACTION_USER_REMOVED.equals(action)) {
                updateCurrentProfileIds();
                return;
            }
            Slog.w(TAG, "Unexpected intent " + intent);
        }
    }

    private static void buildSpellCheckerMapLocked(Context context,
            ArrayList<SpellCheckerInfo> list, HashMap<String, SpellCheckerInfo> map,
            TextServicesSettings settings) {
@@ -223,7 +259,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
            Slog.d(TAG, "--- calledFromForegroundUserOrSystemProcess ? "
                    + "calling uid = " + uid + " system uid = " + Process.SYSTEM_UID
                    + " calling userId = " + userId + ", foreground user id = "
                    + mSettings.getCurrentUserId());
                    + mSettings.getCurrentUserId() + ", calling pid = " + Binder.getCallingPid());
            try {
                final String[] packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid);
                for (int i = 0; i < packageNames.length; ++i) {
@@ -237,12 +273,42 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {

        if (uid == Process.SYSTEM_UID || userId == mSettings.getCurrentUserId()) {
            return true;
        } else {
            Slog.w(TAG, "--- IPC called from background users. Ignore. \n" + getStackTrace());
            return false;
        }

        // Permits current profile to use TSFM as long as the current text service is the system's
        // one. This is a tentative solution and should be replaced with fully functional multiuser
        // support.
        // TODO: Implement multiuser support in TSMS.
        final boolean isCurrentProfile = mSettings.isCurrentProfile(userId);
        if (DBG) {
            Slog.d(TAG, "--- userId = "+ userId + " isCurrentProfile = " + isCurrentProfile);
        }
        if (mSettings.isCurrentProfile(userId)) {
            final SpellCheckerInfo spellCheckerInfo = getCurrentSpellCheckerWithoutVerification();
            if (spellCheckerInfo != null) {
                final ServiceInfo serviceInfo = spellCheckerInfo.getServiceInfo();
                final boolean isSystemSpellChecker =
                        (serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
                if (DBG) {
                    Slog.d(TAG, "--- current spell checker = "+ spellCheckerInfo.getPackageName()
                            + " isSystem = " + isSystemSpellChecker);
                }
                if (isSystemSpellChecker) {
                    return true;
                }
            }
        }

        // Unlike InputMethodManagerService#calledFromValidUser, INTERACT_ACROSS_USERS_FULL isn't
        // taken into account here.  Anyway this method is supposed to be removed once multiuser
        // support is implemented.
        if (DBG) {
            Slog.d(TAG, "--- IPC from userId:" + userId + " is being ignored. \n"
                    + getStackTrace());
        }
        return false;
    }

    private boolean bindCurrentSpellCheckerService(
            Intent service, ServiceConnection conn, int flags) {
        if (service == null || conn == null) {
@@ -292,6 +358,10 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
        if (!calledFromValidUser()) {
            return null;
        }
        return getCurrentSpellCheckerWithoutVerification();
    }

    private SpellCheckerInfo getCurrentSpellCheckerWithoutVerification() {
        synchronized (mSpellCheckerMap) {
            final String curSpellCheckerId = mSettings.getSelectedSpellChecker();
            if (DBG) {
@@ -914,6 +984,10 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
    private static class TextServicesSettings {
        private final ContentResolver mResolver;
        private int mCurrentUserId;
        @GuardedBy("mLock")
        private int[] mCurrentProfileIds = new int[0];
        private Object mLock = new Object();

        public TextServicesSettings(ContentResolver resolver, int userId) {
            mResolver = resolver;
            mCurrentUserId = userId;
@@ -928,6 +1002,22 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
            mCurrentUserId = userId;
        }

        public void setCurrentProfileIds(int[] currentProfileIds) {
            synchronized (mLock) {
                mCurrentProfileIds = currentProfileIds;
            }
        }

        public boolean isCurrentProfile(int userId) {
            synchronized (mLock) {
                if (userId == mCurrentUserId) return true;
                for (int i = 0; i < mCurrentProfileIds.length; i++) {
                    if (userId == mCurrentProfileIds[i]) return true;
                }
                return false;
            }
        }

        public int getCurrentUserId() {
            return mCurrentUserId;
        }