am 22cbf54c: Merge "Conditionally allow non-primay profiles to use TextServices" into lmp-mr1-dev
automerge: b1f5643
* commit 'b1f56430d38f9d6bab0a3512905daaf994ba134b':
Conditionally allow non-primay profiles to use TextServices
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.server;
|
package com.android.server;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.GuardedBy;
|
||||||
import com.android.internal.content.PackageMonitor;
|
import com.android.internal.content.PackageMonitor;
|
||||||
import com.android.internal.textservice.ISpellCheckerService;
|
import com.android.internal.textservice.ISpellCheckerService;
|
||||||
import com.android.internal.textservice.ISpellCheckerSession;
|
import com.android.internal.textservice.ISpellCheckerSession;
|
||||||
@@ -28,14 +29,18 @@ import org.xmlpull.v1.XmlPullParserException;
|
|||||||
import android.app.ActivityManagerNative;
|
import android.app.ActivityManagerNative;
|
||||||
import android.app.AppGlobals;
|
import android.app.AppGlobals;
|
||||||
import android.app.IUserSwitchObserver;
|
import android.app.IUserSwitchObserver;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
import android.content.pm.ServiceInfo;
|
import android.content.pm.ServiceInfo;
|
||||||
|
import android.content.pm.UserInfo;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
@@ -43,6 +48,7 @@ import android.os.IRemoteCallback;
|
|||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
|
import android.os.UserManager;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.service.textservice.SpellCheckerService;
|
import android.service.textservice.SpellCheckerService;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
@@ -84,6 +90,12 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
|
|||||||
public TextServicesManagerService(Context context) {
|
public TextServicesManagerService(Context context) {
|
||||||
mSystemReady = false;
|
mSystemReady = false;
|
||||||
mContext = context;
|
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;
|
int userId = UserHandle.USER_OWNER;
|
||||||
try {
|
try {
|
||||||
ActivityManagerNative.getDefault().registerUserSwitchObserver(
|
ActivityManagerNative.getDefault().registerUserSwitchObserver(
|
||||||
@@ -119,6 +131,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
|
|||||||
|
|
||||||
private void switchUserLocked(int userId) {
|
private void switchUserLocked(int userId) {
|
||||||
mSettings.setCurrentUserId(userId);
|
mSettings.setCurrentUserId(userId);
|
||||||
|
updateCurrentProfileIds();
|
||||||
unbindServiceLocked();
|
unbindServiceLocked();
|
||||||
buildSpellCheckerMapLocked(mContext, mSpellCheckerList, mSpellCheckerMap, mSettings);
|
buildSpellCheckerMapLocked(mContext, mSpellCheckerList, mSpellCheckerMap, mSettings);
|
||||||
SpellCheckerInfo sci = getCurrentSpellChecker(null);
|
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 class TextServicesMonitor extends PackageMonitor {
|
||||||
private boolean isChangingPackagesOfCurrentUser() {
|
private boolean isChangingPackagesOfCurrentUser() {
|
||||||
final int userId = getChangingUserId();
|
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,
|
private static void buildSpellCheckerMapLocked(Context context,
|
||||||
ArrayList<SpellCheckerInfo> list, HashMap<String, SpellCheckerInfo> map,
|
ArrayList<SpellCheckerInfo> list, HashMap<String, SpellCheckerInfo> map,
|
||||||
TextServicesSettings settings) {
|
TextServicesSettings settings) {
|
||||||
@@ -223,7 +259,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
|
|||||||
Slog.d(TAG, "--- calledFromForegroundUserOrSystemProcess ? "
|
Slog.d(TAG, "--- calledFromForegroundUserOrSystemProcess ? "
|
||||||
+ "calling uid = " + uid + " system uid = " + Process.SYSTEM_UID
|
+ "calling uid = " + uid + " system uid = " + Process.SYSTEM_UID
|
||||||
+ " calling userId = " + userId + ", foreground user id = "
|
+ " calling userId = " + userId + ", foreground user id = "
|
||||||
+ mSettings.getCurrentUserId());
|
+ mSettings.getCurrentUserId() + ", calling pid = " + Binder.getCallingPid());
|
||||||
try {
|
try {
|
||||||
final String[] packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid);
|
final String[] packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid);
|
||||||
for (int i = 0; i < packageNames.length; ++i) {
|
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()) {
|
if (uid == Process.SYSTEM_UID || userId == mSettings.getCurrentUserId()) {
|
||||||
return true;
|
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(
|
private boolean bindCurrentSpellCheckerService(
|
||||||
@@ -292,6 +358,10 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
|
|||||||
if (!calledFromValidUser()) {
|
if (!calledFromValidUser()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
return getCurrentSpellCheckerWithoutVerification();
|
||||||
|
}
|
||||||
|
|
||||||
|
private SpellCheckerInfo getCurrentSpellCheckerWithoutVerification() {
|
||||||
synchronized (mSpellCheckerMap) {
|
synchronized (mSpellCheckerMap) {
|
||||||
final String curSpellCheckerId = mSettings.getSelectedSpellChecker();
|
final String curSpellCheckerId = mSettings.getSelectedSpellChecker();
|
||||||
if (DBG) {
|
if (DBG) {
|
||||||
@@ -914,6 +984,10 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
|
|||||||
private static class TextServicesSettings {
|
private static class TextServicesSettings {
|
||||||
private final ContentResolver mResolver;
|
private final ContentResolver mResolver;
|
||||||
private int mCurrentUserId;
|
private int mCurrentUserId;
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private int[] mCurrentProfileIds = new int[0];
|
||||||
|
private Object mLock = new Object();
|
||||||
|
|
||||||
public TextServicesSettings(ContentResolver resolver, int userId) {
|
public TextServicesSettings(ContentResolver resolver, int userId) {
|
||||||
mResolver = resolver;
|
mResolver = resolver;
|
||||||
mCurrentUserId = userId;
|
mCurrentUserId = userId;
|
||||||
@@ -928,6 +1002,22 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
|
|||||||
mCurrentUserId = userId;
|
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() {
|
public int getCurrentUserId() {
|
||||||
return mCurrentUserId;
|
return mCurrentUserId;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user