Merge "Add Copy-On-Write mode to InputMethodSettings." into nyc-dev
This commit is contained in:
@@ -18,6 +18,7 @@ package com.android.internal.inputmethod;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.AppOpsManager;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
@@ -32,6 +33,7 @@ import android.text.TextUtils.SimpleStringSplitter;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Pair;
|
||||
import android.util.Printer;
|
||||
import android.util.Slog;
|
||||
import android.view.inputmethod.InputMethodInfo;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
@@ -826,7 +828,14 @@ public class InputMethodUtils {
|
||||
private final HashMap<String, InputMethodInfo> mMethodMap;
|
||||
private final ArrayList<InputMethodInfo> mMethodList;
|
||||
|
||||
/**
|
||||
* On-memory data store to emulate when {@link #mCopyOnWrite} is {@code true}.
|
||||
*/
|
||||
private final HashMap<String, String> mCopyOnWriteDataStore = new HashMap<>();
|
||||
|
||||
private boolean mCopyOnWrite = false;
|
||||
private String mEnabledInputMethodsStrCache;
|
||||
@UserIdInt
|
||||
private int mCurrentUserId;
|
||||
private int[] mCurrentProfileIds = new int[0];
|
||||
|
||||
@@ -879,48 +888,85 @@ public class InputMethodUtils {
|
||||
return imsList;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public InputMethodSettings(
|
||||
Resources res, ContentResolver resolver,
|
||||
HashMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList,
|
||||
int userId) {
|
||||
setCurrentUserId(userId);
|
||||
@UserIdInt int userId) {
|
||||
this(res, resolver, methodMap, methodList, userId, false /* copyOnWrite */);
|
||||
}
|
||||
|
||||
public InputMethodSettings(
|
||||
Resources res, ContentResolver resolver,
|
||||
HashMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList,
|
||||
@UserIdInt int userId, boolean copyOnWrite) {
|
||||
mRes = res;
|
||||
mResolver = resolver;
|
||||
mMethodMap = methodMap;
|
||||
mMethodList = methodList;
|
||||
switchCurrentUser(userId, copyOnWrite);
|
||||
}
|
||||
|
||||
public void setCurrentUserId(int userId) {
|
||||
/**
|
||||
* Must be called when the current user is changed.
|
||||
*
|
||||
* @param userId The user ID.
|
||||
* @param copyOnWrite If {@code true}, for each settings key
|
||||
* (e.g. {@link Settings.Secure#ACTION_INPUT_METHOD_SUBTYPE_SETTINGS}) we use the actual
|
||||
* settings on the {@link Settings.Secure} until we do the first write operation.
|
||||
*/
|
||||
public void switchCurrentUser(@UserIdInt int userId, boolean copyOnWrite) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "--- Swtich the current user from " + mCurrentUserId + " to " + userId);
|
||||
Slog.d(TAG, "--- Switch the current user from " + mCurrentUserId + " to " + userId);
|
||||
}
|
||||
if (mCurrentUserId != userId || mCopyOnWrite != copyOnWrite) {
|
||||
mCopyOnWriteDataStore.clear();
|
||||
mEnabledInputMethodsStrCache = "";
|
||||
// TODO: mCurrentProfileIds should be cleared here.
|
||||
}
|
||||
// IMMS settings are kept per user, so keep track of current user
|
||||
mCurrentUserId = userId;
|
||||
mCopyOnWrite = copyOnWrite;
|
||||
// TODO: mCurrentProfileIds should be updated here.
|
||||
}
|
||||
|
||||
private void putString(final String key, final String str) {
|
||||
Settings.Secure.putStringForUser(mResolver, key, str, mCurrentUserId);
|
||||
if (mCopyOnWrite) {
|
||||
mCopyOnWriteDataStore.put(key, str);
|
||||
} else {
|
||||
Settings.Secure.putStringForUser(mResolver, key, str, mCurrentUserId);
|
||||
}
|
||||
}
|
||||
|
||||
private String getString(final String key) {
|
||||
if (mCopyOnWrite && mCopyOnWriteDataStore.containsKey(key)) {
|
||||
final String result = mCopyOnWriteDataStore.get(key);
|
||||
return result != null ? result : "";
|
||||
}
|
||||
return Settings.Secure.getStringForUser(mResolver, key, mCurrentUserId);
|
||||
}
|
||||
|
||||
private void putInt(final String key, final int value) {
|
||||
Settings.Secure.putIntForUser(mResolver, key, value, mCurrentUserId);
|
||||
if (mCopyOnWrite) {
|
||||
mCopyOnWriteDataStore.put(key, String.valueOf(value));
|
||||
} else {
|
||||
Settings.Secure.putIntForUser(mResolver, key, value, mCurrentUserId);
|
||||
}
|
||||
}
|
||||
|
||||
private int getInt(final String key, final int defaultValue) {
|
||||
if (mCopyOnWrite && mCopyOnWriteDataStore.containsKey(key)) {
|
||||
final String result = mCopyOnWriteDataStore.get(key);
|
||||
return result != null ? Integer.valueOf(result) : 0;
|
||||
}
|
||||
return Settings.Secure.getIntForUser(mResolver, key, defaultValue, mCurrentUserId);
|
||||
}
|
||||
|
||||
private void putBoolean(final String key, final boolean value) {
|
||||
Settings.Secure.putIntForUser(mResolver, key, value ? 1 : 0, mCurrentUserId);
|
||||
putInt(key, value ? 1 : 0);
|
||||
}
|
||||
|
||||
private boolean getBoolean(final String key, final boolean defaultValue) {
|
||||
return Settings.Secure.getIntForUser(mResolver, key, defaultValue ? 1 : 0,
|
||||
mCurrentUserId) == 1;
|
||||
return getInt(key, defaultValue ? 1 : 0) == 1;
|
||||
}
|
||||
|
||||
public void setCurrentProfileIds(int[] currentProfileIds) {
|
||||
@@ -1290,6 +1336,7 @@ public class InputMethodUtils {
|
||||
putBoolean(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, show);
|
||||
}
|
||||
|
||||
@UserIdInt
|
||||
public int getCurrentUserId() {
|
||||
return mCurrentUserId;
|
||||
}
|
||||
@@ -1324,6 +1371,13 @@ public class InputMethodUtils {
|
||||
}
|
||||
return enabledInputMethodAndSubtypes;
|
||||
}
|
||||
|
||||
public void dumpLocked(final Printer pw, final String prefix) {
|
||||
pw.println(prefix + "mCurrentUserId=" + mCurrentUserId);
|
||||
pw.println(prefix + "mCurrentProfileIds=" + Arrays.toString(mCurrentProfileIds));
|
||||
pw.println(prefix + "mCopyOnWrite=" + mCopyOnWrite);
|
||||
pw.println(prefix + "mEnabledInputMethodsStrCache=" + mEnabledInputMethodsStrCache);
|
||||
}
|
||||
}
|
||||
|
||||
// For spell checker service manager.
|
||||
|
||||
@@ -857,7 +857,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
|
||||
// mSettings should be created before buildInputMethodListLocked
|
||||
mSettings = new InputMethodSettings(
|
||||
mRes, context.getContentResolver(), mMethodMap, mMethodList, userId);
|
||||
mRes, context.getContentResolver(), mMethodMap, mMethodList, userId, !mSystemReady);
|
||||
|
||||
// Let the package manager query which are the default imes
|
||||
// as they get certain permissions granted by default.
|
||||
@@ -872,7 +872,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
// TODO: We are switching the current user id in the settings
|
||||
// object to query it and then revert the user id. Ideally, we
|
||||
// should call a API in settings with the user id as an argument.
|
||||
mSettings.setCurrentUserId(userId);
|
||||
mSettings.switchCurrentUser(userId, true /* copyOnWrite */);
|
||||
List<InputMethodInfo> imes = mSettings
|
||||
.getEnabledInputMethodListLocked();
|
||||
String[] packageNames = null;
|
||||
@@ -884,7 +884,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
packageNames[i] = ime.getPackageName();
|
||||
}
|
||||
}
|
||||
mSettings.setCurrentUserId(currentUserId);
|
||||
// If the system is not ready, then we use copy-on-write mode.
|
||||
final boolean useCopyOnWriteSettings = !mSystemReady;
|
||||
mSettings.switchCurrentUser(currentUserId, useCopyOnWriteSettings);
|
||||
return packageNames;
|
||||
}
|
||||
}
|
||||
@@ -1020,7 +1022,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
|
||||
// ContentObserver should be registered again when the user is changed
|
||||
mSettingsObserver.registerContentObserverLocked(newUserId);
|
||||
mSettings.setCurrentUserId(newUserId);
|
||||
|
||||
// If the system is not ready, then we use copy-on-write settings.
|
||||
final boolean useCopyOnWriteSettings = !mSystemReady;
|
||||
mSettings.switchCurrentUser(newUserId, useCopyOnWriteSettings);
|
||||
updateCurrentProfileIds();
|
||||
// InputMethodFileManager should be reset when the user is changed
|
||||
mFileManager = new InputMethodFileManager(mMethodMap, newUserId);
|
||||
@@ -1079,6 +1084,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
}
|
||||
if (!mSystemReady) {
|
||||
mSystemReady = true;
|
||||
final int currentUserId = mSettings.getCurrentUserId();
|
||||
mSettings.switchCurrentUser(currentUserId, false /* copyOnWrite */);
|
||||
mKeyguardManager = mContext.getSystemService(KeyguardManager.class);
|
||||
mNotificationManager = mContext.getSystemService(NotificationManager.class);
|
||||
mStatusBar = statusBar;
|
||||
@@ -3000,7 +3007,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
if (resetDefaultEnabledIme) {
|
||||
final ArrayList<InputMethodInfo> defaultEnabledIme =
|
||||
InputMethodUtils.getDefaultEnabledImes(mContext, mSystemReady, mMethodList);
|
||||
for (int i = 0; i < defaultEnabledIme.size(); ++i) {
|
||||
final int N = defaultEnabledIme.size();
|
||||
for (int i = 0; i < N; ++i) {
|
||||
final InputMethodInfo imi = defaultEnabledIme.get(i);
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "--- enable ime = " + imi);
|
||||
@@ -3362,16 +3370,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround.
|
||||
// ASEC is not ready in the IMMS constructor. Accordingly, forward-locked
|
||||
// IMEs are not recognized and considered uninstalled.
|
||||
// Actually, we can't move everything after SystemReady because
|
||||
// IMMS needs to run in the encryption lock screen. So, we just skip changing
|
||||
// the default IME here and try cheking the default IME again in systemReady().
|
||||
// TODO: Do nothing before system ready and implement a separated logic for
|
||||
// the encryption lock screen.
|
||||
// TODO: ASEC should be ready before IMMS is instantiated.
|
||||
if (mSystemReady && !setSubtypeOnly) {
|
||||
if (!setSubtypeOnly) {
|
||||
// Set InputMethod here
|
||||
mSettings.putSelectedInputMethod(imi != null ? imi.getId() : "");
|
||||
}
|
||||
@@ -3852,6 +3851,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
p.println(" mSettingsObserver=" + mSettingsObserver);
|
||||
p.println(" mSwitchingController:");
|
||||
mSwitchingController.dump(p);
|
||||
p.println(" mSettings:");
|
||||
mSettings.dumpLocked(p, " ");
|
||||
}
|
||||
|
||||
p.println(" ");
|
||||
|
||||
Reference in New Issue
Block a user