Merge "Conditionally allow non-primay profiles to use TextServices" into lmp-mr1-dev
This commit is contained in:
@@ -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,10 +273,40 @@ 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(
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user