Merge "Add Copy-On-Write mode to InputMethodSettings." into nyc-dev

This commit is contained in:
Yohei Yukawa
2016-02-17 17:11:53 +00:00
committed by Android (Google) Code Review
2 changed files with 80 additions and 25 deletions

View File

@@ -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.

View File

@@ -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(" ");