summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Wilson Wu <wilsonwu@google.com> 2021-11-10 15:42:53 +0800
committer Wilson Wu <wilsonwu@google.com> 2021-11-26 05:28:40 +0000
commit70ff12551b339369b447cc675e5b163bb0acf922 (patch)
treeaa87427f3d697640f25091ea8adf39dd589cb847
parent1f3a923a515309bee7fdac59fca2c95b4fd8cea7 (diff)
Make InputMethodPreference support work profile
Introduces userId into InputMethodPreference and per-user context into InputMethodSettingValuesWrapper. So we can handle the work input method if it's work flow. Bug: 174360557 Bug: 197707782 Test: Manual test as bug video Test: atest SettingsLibTests:com.android.settingslib.inputmethod.InputMethodPreferenceTest Change-Id: Ic233cf183c8783937e638f9ab672c248a136c071
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompat.java45
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java46
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodSettingValuesWrapper.java42
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodPreferenceTest.java4
4 files changed, 104 insertions, 33 deletions
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompat.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompat.java
index 1d8f71ea4031..78ec58b89800 100644
--- a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompat.java
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompat.java
@@ -18,11 +18,13 @@ package com.android.settingslib.inputmethod;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.icu.text.ListFormatter;
+import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.text.TextUtils;
@@ -155,9 +157,41 @@ public class InputMethodAndSubtypeUtilCompat {
return set;
}
- public static void saveInputMethodSubtypeList(PreferenceFragmentCompat context,
+ /**
+ * Save the enabled/disabled input methods and selected subtype states into system settings.
+ *
+ * @param fragment The preference fragment user interact with.
+ * @param resolver The {@link ContentResolver} used to access the database.
+ * @param inputMethodInfos The list of {@link InputMethodInfo} to be checked.
+ * @param hasHardKeyboard {@code true} if the device has the hardware keyboard.
+ */
+ public static void saveInputMethodSubtypeList(PreferenceFragmentCompat fragment,
ContentResolver resolver, List<InputMethodInfo> inputMethodInfos,
boolean hasHardKeyboard) {
+ saveInputMethodSubtypeListForUserInternal(
+ fragment, resolver, inputMethodInfos, hasHardKeyboard, UserHandle.myUserId());
+ }
+
+ /**
+ * Save the enabled/disabled input methods and selected subtype states into system settings as
+ * given userId.
+ *
+ * @param fragment The preference fragment user interact with.
+ * @param resolver The {@link ContentResolver} used to access the database.
+ * @param inputMethodInfos The list of {@link InputMethodInfo} to be checked.
+ * @param hasHardKeyboard {@code true} if the device has the hardware keyboard.
+ * @param userId The given userId
+ */
+ public static void saveInputMethodSubtypeListForUser(PreferenceFragmentCompat fragment,
+ ContentResolver resolver, List<InputMethodInfo> inputMethodInfos,
+ boolean hasHardKeyboard, @UserIdInt int userId) {
+ saveInputMethodSubtypeListForUserInternal(
+ fragment, resolver, inputMethodInfos, hasHardKeyboard, userId);
+ }
+
+ private static void saveInputMethodSubtypeListForUserInternal(PreferenceFragmentCompat fragment,
+ ContentResolver resolver, List<InputMethodInfo> inputMethodInfos,
+ boolean hasHardKeyboard, @UserIdInt int userId) {
String currentInputMethodId = Settings.Secure.getString(resolver,
Settings.Secure.DEFAULT_INPUT_METHOD);
final int selectedInputMethodSubtype = getInputMethodSubtypeSelected(resolver);
@@ -168,7 +202,7 @@ public class InputMethodAndSubtypeUtilCompat {
boolean needsToResetSelectedSubtype = false;
for (final InputMethodInfo imi : inputMethodInfos) {
final String imiId = imi.getId();
- final Preference pref = context.findPreference(imiId);
+ final Preference pref = fragment.findPreference(imiId);
if (pref == null) {
continue;
}
@@ -184,8 +218,11 @@ public class InputMethodAndSubtypeUtilCompat {
}
final boolean isCurrentInputMethod = imiId.equals(currentInputMethodId);
final boolean systemIme = imi.isSystem();
+ // Create context as given userId
+ final Context wrapperContext = userId == UserHandle.myUserId() ? fragment.getActivity()
+ : fragment.getActivity().createContextAsUser(UserHandle.of(userId), 0);
if ((!hasHardKeyboard && InputMethodSettingValuesWrapper.getInstance(
- context.getActivity()).isAlwaysCheckedIme(imi))
+ wrapperContext).isAlwaysCheckedIme(imi))
|| isImeChecked) {
if (!enabledIMEsAndSubtypesMap.containsKey(imiId)) {
// imiId has just been enabled
@@ -198,7 +235,7 @@ public class InputMethodAndSubtypeUtilCompat {
for (int i = 0; i < subtypeCount; ++i) {
final InputMethodSubtype subtype = imi.getSubtypeAt(i);
final String subtypeHashCodeStr = String.valueOf(subtype.hashCode());
- final TwoStatePreference subtypePref = (TwoStatePreference) context
+ final TwoStatePreference subtypePref = (TwoStatePreference) fragment
.findPreference(imiId + subtypeHashCodeStr);
// In the Configure input method screen which does not have subtype preferences.
if (subtypePref == null) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java
index 94a0c00b4222..c1ab706fe45e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java
@@ -18,6 +18,7 @@ package com.android.settingslib.inputmethod;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import android.annotation.UserIdInt;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
@@ -75,30 +76,34 @@ public class InputMethodPreference extends PrimarySwitchPreference
private final OnSavePreferenceListener mOnSaveListener;
private final InputMethodSettingValuesWrapper mInputMethodSettingValues;
private final boolean mIsAllowedByOrganization;
+ @UserIdInt
+ private final int mUserId;
private AlertDialog mDialog = null;
/**
* A preference entry of an input method.
*
- * @param context The Context this is associated with.
+ * @param prefContext The Context this preference is associated with.
* @param imi The {@link InputMethodInfo} of this preference.
* @param isAllowedByOrganization false if the IME has been disabled by a device or profile
* owner.
* @param onSaveListener The listener called when this preference has been changed and needs
* to save the state to shared preference.
+ * @param userId The userId to specify the corresponding user for this preference.
*/
- public InputMethodPreference(final Context context, final InputMethodInfo imi,
- final boolean isAllowedByOrganization, final OnSavePreferenceListener onSaveListener) {
- this(context, imi, imi.loadLabel(context.getPackageManager()), isAllowedByOrganization,
- onSaveListener);
+ public InputMethodPreference(final Context prefContext, final InputMethodInfo imi,
+ final boolean isAllowedByOrganization, final OnSavePreferenceListener onSaveListener,
+ final @UserIdInt int userId) {
+ this(prefContext, imi, imi.loadLabel(prefContext.getPackageManager()),
+ isAllowedByOrganization, onSaveListener, userId);
}
@VisibleForTesting
- InputMethodPreference(final Context context, final InputMethodInfo imi,
+ InputMethodPreference(final Context prefContext, final InputMethodInfo imi,
final CharSequence title, final boolean isAllowedByOrganization,
- final OnSavePreferenceListener onSaveListener) {
- super(context);
+ final OnSavePreferenceListener onSaveListener, final @UserIdInt int userId) {
+ super(prefContext);
setPersistent(false);
mImi = imi;
mIsAllowedByOrganization = isAllowedByOrganization;
@@ -114,7 +119,12 @@ public class InputMethodPreference extends PrimarySwitchPreference
intent.setClassName(imi.getPackageName(), settingsActivity);
setIntent(intent);
}
- mInputMethodSettingValues = InputMethodSettingValuesWrapper.getInstance(context);
+ // Handle the context by given userId because {@link InputMethodSettingValuesWrapper} is
+ // per-user instance.
+ final Context userAwareContext = userId == UserHandle.myUserId() ? prefContext :
+ getContext().createContextAsUser(UserHandle.of(userId), 0);
+ mInputMethodSettingValues = InputMethodSettingValuesWrapper.getInstance(userAwareContext);
+ mUserId = userId;
mHasPriorityInSorting = imi.isSystem()
&& InputMethodAndSubtypeUtil.isValidNonAuxAsciiCapableIme(imi);
setOnPreferenceClickListener(this);
@@ -130,17 +140,15 @@ public class InputMethodPreference extends PrimarySwitchPreference
super.onBindViewHolder(holder);
final Switch switchWidget = getSwitch();
if (switchWidget != null) {
+ // Avoid default behavior in {@link PrimarySwitchPreference#onBindViewHolder}.
switchWidget.setOnClickListener(v -> {
- // no-op, avoid default behavior in {@link PrimarySwitchPreference#onBindViewHolder}
- });
- switchWidget.setOnCheckedChangeListener((buttonView, isChecked) -> {
- // Avoid the invocation after we call {@link PrimarySwitchPreference#setChecked()}
- // in {@link setCheckedInternal}
- if (isChecked != isChecked()) {
- // Keep switch to previous state because we have to show the dialog first
- buttonView.setChecked(!isChecked);
- callChangeListener(isChecked());
+ if (!switchWidget.isEnabled()) {
+ return;
}
+ final boolean newValue = !isChecked();
+ // Keep switch to previous state because we have to show the dialog first.
+ switchWidget.setChecked(isChecked());
+ callChangeListener(newValue);
});
}
final ImageView icon = holder.itemView.findViewById(android.R.id.icon);
@@ -187,7 +195,7 @@ public class InputMethodPreference extends PrimarySwitchPreference
final Intent intent = getIntent();
if (intent != null) {
// Invoke a settings activity of an input method.
- context.startActivity(intent);
+ context.startActivityAsUser(intent, UserHandle.of(mUserId));
}
} catch (final ActivityNotFoundException e) {
Log.d(TAG, "IME's Settings Activity Not Found", e);
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodSettingValuesWrapper.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodSettingValuesWrapper.java
index 13c1b823cb85..39e6dcecba31 100644
--- a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodSettingValuesWrapper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodSettingValuesWrapper.java
@@ -16,13 +16,18 @@
package com.android.settingslib.inputmethod;
+import android.annotation.AnyThread;
+import android.annotation.NonNull;
import android.annotation.UiThread;
import android.content.ContentResolver;
import android.content.Context;
import android.util.Log;
+import android.util.SparseArray;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
+import com.android.internal.annotations.GuardedBy;
+
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -39,20 +44,39 @@ import java.util.List;
public class InputMethodSettingValuesWrapper {
private static final String TAG = InputMethodSettingValuesWrapper.class.getSimpleName();
- private static volatile InputMethodSettingValuesWrapper sInstance;
+ private static final Object sInstanceMapLock = new Object();
+ /**
+ * Manages mapping between user ID and corresponding singleton
+ * {@link InputMethodSettingValuesWrapper} object.
+ */
+ @GuardedBy("sInstanceMapLock")
+ private static SparseArray<InputMethodSettingValuesWrapper> sInstanceMap = new SparseArray<>();
private final ArrayList<InputMethodInfo> mMethodList = new ArrayList<>();
private final ContentResolver mContentResolver;
private final InputMethodManager mImm;
- public static InputMethodSettingValuesWrapper getInstance(Context context) {
- if (sInstance == null) {
- synchronized (TAG) {
- if (sInstance == null) {
- sInstance = new InputMethodSettingValuesWrapper(context);
- }
+ @AnyThread
+ @NonNull
+ public static InputMethodSettingValuesWrapper getInstance(@NonNull Context context) {
+ final int requestUserId = context.getUserId();
+ InputMethodSettingValuesWrapper valuesWrapper;
+ // First time to create the wrapper.
+ synchronized (sInstanceMapLock) {
+ if (sInstanceMap.size() == 0) {
+ valuesWrapper = new InputMethodSettingValuesWrapper(context);
+ sInstanceMap.put(requestUserId, valuesWrapper);
+ return valuesWrapper;
}
+ // We have same user context as request.
+ if (sInstanceMap.indexOfKey(requestUserId) >= 0) {
+ return sInstanceMap.get(requestUserId);
+ }
+ // Request by a new user context.
+ valuesWrapper = new InputMethodSettingValuesWrapper(context);
+ sInstanceMap.put(context.getUserId(), valuesWrapper);
}
- return sInstance;
+
+ return valuesWrapper;
}
// Ensure singleton
@@ -64,7 +88,7 @@ public class InputMethodSettingValuesWrapper {
public void refreshAllInputMethodAndSubtypes() {
mMethodList.clear();
- mMethodList.addAll(mImm.getInputMethodList());
+ mMethodList.addAll(mImm.getInputMethodListAsUser(mContentResolver.getUserId()));
}
public List<InputMethodInfo> getInputMethodList() {
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodPreferenceTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodPreferenceTest.java
index 9962e1ca438a..1e75014d2017 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodPreferenceTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodPreferenceTest.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.os.UserHandle;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;
@@ -112,7 +113,8 @@ public class InputMethodPreferenceTest {
createInputMethodInfo(systemIme, name),
title,
true /* isAllowedByOrganization */,
- p -> {} /* onSavePreferenceListener */);
+ p -> {} /* onSavePreferenceListener */,
+ UserHandle.myUserId());
}
private static InputMethodInfo createInputMethodInfo(