Add getInputMethodList API for locked user state
When work profile disable by quick settings, the
user would be locked then we cannot query installed
input method lists for work user by existings API
InputMethodManager#getInputMethodListAsUser().
Adding a new API to query input method services
regardless of the user state. This API currently
only used by Settings, it shouldn't affect the
original behavior for other usages.
Bug: 210083408
Test: verify we can get input methods list after
disable work apps by quick settings
Test: atest CtsInputMethodTestCases
Change-Id: I54d5dbec7e76d6a68935007ed3af0641f717a7c5
This commit is contained in:
@@ -86,6 +86,7 @@ import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
|
||||
import android.view.autofill.AutofillManager;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.inputmethod.DirectBootAwareness;
|
||||
import com.android.internal.inputmethod.ImeTracing;
|
||||
import com.android.internal.inputmethod.InputBindResult;
|
||||
import com.android.internal.inputmethod.InputMethodDebug;
|
||||
@@ -1233,6 +1234,26 @@ public final class InputMethodManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of installed input methods for the specified user.
|
||||
*
|
||||
* @param userId user ID to query
|
||||
* @param directBootAwareness {@code true} if caller want to query installed input methods list
|
||||
* on user locked state.
|
||||
* @return {@link List} of {@link InputMethodInfo}.
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(INTERACT_ACROSS_USERS_FULL)
|
||||
@NonNull
|
||||
public List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId,
|
||||
@DirectBootAwareness int directBootAwareness) {
|
||||
try {
|
||||
return mService.getAwareLockedInputMethodList(userId, directBootAwareness);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of enabled input methods.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.internal.inputmethod;
|
||||
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
|
||||
/**
|
||||
* Specifies the decided filtering mode regarding IMEs' DirectBoot awareness when querying IMEs.
|
||||
*/
|
||||
@Retention(SOURCE)
|
||||
@IntDef({DirectBootAwareness.AUTO, DirectBootAwareness.ANY})
|
||||
public @interface DirectBootAwareness {
|
||||
/**
|
||||
* The same semantics as {@link android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AUTO}, that
|
||||
* is, if the user to be queried is still locked, then only DirectBoot-aware IMEs will be
|
||||
* matched. If the user to be queried is already unlocked, then IMEs will not be filtered out
|
||||
* based on their DirectBoot awareness.
|
||||
*/
|
||||
int AUTO = 0;
|
||||
/**
|
||||
* The same semantics as specifying <strong>both</strong>
|
||||
* {@link android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE} and
|
||||
* {@link android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE}, that is, IME will never
|
||||
* be filtered out based on their DirectBoot awareness, no matter whether the user to be queried
|
||||
* is still locked or already unlocked.
|
||||
*/
|
||||
int ANY = 1;
|
||||
}
|
||||
@@ -35,6 +35,7 @@ interface IInputMethodManager {
|
||||
|
||||
// TODO: Use ParceledListSlice instead
|
||||
List<InputMethodInfo> getInputMethodList(int userId);
|
||||
List<InputMethodInfo> getAwareLockedInputMethodList(int userId, int directBootAwareness);
|
||||
// TODO: Use ParceledListSlice instead
|
||||
List<InputMethodInfo> getEnabledInputMethodList(int userId);
|
||||
List<InputMethodSubtype> getEnabledInputMethodSubtypeList(in String imiId,
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.view.inputmethod.InputMethodInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.inputmethod.DirectBootAwareness;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -88,7 +89,8 @@ public class InputMethodSettingValuesWrapper {
|
||||
|
||||
public void refreshAllInputMethodAndSubtypes() {
|
||||
mMethodList.clear();
|
||||
mMethodList.addAll(mImm.getInputMethodListAsUser(mContentResolver.getUserId()));
|
||||
mMethodList.addAll(mImm.getInputMethodListAsUser(
|
||||
mContentResolver.getUserId(), DirectBootAwareness.ANY));
|
||||
}
|
||||
|
||||
public List<InputMethodInfo> getInputMethodList() {
|
||||
|
||||
@@ -149,6 +149,7 @@ import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.compat.IPlatformCompat;
|
||||
import com.android.internal.content.PackageMonitor;
|
||||
import com.android.internal.infra.AndroidFuture;
|
||||
import com.android.internal.inputmethod.DirectBootAwareness;
|
||||
import com.android.internal.inputmethod.IInputContentUriToken;
|
||||
import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
|
||||
import com.android.internal.inputmethod.ImeTracing;
|
||||
@@ -1869,8 +1870,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<InputMethodInfo> getInputMethodList(@UserIdInt int userId) {
|
||||
private List<InputMethodInfo> getInputMethodListInternal(@UserIdInt int userId,
|
||||
@DirectBootAwareness int directBootAwareness) {
|
||||
if (UserHandle.getCallingUserId() != userId) {
|
||||
mContext.enforceCallingPermission(
|
||||
Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
|
||||
@@ -1883,13 +1884,24 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
}
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return getInputMethodListLocked(resolvedUserIds[0]);
|
||||
return getInputMethodListLocked(resolvedUserIds[0], directBootAwareness);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<InputMethodInfo> getInputMethodList(@UserIdInt int userId) {
|
||||
return getInputMethodListInternal(userId, DirectBootAwareness.AUTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<InputMethodInfo> getAwareLockedInputMethodList(@UserIdInt int userId,
|
||||
@DirectBootAwareness int directBootAwareness) {
|
||||
return getInputMethodListInternal(userId, directBootAwareness);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<InputMethodInfo> getEnabledInputMethodList(@UserIdInt int userId) {
|
||||
if (UserHandle.getCallingUserId() != userId) {
|
||||
@@ -1912,9 +1924,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
}
|
||||
|
||||
@GuardedBy("mMethodMap")
|
||||
private List<InputMethodInfo> getInputMethodListLocked(@UserIdInt int userId) {
|
||||
private List<InputMethodInfo> getInputMethodListLocked(@UserIdInt int userId,
|
||||
@DirectBootAwareness int directBootAwareness) {
|
||||
final ArrayList<InputMethodInfo> methodList;
|
||||
if (userId == mSettings.getCurrentUserId()) {
|
||||
if (userId == mSettings.getCurrentUserId()
|
||||
&& directBootAwareness == DirectBootAwareness.AUTO) {
|
||||
// Create a copy.
|
||||
methodList = new ArrayList<>(mMethodList);
|
||||
} else {
|
||||
@@ -1924,7 +1938,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
new ArrayMap<>();
|
||||
AdditionalSubtypeUtils.load(additionalSubtypeMap, userId);
|
||||
queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, methodMap,
|
||||
methodList);
|
||||
methodList, directBootAwareness);
|
||||
}
|
||||
return methodList;
|
||||
}
|
||||
@@ -4389,17 +4403,31 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
|
||||
static void queryInputMethodServicesInternal(Context context,
|
||||
@UserIdInt int userId, ArrayMap<String, List<InputMethodSubtype>> additionalSubtypeMap,
|
||||
ArrayMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList) {
|
||||
ArrayMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList,
|
||||
@DirectBootAwareness int directBootAwareness) {
|
||||
methodList.clear();
|
||||
methodMap.clear();
|
||||
|
||||
// Note: We do not specify PackageManager.MATCH_ENCRYPTION_* flags here because the default
|
||||
// behavior of PackageManager is exactly what we want. It by default picks up appropriate
|
||||
// services depending on the unlock state for the specified user.
|
||||
final int directBootAwarenessFlags;
|
||||
switch (directBootAwareness) {
|
||||
case DirectBootAwareness.ANY:
|
||||
directBootAwarenessFlags = PackageManager.MATCH_DIRECT_BOOT_AWARE
|
||||
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
|
||||
break;
|
||||
case DirectBootAwareness.AUTO:
|
||||
directBootAwarenessFlags = PackageManager.MATCH_DIRECT_BOOT_AUTO;
|
||||
break;
|
||||
default:
|
||||
directBootAwarenessFlags = PackageManager.MATCH_DIRECT_BOOT_AUTO;
|
||||
Slog.e(TAG, "Unknown directBootAwareness=" + directBootAwareness
|
||||
+ ". Falling back to DirectBootAwareness.AUTO");
|
||||
break;
|
||||
}
|
||||
final int flags = PackageManager.GET_META_DATA
|
||||
| PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
|
||||
| directBootAwarenessFlags;
|
||||
final List<ResolveInfo> services = context.getPackageManager().queryIntentServicesAsUser(
|
||||
new Intent(InputMethod.SERVICE_INTERFACE),
|
||||
PackageManager.GET_META_DATA | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS,
|
||||
userId);
|
||||
new Intent(InputMethod.SERVICE_INTERFACE), flags, userId);
|
||||
|
||||
methodList.ensureCapacity(services.size());
|
||||
methodMap.ensureCapacity(services.size());
|
||||
@@ -4448,7 +4476,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
mMyPackageMonitor.clearKnownImePackageNamesLocked();
|
||||
|
||||
queryInputMethodServicesInternal(mContext, mSettings.getCurrentUserId(),
|
||||
mAdditionalSubtypeMap, mMethodMap, mMethodList);
|
||||
mAdditionalSubtypeMap, mMethodMap, mMethodList, DirectBootAwareness.AUTO);
|
||||
|
||||
// Construct the set of possible IME packages for onPackageChanged() to avoid false
|
||||
// negatives when the package state remains to be the same but only the component state is
|
||||
@@ -4752,7 +4780,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
|
||||
private List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId) {
|
||||
synchronized (mMethodMap) {
|
||||
return getInputMethodListLocked(userId);
|
||||
return getInputMethodListLocked(userId, DirectBootAwareness.AUTO);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4777,7 +4805,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
new ArrayMap<>();
|
||||
AdditionalSubtypeUtils.load(additionalSubtypeMap, userId);
|
||||
queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap,
|
||||
methodMap, methodList);
|
||||
methodMap, methodList, DirectBootAwareness.AUTO);
|
||||
return methodMap;
|
||||
}
|
||||
|
||||
@@ -5406,7 +5434,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
mSettings.getCurrentUserId(), shellCommand.getErrPrintWriter());
|
||||
for (int userId : userIds) {
|
||||
final List<InputMethodInfo> methods = all
|
||||
? getInputMethodListLocked(userId)
|
||||
? getInputMethodListLocked(userId, DirectBootAwareness.AUTO)
|
||||
: getEnabledInputMethodListLocked(userId);
|
||||
if (userIds.length > 1) {
|
||||
pr.print("User #");
|
||||
@@ -5641,7 +5669,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
new ArrayMap<>();
|
||||
AdditionalSubtypeUtils.load(additionalSubtypeMap, userId);
|
||||
queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap,
|
||||
methodMap, methodList);
|
||||
methodMap, methodList, DirectBootAwareness.AUTO);
|
||||
final InputMethodSettings settings = new InputMethodSettings(
|
||||
mContext.getResources(), mContext.getContentResolver(), methodMap,
|
||||
userId, false);
|
||||
|
||||
Reference in New Issue
Block a user