am 4e1ab15b: Enable multi-user function for IMF
* commit '4e1ab15b305aac26ad8819fc3b2951e20985944d': Enable multi-user function for IMF
This commit is contained in:
@@ -34,7 +34,9 @@ import org.xmlpull.v1.XmlPullParserException;
|
|||||||
import org.xmlpull.v1.XmlSerializer;
|
import org.xmlpull.v1.XmlSerializer;
|
||||||
|
|
||||||
import android.app.ActivityManagerNative;
|
import android.app.ActivityManagerNative;
|
||||||
|
import android.app.AppGlobals;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
|
import android.app.IUserSwitchObserver;
|
||||||
import android.app.KeyguardManager;
|
import android.app.KeyguardManager;
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
@@ -49,6 +51,7 @@ import android.content.Intent;
|
|||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.IPackageManager;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
@@ -63,12 +66,15 @@ import android.os.Environment;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.IInterface;
|
import android.os.IInterface;
|
||||||
|
import android.os.IRemoteCallback;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
|
import android.os.Process;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ResultReceiver;
|
import android.os.ResultReceiver;
|
||||||
import android.os.ServiceManager;
|
import android.os.ServiceManager;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
import android.os.UserHandle;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.provider.Settings.Secure;
|
import android.provider.Settings.Secure;
|
||||||
import android.provider.Settings.SettingNotFoundException;
|
import android.provider.Settings.SettingNotFoundException;
|
||||||
@@ -378,6 +384,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
private InputMethodInfo[] mIms;
|
private InputMethodInfo[] mIms;
|
||||||
private int[] mSubtypeIds;
|
private int[] mSubtypeIds;
|
||||||
private Locale mLastSystemLocale;
|
private Locale mLastSystemLocale;
|
||||||
|
private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor();
|
||||||
|
private final IPackageManager mIPackageManager;
|
||||||
|
|
||||||
class SettingsObserver extends ContentObserver {
|
class SettingsObserver extends ContentObserver {
|
||||||
SettingsObserver(Handler handler) {
|
SettingsObserver(Handler handler) {
|
||||||
@@ -398,37 +406,55 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ScreenOnOffReceiver extends android.content.BroadcastReceiver {
|
class ImmsBroadcastReceiver extends android.content.BroadcastReceiver {
|
||||||
@Override
|
private void updateActive() {
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
|
|
||||||
mScreenOn = true;
|
|
||||||
refreshImeWindowVisibilityLocked();
|
|
||||||
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
|
|
||||||
mScreenOn = false;
|
|
||||||
setImeWindowVisibilityStatusHiddenLocked();
|
|
||||||
} else if (intent.getAction().equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
|
|
||||||
hideInputMethodMenu();
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
Slog.w(TAG, "Unexpected intent " + intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inform the current client of the change in active status
|
// Inform the current client of the change in active status
|
||||||
if (mCurClient != null && mCurClient.client != null) {
|
if (mCurClient != null && mCurClient.client != null) {
|
||||||
executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
|
executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
|
||||||
MSG_SET_ACTIVE, mScreenOn ? 1 : 0, mCurClient));
|
MSG_SET_ACTIVE, mScreenOn ? 1 : 0, mCurClient));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
final String action = intent.getAction();
|
||||||
|
if (Intent.ACTION_SCREEN_ON.equals(action)) {
|
||||||
|
mScreenOn = true;
|
||||||
|
refreshImeWindowVisibilityLocked();
|
||||||
|
updateActive();
|
||||||
|
return;
|
||||||
|
} else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
|
||||||
|
mScreenOn = false;
|
||||||
|
setImeWindowVisibilityStatusHiddenLocked();
|
||||||
|
updateActive();
|
||||||
|
return;
|
||||||
|
} else if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
|
||||||
|
hideInputMethodMenu();
|
||||||
|
// No need to updateActive
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
Slog.w(TAG, "Unexpected intent " + intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyPackageMonitor extends PackageMonitor {
|
class MyPackageMonitor extends PackageMonitor {
|
||||||
|
private boolean isChangingPackagesOfCurrentUser() {
|
||||||
|
final int userId = getChangingUserId();
|
||||||
|
final boolean retval = userId == mSettings.getCurrentUserId();
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG, "--- ignore this call back from a background user: " + userId);
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
|
public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
|
||||||
|
if (!isChangingPackagesOfCurrentUser()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
synchronized (mMethodMap) {
|
synchronized (mMethodMap) {
|
||||||
String curInputMethodId = Settings.Secure.getString(mContext
|
String curInputMethodId = mSettings.getSelectedInputMethod();
|
||||||
.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
|
|
||||||
final int N = mMethodList.size();
|
final int N = mMethodList.size();
|
||||||
if (curInputMethodId != null) {
|
if (curInputMethodId != null) {
|
||||||
for (int i=0; i<N; i++) {
|
for (int i=0; i<N; i++) {
|
||||||
@@ -453,10 +479,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSomePackagesChanged() {
|
public void onSomePackagesChanged() {
|
||||||
|
if (!isChangingPackagesOfCurrentUser()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
synchronized (mMethodMap) {
|
synchronized (mMethodMap) {
|
||||||
InputMethodInfo curIm = null;
|
InputMethodInfo curIm = null;
|
||||||
String curInputMethodId = Settings.Secure.getString(mContext
|
String curInputMethodId = mSettings.getSelectedInputMethod();
|
||||||
.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
|
|
||||||
final int N = mMethodList.size();
|
final int N = mMethodList.size();
|
||||||
if (curInputMethodId != null) {
|
if (curInputMethodId != null) {
|
||||||
for (int i=0; i<N; i++) {
|
for (int i=0; i<N; i++) {
|
||||||
@@ -489,9 +517,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
|| change == PACKAGE_PERMANENT_CHANGE) {
|
|| change == PACKAGE_PERMANENT_CHANGE) {
|
||||||
ServiceInfo si = null;
|
ServiceInfo si = null;
|
||||||
try {
|
try {
|
||||||
si = mContext.getPackageManager().getServiceInfo(
|
si = mIPackageManager.getServiceInfo(
|
||||||
curIm.getComponent(), 0);
|
curIm.getComponent(), 0, mSettings.getCurrentUserId());
|
||||||
} catch (PackageManager.NameNotFoundException ex) {
|
} catch (RemoteException ex) {
|
||||||
}
|
}
|
||||||
if (si == null) {
|
if (si == null) {
|
||||||
// Uh oh, current input method is no longer around!
|
// Uh oh, current input method is no longer around!
|
||||||
@@ -565,6 +593,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
public InputMethodManagerService(Context context, WindowManagerService windowManager) {
|
public InputMethodManagerService(Context context, WindowManagerService windowManager) {
|
||||||
|
mIPackageManager = AppGlobals.getPackageManager();
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mRes = context.getResources();
|
mRes = context.getResources();
|
||||||
mHandler = new Handler(this);
|
mHandler = new Handler(this);
|
||||||
@@ -601,23 +630,44 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
}
|
}
|
||||||
mImListManager = new InputMethodAndSubtypeListManager(context, this);
|
mImListManager = new InputMethodAndSubtypeListManager(context, this);
|
||||||
|
|
||||||
(new MyPackageMonitor()).register(mContext, null, true);
|
final IntentFilter broadcastFilter = new IntentFilter();
|
||||||
|
broadcastFilter.addAction(Intent.ACTION_SCREEN_ON);
|
||||||
IntentFilter screenOnOffFilt = new IntentFilter();
|
broadcastFilter.addAction(Intent.ACTION_SCREEN_OFF);
|
||||||
screenOnOffFilt.addAction(Intent.ACTION_SCREEN_ON);
|
broadcastFilter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
|
||||||
screenOnOffFilt.addAction(Intent.ACTION_SCREEN_OFF);
|
mContext.registerReceiver(new ImmsBroadcastReceiver(), broadcastFilter);
|
||||||
screenOnOffFilt.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
|
|
||||||
mContext.registerReceiver(new ScreenOnOffReceiver(), screenOnOffFilt);
|
|
||||||
|
|
||||||
mNotificationShown = false;
|
mNotificationShown = false;
|
||||||
|
int userId = 0;
|
||||||
|
try {
|
||||||
|
ActivityManagerNative.getDefault().registerUserSwitchObserver(
|
||||||
|
new IUserSwitchObserver.Stub() {
|
||||||
|
@Override
|
||||||
|
public void onUserSwitching(int newUserId, IRemoteCallback reply) {
|
||||||
|
switchUser(newUserId);
|
||||||
|
if (reply != null) {
|
||||||
|
try {
|
||||||
|
reply.sendResult(null);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUserSwitchComplete(int newUserId) throws RemoteException {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
userId = ActivityManagerNative.getDefault().getCurrentUser().id;
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.w(TAG, "Couldn't get current user ID; guessing it's 0", e);
|
||||||
|
}
|
||||||
|
mMyPackageMonitor.register(mContext, null, true);
|
||||||
|
|
||||||
// mSettings should be created before buildInputMethodListLocked
|
// mSettings should be created before buildInputMethodListLocked
|
||||||
mSettings = new InputMethodSettings(
|
mSettings = new InputMethodSettings(
|
||||||
mRes, context.getContentResolver(), mMethodMap, mMethodList);
|
mRes, context.getContentResolver(), mMethodMap, mMethodList, userId);
|
||||||
|
|
||||||
// Just checking if defaultImiId is empty or not
|
// Just checking if defaultImiId is empty or not
|
||||||
final String defaultImiId = Settings.Secure.getString(
|
final String defaultImiId = mSettings.getSelectedInputMethod();
|
||||||
mContext.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
|
|
||||||
mImeSelectedOnBoot = !TextUtils.isEmpty(defaultImiId);
|
mImeSelectedOnBoot = !TextUtils.isEmpty(defaultImiId);
|
||||||
|
|
||||||
buildInputMethodListLocked(mMethodList, mMethodMap);
|
buildInputMethodListLocked(mMethodList, mMethodMap);
|
||||||
@@ -646,24 +696,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
}, filter);
|
}, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkCurrentLocaleChangedLocked() {
|
|
||||||
if (!mSystemReady) {
|
|
||||||
// not system ready
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final Locale newLocale = mRes.getConfiguration().locale;
|
|
||||||
if (newLocale != null && !newLocale.equals(mLastSystemLocale)) {
|
|
||||||
if (DEBUG) {
|
|
||||||
Slog.i(TAG, "Locale has been changed to " + newLocale);
|
|
||||||
}
|
|
||||||
buildInputMethodListLocked(mMethodList, mMethodMap);
|
|
||||||
// Reset the current ime to the proper one
|
|
||||||
resetDefaultImeLocked(mContext);
|
|
||||||
updateFromSettingsLocked();
|
|
||||||
mLastSystemLocale = newLocale;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resetDefaultImeLocked(Context context) {
|
private void resetDefaultImeLocked(Context context) {
|
||||||
// Do not reset the default (current) IME when it is a 3rd-party IME
|
// Do not reset the default (current) IME when it is a 3rd-party IME
|
||||||
if (mCurMethodId != null && !isSystemIme(mMethodMap.get(mCurMethodId))) {
|
if (mCurMethodId != null && !isSystemIme(mMethodMap.get(mCurMethodId))) {
|
||||||
@@ -688,6 +720,52 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void resetAllInternalStateLocked(boolean updateOnlyWhenLocaleChanged) {
|
||||||
|
if (!mSystemReady) {
|
||||||
|
// not system ready
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final Locale newLocale = mRes.getConfiguration().locale;
|
||||||
|
if (!updateOnlyWhenLocaleChanged
|
||||||
|
|| (newLocale != null && !newLocale.equals(mLastSystemLocale))) {
|
||||||
|
if (!updateOnlyWhenLocaleChanged) {
|
||||||
|
hideCurrentInputLocked(0, null);
|
||||||
|
mCurMethodId = null;
|
||||||
|
unbindCurrentMethodLocked(true);
|
||||||
|
}
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.i(TAG, "Locale has been changed to " + newLocale);
|
||||||
|
}
|
||||||
|
buildInputMethodListLocked(mMethodList, mMethodMap);
|
||||||
|
if (!updateOnlyWhenLocaleChanged) {
|
||||||
|
final String selectedImiId = mSettings.getSelectedInputMethod();
|
||||||
|
if (TextUtils.isEmpty(selectedImiId)) {
|
||||||
|
// This is the first time of the user switch and
|
||||||
|
// set the current ime to the proper one.
|
||||||
|
resetDefaultImeLocked(mContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateFromSettingsLocked();
|
||||||
|
mLastSystemLocale = newLocale;
|
||||||
|
if (!updateOnlyWhenLocaleChanged) {
|
||||||
|
try {
|
||||||
|
startInputInnerLocked();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
Slog.w(TAG, "Unexpected exception", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkCurrentLocaleChangedLocked() {
|
||||||
|
resetAllInternalStateLocked(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void switchUser(int newUserId) {
|
||||||
|
mSettings.setCurrentUserId(newUserId);
|
||||||
|
resetAllInternalStateLocked(false);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isValidSystemDefaultIme(InputMethodInfo imi, Context context) {
|
private boolean isValidSystemDefaultIme(InputMethodInfo imi, Context context) {
|
||||||
if (!mSystemReady) {
|
if (!mSystemReady) {
|
||||||
return false;
|
return false;
|
||||||
@@ -748,10 +826,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
|
|
||||||
public void systemReady(StatusBarManagerService statusBar) {
|
public void systemReady(StatusBarManagerService statusBar) {
|
||||||
synchronized (mMethodMap) {
|
synchronized (mMethodMap) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG, "--- systemReady");
|
||||||
|
}
|
||||||
if (!mSystemReady) {
|
if (!mSystemReady) {
|
||||||
mSystemReady = true;
|
mSystemReady = true;
|
||||||
mKeyguardManager = (KeyguardManager)
|
mKeyguardManager =
|
||||||
mContext.getSystemService(Context.KEYGUARD_SERVICE);
|
(KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
|
||||||
mNotificationManager = (NotificationManager)
|
mNotificationManager = (NotificationManager)
|
||||||
mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
mStatusBar = statusBar;
|
mStatusBar = statusBar;
|
||||||
@@ -802,8 +883,42 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
setImeWindowStatus(mCurToken, mImeWindowVis, mBackDisposition);
|
setImeWindowStatus(mCurToken, mImeWindowVis, mBackDisposition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------
|
||||||
|
// Check whether or not this is a valid IPC. Assumes an IPC is valid when either
|
||||||
|
// 1) it comes from the system process
|
||||||
|
// 2) the calling process' user id is identical to the current user id IMMS thinks.
|
||||||
|
private boolean calledFromValidUser() {
|
||||||
|
final int uid = Binder.getCallingUid();
|
||||||
|
final int userId = UserHandle.getUserId(uid);
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG, "--- calledFromForegroundUserOrSystemProcess ? "
|
||||||
|
+ "calling uid = " + uid + " system uid = " + Process.SYSTEM_UID
|
||||||
|
+ " calling userId = " + userId + ", foreground user id = "
|
||||||
|
+ mSettings.getCurrentUserId());
|
||||||
|
}
|
||||||
|
if (uid == Process.SYSTEM_UID || userId == mSettings.getCurrentUserId()) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
Slog.w(TAG, "--- IPC called from background users. Ignore. \n" + getStackTrace());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean bindCurrentInputMethodService(
|
||||||
|
Intent service, ServiceConnection conn, int flags) {
|
||||||
|
if (service == null || conn == null) {
|
||||||
|
Slog.e(TAG, "--- bind failed: service = " + service + ", conn = " + conn);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return mContext.bindService(service, conn, flags, mSettings.getCurrentUserId());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<InputMethodInfo> getInputMethodList() {
|
public List<InputMethodInfo> getInputMethodList() {
|
||||||
|
// TODO: Make this work even for non-current users?
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
synchronized (mMethodMap) {
|
synchronized (mMethodMap) {
|
||||||
return new ArrayList<InputMethodInfo>(mMethodList);
|
return new ArrayList<InputMethodInfo>(mMethodList);
|
||||||
}
|
}
|
||||||
@@ -811,6 +926,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<InputMethodInfo> getEnabledInputMethodList() {
|
public List<InputMethodInfo> getEnabledInputMethodList() {
|
||||||
|
// TODO: Make this work even for non-current users?
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
synchronized (mMethodMap) {
|
synchronized (mMethodMap) {
|
||||||
return mSettings.getEnabledInputMethodListLocked();
|
return mSettings.getEnabledInputMethodListLocked();
|
||||||
}
|
}
|
||||||
@@ -820,7 +939,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
getExplicitlyOrImplicitlyEnabledInputMethodsAndSubtypeListLocked() {
|
getExplicitlyOrImplicitlyEnabledInputMethodsAndSubtypeListLocked() {
|
||||||
HashMap<InputMethodInfo, List<InputMethodSubtype>> enabledInputMethodAndSubtypes =
|
HashMap<InputMethodInfo, List<InputMethodSubtype>> enabledInputMethodAndSubtypes =
|
||||||
new HashMap<InputMethodInfo, List<InputMethodSubtype>>();
|
new HashMap<InputMethodInfo, List<InputMethodSubtype>>();
|
||||||
for (InputMethodInfo imi: getEnabledInputMethodList()) {
|
for (InputMethodInfo imi: mSettings.getEnabledInputMethodListLocked()) {
|
||||||
enabledInputMethodAndSubtypes.put(
|
enabledInputMethodAndSubtypes.put(
|
||||||
imi, getEnabledInputMethodSubtypeListLocked(imi, true));
|
imi, getEnabledInputMethodSubtypeListLocked(imi, true));
|
||||||
}
|
}
|
||||||
@@ -843,6 +962,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
@Override
|
@Override
|
||||||
public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(InputMethodInfo imi,
|
public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(InputMethodInfo imi,
|
||||||
boolean allowsImplicitlySelectedSubtypes) {
|
boolean allowsImplicitlySelectedSubtypes) {
|
||||||
|
// TODO: Make this work even for non-current users?
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
synchronized (mMethodMap) {
|
synchronized (mMethodMap) {
|
||||||
return getEnabledInputMethodSubtypeListLocked(imi, allowsImplicitlySelectedSubtypes);
|
return getEnabledInputMethodSubtypeListLocked(imi, allowsImplicitlySelectedSubtypes);
|
||||||
}
|
}
|
||||||
@@ -851,6 +974,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
@Override
|
@Override
|
||||||
public void addClient(IInputMethodClient client,
|
public void addClient(IInputMethodClient client,
|
||||||
IInputContext inputContext, int uid, int pid) {
|
IInputContext inputContext, int uid, int pid) {
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
synchronized (mMethodMap) {
|
synchronized (mMethodMap) {
|
||||||
mClients.put(client.asBinder(), new ClientState(client,
|
mClients.put(client.asBinder(), new ClientState(client,
|
||||||
inputContext, uid, pid));
|
inputContext, uid, pid));
|
||||||
@@ -859,6 +985,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeClient(IInputMethodClient client) {
|
public void removeClient(IInputMethodClient client) {
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
synchronized (mMethodMap) {
|
synchronized (mMethodMap) {
|
||||||
mClients.remove(client.asBinder());
|
mClients.remove(client.asBinder());
|
||||||
}
|
}
|
||||||
@@ -1060,7 +1189,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
com.android.internal.R.string.input_method_binding_label);
|
com.android.internal.R.string.input_method_binding_label);
|
||||||
mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
|
mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
|
||||||
mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0));
|
mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0));
|
||||||
if (mContext.bindService(mCurIntent, this, Context.BIND_AUTO_CREATE
|
if (bindCurrentInputMethodService(mCurIntent, this, Context.BIND_AUTO_CREATE
|
||||||
| Context.BIND_NOT_VISIBLE)) {
|
| Context.BIND_NOT_VISIBLE)) {
|
||||||
mLastBindTime = SystemClock.uptimeMillis();
|
mLastBindTime = SystemClock.uptimeMillis();
|
||||||
mHaveConnection = true;
|
mHaveConnection = true;
|
||||||
@@ -1084,6 +1213,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
@Override
|
@Override
|
||||||
public InputBindResult startInput(IInputMethodClient client,
|
public InputBindResult startInput(IInputMethodClient client,
|
||||||
IInputContext inputContext, EditorInfo attribute, int controlFlags) {
|
IInputContext inputContext, EditorInfo attribute, int controlFlags) {
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
synchronized (mMethodMap) {
|
synchronized (mMethodMap) {
|
||||||
final long ident = Binder.clearCallingIdentity();
|
final long ident = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
@@ -1242,10 +1374,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
if (DEBUG) Slog.d(TAG, "show a small icon for the input method");
|
if (DEBUG) Slog.d(TAG, "show a small icon for the input method");
|
||||||
CharSequence contentDescription = null;
|
CharSequence contentDescription = null;
|
||||||
try {
|
try {
|
||||||
PackageManager packageManager = mContext.getPackageManager();
|
// Use PackageManager to load label
|
||||||
|
final PackageManager packageManager = mContext.getPackageManager();
|
||||||
contentDescription = packageManager.getApplicationLabel(
|
contentDescription = packageManager.getApplicationLabel(
|
||||||
packageManager.getApplicationInfo(packageName, 0));
|
mIPackageManager.getApplicationInfo(packageName, 0,
|
||||||
} catch (NameNotFoundException nnfe) {
|
mSettings.getCurrentUserId()));
|
||||||
|
} catch (RemoteException e) {
|
||||||
/* ignore */
|
/* ignore */
|
||||||
}
|
}
|
||||||
if (mStatusBar != null) {
|
if (mStatusBar != null) {
|
||||||
@@ -1309,13 +1443,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Caution! This method is called in this class. Handle multi-user carefully
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
|
public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
|
||||||
int uid = Binder.getCallingUid();
|
final long ident = Binder.clearCallingIdentity();
|
||||||
long ident = Binder.clearCallingIdentity();
|
|
||||||
try {
|
try {
|
||||||
if (token == null || mCurToken != token) {
|
if (token == null || mCurToken != token) {
|
||||||
|
int uid = Binder.getCallingUid();
|
||||||
Slog.w(TAG, "Ignoring setImeWindowStatus of uid " + uid + " token: " + token);
|
Slog.w(TAG, "Ignoring setImeWindowStatus of uid " + uid + " token: " + token);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1329,10 +1464,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
final boolean iconVisibility = (vis & InputMethodService.IME_ACTIVE) != 0;
|
final boolean iconVisibility = (vis & InputMethodService.IME_ACTIVE) != 0;
|
||||||
final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
|
final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
|
||||||
if (imi != null && iconVisibility && needsToShowImeSwitchOngoingNotification()) {
|
if (imi != null && iconVisibility && needsToShowImeSwitchOngoingNotification()) {
|
||||||
|
// Used to load label
|
||||||
final PackageManager pm = mContext.getPackageManager();
|
final PackageManager pm = mContext.getPackageManager();
|
||||||
final CharSequence title = mRes.getText(
|
final CharSequence title = mRes.getText(
|
||||||
com.android.internal.R.string.select_input_method);
|
com.android.internal.R.string.select_input_method);
|
||||||
final CharSequence imiLabel = imi.loadLabel(pm);
|
final CharSequence imiLabel = imi.loadLabel(pm);
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG, "--- imiLabel = " + imiLabel);
|
||||||
|
}
|
||||||
final CharSequence summary = mCurrentSubtype != null
|
final CharSequence summary = mCurrentSubtype != null
|
||||||
? TextUtils.concat(mCurrentSubtype.getDisplayName(mContext,
|
? TextUtils.concat(mCurrentSubtype.getDisplayName(mContext,
|
||||||
imi.getPackageName(), imi.getServiceInfo().applicationInfo),
|
imi.getPackageName(), imi.getServiceInfo().applicationInfo),
|
||||||
@@ -1363,6 +1502,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerSuggestionSpansForNotification(SuggestionSpan[] spans) {
|
public void registerSuggestionSpansForNotification(SuggestionSpan[] spans) {
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
synchronized (mMethodMap) {
|
synchronized (mMethodMap) {
|
||||||
final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId);
|
final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId);
|
||||||
for (int i = 0; i < spans.length; ++i) {
|
for (int i = 0; i < spans.length; ++i) {
|
||||||
@@ -1377,6 +1519,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean notifySuggestionPicked(SuggestionSpan span, String originalString, int index) {
|
public boolean notifySuggestionPicked(SuggestionSpan span, String originalString, int index) {
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
synchronized (mMethodMap) {
|
synchronized (mMethodMap) {
|
||||||
final InputMethodInfo targetImi = mSecureSuggestionSpans.get(span);
|
final InputMethodInfo targetImi = mSecureSuggestionSpans.get(span);
|
||||||
// TODO: Do not send the intent if the process of the targetImi is already dead.
|
// TODO: Do not send the intent if the process of the targetImi is already dead.
|
||||||
@@ -1404,12 +1549,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
// ENABLED_INPUT_METHODS is taking care of keeping them correctly in
|
// ENABLED_INPUT_METHODS is taking care of keeping them correctly in
|
||||||
// sync, so we will never have a DEFAULT_INPUT_METHOD that is not
|
// sync, so we will never have a DEFAULT_INPUT_METHOD that is not
|
||||||
// enabled.
|
// enabled.
|
||||||
String id = Settings.Secure.getString(mContext.getContentResolver(),
|
String id = mSettings.getSelectedInputMethod();
|
||||||
Settings.Secure.DEFAULT_INPUT_METHOD);
|
|
||||||
// There is no input method selected, try to choose new applicable input method.
|
// There is no input method selected, try to choose new applicable input method.
|
||||||
if (TextUtils.isEmpty(id) && chooseNewDefaultIMELocked()) {
|
if (TextUtils.isEmpty(id) && chooseNewDefaultIMELocked()) {
|
||||||
id = Settings.Secure.getString(mContext.getContentResolver(),
|
id = mSettings.getSelectedInputMethod();
|
||||||
Settings.Secure.DEFAULT_INPUT_METHOD);
|
|
||||||
}
|
}
|
||||||
if (!TextUtils.isEmpty(id)) {
|
if (!TextUtils.isEmpty(id)) {
|
||||||
try {
|
try {
|
||||||
@@ -1446,7 +1589,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
} else {
|
} else {
|
||||||
// If subtype is null, try to find the most applicable one from
|
// If subtype is null, try to find the most applicable one from
|
||||||
// getCurrentInputMethodSubtype.
|
// getCurrentInputMethodSubtype.
|
||||||
newSubtype = getCurrentInputMethodSubtype();
|
newSubtype = getCurrentInputMethodSubtypeLocked();
|
||||||
}
|
}
|
||||||
if (newSubtype == null || oldSubtype == null) {
|
if (newSubtype == null || oldSubtype == null) {
|
||||||
Slog.w(TAG, "Illegal subtype state: old subtype = " + oldSubtype
|
Slog.w(TAG, "Illegal subtype state: old subtype = " + oldSubtype
|
||||||
@@ -1493,6 +1636,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
@Override
|
@Override
|
||||||
public boolean showSoftInput(IInputMethodClient client, int flags,
|
public boolean showSoftInput(IInputMethodClient client, int flags,
|
||||||
ResultReceiver resultReceiver) {
|
ResultReceiver resultReceiver) {
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
int uid = Binder.getCallingUid();
|
int uid = Binder.getCallingUid();
|
||||||
long ident = Binder.clearCallingIdentity();
|
long ident = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
@@ -1541,7 +1687,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
resultReceiver));
|
resultReceiver));
|
||||||
mInputShown = true;
|
mInputShown = true;
|
||||||
if (mHaveConnection && !mVisibleBound) {
|
if (mHaveConnection && !mVisibleBound) {
|
||||||
mContext.bindService(mCurIntent, mVisibleConnection, Context.BIND_AUTO_CREATE);
|
bindCurrentInputMethodService(
|
||||||
|
mCurIntent, mVisibleConnection, Context.BIND_AUTO_CREATE);
|
||||||
mVisibleBound = true;
|
mVisibleBound = true;
|
||||||
}
|
}
|
||||||
res = true;
|
res = true;
|
||||||
@@ -1555,8 +1702,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
SystemClock.uptimeMillis()-mLastBindTime,1);
|
SystemClock.uptimeMillis()-mLastBindTime,1);
|
||||||
Slog.w(TAG, "Force disconnect/connect to the IME in showCurrentInputLocked()");
|
Slog.w(TAG, "Force disconnect/connect to the IME in showCurrentInputLocked()");
|
||||||
mContext.unbindService(this);
|
mContext.unbindService(this);
|
||||||
mContext.bindService(mCurIntent, this, Context.BIND_AUTO_CREATE
|
bindCurrentInputMethodService(mCurIntent, this, Context.BIND_AUTO_CREATE
|
||||||
| Context.BIND_NOT_VISIBLE);
|
| Context.BIND_NOT_VISIBLE);
|
||||||
|
} else {
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG, "Can't show input: connection = " + mHaveConnection + ", time = "
|
||||||
|
+ ((mLastBindTime+TIME_TO_RECONNECT) - SystemClock.uptimeMillis()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
@@ -1565,6 +1717,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
@Override
|
@Override
|
||||||
public boolean hideSoftInput(IInputMethodClient client, int flags,
|
public boolean hideSoftInput(IInputMethodClient client, int flags,
|
||||||
ResultReceiver resultReceiver) {
|
ResultReceiver resultReceiver) {
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
int uid = Binder.getCallingUid();
|
int uid = Binder.getCallingUid();
|
||||||
long ident = Binder.clearCallingIdentity();
|
long ident = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
@@ -1630,6 +1785,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
public InputBindResult windowGainedFocus(IInputMethodClient client, IBinder windowToken,
|
public InputBindResult windowGainedFocus(IInputMethodClient client, IBinder windowToken,
|
||||||
int controlFlags, int softInputMode, int windowFlags,
|
int controlFlags, int softInputMode, int windowFlags,
|
||||||
EditorInfo attribute, IInputContext inputContext) {
|
EditorInfo attribute, IInputContext inputContext) {
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
InputBindResult res = null;
|
InputBindResult res = null;
|
||||||
long ident = Binder.clearCallingIdentity();
|
long ident = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
@@ -1770,6 +1928,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showInputMethodPickerFromClient(IInputMethodClient client) {
|
public void showInputMethodPickerFromClient(IInputMethodClient client) {
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
synchronized (mMethodMap) {
|
synchronized (mMethodMap) {
|
||||||
if (mCurClient == null || client == null
|
if (mCurClient == null || client == null
|
||||||
|| mCurClient.client.asBinder() != client.asBinder()) {
|
|| mCurClient.client.asBinder() != client.asBinder()) {
|
||||||
@@ -1785,11 +1946,17 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setInputMethod(IBinder token, String id) {
|
public void setInputMethod(IBinder token, String id) {
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
setInputMethodWithSubtypeId(token, id, NOT_A_SUBTYPE_ID);
|
setInputMethodWithSubtypeId(token, id, NOT_A_SUBTYPE_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) {
|
public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) {
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
synchronized (mMethodMap) {
|
synchronized (mMethodMap) {
|
||||||
if (subtype != null) {
|
if (subtype != null) {
|
||||||
setInputMethodWithSubtypeId(token, id, getSubtypeIdFromHashCode(
|
setInputMethodWithSubtypeId(token, id, getSubtypeIdFromHashCode(
|
||||||
@@ -1803,6 +1970,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
@Override
|
@Override
|
||||||
public void showInputMethodAndSubtypeEnablerFromClient(
|
public void showInputMethodAndSubtypeEnablerFromClient(
|
||||||
IInputMethodClient client, String inputMethodId) {
|
IInputMethodClient client, String inputMethodId) {
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
synchronized (mMethodMap) {
|
synchronized (mMethodMap) {
|
||||||
if (mCurClient == null || client == null
|
if (mCurClient == null || client == null
|
||||||
|| mCurClient.client.asBinder() != client.asBinder()) {
|
|| mCurClient.client.asBinder() != client.asBinder()) {
|
||||||
@@ -1815,6 +1985,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean switchToLastInputMethod(IBinder token) {
|
public boolean switchToLastInputMethod(IBinder token) {
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
synchronized (mMethodMap) {
|
synchronized (mMethodMap) {
|
||||||
final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
|
final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
|
||||||
final InputMethodInfo lastImi;
|
final InputMethodInfo lastImi;
|
||||||
@@ -1882,6 +2055,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean switchToNextInputMethod(IBinder token, boolean onlyCurrentIme) {
|
public boolean switchToNextInputMethod(IBinder token, boolean onlyCurrentIme) {
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
synchronized (mMethodMap) {
|
synchronized (mMethodMap) {
|
||||||
final ImeSubtypeListItem nextSubtype = mImListManager.getNextInputMethod(
|
final ImeSubtypeListItem nextSubtype = mImListManager.getNextInputMethod(
|
||||||
onlyCurrentIme, mMethodMap.get(mCurMethodId), mCurrentSubtype);
|
onlyCurrentIme, mMethodMap.get(mCurMethodId), mCurrentSubtype);
|
||||||
@@ -1895,6 +2071,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InputMethodSubtype getLastInputMethodSubtype() {
|
public InputMethodSubtype getLastInputMethodSubtype() {
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
synchronized (mMethodMap) {
|
synchronized (mMethodMap) {
|
||||||
final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
|
final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
|
||||||
// TODO: Handle the case of the last IME with no subtypes
|
// TODO: Handle the case of the last IME with no subtypes
|
||||||
@@ -1917,14 +2096,22 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
|
public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// By this IPC call, only a process which shares the same uid with the IME can add
|
// By this IPC call, only a process which shares the same uid with the IME can add
|
||||||
// additional input method subtypes to the IME.
|
// additional input method subtypes to the IME.
|
||||||
if (TextUtils.isEmpty(imiId) || subtypes == null || subtypes.length == 0) return;
|
if (TextUtils.isEmpty(imiId) || subtypes == null || subtypes.length == 0) return;
|
||||||
synchronized (mMethodMap) {
|
synchronized (mMethodMap) {
|
||||||
final InputMethodInfo imi = mMethodMap.get(imiId);
|
final InputMethodInfo imi = mMethodMap.get(imiId);
|
||||||
if (imi == null) return;
|
if (imi == null) return;
|
||||||
final PackageManager pm = mContext.getPackageManager();
|
final String[] packageInfos;
|
||||||
final String[] packageInfos = pm.getPackagesForUid(Binder.getCallingUid());
|
try {
|
||||||
|
packageInfos = mIPackageManager.getPackagesForUid(Binder.getCallingUid());
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.e(TAG, "Failed to get package infos");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (packageInfos != null) {
|
if (packageInfos != null) {
|
||||||
final int packageNum = packageInfos.length;
|
final int packageNum = packageInfos.length;
|
||||||
for (int i = 0; i < packageNum; ++i) {
|
for (int i = 0; i < packageNum; ++i) {
|
||||||
@@ -1971,6 +2158,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hideMySoftInput(IBinder token, int flags) {
|
public void hideMySoftInput(IBinder token, int flags) {
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
synchronized (mMethodMap) {
|
synchronized (mMethodMap) {
|
||||||
if (token == null || mCurToken != token) {
|
if (token == null || mCurToken != token) {
|
||||||
if (DEBUG) Slog.w(TAG, "Ignoring hideInputMethod of uid "
|
if (DEBUG) Slog.w(TAG, "Ignoring hideInputMethod of uid "
|
||||||
@@ -1988,6 +2178,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showMySoftInput(IBinder token, int flags) {
|
public void showMySoftInput(IBinder token, int flags) {
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
synchronized (mMethodMap) {
|
synchronized (mMethodMap) {
|
||||||
if (token == null || mCurToken != token) {
|
if (token == null || mCurToken != token) {
|
||||||
Slog.w(TAG, "Ignoring showMySoftInput of uid "
|
Slog.w(TAG, "Ignoring showMySoftInput of uid "
|
||||||
@@ -2224,19 +2417,22 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
|
|
||||||
void buildInputMethodListLocked(ArrayList<InputMethodInfo> list,
|
void buildInputMethodListLocked(ArrayList<InputMethodInfo> list,
|
||||||
HashMap<String, InputMethodInfo> map) {
|
HashMap<String, InputMethodInfo> map) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG, "--- re-buildInputMethodList " + ", \n ------ \n" + getStackTrace());
|
||||||
|
}
|
||||||
list.clear();
|
list.clear();
|
||||||
map.clear();
|
map.clear();
|
||||||
|
|
||||||
PackageManager pm = mContext.getPackageManager();
|
// Use for queryIntentServicesAsUser
|
||||||
|
final PackageManager pm = mContext.getPackageManager();
|
||||||
final Configuration config = mRes.getConfiguration();
|
final Configuration config = mRes.getConfiguration();
|
||||||
final boolean haveHardKeyboard = config.keyboard == Configuration.KEYBOARD_QWERTY;
|
final boolean haveHardKeyboard = config.keyboard == Configuration.KEYBOARD_QWERTY;
|
||||||
String disabledSysImes = Settings.Secure.getString(mContext.getContentResolver(),
|
String disabledSysImes = mSettings.getDisabledSystemInputMethods();
|
||||||
Secure.DISABLED_SYSTEM_INPUT_METHODS);
|
|
||||||
if (disabledSysImes == null) disabledSysImes = "";
|
if (disabledSysImes == null) disabledSysImes = "";
|
||||||
|
|
||||||
List<ResolveInfo> services = pm.queryIntentServices(
|
final List<ResolveInfo> services = pm.queryIntentServicesAsUser(
|
||||||
new Intent(InputMethod.SERVICE_INTERFACE),
|
new Intent(InputMethod.SERVICE_INTERFACE),
|
||||||
PackageManager.GET_META_DATA);
|
PackageManager.GET_META_DATA, mSettings.getCurrentUserId());
|
||||||
|
|
||||||
final HashMap<String, List<InputMethodSubtype>> additionalSubtypes =
|
final HashMap<String, List<InputMethodSubtype>> additionalSubtypes =
|
||||||
mFileManager.getAllAdditionalInputMethodSubtypes();
|
mFileManager.getAllAdditionalInputMethodSubtypes();
|
||||||
@@ -2279,8 +2475,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final String defaultImiId = Settings.Secure.getString(mContext
|
final String defaultImiId = mSettings.getSelectedInputMethod();
|
||||||
.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
|
|
||||||
if (!TextUtils.isEmpty(defaultImiId)) {
|
if (!TextUtils.isEmpty(defaultImiId)) {
|
||||||
if (!map.containsKey(defaultImiId)) {
|
if (!map.containsKey(defaultImiId)) {
|
||||||
Slog.w(TAG, "Default IME is uninstalled. Choose new default IME.");
|
Slog.w(TAG, "Default IME is uninstalled. Choose new default IME.");
|
||||||
@@ -2331,11 +2526,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
if (DEBUG) Slog.v(TAG, "Show switching menu");
|
if (DEBUG) Slog.v(TAG, "Show switching menu");
|
||||||
|
|
||||||
final Context context = mContext;
|
final Context context = mContext;
|
||||||
final PackageManager pm = context.getPackageManager();
|
|
||||||
final boolean isScreenLocked = isScreenLocked();
|
final boolean isScreenLocked = isScreenLocked();
|
||||||
|
|
||||||
final String lastInputMethodId = Settings.Secure.getString(context
|
final String lastInputMethodId = mSettings.getSelectedInputMethod();
|
||||||
.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
|
|
||||||
int lastInputMethodSubtypeId = getSelectedInputMethodSubtypeId(lastInputMethodId);
|
int lastInputMethodSubtypeId = getSelectedInputMethodSubtypeId(lastInputMethodId);
|
||||||
if (DEBUG) Slog.v(TAG, "Current IME: " + lastInputMethodId);
|
if (DEBUG) Slog.v(TAG, "Current IME: " + lastInputMethodId);
|
||||||
|
|
||||||
@@ -2353,7 +2546,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
showSubtypes, mInputShown, isScreenLocked);
|
showSubtypes, mInputShown, isScreenLocked);
|
||||||
|
|
||||||
if (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID) {
|
if (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID) {
|
||||||
final InputMethodSubtype currentSubtype = getCurrentInputMethodSubtype();
|
final InputMethodSubtype currentSubtype = getCurrentInputMethodSubtypeLocked();
|
||||||
if (currentSubtype != null) {
|
if (currentSubtype != null) {
|
||||||
final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId);
|
final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId);
|
||||||
lastInputMethodSubtypeId =
|
lastInputMethodSubtypeId =
|
||||||
@@ -2582,6 +2775,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setInputMethodEnabled(String id, boolean enabled) {
|
public boolean setInputMethodEnabled(String id, boolean enabled) {
|
||||||
|
// TODO: Make this work even for non-current users?
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
synchronized (mMethodMap) {
|
synchronized (mMethodMap) {
|
||||||
if (mContext.checkCallingOrSelfPermission(
|
if (mContext.checkCallingOrSelfPermission(
|
||||||
android.Manifest.permission.WRITE_SECURE_SETTINGS)
|
android.Manifest.permission.WRITE_SECURE_SETTINGS)
|
||||||
@@ -2626,8 +2823,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
if (mSettings.buildAndPutEnabledInputMethodsStrRemovingIdLocked(
|
if (mSettings.buildAndPutEnabledInputMethodsStrRemovingIdLocked(
|
||||||
builder, enabledInputMethodsList, id)) {
|
builder, enabledInputMethodsList, id)) {
|
||||||
// Disabled input method is currently selected, switch to another one.
|
// Disabled input method is currently selected, switch to another one.
|
||||||
String selId = Settings.Secure.getString(mContext.getContentResolver(),
|
final String selId = mSettings.getSelectedInputMethod();
|
||||||
Settings.Secure.DEFAULT_INPUT_METHOD);
|
|
||||||
if (id.equals(selId) && !chooseNewDefaultIMELocked()) {
|
if (id.equals(selId) && !chooseNewDefaultIMELocked()) {
|
||||||
Slog.i(TAG, "Can't find new IME, unsetting the current input method.");
|
Slog.i(TAG, "Can't find new IME, unsetting the current input method.");
|
||||||
resetSelectedInputMethodAndSubtypeLocked("");
|
resetSelectedInputMethodAndSubtypeLocked("");
|
||||||
@@ -2674,7 +2870,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
} else {
|
} else {
|
||||||
mSettings.putSelectedSubtype(NOT_A_SUBTYPE_ID);
|
mSettings.putSelectedSubtype(NOT_A_SUBTYPE_ID);
|
||||||
// If the subtype is not specified, choose the most applicable one
|
// If the subtype is not specified, choose the most applicable one
|
||||||
mCurrentSubtype = getCurrentInputMethodSubtype();
|
mCurrentSubtype = getCurrentInputMethodSubtypeLocked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2716,14 +2912,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
if (imi == null) {
|
if (imi == null) {
|
||||||
return NOT_A_SUBTYPE_ID;
|
return NOT_A_SUBTYPE_ID;
|
||||||
}
|
}
|
||||||
int subtypeId;
|
final int subtypeHashCode = mSettings.getSelectedInputMethodSubtypeHashCode();
|
||||||
try {
|
return getSubtypeIdFromHashCode(imi, subtypeHashCode);
|
||||||
subtypeId = Settings.Secure.getInt(mContext.getContentResolver(),
|
|
||||||
Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE);
|
|
||||||
} catch (SettingNotFoundException e) {
|
|
||||||
return NOT_A_SUBTYPE_ID;
|
|
||||||
}
|
|
||||||
return getSubtypeIdFromHashCode(imi, subtypeId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isValidSubtypeId(InputMethodInfo imi, int subtypeHashCode) {
|
private static boolean isValidSubtypeId(InputMethodInfo imi, int subtypeHashCode) {
|
||||||
@@ -2886,7 +3076,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
}
|
}
|
||||||
InputMethodSubtype subtype = null;
|
InputMethodSubtype subtype = null;
|
||||||
final List<InputMethodSubtype> enabledSubtypes =
|
final List<InputMethodSubtype> enabledSubtypes =
|
||||||
getEnabledInputMethodSubtypeList(imi, true);
|
getEnabledInputMethodSubtypeListLocked(imi, true);
|
||||||
// 1. Search by the current subtype's locale from enabledSubtypes.
|
// 1. Search by the current subtype's locale from enabledSubtypes.
|
||||||
if (mCurrentSubtype != null) {
|
if (mCurrentSubtype != null) {
|
||||||
subtype = findLastResortApplicableSubtypeLocked(
|
subtype = findLastResortApplicableSubtypeLocked(
|
||||||
@@ -2955,49 +3145,53 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public InputMethodSubtype getCurrentInputMethodSubtype() {
|
public InputMethodSubtype getCurrentInputMethodSubtype() {
|
||||||
|
// TODO: Make this work even for non-current users?
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
synchronized (mMethodMap) {
|
||||||
|
return getCurrentInputMethodSubtypeLocked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private InputMethodSubtype getCurrentInputMethodSubtypeLocked() {
|
||||||
if (mCurMethodId == null) {
|
if (mCurMethodId == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
boolean subtypeIsSelected = false;
|
final boolean subtypeIsSelected =
|
||||||
try {
|
mSettings.getSelectedInputMethodSubtypeHashCode() != NOT_A_SUBTYPE_ID;
|
||||||
subtypeIsSelected = Settings.Secure.getInt(mContext.getContentResolver(),
|
final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
|
||||||
Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE) != NOT_A_SUBTYPE_ID;
|
if (imi == null || imi.getSubtypeCount() == 0) {
|
||||||
} catch (SettingNotFoundException e) {
|
return null;
|
||||||
}
|
}
|
||||||
synchronized (mMethodMap) {
|
if (!subtypeIsSelected || mCurrentSubtype == null
|
||||||
final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
|
|| !isValidSubtypeId(imi, mCurrentSubtype.hashCode())) {
|
||||||
if (imi == null || imi.getSubtypeCount() == 0) {
|
int subtypeId = getSelectedInputMethodSubtypeId(mCurMethodId);
|
||||||
return null;
|
if (subtypeId == NOT_A_SUBTYPE_ID) {
|
||||||
}
|
// If there are no selected subtypes, the framework will try to find
|
||||||
if (!subtypeIsSelected || mCurrentSubtype == null
|
// the most applicable subtype from explicitly or implicitly enabled
|
||||||
|| !isValidSubtypeId(imi, mCurrentSubtype.hashCode())) {
|
// subtypes.
|
||||||
int subtypeId = getSelectedInputMethodSubtypeId(mCurMethodId);
|
List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypes =
|
||||||
if (subtypeId == NOT_A_SUBTYPE_ID) {
|
getEnabledInputMethodSubtypeListLocked(imi, true);
|
||||||
// If there are no selected subtypes, the framework will try to find
|
// If there is only one explicitly or implicitly enabled subtype,
|
||||||
// the most applicable subtype from explicitly or implicitly enabled
|
// just returns it.
|
||||||
// subtypes.
|
if (explicitlyOrImplicitlyEnabledSubtypes.size() == 1) {
|
||||||
List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypes =
|
mCurrentSubtype = explicitlyOrImplicitlyEnabledSubtypes.get(0);
|
||||||
getEnabledInputMethodSubtypeList(imi, true);
|
} else if (explicitlyOrImplicitlyEnabledSubtypes.size() > 1) {
|
||||||
// If there is only one explicitly or implicitly enabled subtype,
|
mCurrentSubtype = findLastResortApplicableSubtypeLocked(
|
||||||
// just returns it.
|
mRes, explicitlyOrImplicitlyEnabledSubtypes,
|
||||||
if (explicitlyOrImplicitlyEnabledSubtypes.size() == 1) {
|
SUBTYPE_MODE_KEYBOARD, null, true);
|
||||||
mCurrentSubtype = explicitlyOrImplicitlyEnabledSubtypes.get(0);
|
if (mCurrentSubtype == null) {
|
||||||
} else if (explicitlyOrImplicitlyEnabledSubtypes.size() > 1) {
|
|
||||||
mCurrentSubtype = findLastResortApplicableSubtypeLocked(
|
mCurrentSubtype = findLastResortApplicableSubtypeLocked(
|
||||||
mRes, explicitlyOrImplicitlyEnabledSubtypes,
|
mRes, explicitlyOrImplicitlyEnabledSubtypes, null, null,
|
||||||
SUBTYPE_MODE_KEYBOARD, null, true);
|
true);
|
||||||
if (mCurrentSubtype == null) {
|
|
||||||
mCurrentSubtype = findLastResortApplicableSubtypeLocked(
|
|
||||||
mRes, explicitlyOrImplicitlyEnabledSubtypes, null, null,
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
mCurrentSubtype = getSubtypes(imi).get(subtypeId);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
mCurrentSubtype = getSubtypes(imi).get(subtypeId);
|
||||||
}
|
}
|
||||||
return mCurrentSubtype;
|
|
||||||
}
|
}
|
||||||
|
return mCurrentSubtype;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addShortcutInputMethodAndSubtypes(InputMethodInfo imi,
|
private void addShortcutInputMethodAndSubtypes(InputMethodInfo imi,
|
||||||
@@ -3042,6 +3236,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
|
public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
|
||||||
|
// TODO: Make this work even for non-current users?
|
||||||
|
if (!calledFromValidUser()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
synchronized (mMethodMap) {
|
synchronized (mMethodMap) {
|
||||||
if (subtype != null && mCurMethodId != null) {
|
if (subtype != null && mCurMethodId != null) {
|
||||||
InputMethodInfo imi = mMethodMap.get(mCurMethodId);
|
InputMethodInfo imi = mMethodMap.get(mCurMethodId);
|
||||||
@@ -3057,6 +3255,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
|
|
||||||
private static class InputMethodAndSubtypeListManager {
|
private static class InputMethodAndSubtypeListManager {
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
// Used to load label
|
||||||
private final PackageManager mPm;
|
private final PackageManager mPm;
|
||||||
private final InputMethodManagerService mImms;
|
private final InputMethodManagerService mImms;
|
||||||
private final String mSystemLocaleStr;
|
private final String mSystemLocaleStr;
|
||||||
@@ -3193,6 +3392,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
private final ArrayList<InputMethodInfo> mMethodList;
|
private final ArrayList<InputMethodInfo> mMethodList;
|
||||||
|
|
||||||
private String mEnabledInputMethodsStrCache;
|
private String mEnabledInputMethodsStrCache;
|
||||||
|
private int mCurrentUserId;
|
||||||
|
|
||||||
private static void buildEnabledInputMethodsSettingString(
|
private static void buildEnabledInputMethodsSettingString(
|
||||||
StringBuilder builder, Pair<String, ArrayList<String>> pair) {
|
StringBuilder builder, Pair<String, ArrayList<String>> pair) {
|
||||||
@@ -3208,13 +3408,24 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
|
|
||||||
public InputMethodSettings(
|
public InputMethodSettings(
|
||||||
Resources res, ContentResolver resolver,
|
Resources res, ContentResolver resolver,
|
||||||
HashMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList) {
|
HashMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList,
|
||||||
|
int userId) {
|
||||||
|
setCurrentUserId(userId);
|
||||||
mRes = res;
|
mRes = res;
|
||||||
mResolver = resolver;
|
mResolver = resolver;
|
||||||
mMethodMap = methodMap;
|
mMethodMap = methodMap;
|
||||||
mMethodList = methodList;
|
mMethodList = methodList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCurrentUserId(int userId) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG, "--- Swtich the current user from " + mCurrentUserId + " to "
|
||||||
|
+ userId + ", new ime = " + getSelectedInputMethod());
|
||||||
|
}
|
||||||
|
// IMMS settings are kept per user, so keep track of current user
|
||||||
|
mCurrentUserId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
public List<InputMethodInfo> getEnabledInputMethodListLocked() {
|
public List<InputMethodInfo> getEnabledInputMethodListLocked() {
|
||||||
return createEnabledInputMethodListLocked(
|
return createEnabledInputMethodListLocked(
|
||||||
getEnabledInputMethodsAndSubtypeListLocked());
|
getEnabledInputMethodsAndSubtypeListLocked());
|
||||||
@@ -3363,15 +3574,20 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void putEnabledInputMethodsStr(String str) {
|
private void putEnabledInputMethodsStr(String str) {
|
||||||
Settings.Secure.putString(mResolver, Settings.Secure.ENABLED_INPUT_METHODS, str);
|
Settings.Secure.putStringForUser(
|
||||||
|
mResolver, Settings.Secure.ENABLED_INPUT_METHODS, str, mCurrentUserId);
|
||||||
mEnabledInputMethodsStrCache = str;
|
mEnabledInputMethodsStrCache = str;
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG, "putEnabledInputMethodStr: " + str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getEnabledInputMethodsStr() {
|
private String getEnabledInputMethodsStr() {
|
||||||
mEnabledInputMethodsStrCache = Settings.Secure.getString(
|
mEnabledInputMethodsStrCache = Settings.Secure.getStringForUser(
|
||||||
mResolver, Settings.Secure.ENABLED_INPUT_METHODS);
|
mResolver, Settings.Secure.ENABLED_INPUT_METHODS, mCurrentUserId);
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.d(TAG, "getEnabledInputMethodsStr: " + mEnabledInputMethodsStrCache);
|
Slog.d(TAG, "getEnabledInputMethodsStr: " + mEnabledInputMethodsStrCache
|
||||||
|
+ ", " + mCurrentUserId);
|
||||||
}
|
}
|
||||||
return mEnabledInputMethodsStrCache;
|
return mEnabledInputMethodsStrCache;
|
||||||
}
|
}
|
||||||
@@ -3426,8 +3642,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.d(TAG, "putSubtypeHistoryStr: " + str);
|
Slog.d(TAG, "putSubtypeHistoryStr: " + str);
|
||||||
}
|
}
|
||||||
Settings.Secure.putString(
|
Settings.Secure.putStringForUser(
|
||||||
mResolver, Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, str);
|
mResolver, Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, str, mCurrentUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pair<String, String> getLastInputMethodAndSubtypeLocked() {
|
public Pair<String, String> getLastInputMethodAndSubtypeLocked() {
|
||||||
@@ -3546,20 +3762,57 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
|
|
||||||
private String getSubtypeHistoryStr() {
|
private String getSubtypeHistoryStr() {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.d(TAG, "getSubtypeHistoryStr: " + Settings.Secure.getString(
|
Slog.d(TAG, "getSubtypeHistoryStr: " + Settings.Secure.getStringForUser(
|
||||||
mResolver, Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY));
|
mResolver, Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, mCurrentUserId));
|
||||||
}
|
}
|
||||||
return Settings.Secure.getString(
|
return Settings.Secure.getStringForUser(
|
||||||
mResolver, Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY);
|
mResolver, Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, mCurrentUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putSelectedInputMethod(String imeId) {
|
public void putSelectedInputMethod(String imeId) {
|
||||||
Settings.Secure.putString(mResolver, Settings.Secure.DEFAULT_INPUT_METHOD, imeId);
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG, "putSelectedInputMethodStr: " + imeId + ", "
|
||||||
|
+ mCurrentUserId);
|
||||||
|
}
|
||||||
|
Settings.Secure.putStringForUser(
|
||||||
|
mResolver, Settings.Secure.DEFAULT_INPUT_METHOD, imeId, mCurrentUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putSelectedSubtype(int subtypeId) {
|
public void putSelectedSubtype(int subtypeId) {
|
||||||
Settings.Secure.putInt(
|
if (DEBUG) {
|
||||||
mResolver, Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, subtypeId);
|
Slog.d(TAG, "putSelectedInputMethodSubtypeStr: " + subtypeId + ", "
|
||||||
|
+ mCurrentUserId);
|
||||||
|
}
|
||||||
|
Settings.Secure.putIntForUser(mResolver, Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE,
|
||||||
|
subtypeId, mCurrentUserId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDisabledSystemInputMethods() {
|
||||||
|
return Settings.Secure.getStringForUser(
|
||||||
|
mResolver, Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS, mCurrentUserId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSelectedInputMethod() {
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG, "getSelectedInputMethodStr: " + Settings.Secure.getStringForUser(
|
||||||
|
mResolver, Settings.Secure.DEFAULT_INPUT_METHOD, mCurrentUserId)
|
||||||
|
+ ", " + mCurrentUserId);
|
||||||
|
}
|
||||||
|
return Settings.Secure.getStringForUser(
|
||||||
|
mResolver, Settings.Secure.DEFAULT_INPUT_METHOD, mCurrentUserId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSelectedInputMethodSubtypeHashCode() {
|
||||||
|
try {
|
||||||
|
return Settings.Secure.getIntForUser(
|
||||||
|
mResolver, Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, mCurrentUserId);
|
||||||
|
} catch (SettingNotFoundException e) {
|
||||||
|
return NOT_A_SUBTYPE_ID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCurrentUserId() {
|
||||||
|
return mCurrentUserId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3762,6 +4015,20 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
// Utilities for debug
|
||||||
|
private static String getStackTrace() {
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
try {
|
||||||
|
throw new RuntimeException();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
final StackTraceElement[] frames = e.getStackTrace();
|
||||||
|
// Start at 1 because the first frame is here and we don't care about it
|
||||||
|
for (int j = 1; j < frames.length; ++j) {
|
||||||
|
sb.append(frames[j].toString() + "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||||
|
|||||||
Reference in New Issue
Block a user