Merge changes Ib00124b3,Ie850a67c
* changes: Refine WindowManagerInternal#getDisplayImePolicy Reduce potential lock contention during start input
This commit is contained in:
@@ -2347,11 +2347,20 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
curId, getSequenceNumberLocked(), suppressesSpellChecker);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by {@link #startInputOrWindowGainedFocusInternalLocked} to bind/unbind/attach the
|
||||
* selected InputMethod to the given focused IME client.
|
||||
*
|
||||
* Note that this should be called after validating if the IME client has IME focus.
|
||||
*
|
||||
* @see WindowManagerInternal#hasInputMethodClientFocus(IBinder, int, int, int)
|
||||
*/
|
||||
@GuardedBy("ImfLock.class")
|
||||
@NonNull
|
||||
InputBindResult startInputUncheckedLocked(@NonNull ClientState cs, IInputContext inputContext,
|
||||
@NonNull EditorInfo attribute, @StartInputFlags int startInputFlags,
|
||||
@StartInputReason int startInputReason, int unverifiedTargetSdkVersion) {
|
||||
private InputBindResult startInputUncheckedLocked(@NonNull ClientState cs,
|
||||
IInputContext inputContext, @NonNull EditorInfo attribute,
|
||||
@StartInputFlags int startInputFlags, @StartInputReason int startInputReason,
|
||||
int unverifiedTargetSdkVersion) {
|
||||
// If no method is currently selected, do nothing.
|
||||
String selectedMethodId = getSelectedMethodIdLocked();
|
||||
if (selectedMethodId == null) {
|
||||
@@ -2373,10 +2382,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
return InputBindResult.INVALID_PACKAGE_NAME;
|
||||
}
|
||||
|
||||
if (!mWindowManagerInternal.isUidAllowedOnDisplay(cs.selfReportedDisplayId, cs.uid)) {
|
||||
// Wait, the client no longer has access to the display.
|
||||
return InputBindResult.INVALID_DISPLAY_ID;
|
||||
}
|
||||
// Compute the final shown display ID with validated cs.selfReportedDisplayId for this
|
||||
// session & other conditions.
|
||||
mDisplayIdToShowIme = computeImeDisplayIdForTarget(cs.selfReportedDisplayId,
|
||||
@@ -3200,14 +3205,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
// be made before input is started in it.
|
||||
final ClientState cs = mClients.get(client.asBinder());
|
||||
if (cs == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"unknown client " + client.asBinder());
|
||||
throw new IllegalArgumentException("unknown client " + client.asBinder());
|
||||
}
|
||||
if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid,
|
||||
cs.selfReportedDisplayId)) {
|
||||
if (!isImeClientFocused(windowToken, cs)) {
|
||||
if (DEBUG) {
|
||||
Slog.w(TAG,
|
||||
"Ignoring hideSoftInput of uid " + uid + ": " + client);
|
||||
Slog.w(TAG, "Ignoring hideSoftInput of uid " + uid + ": " + client);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -3277,6 +3279,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
return res;
|
||||
}
|
||||
|
||||
private boolean isImeClientFocused(IBinder windowToken, ClientState cs) {
|
||||
final int imeClientFocus = mWindowManagerInternal.hasInputMethodClientFocus(
|
||||
windowToken, cs.uid, cs.pid, cs.selfReportedDisplayId);
|
||||
return imeClientFocus == WindowManagerInternal.ImeClientFocusResult.HAS_IME_FOCUS;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public InputBindResult startInputOrWindowGainedFocus(
|
||||
@@ -3370,31 +3378,30 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
+ " unverifiedTargetSdkVersion=" + unverifiedTargetSdkVersion);
|
||||
}
|
||||
|
||||
final int windowDisplayId = mWindowManagerInternal.getDisplayIdForWindow(windowToken);
|
||||
|
||||
final ClientState cs = mClients.get(client.asBinder());
|
||||
if (cs == null) {
|
||||
throw new IllegalArgumentException("unknown client " + client.asBinder());
|
||||
}
|
||||
if (cs.selfReportedDisplayId != windowDisplayId) {
|
||||
Slog.e(TAG, "startInputOrWindowGainedFocusInternal: display ID mismatch."
|
||||
+ " from client:" + cs.selfReportedDisplayId
|
||||
+ " from window:" + windowDisplayId);
|
||||
return InputBindResult.DISPLAY_ID_MISMATCH;
|
||||
}
|
||||
|
||||
if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid,
|
||||
cs.selfReportedDisplayId)) {
|
||||
// Check with the window manager to make sure this client actually
|
||||
// has a window with focus. If not, reject. This is thread safe
|
||||
// because if the focus changes some time before or after, the
|
||||
// next client receiving focus that has any interest in input will
|
||||
// be calling through here after that change happens.
|
||||
if (DEBUG) {
|
||||
Slog.w(TAG, "Focus gain on non-focused client " + cs.client
|
||||
+ " (uid=" + cs.uid + " pid=" + cs.pid + ")");
|
||||
}
|
||||
return InputBindResult.NOT_IME_TARGET_WINDOW;
|
||||
final int imeClientFocus = mWindowManagerInternal.hasInputMethodClientFocus(
|
||||
windowToken, cs.uid, cs.pid, cs.selfReportedDisplayId);
|
||||
switch (imeClientFocus) {
|
||||
case WindowManagerInternal.ImeClientFocusResult.DISPLAY_ID_MISMATCH:
|
||||
Slog.e(TAG, "startInputOrWindowGainedFocusInternal: display ID mismatch.");
|
||||
return InputBindResult.DISPLAY_ID_MISMATCH;
|
||||
case WindowManagerInternal.ImeClientFocusResult.NOT_IME_TARGET_WINDOW:
|
||||
// Check with the window manager to make sure this client actually
|
||||
// has a window with focus. If not, reject. This is thread safe
|
||||
// because if the focus changes some time before or after, the
|
||||
// next client receiving focus that has any interest in input will
|
||||
// be calling through here after that change happens.
|
||||
if (DEBUG) {
|
||||
Slog.w(TAG, "Focus gain on non-focused client " + cs.client
|
||||
+ " (uid=" + cs.uid + " pid=" + cs.pid + ")");
|
||||
}
|
||||
return InputBindResult.NOT_IME_TARGET_WINDOW;
|
||||
case WindowManagerInternal.ImeClientFocusResult.INVALID_DISPLAY_ID:
|
||||
return InputBindResult.INVALID_DISPLAY_ID;
|
||||
}
|
||||
|
||||
if (mUserSwitchHandlerTask != null) {
|
||||
@@ -3622,8 +3629,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
if (cs == null) {
|
||||
throw new IllegalArgumentException("unknown client " + client.asBinder());
|
||||
}
|
||||
if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid,
|
||||
cs.selfReportedDisplayId)) {
|
||||
if (!isImeClientFocused(mCurFocusedWindow, cs)) {
|
||||
Slog.w(TAG, String.format("Ignoring %s of uid %d : %s", methodName, uid, client));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2001,6 +2001,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
}
|
||||
|
||||
void configureDisplayPolicy() {
|
||||
mRootWindowContainer.updateDisplayImePolicyCache();
|
||||
mDisplayPolicy.updateConfigurationAndScreenSizeDependentBehaviors();
|
||||
mDisplayRotation.configure(mBaseDisplayWidth, mBaseDisplayHeight);
|
||||
}
|
||||
@@ -3939,6 +3940,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
}
|
||||
}
|
||||
|
||||
// IMPORTANT: When introducing new dependencies in this method, make sure that
|
||||
// changes to those result in RootWindowContainer.updateDisplayImePolicyCache()
|
||||
// being called.
|
||||
@DisplayImePolicy int getImePolicy() {
|
||||
if (!isTrusted()) {
|
||||
return DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
|
||||
|
||||
@@ -165,6 +165,7 @@ import java.io.PrintWriter;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
@@ -2530,9 +2531,16 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
|
||||
// Drop any cached DisplayInfos associated with this display id - the values are now
|
||||
// out of date given this display changed event.
|
||||
mWmService.mPossibleDisplayInfoMapper.removePossibleDisplayInfos(displayId);
|
||||
updateDisplayImePolicyCache();
|
||||
}
|
||||
}
|
||||
|
||||
void updateDisplayImePolicyCache() {
|
||||
ArrayMap<Integer, Integer> displayImePolicyMap = new ArrayMap<>();
|
||||
forAllDisplays(dc -> displayImePolicyMap.put(dc.getDisplayId(), dc.getImePolicy()));
|
||||
mWmService.mDisplayImePolicyCache = Collections.unmodifiableMap(displayImePolicyMap);
|
||||
}
|
||||
|
||||
/** Update lists of UIDs that are present on displays and have access to them. */
|
||||
void updateUIDsPresentOnDisplay() {
|
||||
mDisplayAccessUIDs.clear();
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.ClipData;
|
||||
@@ -40,6 +43,7 @@ import com.android.internal.policy.KeyInterceptionInfo;
|
||||
import com.android.server.input.InputManagerService;
|
||||
import com.android.server.policy.WindowManagerPolicy;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -609,6 +613,7 @@ public abstract class WindowManagerInternal {
|
||||
/**
|
||||
* Checks whether the specified IME client has IME focus or not.
|
||||
*
|
||||
* @param windowToken The window token of the input method client
|
||||
* @param uid UID of the process to be queried
|
||||
* @param pid PID of the process to be queried
|
||||
* @param displayId Display ID reported from the client. Note that this method also verifies
|
||||
@@ -616,7 +621,22 @@ public abstract class WindowManagerInternal {
|
||||
* @return {@code true} if the IME client specified with {@code uid}, {@code pid}, and
|
||||
* {@code displayId} has IME focus
|
||||
*/
|
||||
public abstract boolean isInputMethodClientFocus(int uid, int pid, int displayId);
|
||||
public abstract @ImeClientFocusResult int hasInputMethodClientFocus(IBinder windowToken,
|
||||
int uid, int pid, int displayId);
|
||||
|
||||
@Retention(SOURCE)
|
||||
@IntDef({
|
||||
ImeClientFocusResult.HAS_IME_FOCUS,
|
||||
ImeClientFocusResult.NOT_IME_TARGET_WINDOW,
|
||||
ImeClientFocusResult.DISPLAY_ID_MISMATCH,
|
||||
ImeClientFocusResult.INVALID_DISPLAY_ID
|
||||
})
|
||||
public @interface ImeClientFocusResult {
|
||||
int HAS_IME_FOCUS = 0;
|
||||
int NOT_IME_TARGET_WINDOW = -1;
|
||||
int DISPLAY_ID_MISMATCH = -2;
|
||||
int INVALID_DISPLAY_ID = -3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given {@code uid} is allowed to use the given {@code displayId} or not.
|
||||
|
||||
@@ -586,6 +586,13 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
*/
|
||||
final ArrayList<WindowState> mResizingWindows = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Mapping of displayId to {@link DisplayImePolicy}.
|
||||
* Note that this can be accessed without holding the lock.
|
||||
*/
|
||||
volatile Map<Integer, Integer> mDisplayImePolicyCache = Collections.unmodifiableMap(
|
||||
new ArrayMap<>());
|
||||
|
||||
/**
|
||||
* Windows whose surface should be destroyed.
|
||||
*/
|
||||
@@ -6897,6 +6904,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
void setForceDesktopModeOnExternalDisplays(boolean forceDesktopModeOnExternalDisplays) {
|
||||
synchronized (mGlobalLock) {
|
||||
mForceDesktopModeOnExternalDisplays = forceDesktopModeOnExternalDisplays;
|
||||
mRoot.updateDisplayImePolicyCache();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7328,16 +7336,14 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "getDisplayImePolicy()")) {
|
||||
throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
|
||||
}
|
||||
final DisplayContent dc = mRoot.getDisplayContent(displayId);
|
||||
if (dc == null) {
|
||||
final Map<Integer, Integer> displayImePolicyCache = mDisplayImePolicyCache;
|
||||
if (!displayImePolicyCache.containsKey(displayId)) {
|
||||
ProtoLog.w(WM_ERROR,
|
||||
"Attempted to get IME policy of a display that does not exist: %d",
|
||||
displayId);
|
||||
return DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
|
||||
}
|
||||
synchronized (mGlobalLock) {
|
||||
return dc.getImePolicy();
|
||||
}
|
||||
return displayImePolicyCache.get(displayId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -7686,19 +7692,32 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInputMethodClientFocus(int uid, int pid, int displayId) {
|
||||
public @ImeClientFocusResult int hasInputMethodClientFocus(IBinder windowToken,
|
||||
int uid, int pid, int displayId) {
|
||||
if (displayId == Display.INVALID_DISPLAY) {
|
||||
return false;
|
||||
return ImeClientFocusResult.INVALID_DISPLAY_ID;
|
||||
}
|
||||
synchronized (mGlobalLock) {
|
||||
final DisplayContent displayContent = mRoot.getTopFocusedDisplayContent();
|
||||
final WindowState window = mWindowMap.get(windowToken);
|
||||
if (window == null) {
|
||||
return ImeClientFocusResult.NOT_IME_TARGET_WINDOW;
|
||||
}
|
||||
final int tokenDisplayId = window.getDisplayContent().getDisplayId();
|
||||
if (tokenDisplayId != displayId) {
|
||||
Slog.e(TAG, "isInputMethodClientFocus: display ID mismatch."
|
||||
+ " from client: " + displayId
|
||||
+ " from window: " + tokenDisplayId);
|
||||
return ImeClientFocusResult.DISPLAY_ID_MISMATCH;
|
||||
}
|
||||
if (displayContent == null
|
||||
|| displayContent.getDisplayId() != displayId
|
||||
|| !displayContent.hasAccess(uid)) {
|
||||
return false;
|
||||
return ImeClientFocusResult.INVALID_DISPLAY_ID;
|
||||
}
|
||||
|
||||
if (displayContent.isInputMethodClientFocus(uid, pid)) {
|
||||
return true;
|
||||
return ImeClientFocusResult.HAS_IME_FOCUS;
|
||||
}
|
||||
// Okay, how about this... what is the current focus?
|
||||
// It seems in some cases we may not have moved the IM
|
||||
@@ -7711,10 +7730,11 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
final WindowState currentFocus = displayContent.mCurrentFocus;
|
||||
if (currentFocus != null && currentFocus.mSession.mUid == uid
|
||||
&& currentFocus.mSession.mPid == pid) {
|
||||
return currentFocus.canBeImeTarget();
|
||||
return currentFocus.canBeImeTarget() ? ImeClientFocusResult.HAS_IME_FOCUS
|
||||
: ImeClientFocusResult.NOT_IME_TARGET_WINDOW;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return ImeClientFocusResult.NOT_IME_TARGET_WINDOW;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -7813,9 +7833,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
|
||||
@Override
|
||||
public @DisplayImePolicy int getDisplayImePolicy(int displayId) {
|
||||
synchronized (mGlobalLock) {
|
||||
return WindowManagerService.this.getDisplayImePolicy(displayId);
|
||||
}
|
||||
return WindowManagerService.this.getDisplayImePolicy(displayId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -8710,20 +8728,21 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
|
||||
boolean shouldRestoreImeVisibility(IBinder imeTargetWindowToken) {
|
||||
final Task imeTargetWindowTask;
|
||||
synchronized (mGlobalLock) {
|
||||
final WindowState imeTargetWindow = mWindowMap.get(imeTargetWindowToken);
|
||||
if (imeTargetWindow == null) {
|
||||
return false;
|
||||
}
|
||||
final Task imeTargetWindowTask = imeTargetWindow.getTask();
|
||||
imeTargetWindowTask = imeTargetWindow.getTask();
|
||||
if (imeTargetWindowTask == null) {
|
||||
return false;
|
||||
}
|
||||
final TaskSnapshot snapshot = getTaskSnapshot(imeTargetWindowTask.mTaskId,
|
||||
imeTargetWindowTask.mUserId, false /* isLowResolution */,
|
||||
false /* restoreFromDisk */);
|
||||
return snapshot != null && snapshot.hasImeSurface();
|
||||
}
|
||||
final TaskSnapshot snapshot = getTaskSnapshot(imeTargetWindowTask.mTaskId,
|
||||
imeTargetWindowTask.mUserId, false /* isLowResolution */,
|
||||
false /* restoreFromDisk */);
|
||||
return snapshot != null && snapshot.hasImeSurface();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user