Merge "Revert "Fix SHOW_IMPLICIT and SHOW_EXPLICIT handling"" into udc-qpr-dev
This commit is contained in:
@@ -433,7 +433,7 @@ class IInputMethodWrapper extends IInputMethod.Stub
|
||||
@BinderThread
|
||||
@Override
|
||||
public void showSoftInput(IBinder showInputToken, @Nullable ImeTracker.Token statsToken,
|
||||
@InputMethod.ShowFlags int flags, ResultReceiver resultReceiver) {
|
||||
int flags, ResultReceiver resultReceiver) {
|
||||
ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER);
|
||||
mCaller.executeOrSendMessage(mCaller.obtainMessageIOOO(DO_SHOW_SOFT_INPUT,
|
||||
flags, showInputToken, resultReceiver, statsToken));
|
||||
|
||||
@@ -607,7 +607,6 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
InputConnection mStartedInputConnection;
|
||||
EditorInfo mInputEditorInfo;
|
||||
|
||||
@InputMethod.ShowFlags
|
||||
int mShowInputFlags;
|
||||
boolean mShowInputRequested;
|
||||
boolean mLastShowInputRequested;
|
||||
@@ -932,9 +931,8 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
*/
|
||||
@MainThread
|
||||
@Override
|
||||
public void showSoftInputWithToken(@InputMethod.ShowFlags int flags,
|
||||
ResultReceiver resultReceiver, IBinder showInputToken,
|
||||
@Nullable ImeTracker.Token statsToken) {
|
||||
public void showSoftInputWithToken(int flags, ResultReceiver resultReceiver,
|
||||
IBinder showInputToken, @Nullable ImeTracker.Token statsToken) {
|
||||
mSystemCallingShowSoftInput = true;
|
||||
mCurShowInputToken = showInputToken;
|
||||
mCurStatsToken = statsToken;
|
||||
@@ -952,7 +950,7 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
*/
|
||||
@MainThread
|
||||
@Override
|
||||
public void showSoftInput(@InputMethod.ShowFlags int flags, ResultReceiver resultReceiver) {
|
||||
public void showSoftInput(int flags, ResultReceiver resultReceiver) {
|
||||
ImeTracker.forLogging().onProgress(
|
||||
mCurStatsToken, ImeTracker.PHASE_IME_SHOW_SOFT_INPUT);
|
||||
if (DEBUG) Log.v(TAG, "showSoftInput()");
|
||||
@@ -1323,8 +1321,7 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
* InputMethodService#requestShowSelf} or {@link InputMethodService#requestHideSelf}
|
||||
*/
|
||||
@Deprecated
|
||||
public void toggleSoftInput(@InputMethodManager.ShowFlags int showFlags,
|
||||
@InputMethodManager.HideFlags int hideFlags) {
|
||||
public void toggleSoftInput(int showFlags, int hideFlags) {
|
||||
InputMethodService.this.onToggleSoftInput(showFlags, hideFlags);
|
||||
}
|
||||
|
||||
@@ -2796,16 +2793,18 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
* {@link #onEvaluateInputViewShown()}, {@link #onEvaluateFullscreenMode()},
|
||||
* and the current configuration to decide whether the input view should
|
||||
* be shown at this point.
|
||||
*
|
||||
*
|
||||
* @param flags Provides additional information about the show request,
|
||||
* as per {@link InputMethod#showSoftInput InputMethod.showSoftInput()}.
|
||||
* @param configChange This is true if we are re-showing due to a
|
||||
* configuration change.
|
||||
* @return Returns true to indicate that the window should be shown.
|
||||
*/
|
||||
public boolean onShowInputRequested(@InputMethod.ShowFlags int flags, boolean configChange) {
|
||||
public boolean onShowInputRequested(int flags, boolean configChange) {
|
||||
if (!onEvaluateInputViewShown()) {
|
||||
return false;
|
||||
}
|
||||
if ((flags & InputMethod.SHOW_EXPLICIT) == 0) {
|
||||
if ((flags&InputMethod.SHOW_EXPLICIT) == 0) {
|
||||
if (!configChange && onEvaluateFullscreenMode() && !isInputViewShown()) {
|
||||
// Don't show if this is not explicitly requested by the user and
|
||||
// the input method is fullscreen unless it is already shown. That
|
||||
@@ -2831,14 +2830,14 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
* exposed to IME authors as an overridable public method without {@code @CallSuper}, we have
|
||||
* to have this method to ensure that those internal states are always updated no matter how
|
||||
* {@link #onShowInputRequested(int, boolean)} is overridden by the IME author.
|
||||
*
|
||||
* @param flags Provides additional information about the show request,
|
||||
* as per {@link InputMethod#showSoftInput InputMethod.showSoftInput()}.
|
||||
* @param configChange This is true if we are re-showing due to a
|
||||
* configuration change.
|
||||
* @return Returns true to indicate that the window should be shown.
|
||||
* @see #onShowInputRequested(int, boolean)
|
||||
*/
|
||||
private boolean dispatchOnShowInputRequested(@InputMethod.ShowFlags int flags,
|
||||
boolean configChange) {
|
||||
private boolean dispatchOnShowInputRequested(int flags, boolean configChange) {
|
||||
final boolean result = onShowInputRequested(flags, configChange);
|
||||
mInlineSuggestionSessionController.notifyOnShowInputRequested(result);
|
||||
if (result) {
|
||||
@@ -3271,13 +3270,16 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
*
|
||||
* The input method will continue running, but the user can no longer use it to generate input
|
||||
* by touching the screen.
|
||||
*
|
||||
* @see InputMethodManager#HIDE_IMPLICIT_ONLY
|
||||
* @see InputMethodManager#HIDE_NOT_ALWAYS
|
||||
* @param flags Provides additional operating flags.
|
||||
*/
|
||||
public void requestHideSelf(@InputMethodManager.HideFlags int flags) {
|
||||
public void requestHideSelf(int flags) {
|
||||
requestHideSelf(flags, SoftInputShowHideReason.HIDE_SOFT_INPUT_FROM_IME);
|
||||
}
|
||||
|
||||
private void requestHideSelf(@InputMethodManager.HideFlags int flags,
|
||||
@SoftInputShowHideReason int reason) {
|
||||
private void requestHideSelf(int flags, @SoftInputShowHideReason int reason) {
|
||||
ImeTracing.getInstance().triggerServiceDump("InputMethodService#requestHideSelf", mDumper,
|
||||
null /* icProto */);
|
||||
mPrivOps.hideMySoftInput(flags, reason);
|
||||
@@ -3286,8 +3288,12 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
/**
|
||||
* Show the input method's soft input area, so the user sees the input method window and can
|
||||
* interact with it.
|
||||
*
|
||||
* @see InputMethodManager#SHOW_IMPLICIT
|
||||
* @see InputMethodManager#SHOW_FORCED
|
||||
* @param flags Provides additional operating flags.
|
||||
*/
|
||||
public final void requestShowSelf(@InputMethodManager.ShowFlags int flags) {
|
||||
public final void requestShowSelf(int flags) {
|
||||
ImeTracing.getInstance().triggerServiceDump("InputMethodService#requestShowSelf", mDumper,
|
||||
null /* icProto */);
|
||||
mPrivOps.showMySoftInput(flags);
|
||||
@@ -3447,8 +3453,7 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
/**
|
||||
* Handle a request by the system to toggle the soft input area.
|
||||
*/
|
||||
private void onToggleSoftInput(@InputMethodManager.ShowFlags int showFlags,
|
||||
@InputMethodManager.HideFlags int hideFlags) {
|
||||
private void onToggleSoftInput(int showFlags, int hideFlags) {
|
||||
if (DEBUG) Log.v(TAG, "toggleSoftInput()");
|
||||
if (isInputViewShown()) {
|
||||
requestHideSelf(
|
||||
|
||||
@@ -295,8 +295,8 @@ final class IInputMethodManagerGlobalInvoker {
|
||||
|
||||
@AnyThread
|
||||
static boolean showSoftInput(@NonNull IInputMethodClient client, @Nullable IBinder windowToken,
|
||||
@Nullable ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
|
||||
int lastClickToolType, @Nullable ResultReceiver resultReceiver,
|
||||
@Nullable ImeTracker.Token statsToken, int flags, int lastClickToolType,
|
||||
@Nullable ResultReceiver resultReceiver,
|
||||
@SoftInputShowHideReason int reason) {
|
||||
final IInputMethodManager service = getService();
|
||||
if (service == null) {
|
||||
@@ -312,7 +312,7 @@ final class IInputMethodManagerGlobalInvoker {
|
||||
|
||||
@AnyThread
|
||||
static boolean hideSoftInput(@NonNull IInputMethodClient client, @Nullable IBinder windowToken,
|
||||
@Nullable ImeTracker.Token statsToken, @InputMethodManager.HideFlags int flags,
|
||||
@Nullable ImeTracker.Token statsToken, int flags,
|
||||
@Nullable ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
|
||||
final IInputMethodManager service = getService();
|
||||
if (service == null) {
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package android.view.inputmethod;
|
||||
|
||||
import android.annotation.DurationMillisLong;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.MainThread;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
@@ -37,8 +36,6 @@ import com.android.internal.inputmethod.IInputMethod;
|
||||
import com.android.internal.inputmethod.InlineSuggestionsRequestInfo;
|
||||
import com.android.internal.inputmethod.InputMethodNavButtonFlags;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -272,14 +269,6 @@ public interface InputMethod {
|
||||
*/
|
||||
@MainThread
|
||||
public void revokeSession(InputMethodSession session);
|
||||
|
||||
/** @hide */
|
||||
@IntDef(flag = true, prefix = { "SHOW_" }, value = {
|
||||
SHOW_EXPLICIT,
|
||||
SHOW_FORCED,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@interface ShowFlags {}
|
||||
|
||||
/**
|
||||
* Flag for {@link #showSoftInput}: this show has been explicitly
|
||||
@@ -299,6 +288,8 @@ public interface InputMethod {
|
||||
/**
|
||||
* Request that any soft input part of the input method be shown to the user.
|
||||
*
|
||||
* @param flags Provides additional information about the show request.
|
||||
* Currently may be 0 or have the bit {@link #SHOW_EXPLICIT} set.
|
||||
* @param resultReceiver The client requesting the show may wish to
|
||||
* be told the impact of their request, which should be supplied here.
|
||||
* The result code should be
|
||||
@@ -313,7 +304,7 @@ public interface InputMethod {
|
||||
* @hide
|
||||
*/
|
||||
@MainThread
|
||||
public default void showSoftInputWithToken(@ShowFlags int flags, ResultReceiver resultReceiver,
|
||||
public default void showSoftInputWithToken(int flags, ResultReceiver resultReceiver,
|
||||
IBinder showInputToken, @Nullable ImeTracker.Token statsToken) {
|
||||
showSoftInput(flags, resultReceiver);
|
||||
}
|
||||
@@ -321,6 +312,8 @@ public interface InputMethod {
|
||||
/**
|
||||
* Request that any soft input part of the input method be shown to the user.
|
||||
*
|
||||
* @param flags Provides additional information about the show request.
|
||||
* Currently may be 0 or have the bit {@link #SHOW_EXPLICIT} set.
|
||||
* @param resultReceiver The client requesting the show may wish to
|
||||
* be told the impact of their request, which should be supplied here.
|
||||
* The result code should be
|
||||
@@ -330,12 +323,11 @@ public interface InputMethod {
|
||||
* {@link InputMethodManager#RESULT_HIDDEN InputMethodManager.RESULT_HIDDEN}.
|
||||
*/
|
||||
@MainThread
|
||||
public void showSoftInput(@ShowFlags int flags, ResultReceiver resultReceiver);
|
||||
public void showSoftInput(int flags, ResultReceiver resultReceiver);
|
||||
|
||||
/**
|
||||
* Request that any soft input part of the input method be hidden from the user.
|
||||
*
|
||||
* @param flags Provides additional information about the hide request.
|
||||
* @param flags Provides additional information about the show request.
|
||||
* Currently always 0.
|
||||
* @param resultReceiver The client requesting the show may wish to
|
||||
* be told the impact of their request, which should be supplied here.
|
||||
@@ -358,8 +350,7 @@ public interface InputMethod {
|
||||
|
||||
/**
|
||||
* Request that any soft input part of the input method be hidden from the user.
|
||||
*
|
||||
* @param flags Provides additional information about the hide request.
|
||||
* @param flags Provides additional information about the show request.
|
||||
* Currently always 0.
|
||||
* @param resultReceiver The client requesting the show may wish to
|
||||
* be told the impact of their request, which should be supplied here.
|
||||
|
||||
@@ -39,7 +39,6 @@ import android.Manifest;
|
||||
import android.annotation.DisplayContext;
|
||||
import android.annotation.DrawableRes;
|
||||
import android.annotation.DurationMillisLong;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.RequiresFeature;
|
||||
@@ -122,8 +121,6 @@ import com.android.internal.view.IInputMethodManager;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -2007,14 +2004,6 @@ public final class InputMethodManager {
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@IntDef(flag = true, prefix = { "SHOW_" }, value = {
|
||||
SHOW_IMPLICIT,
|
||||
SHOW_FORCED,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface ShowFlags {}
|
||||
|
||||
/**
|
||||
* Flag for {@link #showSoftInput} to indicate that this is an implicit
|
||||
* request to show the input window, not as the result of a direct request
|
||||
@@ -2046,8 +2035,10 @@ public final class InputMethodManager {
|
||||
* {@link View#isFocused view focus}, and its containing window has
|
||||
* {@link View#hasWindowFocus window focus}. Otherwise the call fails and
|
||||
* returns {@code false}.
|
||||
* @param flags Provides additional operating flags. Currently may be
|
||||
* 0 or have the {@link #SHOW_IMPLICIT} bit set.
|
||||
*/
|
||||
public boolean showSoftInput(View view, @ShowFlags int flags) {
|
||||
public boolean showSoftInput(View view, int flags) {
|
||||
// Re-dispatch if there is a context mismatch.
|
||||
final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
|
||||
if (fallbackImm != null) {
|
||||
@@ -2110,20 +2101,21 @@ public final class InputMethodManager {
|
||||
* {@link View#isFocused view focus}, and its containing window has
|
||||
* {@link View#hasWindowFocus window focus}. Otherwise the call fails and
|
||||
* returns {@code false}.
|
||||
* @param flags Provides additional operating flags. Currently may be
|
||||
* 0 or have the {@link #SHOW_IMPLICIT} bit set.
|
||||
* @param resultReceiver If non-null, this will be called by the IME when
|
||||
* it has processed your request to tell you what it has done. The result
|
||||
* code you receive may be either {@link #RESULT_UNCHANGED_SHOWN},
|
||||
* {@link #RESULT_UNCHANGED_HIDDEN}, {@link #RESULT_SHOWN}, or
|
||||
* {@link #RESULT_HIDDEN}.
|
||||
*/
|
||||
public boolean showSoftInput(View view, @ShowFlags int flags, ResultReceiver resultReceiver) {
|
||||
public boolean showSoftInput(View view, int flags, ResultReceiver resultReceiver) {
|
||||
return showSoftInput(view, null /* statsToken */, flags, resultReceiver,
|
||||
SoftInputShowHideReason.SHOW_SOFT_INPUT);
|
||||
}
|
||||
|
||||
private boolean showSoftInput(View view, @Nullable ImeTracker.Token statsToken,
|
||||
@ShowFlags int flags, ResultReceiver resultReceiver,
|
||||
@SoftInputShowHideReason int reason) {
|
||||
private boolean showSoftInput(View view, @Nullable ImeTracker.Token statsToken, int flags,
|
||||
ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
|
||||
if (statsToken == null) {
|
||||
statsToken = ImeTracker.forLogging().onRequestShow(null /* component */,
|
||||
Process.myUid(), ImeTracker.ORIGIN_CLIENT_SHOW_SOFT_INPUT, reason);
|
||||
@@ -2177,7 +2169,7 @@ public final class InputMethodManager {
|
||||
*/
|
||||
@Deprecated
|
||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768499)
|
||||
public void showSoftInputUnchecked(@ShowFlags int flags, ResultReceiver resultReceiver) {
|
||||
public void showSoftInputUnchecked(int flags, ResultReceiver resultReceiver) {
|
||||
synchronized (mH) {
|
||||
final ImeTracker.Token statsToken = ImeTracker.forLogging().onRequestShow(
|
||||
null /* component */, Process.myUid(), ImeTracker.ORIGIN_CLIENT_SHOW_SOFT_INPUT,
|
||||
@@ -2208,14 +2200,6 @@ public final class InputMethodManager {
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@IntDef(flag = true, prefix = { "HIDE_" }, value = {
|
||||
HIDE_IMPLICIT_ONLY,
|
||||
HIDE_NOT_ALWAYS,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface HideFlags {}
|
||||
|
||||
/**
|
||||
* Flag for {@link #hideSoftInputFromWindow} and {@link InputMethodService#requestHideSelf(int)}
|
||||
* to indicate that the soft input window should only be hidden if it was not explicitly shown
|
||||
@@ -2237,8 +2221,10 @@ public final class InputMethodManager {
|
||||
*
|
||||
* @param windowToken The token of the window that is making the request,
|
||||
* as returned by {@link View#getWindowToken() View.getWindowToken()}.
|
||||
* @param flags Provides additional operating flags. Currently may be
|
||||
* 0 or have the {@link #HIDE_IMPLICIT_ONLY} bit set.
|
||||
*/
|
||||
public boolean hideSoftInputFromWindow(IBinder windowToken, @HideFlags int flags) {
|
||||
public boolean hideSoftInputFromWindow(IBinder windowToken, int flags) {
|
||||
return hideSoftInputFromWindow(windowToken, flags, null);
|
||||
}
|
||||
|
||||
@@ -2260,19 +2246,21 @@ public final class InputMethodManager {
|
||||
*
|
||||
* @param windowToken The token of the window that is making the request,
|
||||
* as returned by {@link View#getWindowToken() View.getWindowToken()}.
|
||||
* @param flags Provides additional operating flags. Currently may be
|
||||
* 0 or have the {@link #HIDE_IMPLICIT_ONLY} bit set.
|
||||
* @param resultReceiver If non-null, this will be called by the IME when
|
||||
* it has processed your request to tell you what it has done. The result
|
||||
* code you receive may be either {@link #RESULT_UNCHANGED_SHOWN},
|
||||
* {@link #RESULT_UNCHANGED_HIDDEN}, {@link #RESULT_SHOWN}, or
|
||||
* {@link #RESULT_HIDDEN}.
|
||||
*/
|
||||
public boolean hideSoftInputFromWindow(IBinder windowToken, @HideFlags int flags,
|
||||
public boolean hideSoftInputFromWindow(IBinder windowToken, int flags,
|
||||
ResultReceiver resultReceiver) {
|
||||
return hideSoftInputFromWindow(windowToken, flags, resultReceiver,
|
||||
SoftInputShowHideReason.HIDE_SOFT_INPUT);
|
||||
}
|
||||
|
||||
private boolean hideSoftInputFromWindow(IBinder windowToken, @HideFlags int flags,
|
||||
private boolean hideSoftInputFromWindow(IBinder windowToken, int flags,
|
||||
ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
|
||||
final ImeTracker.Token statsToken = ImeTracker.forLogging().onRequestHide(
|
||||
null /* component */, Process.myUid(),
|
||||
@@ -2475,6 +2463,12 @@ public final class InputMethodManager {
|
||||
* If not the input window will be displayed.
|
||||
* @param windowToken The token of the window that is making the request,
|
||||
* as returned by {@link View#getWindowToken() View.getWindowToken()}.
|
||||
* @param showFlags Provides additional operating flags. May be
|
||||
* 0 or have the {@link #SHOW_IMPLICIT},
|
||||
* {@link #SHOW_FORCED} bit set.
|
||||
* @param hideFlags Provides additional operating flags. May be
|
||||
* 0 or have the {@link #HIDE_IMPLICIT_ONLY},
|
||||
* {@link #HIDE_NOT_ALWAYS} bit set.
|
||||
*
|
||||
* @deprecated Use {@link #showSoftInput(View, int)} or
|
||||
* {@link #hideSoftInputFromWindow(IBinder, int)} explicitly instead.
|
||||
@@ -2483,8 +2477,7 @@ public final class InputMethodManager {
|
||||
* has an effect if the calling app is the current IME focus.
|
||||
*/
|
||||
@Deprecated
|
||||
public void toggleSoftInputFromWindow(IBinder windowToken, @ShowFlags int showFlags,
|
||||
@HideFlags int hideFlags) {
|
||||
public void toggleSoftInputFromWindow(IBinder windowToken, int showFlags, int hideFlags) {
|
||||
ImeTracing.getInstance().triggerClientDump(
|
||||
"InputMethodManager#toggleSoftInputFromWindow", InputMethodManager.this,
|
||||
null /* icProto */);
|
||||
@@ -2502,6 +2495,12 @@ public final class InputMethodManager {
|
||||
*
|
||||
* If the input window is already displayed, it gets hidden.
|
||||
* If not the input window will be displayed.
|
||||
* @param showFlags Provides additional operating flags. May be
|
||||
* 0 or have the {@link #SHOW_IMPLICIT},
|
||||
* {@link #SHOW_FORCED} bit set.
|
||||
* @param hideFlags Provides additional operating flags. May be
|
||||
* 0 or have the {@link #HIDE_IMPLICIT_ONLY},
|
||||
* {@link #HIDE_NOT_ALWAYS} bit set.
|
||||
*
|
||||
* @deprecated Use {@link #showSoftInput(View, int)} or
|
||||
* {@link #hideSoftInputFromWindow(IBinder, int)} explicitly instead.
|
||||
@@ -2510,7 +2509,7 @@ public final class InputMethodManager {
|
||||
* has an effect if the calling app is the current IME focus.
|
||||
*/
|
||||
@Deprecated
|
||||
public void toggleSoftInput(@ShowFlags int showFlags, @HideFlags int hideFlags) {
|
||||
public void toggleSoftInput(int showFlags, int hideFlags) {
|
||||
ImeTracing.getInstance().triggerClientDump(
|
||||
"InputMethodManager#toggleSoftInput", InputMethodManager.this,
|
||||
null /* icProto */);
|
||||
@@ -3523,12 +3522,15 @@ public final class InputMethodManager {
|
||||
* @param token Supplies the identifying token given to an input method
|
||||
* when it was started, which allows it to perform this operation on
|
||||
* itself.
|
||||
* @param flags Provides additional operating flags. Currently may be
|
||||
* 0 or have the {@link #HIDE_IMPLICIT_ONLY},
|
||||
* {@link #HIDE_NOT_ALWAYS} bit set.
|
||||
* @deprecated Use {@link InputMethodService#requestHideSelf(int)} instead. This method was
|
||||
* intended for IME developers who should be accessing APIs through the service. APIs in this
|
||||
* class are intended for app developers interacting with the IME.
|
||||
*/
|
||||
@Deprecated
|
||||
public void hideSoftInputFromInputMethod(IBinder token, @HideFlags int flags) {
|
||||
public void hideSoftInputFromInputMethod(IBinder token, int flags) {
|
||||
InputMethodPrivilegedOperationsRegistry.get(token).hideMySoftInput(
|
||||
flags, SoftInputShowHideReason.HIDE_SOFT_INPUT_IMM_DEPRECATION);
|
||||
}
|
||||
@@ -3542,12 +3544,15 @@ public final class InputMethodManager {
|
||||
* @param token Supplies the identifying token given to an input method
|
||||
* when it was started, which allows it to perform this operation on
|
||||
* itself.
|
||||
* @param flags Provides additional operating flags. Currently may be
|
||||
* 0 or have the {@link #SHOW_IMPLICIT} or
|
||||
* {@link #SHOW_FORCED} bit set.
|
||||
* @deprecated Use {@link InputMethodService#requestShowSelf(int)} instead. This method was
|
||||
* intended for IME developers who should be accessing APIs through the service. APIs in this
|
||||
* class are intended for app developers interacting with the IME.
|
||||
*/
|
||||
@Deprecated
|
||||
public void showSoftInputFromInputMethod(IBinder token, @ShowFlags int flags) {
|
||||
public void showSoftInputFromInputMethod(IBinder token, int flags) {
|
||||
InputMethodPrivilegedOperationsRegistry.get(token).showMySoftInput(flags);
|
||||
}
|
||||
|
||||
|
||||
@@ -169,6 +169,12 @@ public interface InputMethodSession {
|
||||
/**
|
||||
* Toggle the soft input window.
|
||||
* Applications can toggle the state of the soft input window.
|
||||
* @param showFlags Provides additional operating flags. May be
|
||||
* 0 or have the {@link InputMethodManager#SHOW_IMPLICIT},
|
||||
* {@link InputMethodManager#SHOW_FORCED} bit set.
|
||||
* @param hideFlags Provides additional operating flags. May be
|
||||
* 0 or have the {@link InputMethodManager#HIDE_IMPLICIT_ONLY},
|
||||
* {@link InputMethodManager#HIDE_NOT_ALWAYS} bit set.
|
||||
*
|
||||
* @deprecated Starting in {@link android.os.Build.VERSION_CODES#S} the system no longer invokes
|
||||
* this method, instead it explicitly shows or hides the IME. An {@code InputMethodService}
|
||||
@@ -176,8 +182,7 @@ public interface InputMethodSession {
|
||||
* InputMethodService#requestShowSelf} or {@link InputMethodService#requestHideSelf}
|
||||
*/
|
||||
@Deprecated
|
||||
public void toggleSoftInput(@InputMethodManager.ShowFlags int showFlags,
|
||||
@InputMethodManager.HideFlags int hideFlags);
|
||||
public void toggleSoftInput(int showFlags, int hideFlags);
|
||||
|
||||
/**
|
||||
* This method is called when the cursor and/or the character position relevant to text input
|
||||
|
||||
@@ -26,7 +26,6 @@ import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.ImeTracker;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
@@ -254,11 +253,13 @@ public final class InputMethodPrivilegedOperations {
|
||||
/**
|
||||
* Calls {@link IInputMethodPrivilegedOperations#hideMySoftInput(int, int, AndroidFuture)}
|
||||
*
|
||||
* @param flags additional operating flags
|
||||
* @param reason the reason to hide soft input
|
||||
* @see android.view.inputmethod.InputMethodManager#HIDE_IMPLICIT_ONLY
|
||||
* @see android.view.inputmethod.InputMethodManager#HIDE_NOT_ALWAYS
|
||||
*/
|
||||
@AnyThread
|
||||
public void hideMySoftInput(@InputMethodManager.HideFlags int flags,
|
||||
@SoftInputShowHideReason int reason) {
|
||||
public void hideMySoftInput(int flags, @SoftInputShowHideReason int reason) {
|
||||
final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
|
||||
if (ops == null) {
|
||||
return;
|
||||
@@ -274,9 +275,13 @@ public final class InputMethodPrivilegedOperations {
|
||||
|
||||
/**
|
||||
* Calls {@link IInputMethodPrivilegedOperations#showMySoftInput(int, AndroidFuture)}
|
||||
*
|
||||
* @param flags additional operating flags
|
||||
* @see android.view.inputmethod.InputMethodManager#SHOW_IMPLICIT
|
||||
* @see android.view.inputmethod.InputMethodManager#SHOW_FORCED
|
||||
*/
|
||||
@AnyThread
|
||||
public void showMySoftInput(@InputMethodManager.ShowFlags int flags) {
|
||||
public void showMySoftInput(int flags) {
|
||||
final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
|
||||
if (ops == null) {
|
||||
return;
|
||||
|
||||
@@ -37,7 +37,6 @@ import android.os.ResultReceiver;
|
||||
import android.util.EventLog;
|
||||
import android.util.Slog;
|
||||
import android.view.inputmethod.ImeTracker;
|
||||
import android.view.inputmethod.InputMethod;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
@@ -76,8 +75,7 @@ final class DefaultImeVisibilityApplier implements ImeVisibilityApplier {
|
||||
@GuardedBy("ImfLock.class")
|
||||
@Override
|
||||
public void performShowIme(IBinder showInputToken, @Nullable ImeTracker.Token statsToken,
|
||||
@InputMethod.ShowFlags int showFlags, ResultReceiver resultReceiver,
|
||||
@SoftInputShowHideReason int reason) {
|
||||
int showFlags, ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
|
||||
final IInputMethodInvoker curMethod = mService.getCurMethodLocked();
|
||||
if (curMethod != null) {
|
||||
if (DEBUG) {
|
||||
|
||||
@@ -30,7 +30,6 @@ import android.view.MotionEvent;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.ImeTracker;
|
||||
import android.view.inputmethod.InputBinding;
|
||||
import android.view.inputmethod.InputMethod;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
import android.window.ImeOnBackInvokedDispatcher;
|
||||
|
||||
@@ -199,8 +198,8 @@ final class IInputMethodInvoker {
|
||||
|
||||
// TODO(b/192412909): Convert this back to void method
|
||||
@AnyThread
|
||||
boolean showSoftInput(IBinder showInputToken, @Nullable ImeTracker.Token statsToken,
|
||||
@InputMethod.ShowFlags int flags, ResultReceiver resultReceiver) {
|
||||
boolean showSoftInput(IBinder showInputToken, @Nullable ImeTracker.Token statsToken, int flags,
|
||||
ResultReceiver resultReceiver) {
|
||||
try {
|
||||
mTarget.showSoftInput(showInputToken, statsToken, flags, resultReceiver);
|
||||
} catch (RemoteException e) {
|
||||
|
||||
@@ -21,7 +21,6 @@ import android.annotation.Nullable;
|
||||
import android.os.IBinder;
|
||||
import android.os.ResultReceiver;
|
||||
import android.view.inputmethod.ImeTracker;
|
||||
import android.view.inputmethod.InputMethod;
|
||||
|
||||
import com.android.internal.inputmethod.SoftInputShowHideReason;
|
||||
|
||||
@@ -35,13 +34,13 @@ interface ImeVisibilityApplier {
|
||||
*
|
||||
* @param showInputToken A token that represents the requester to show IME.
|
||||
* @param statsToken A token that tracks the progress of an IME request.
|
||||
* @param showFlags Provides additional operating flags to show IME.
|
||||
* @param resultReceiver If non-null, this will be called back to the caller when
|
||||
* it has processed request to tell what it has done.
|
||||
* @param reason The reason for requesting to show IME.
|
||||
*/
|
||||
default void performShowIme(IBinder showInputToken, @Nullable ImeTracker.Token statsToken,
|
||||
@InputMethod.ShowFlags int showFlags, ResultReceiver resultReceiver,
|
||||
@SoftInputShowHideReason int reason) {}
|
||||
int showFlags, ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {}
|
||||
|
||||
/**
|
||||
* Performs hiding IME to the given window
|
||||
|
||||
@@ -221,21 +221,17 @@ public final class ImeVisibilityStateComputer {
|
||||
|
||||
/**
|
||||
* Called when {@link InputMethodManagerService} is processing the show IME request.
|
||||
*
|
||||
* @param statsToken The token for tracking this show request.
|
||||
* @return {@code true} when the show request can proceed.
|
||||
* @param statsToken The token for tracking this show request
|
||||
* @param showFlags The additional operation flags to indicate whether this show request mode is
|
||||
* implicit or explicit.
|
||||
* @return {@code true} when the computer has proceed this show request operation.
|
||||
*/
|
||||
boolean onImeShowFlags(@NonNull ImeTracker.Token statsToken,
|
||||
@InputMethodManager.ShowFlags int showFlags) {
|
||||
boolean onImeShowFlags(@NonNull ImeTracker.Token statsToken, int showFlags) {
|
||||
if (mPolicy.mA11yRequestingNoSoftKeyboard || mPolicy.mImeHiddenByDisplayPolicy) {
|
||||
ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_SERVER_ACCESSIBILITY);
|
||||
return false;
|
||||
}
|
||||
ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_ACCESSIBILITY);
|
||||
// We only "set" the state corresponding to the flags, as this will be reset
|
||||
// in clearImeShowFlags during a hide request.
|
||||
// Thus, we keep the strongest values set (e.g. an implicit show right after
|
||||
// an explicit show will still be considered explicit, likewise for forced).
|
||||
if ((showFlags & InputMethodManager.SHOW_FORCED) != 0) {
|
||||
mRequestedShowExplicitly = true;
|
||||
mShowForced = true;
|
||||
@@ -247,12 +243,12 @@ public final class ImeVisibilityStateComputer {
|
||||
|
||||
/**
|
||||
* Called when {@link InputMethodManagerService} is processing the hide IME request.
|
||||
*
|
||||
* @param statsToken The token for tracking this hide request.
|
||||
* @return {@code true} when the hide request can proceed.
|
||||
* @param statsToken The token for tracking this hide request
|
||||
* @param hideFlags The additional operation flags to indicate whether this hide request mode is
|
||||
* implicit or explicit.
|
||||
* @return {@code true} when the computer has proceed this hide request operations.
|
||||
*/
|
||||
boolean canHideIme(@NonNull ImeTracker.Token statsToken,
|
||||
@InputMethodManager.HideFlags int hideFlags) {
|
||||
boolean canHideIme(@NonNull ImeTracker.Token statsToken, int hideFlags) {
|
||||
if ((hideFlags & InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
|
||||
&& (mRequestedShowExplicitly || mShowForced)) {
|
||||
if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide");
|
||||
@@ -268,31 +264,13 @@ public final class ImeVisibilityStateComputer {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the show flags for IME. This translates from {@link InputMethodManager.ShowFlags}
|
||||
* to {@link InputMethod.ShowFlags}.
|
||||
*/
|
||||
@InputMethod.ShowFlags
|
||||
int getShowFlagsForInputMethodServiceOnly() {
|
||||
int getImeShowFlags() {
|
||||
int flags = 0;
|
||||
if (mShowForced) {
|
||||
flags |= InputMethod.SHOW_FORCED | InputMethod.SHOW_EXPLICIT;
|
||||
} else if (mRequestedShowExplicitly) {
|
||||
flags |= InputMethod.SHOW_EXPLICIT;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the show flags for IMM. This translates from {@link InputMethod.ShowFlags}
|
||||
* to {@link InputMethodManager.ShowFlags}.
|
||||
*/
|
||||
@InputMethodManager.ShowFlags
|
||||
int getShowFlags() {
|
||||
int flags = 0;
|
||||
if (mShowForced) {
|
||||
flags |= InputMethodManager.SHOW_FORCED;
|
||||
} else if (!mRequestedShowExplicitly) {
|
||||
} else {
|
||||
flags |= InputMethodManager.SHOW_IMPLICIT;
|
||||
}
|
||||
return flags;
|
||||
|
||||
@@ -2462,7 +2462,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
final ImeTracker.Token statsToken = mCurStatsToken;
|
||||
mCurStatsToken = null;
|
||||
showCurrentInputLocked(mCurFocusedWindow, statsToken,
|
||||
mVisibilityStateComputer.getShowFlags(),
|
||||
mVisibilityStateComputer.getImeShowFlags(),
|
||||
null /* resultReceiver */, SoftInputShowHideReason.ATTACH_NEW_INPUT);
|
||||
}
|
||||
|
||||
@@ -3398,9 +3398,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
|
||||
@Override
|
||||
public boolean showSoftInput(IInputMethodClient client, IBinder windowToken,
|
||||
@Nullable ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
|
||||
int lastClickTooType, ResultReceiver resultReceiver,
|
||||
@SoftInputShowHideReason int reason) {
|
||||
@Nullable ImeTracker.Token statsToken, int flags, int lastClickTooType,
|
||||
ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
|
||||
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.showSoftInput");
|
||||
int uid = Binder.getCallingUid();
|
||||
ImeTracing.getInstance().triggerManagerServiceDump(
|
||||
@@ -3573,17 +3572,15 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
|
||||
@GuardedBy("ImfLock.class")
|
||||
boolean showCurrentInputLocked(IBinder windowToken, @Nullable ImeTracker.Token statsToken,
|
||||
@InputMethodManager.ShowFlags int flags, ResultReceiver resultReceiver,
|
||||
@SoftInputShowHideReason int reason) {
|
||||
int flags, ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
|
||||
return showCurrentInputLocked(windowToken, statsToken, flags,
|
||||
MotionEvent.TOOL_TYPE_UNKNOWN, resultReceiver, reason);
|
||||
}
|
||||
|
||||
@GuardedBy("ImfLock.class")
|
||||
private boolean showCurrentInputLocked(IBinder windowToken,
|
||||
@Nullable ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
|
||||
int lastClickToolType, ResultReceiver resultReceiver,
|
||||
@SoftInputShowHideReason int reason) {
|
||||
@Nullable ImeTracker.Token statsToken, int flags, int lastClickToolType,
|
||||
ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
|
||||
// Create statsToken is none exists.
|
||||
if (statsToken == null) {
|
||||
statsToken = createStatsTokenForFocusedClient(true /* show */,
|
||||
@@ -3614,8 +3611,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
curMethod.updateEditorToolType(lastClickToolType);
|
||||
}
|
||||
mVisibilityApplier.performShowIme(windowToken, statsToken,
|
||||
mVisibilityStateComputer.getShowFlagsForInputMethodServiceOnly(),
|
||||
resultReceiver, reason);
|
||||
mVisibilityStateComputer.getImeShowFlags(), resultReceiver, reason);
|
||||
mVisibilityStateComputer.setInputShown(true);
|
||||
return true;
|
||||
} else {
|
||||
@@ -3627,8 +3623,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
|
||||
@Override
|
||||
public boolean hideSoftInput(IInputMethodClient client, IBinder windowToken,
|
||||
@Nullable ImeTracker.Token statsToken, @InputMethodManager.HideFlags int flags,
|
||||
ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
|
||||
@Nullable ImeTracker.Token statsToken, int flags, ResultReceiver resultReceiver,
|
||||
@SoftInputShowHideReason int reason) {
|
||||
int uid = Binder.getCallingUid();
|
||||
ImeTracing.getInstance().triggerManagerServiceDump(
|
||||
"InputMethodManagerService#hideSoftInput");
|
||||
@@ -3658,8 +3654,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
|
||||
@GuardedBy("ImfLock.class")
|
||||
boolean hideCurrentInputLocked(IBinder windowToken, @Nullable ImeTracker.Token statsToken,
|
||||
@InputMethodManager.HideFlags int flags, ResultReceiver resultReceiver,
|
||||
@SoftInputShowHideReason int reason) {
|
||||
int flags, ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
|
||||
// Create statsToken is none exists.
|
||||
if (statsToken == null) {
|
||||
statsToken = createStatsTokenForFocusedClient(false /* show */,
|
||||
@@ -4846,7 +4841,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
}
|
||||
|
||||
@BinderThread
|
||||
private void hideMySoftInput(@NonNull IBinder token, @InputMethodManager.HideFlags int flags,
|
||||
private void hideMySoftInput(@NonNull IBinder token, int flags,
|
||||
@SoftInputShowHideReason int reason) {
|
||||
try {
|
||||
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.hideMySoftInput");
|
||||
@@ -4868,7 +4863,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
}
|
||||
|
||||
@BinderThread
|
||||
private void showMySoftInput(@NonNull IBinder token, @InputMethodManager.ShowFlags int flags) {
|
||||
private void showMySoftInput(@NonNull IBinder token, int flags) {
|
||||
try {
|
||||
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.showMySoftInput");
|
||||
synchronized (ImfLock.class) {
|
||||
@@ -6827,8 +6822,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
|
||||
@BinderThread
|
||||
@Override
|
||||
public void hideMySoftInput(@InputMethodManager.HideFlags int flags,
|
||||
@SoftInputShowHideReason int reason, AndroidFuture future /* T=Void */) {
|
||||
public void hideMySoftInput(int flags, @SoftInputShowHideReason int reason,
|
||||
AndroidFuture future /* T=Void */) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final AndroidFuture<Void> typedFuture = future;
|
||||
try {
|
||||
@@ -6841,8 +6836,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
|
||||
@BinderThread
|
||||
@Override
|
||||
public void showMySoftInput(@InputMethodManager.ShowFlags int flags,
|
||||
AndroidFuture future /* T=Void */) {
|
||||
public void showMySoftInput(int flags, AndroidFuture future /* T=Void */) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final AndroidFuture<Void> typedFuture = future;
|
||||
try {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.frameworks.inputmethodtests">
|
||||
|
||||
<uses-sdk android:targetSdkVersion="31" />
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.view.InputMethod" />
|
||||
|
||||
@@ -9,16 +9,5 @@
|
||||
{"exclude-annotation": "org.junit.Ignore"}
|
||||
]
|
||||
}
|
||||
],
|
||||
"postsubmit": [
|
||||
{
|
||||
"name": "FrameworksImeTests",
|
||||
"options": [
|
||||
{"include-filter": "com.android.inputmethodservice"},
|
||||
{"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
|
||||
{"exclude-annotation": "androidx.test.filters.FlakyTest"},
|
||||
{"exclude-annotation": "org.junit.Ignore"}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.inputmethod.imetests">
|
||||
|
||||
<uses-sdk android:targetSdkVersion="31" />
|
||||
|
||||
<!-- Permissions required for granting and logging -->
|
||||
<uses-permission android:name="android.permission.LOG_COMPAT_CHANGE"/>
|
||||
<uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"/>
|
||||
|
||||
@@ -20,8 +20,6 @@ import static com.android.compatibility.common.util.SystemUtil.eventually;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
@@ -47,7 +45,6 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -59,9 +56,9 @@ public class InputMethodServiceTest {
|
||||
private static final String EDIT_TEXT_DESC = "Input box";
|
||||
private static final long TIMEOUT_IN_SECONDS = 3;
|
||||
private static final String ENABLE_SHOW_IME_WITH_HARD_KEYBOARD_CMD =
|
||||
"settings put secure " + Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD + " 1";
|
||||
"settings put secure show_ime_with_hard_keyboard 1";
|
||||
private static final String DISABLE_SHOW_IME_WITH_HARD_KEYBOARD_CMD =
|
||||
"settings put secure " + Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD + " 0";
|
||||
"settings put secure show_ime_with_hard_keyboard 0";
|
||||
|
||||
private Instrumentation mInstrumentation;
|
||||
private UiDevice mUiDevice;
|
||||
@@ -85,19 +82,29 @@ public class InputMethodServiceTest {
|
||||
mUiDevice.freezeRotation();
|
||||
mUiDevice.setOrientationNatural();
|
||||
// Waits for input binding ready.
|
||||
eventually(() -> {
|
||||
mInputMethodService =
|
||||
InputMethodServiceWrapper.getInputMethodServiceWrapperForTesting();
|
||||
assertThat(mInputMethodService).isNotNull();
|
||||
eventually(
|
||||
() -> {
|
||||
mInputMethodService =
|
||||
InputMethodServiceWrapper.getInputMethodServiceWrapperForTesting();
|
||||
assertThat(mInputMethodService).isNotNull();
|
||||
|
||||
// The editor won't bring up keyboard by default.
|
||||
assertThat(mInputMethodService.getCurrentInputStarted()).isTrue();
|
||||
assertThat(mInputMethodService.getCurrentInputViewStarted()).isFalse();
|
||||
});
|
||||
// Save the original value of show_ime_with_hard_keyboard from Settings.
|
||||
// The editor won't bring up keyboard by default.
|
||||
assertThat(mInputMethodService.getCurrentInputStarted()).isTrue();
|
||||
assertThat(mInputMethodService.getCurrentInputViewStarted()).isFalse();
|
||||
});
|
||||
// Save the original value of show_ime_with_hard_keyboard in Settings.
|
||||
mShowImeWithHardKeyboardEnabled = Settings.Secure.getInt(
|
||||
mInputMethodService.getContentResolver(),
|
||||
Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0) != 0;
|
||||
// Disable showing Ime with hard keyboard because it is the precondition the for most test
|
||||
// cases
|
||||
if (mShowImeWithHardKeyboardEnabled) {
|
||||
executeShellCommand(DISABLE_SHOW_IME_WITH_HARD_KEYBOARD_CMD);
|
||||
}
|
||||
mInputMethodService.getResources().getConfiguration().keyboard =
|
||||
Configuration.KEYBOARD_NOKEYS;
|
||||
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
|
||||
Configuration.HARDKEYBOARDHIDDEN_YES;
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -105,141 +112,82 @@ public class InputMethodServiceTest {
|
||||
mUiDevice.unfreezeRotation();
|
||||
executeShellCommand("ime disable " + mInputMethodId);
|
||||
// Change back the original value of show_ime_with_hard_keyboard in Settings.
|
||||
executeShellCommand(mShowImeWithHardKeyboardEnabled
|
||||
? ENABLE_SHOW_IME_WITH_HARD_KEYBOARD_CMD
|
||||
executeShellCommand(mShowImeWithHardKeyboardEnabled ? ENABLE_SHOW_IME_WITH_HARD_KEYBOARD_CMD
|
||||
: DISABLE_SHOW_IME_WITH_HARD_KEYBOARD_CMD);
|
||||
}
|
||||
|
||||
/**
|
||||
* This checks that the IME can be shown and hidden by user actions
|
||||
* (i.e. tapping on an EditText, tapping the Home button).
|
||||
*/
|
||||
@Test
|
||||
public void testShowHideKeyboard_byUserAction() throws Exception {
|
||||
setShowImeWithHardKeyboard(true /* enabled */);
|
||||
|
||||
public void testShowHideKeyboard_byUserAction() throws InterruptedException {
|
||||
// Performs click on editor box to bring up the soft keyboard.
|
||||
Log.i(TAG, "Click on EditText.");
|
||||
verifyInputViewStatus(
|
||||
() -> clickOnEditorText(),
|
||||
true /* expected */,
|
||||
true /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isTrue();
|
||||
verifyInputViewStatus(() -> clickOnEditorText(), true /* inputViewStarted */);
|
||||
|
||||
// Press home key to hide soft keyboard.
|
||||
Log.i(TAG, "Press home");
|
||||
// Press back key to hide soft keyboard.
|
||||
Log.i(TAG, "Press back");
|
||||
verifyInputViewStatus(
|
||||
() -> assertThat(mUiDevice.pressHome()).isTrue(),
|
||||
true /* expected */,
|
||||
false /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isFalse();
|
||||
() -> assertThat(mUiDevice.pressHome()).isTrue(), false /* inputViewStarted */);
|
||||
}
|
||||
|
||||
/**
|
||||
* This checks that the IME can be shown and hidden using the WindowInsetsController APIs.
|
||||
*/
|
||||
@Test
|
||||
public void testShowHideKeyboard_byApi() throws Exception {
|
||||
setShowImeWithHardKeyboard(true /* enabled */);
|
||||
|
||||
public void testShowHideKeyboard_byApi() throws InterruptedException {
|
||||
// Triggers to show IME via public API.
|
||||
verifyInputViewStatus(
|
||||
() -> assertThat(mActivity.showImeWithWindowInsetsController()).isTrue(),
|
||||
true /* expected */,
|
||||
true /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isTrue();
|
||||
|
||||
// Triggers to hide IME via public API.
|
||||
verifyInputViewStatusOnMainSync(
|
||||
() -> assertThat(mActivity.hideImeWithWindowInsetsController()).isTrue(),
|
||||
true /* expected */,
|
||||
() -> assertThat(mActivity.hideImeWithInputMethodManager(0 /* flags */)).isTrue(),
|
||||
false /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isFalse();
|
||||
}
|
||||
|
||||
/**
|
||||
* This checks the result of calling IMS#requestShowSelf and IMS#requestHideSelf.
|
||||
*/
|
||||
@Test
|
||||
public void testShowHideSelf() throws Exception {
|
||||
setShowImeWithHardKeyboard(true /* enabled */);
|
||||
|
||||
// IME request to show itself without any flags, expect shown.
|
||||
public void testShowHideSelf() throws InterruptedException {
|
||||
// IME requests to show itself without any flags: expect shown.
|
||||
Log.i(TAG, "Call IMS#requestShowSelf(0)");
|
||||
verifyInputViewStatusOnMainSync(
|
||||
() -> mInputMethodService.requestShowSelf(0 /* flags */),
|
||||
true /* expected */,
|
||||
true /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isTrue();
|
||||
() -> mInputMethodService.requestShowSelf(0), true /* inputViewStarted */);
|
||||
|
||||
// IME request to hide itself with flag HIDE_IMPLICIT_ONLY, expect not hide (shown).
|
||||
// IME requests to hide itself with flag: HIDE_IMPLICIT_ONLY, expect not hide (shown).
|
||||
Log.i(TAG, "Call IMS#requestHideSelf(InputMethodManager.HIDE_IMPLICIT_ONLY)");
|
||||
verifyInputViewStatusOnMainSync(
|
||||
() -> mInputMethodService.requestHideSelf(InputMethodManager.HIDE_IMPLICIT_ONLY),
|
||||
false /* expected */,
|
||||
true /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isTrue();
|
||||
|
||||
// IME request to hide itself without any flags, expect hidden.
|
||||
// IME request to hide itself without any flags: expect hidden.
|
||||
Log.i(TAG, "Call IMS#requestHideSelf(0)");
|
||||
verifyInputViewStatusOnMainSync(
|
||||
() -> mInputMethodService.requestHideSelf(0 /* flags */),
|
||||
true /* expected */,
|
||||
false /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isFalse();
|
||||
() -> mInputMethodService.requestHideSelf(0), false /* inputViewStarted */);
|
||||
|
||||
// IME request to show itself with flag SHOW_IMPLICIT, expect shown.
|
||||
// IME request to show itself with flag SHOW_IMPLICIT: expect shown.
|
||||
Log.i(TAG, "Call IMS#requestShowSelf(InputMethodManager.SHOW_IMPLICIT)");
|
||||
verifyInputViewStatusOnMainSync(
|
||||
() -> mInputMethodService.requestShowSelf(InputMethodManager.SHOW_IMPLICIT),
|
||||
true /* expected */,
|
||||
true /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isTrue();
|
||||
|
||||
// IME request to hide itself with flag HIDE_IMPLICIT_ONLY, expect hidden.
|
||||
// IME request to hide itself with flag: HIDE_IMPLICIT_ONLY, expect hidden.
|
||||
Log.i(TAG, "Call IMS#requestHideSelf(InputMethodManager.HIDE_IMPLICIT_ONLY)");
|
||||
verifyInputViewStatusOnMainSync(
|
||||
() -> mInputMethodService.requestHideSelf(InputMethodManager.HIDE_IMPLICIT_ONLY),
|
||||
true /* expected */,
|
||||
false /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isFalse();
|
||||
}
|
||||
|
||||
/**
|
||||
* This checks the return value of IMS#onEvaluateInputViewShown,
|
||||
* when show_ime_with_hard_keyboard is enabled.
|
||||
*/
|
||||
@Test
|
||||
public void testOnEvaluateInputViewShown_showImeWithHardKeyboard() throws Exception {
|
||||
setShowImeWithHardKeyboard(true /* enabled */);
|
||||
executeShellCommand(ENABLE_SHOW_IME_WITH_HARD_KEYBOARD_CMD);
|
||||
mInstrumentation.waitForIdleSync();
|
||||
|
||||
// Simulate connecting a hard keyboard
|
||||
mInputMethodService.getResources().getConfiguration().keyboard =
|
||||
Configuration.KEYBOARD_QWERTY;
|
||||
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
|
||||
Configuration.HARDKEYBOARDHIDDEN_NO;
|
||||
eventually(() -> assertThat(mInputMethodService.onEvaluateInputViewShown()).isTrue());
|
||||
|
||||
mInputMethodService.getResources().getConfiguration().keyboard =
|
||||
Configuration.KEYBOARD_NOKEYS;
|
||||
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
|
||||
Configuration.HARDKEYBOARDHIDDEN_NO;
|
||||
eventually(() -> assertThat(mInputMethodService.onEvaluateInputViewShown()).isTrue());
|
||||
|
||||
mInputMethodService.getResources().getConfiguration().keyboard =
|
||||
Configuration.KEYBOARD_QWERTY;
|
||||
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
|
||||
Configuration.HARDKEYBOARDHIDDEN_YES;
|
||||
eventually(() -> assertThat(mInputMethodService.onEvaluateInputViewShown()).isTrue());
|
||||
}
|
||||
|
||||
/**
|
||||
* This checks the return value of IMSonEvaluateInputViewShown,
|
||||
* when show_ime_with_hard_keyboard is disabled.
|
||||
*/
|
||||
@Test
|
||||
public void testOnEvaluateInputViewShown_disableShowImeWithHardKeyboard() throws Exception {
|
||||
setShowImeWithHardKeyboard(false /* enabled */);
|
||||
|
||||
public void testOnEvaluateInputViewShown_disableShowImeWithHardKeyboard() {
|
||||
mInputMethodService.getResources().getConfiguration().keyboard =
|
||||
Configuration.KEYBOARD_QWERTY;
|
||||
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
|
||||
@@ -248,8 +196,6 @@ public class InputMethodServiceTest {
|
||||
|
||||
mInputMethodService.getResources().getConfiguration().keyboard =
|
||||
Configuration.KEYBOARD_NOKEYS;
|
||||
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
|
||||
Configuration.HARDKEYBOARDHIDDEN_NO;
|
||||
eventually(() -> assertThat(mInputMethodService.onEvaluateInputViewShown()).isTrue());
|
||||
|
||||
mInputMethodService.getResources().getConfiguration().keyboard =
|
||||
@@ -259,386 +205,149 @@ public class InputMethodServiceTest {
|
||||
eventually(() -> assertThat(mInputMethodService.onEvaluateInputViewShown()).isTrue());
|
||||
}
|
||||
|
||||
/**
|
||||
* This checks that any (implicit or explicit) show request,
|
||||
* when IMS#onEvaluateInputViewShown returns false, results in the IME not being shown.
|
||||
*/
|
||||
@Test
|
||||
public void testShowSoftInput_disableShowImeWithHardKeyboard() throws Exception {
|
||||
setShowImeWithHardKeyboard(false /* enabled */);
|
||||
|
||||
// Simulate connecting a hard keyboard.
|
||||
// Simulate connecting a hard keyboard
|
||||
mInputMethodService.getResources().getConfiguration().keyboard =
|
||||
Configuration.KEYBOARD_QWERTY;
|
||||
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
|
||||
Configuration.HARDKEYBOARDHIDDEN_NO;
|
||||
|
||||
// When InputMethodService#onEvaluateInputViewShown() returns false, the Ime should not be
|
||||
// shown no matter what the show flag is.
|
||||
verifyInputViewStatusOnMainSync(() -> assertThat(
|
||||
mActivity.showImeWithInputMethodManager(InputMethodManager.SHOW_IMPLICIT)).isTrue(),
|
||||
false /* expected */,
|
||||
false /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isFalse();
|
||||
|
||||
verifyInputViewStatusOnMainSync(
|
||||
() -> assertThat(mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
|
||||
false /* expected */,
|
||||
false /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isFalse();
|
||||
}
|
||||
|
||||
/**
|
||||
* This checks that an explicit show request results in the IME being shown.
|
||||
*/
|
||||
@Test
|
||||
public void testShowSoftInputExplicitly() throws Exception {
|
||||
setShowImeWithHardKeyboard(true /* enabled */);
|
||||
|
||||
// When InputMethodService#onEvaluateInputViewShown() returns true and flag is EXPLICIT, the
|
||||
// Ime should be shown.
|
||||
verifyInputViewStatusOnMainSync(
|
||||
() -> assertThat(mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
|
||||
true /* expected */,
|
||||
true /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* This checks that an implicit show request results in the IME being shown.
|
||||
*/
|
||||
@Test
|
||||
public void testShowSoftInputImplicitly() throws Exception {
|
||||
setShowImeWithHardKeyboard(true /* enabled */);
|
||||
|
||||
// When InputMethodService#onEvaluateInputViewShown() returns true and flag is IMPLICIT,
|
||||
// the IME should be shown.
|
||||
// When InputMethodService#onEvaluateInputViewShown() returns true and flag is IMPLICIT, the
|
||||
// Ime should be shown.
|
||||
verifyInputViewStatusOnMainSync(() -> assertThat(
|
||||
mActivity.showImeWithInputMethodManager(InputMethodManager.SHOW_IMPLICIT)).isTrue(),
|
||||
true /* expected */,
|
||||
true /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* This checks that an explicit show request when the IME is not previously shown,
|
||||
* and it should be shown in fullscreen mode, results in the IME being shown.
|
||||
*/
|
||||
@Test
|
||||
public void testShowSoftInputExplicitly_fullScreenMode() throws Exception {
|
||||
setShowImeWithHardKeyboard(true /* enabled */);
|
||||
|
||||
// Set orientation landscape to enable fullscreen mode.
|
||||
setOrientation(2);
|
||||
eventually(() -> assertThat(mUiDevice.isNaturalOrientation()).isFalse());
|
||||
// Wait for the TestActivity to be recreated.
|
||||
eventually(() ->
|
||||
assertThat(TestActivity.getLastCreatedInstance()).isNotEqualTo(mActivity));
|
||||
// Get the new TestActivity.
|
||||
mActivity = TestActivity.getLastCreatedInstance();
|
||||
assertThat(mActivity).isNotNull();
|
||||
InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
|
||||
// Wait for the new EditText to be served by InputMethodManager.
|
||||
eventually(() -> assertThat(
|
||||
imm.hasActiveInputConnection(mActivity.getEditText())).isTrue());
|
||||
|
||||
verifyInputViewStatusOnMainSync(() -> assertThat(
|
||||
mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
|
||||
true /* expected */,
|
||||
true /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* This checks that an implicit show request when the IME is not previously shown,
|
||||
* and it should be shown in fullscreen mode, results in the IME not being shown.
|
||||
*/
|
||||
@Test
|
||||
public void testShowSoftInputImplicitly_fullScreenMode() throws Exception {
|
||||
setShowImeWithHardKeyboard(true /* enabled */);
|
||||
|
||||
// Set orientation landscape to enable fullscreen mode.
|
||||
// When keyboard is off, InputMethodService#onEvaluateInputViewShown returns true, flag is
|
||||
// IMPLICIT and InputMethodService#onEvaluateFullScreenMode returns true, the Ime should not
|
||||
// be shown.
|
||||
setOrientation(2);
|
||||
eventually(() -> assertThat(mUiDevice.isNaturalOrientation()).isFalse());
|
||||
// Wait for the TestActivity to be recreated.
|
||||
// Wait for the TestActivity to be recreated
|
||||
eventually(() ->
|
||||
assertThat(TestActivity.getLastCreatedInstance()).isNotEqualTo(mActivity));
|
||||
// Get the new TestActivity.
|
||||
// Get the new TestActivity
|
||||
mActivity = TestActivity.getLastCreatedInstance();
|
||||
assertThat(mActivity).isNotNull();
|
||||
InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
|
||||
// Wait for the new EditText to be served by InputMethodManager.
|
||||
eventually(() -> assertThat(
|
||||
imm.hasActiveInputConnection(mActivity.getEditText())).isTrue());
|
||||
|
||||
// Wait for the new EditText to be served by InputMethodManager
|
||||
eventually(() ->
|
||||
assertThat(imm.hasActiveInputConnection(mActivity.getEditText())).isTrue());
|
||||
verifyInputViewStatusOnMainSync(() -> assertThat(
|
||||
mActivity.showImeWithInputMethodManager(InputMethodManager.SHOW_IMPLICIT)).isTrue(),
|
||||
false /* expected */,
|
||||
false /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isFalse();
|
||||
}
|
||||
|
||||
/**
|
||||
* This checks that an explicit show request when a hard keyboard is connected,
|
||||
* results in the IME being shown.
|
||||
*/
|
||||
@Test
|
||||
public void testShowSoftInputExplicitly_withHardKeyboard() throws Exception {
|
||||
setShowImeWithHardKeyboard(false /* enabled */);
|
||||
|
||||
// Simulate connecting a hard keyboard.
|
||||
mInputMethodService.getResources().getConfiguration().keyboard =
|
||||
Configuration.KEYBOARD_QWERTY;
|
||||
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
|
||||
Configuration.HARDKEYBOARDHIDDEN_YES;
|
||||
|
||||
verifyInputViewStatusOnMainSync(() -> assertThat(
|
||||
mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
|
||||
true /* expected */,
|
||||
true /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* This checks that an implicit show request when a hard keyboard is connected,
|
||||
* results in the IME not being shown.
|
||||
*/
|
||||
@Test
|
||||
public void testShowSoftInputImplicitly_withHardKeyboard() throws Exception {
|
||||
setShowImeWithHardKeyboard(false /* enabled */);
|
||||
|
||||
// Simulate connecting a hard keyboard.
|
||||
mInputMethodService.getResources().getConfiguration().keyboard =
|
||||
Configuration.KEYBOARD_QWERTY;
|
||||
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
|
||||
Configuration.HARDKEYBOARDHIDDEN_YES;
|
||||
|
||||
// When connecting to a hard keyboard and the flag is IMPLICIT, the Ime should not be shown.
|
||||
verifyInputViewStatusOnMainSync(() -> assertThat(
|
||||
mActivity.showImeWithInputMethodManager(InputMethodManager.SHOW_IMPLICIT)).isTrue(),
|
||||
false /* expected */,
|
||||
false /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isFalse();
|
||||
}
|
||||
|
||||
/**
|
||||
* This checks that an explicit show request followed by connecting a hard keyboard
|
||||
* and a configuration change, still results in the IME being shown.
|
||||
*/
|
||||
@Test
|
||||
public void testShowSoftInputExplicitly_thenConfigurationChanged() throws Exception {
|
||||
setShowImeWithHardKeyboard(false /* enabled */);
|
||||
|
||||
// Start with no hard keyboard.
|
||||
mInputMethodService.getResources().getConfiguration().keyboard =
|
||||
Configuration.KEYBOARD_NOKEYS;
|
||||
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
|
||||
Configuration.HARDKEYBOARDHIDDEN_YES;
|
||||
|
||||
public void testConfigurationChanged_withKeyboardShownExplicitly() throws InterruptedException {
|
||||
verifyInputViewStatusOnMainSync(
|
||||
() -> assertThat(mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
|
||||
true /* expected */,
|
||||
true /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isTrue();
|
||||
|
||||
// Simulate connecting a hard keyboard.
|
||||
mInputMethodService.getResources().getConfiguration().keyboard =
|
||||
Configuration.KEYBOARD_QWERTY;
|
||||
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
|
||||
Configuration.HARDKEYBOARDHIDDEN_YES;
|
||||
|
||||
// Simulate a fake configuration change to avoid triggering the recreation of TestActivity.
|
||||
mInputMethodService.getResources().getConfiguration().orientation =
|
||||
Configuration.ORIENTATION_LANDSCAPE;
|
||||
|
||||
verifyInputViewStatusOnMainSync(() -> mInputMethodService.onConfigurationChanged(
|
||||
mInputMethodService.getResources().getConfiguration()),
|
||||
true /* expected */,
|
||||
true /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* This checks that an implicit show request followed by connecting a hard keyboard
|
||||
* and a configuration change, does not trigger IMS#onFinishInputView,
|
||||
* but results in the IME being hidden.
|
||||
*/
|
||||
@Test
|
||||
public void testShowSoftInputImplicitly_thenConfigurationChanged() throws Exception {
|
||||
setShowImeWithHardKeyboard(false /* enabled */);
|
||||
|
||||
// Start with no hard keyboard.
|
||||
mInputMethodService.getResources().getConfiguration().keyboard =
|
||||
Configuration.KEYBOARD_NOKEYS;
|
||||
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
|
||||
Configuration.HARDKEYBOARDHIDDEN_YES;
|
||||
|
||||
public void testConfigurationChanged_withKeyboardShownImplicitly() throws InterruptedException {
|
||||
verifyInputViewStatusOnMainSync(() -> assertThat(
|
||||
mActivity.showImeWithInputMethodManager(InputMethodManager.SHOW_IMPLICIT)).isTrue(),
|
||||
true /* expected */,
|
||||
true /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isTrue();
|
||||
|
||||
// Simulate connecting a hard keyboard.
|
||||
mInputMethodService.getResources().getConfiguration().keyboard =
|
||||
Configuration.KEYBOARD_QWERTY;
|
||||
mInputMethodService.getResources().getConfiguration().keyboard =
|
||||
Configuration.HARDKEYBOARDHIDDEN_YES;
|
||||
|
||||
// Simulate a fake configuration change to avoid triggering the recreation of TestActivity.
|
||||
mInputMethodService.getResources().getConfiguration().orientation =
|
||||
Configuration.ORIENTATION_LANDSCAPE;
|
||||
mInputMethodService.getResources().getConfiguration().keyboard =
|
||||
Configuration.KEYBOARD_QWERTY;
|
||||
|
||||
// Normally, IMS#onFinishInputView will be called when finishing the input view by the user.
|
||||
// But if IMS#hideWindow is called when receiving a new configuration change, we don't
|
||||
// expect that it's user-driven to finish the lifecycle of input view with
|
||||
// IMS#onFinishInputView, because the input view will be re-initialized according to the
|
||||
// last #mShowInputRequested state. So in this case we treat the input view as still alive.
|
||||
// last mShowSoftRequested state. So in this case we treat the input view is still alive.
|
||||
verifyInputViewStatusOnMainSync(() -> mInputMethodService.onConfigurationChanged(
|
||||
mInputMethodService.getResources().getConfiguration()),
|
||||
true /* expected */,
|
||||
mInputMethodService.getResources().getConfiguration()),
|
||||
true /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isFalse();
|
||||
}
|
||||
|
||||
/**
|
||||
* This checks that an explicit show request directly followed by an implicit show request,
|
||||
* while a hardware keyboard is connected, still results in the IME being shown
|
||||
* (i.e. the implicit show request is treated as explicit).
|
||||
*/
|
||||
@Test
|
||||
public void testShowSoftInputExplicitly_thenShowSoftInputImplicitly_withHardKeyboard()
|
||||
throws Exception {
|
||||
setShowImeWithHardKeyboard(false /* enabled */);
|
||||
|
||||
// Simulate connecting a hard keyboard.
|
||||
mInputMethodService.getResources().getConfiguration().keyboard =
|
||||
Configuration.KEYBOARD_QWERTY;
|
||||
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
|
||||
Configuration.HARDKEYBOARDHIDDEN_YES;
|
||||
|
||||
// Explicit show request.
|
||||
verifyInputViewStatusOnMainSync(() -> assertThat(
|
||||
mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
|
||||
true /* expected */,
|
||||
true /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isTrue();
|
||||
|
||||
// Implicit show request.
|
||||
verifyInputViewStatusOnMainSync(() -> assertThat(
|
||||
mActivity.showImeWithInputMethodManager(InputMethodManager.SHOW_IMPLICIT)).isTrue(),
|
||||
false /* expected */,
|
||||
true /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isTrue();
|
||||
|
||||
// Simulate a fake configuration change to avoid triggering the recreation of TestActivity.
|
||||
// This should now consider the implicit show request, but keep the state from the
|
||||
// explicit show request, and thus not hide the keyboard.
|
||||
verifyInputViewStatusOnMainSync(() -> mInputMethodService.onConfigurationChanged(
|
||||
mInputMethodService.getResources().getConfiguration()),
|
||||
true /* expected */,
|
||||
true /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* This checks that a forced show request directly followed by an explicit show request,
|
||||
* and then a hide not always request, still results in the IME being shown
|
||||
* (i.e. the explicit show request retains the forced state).
|
||||
*/
|
||||
@Test
|
||||
public void testShowSoftInputForced_testShowSoftInputExplicitly_thenHideSoftInputNotAlways()
|
||||
throws Exception {
|
||||
setShowImeWithHardKeyboard(true /* enabled */);
|
||||
|
||||
verifyInputViewStatusOnMainSync(() -> assertThat(
|
||||
mActivity.showImeWithInputMethodManager(InputMethodManager.SHOW_FORCED)).isTrue(),
|
||||
true /* expected */,
|
||||
true /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isTrue();
|
||||
|
||||
verifyInputViewStatusOnMainSync(() -> assertThat(
|
||||
mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
|
||||
false /* expected */,
|
||||
true /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isTrue();
|
||||
|
||||
verifyInputViewStatusOnMainSync(() ->
|
||||
mActivity.hideImeWithInputMethodManager(InputMethodManager.HIDE_NOT_ALWAYS),
|
||||
false /* expected */,
|
||||
true /* inputViewStarted */);
|
||||
assertThat(mInputMethodService.isInputViewShown()).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* This checks that the IME fullscreen mode state is updated after changing orientation.
|
||||
*/
|
||||
@Test
|
||||
public void testFullScreenMode() throws Exception {
|
||||
setShowImeWithHardKeyboard(true /* enabled */);
|
||||
|
||||
Log.i(TAG, "Set orientation natural");
|
||||
verifyFullscreenMode(() -> setOrientation(0),
|
||||
false /* expected */,
|
||||
true /* orientationPortrait */);
|
||||
|
||||
Log.i(TAG, "Set orientation left");
|
||||
verifyFullscreenMode(() -> setOrientation(1),
|
||||
true /* expected */,
|
||||
false /* orientationPortrait */);
|
||||
|
||||
Log.i(TAG, "Set orientation right");
|
||||
verifyFullscreenMode(() -> setOrientation(2),
|
||||
false /* expected */,
|
||||
false /* orientationPortrait */);
|
||||
}
|
||||
|
||||
private void verifyInputViewStatus(
|
||||
Runnable runnable, boolean expected, boolean inputViewStarted)
|
||||
private void verifyInputViewStatus(Runnable runnable, boolean inputViewStarted)
|
||||
throws InterruptedException {
|
||||
verifyInputViewStatusInternal(runnable, expected, inputViewStarted,
|
||||
false /* runOnMainSync */);
|
||||
verifyInputViewStatusInternal(runnable, inputViewStarted, false /*runOnMainSync*/);
|
||||
}
|
||||
|
||||
private void verifyInputViewStatusOnMainSync(
|
||||
Runnable runnable, boolean expected, boolean inputViewStarted)
|
||||
private void verifyInputViewStatusOnMainSync(Runnable runnable, boolean inputViewStarted)
|
||||
throws InterruptedException {
|
||||
verifyInputViewStatusInternal(runnable, expected, inputViewStarted,
|
||||
true /* runOnMainSync */);
|
||||
verifyInputViewStatusInternal(runnable, inputViewStarted, true /*runOnMainSync*/);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the status of the Input View after executing the given runnable.
|
||||
*
|
||||
* @param runnable the runnable to execute for showing or hiding the IME.
|
||||
* @param expected whether the runnable is expected to trigger the signal.
|
||||
* @param inputViewStarted the expected state of the Input View after executing the runnable.
|
||||
* @param runOnMainSync whether to execute the runnable on the main thread.
|
||||
*/
|
||||
private void verifyInputViewStatusInternal(
|
||||
Runnable runnable, boolean expected, boolean inputViewStarted, boolean runOnMainSync)
|
||||
Runnable runnable, boolean inputViewStarted, boolean runOnMainSync)
|
||||
throws InterruptedException {
|
||||
CountDownLatch signal = new CountDownLatch(1);
|
||||
mInputMethodService.setCountDownLatchForTesting(signal);
|
||||
// Runnable to trigger onStartInputView() / onFinishInputView() / onConfigurationChanged()
|
||||
// Runnable to trigger onStartInputView()/ onFinishInputView()
|
||||
if (runOnMainSync) {
|
||||
mInstrumentation.runOnMainSync(runnable);
|
||||
} else {
|
||||
runnable.run();
|
||||
}
|
||||
// Waits for onStartInputView() to finish.
|
||||
mInstrumentation.waitForIdleSync();
|
||||
boolean completed = signal.await(TIMEOUT_IN_SECONDS, TimeUnit.SECONDS);
|
||||
if (expected && !completed) {
|
||||
fail("Timed out waiting for"
|
||||
+ " onStartInputView() / onFinishInputView() / onConfigurationChanged()");
|
||||
} else if (!expected && completed) {
|
||||
fail("Unexpected call"
|
||||
+ " onStartInputView() / onFinishInputView() / onConfigurationChanged()");
|
||||
}
|
||||
signal.await(TIMEOUT_IN_SECONDS, TimeUnit.SECONDS);
|
||||
// Input is not finished.
|
||||
assertThat(mInputMethodService.getCurrentInputStarted()).isTrue();
|
||||
assertThat(mInputMethodService.getCurrentInputViewStarted()).isEqualTo(inputViewStarted);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFullScreenMode() throws Exception {
|
||||
Log.i(TAG, "Set orientation natural");
|
||||
verifyFullscreenMode(() -> setOrientation(0), true /* orientationPortrait */);
|
||||
|
||||
Log.i(TAG, "Set orientation left");
|
||||
verifyFullscreenMode(() -> setOrientation(1), false /* orientationPortrait */);
|
||||
|
||||
Log.i(TAG, "Set orientation right");
|
||||
verifyFullscreenMode(() -> setOrientation(2), false /* orientationPortrait */);
|
||||
}
|
||||
|
||||
private void setOrientation(int orientation) {
|
||||
// Simple wrapper for catching RemoteException.
|
||||
try {
|
||||
@@ -657,15 +366,7 @@ public class InputMethodServiceTest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the IME fullscreen mode state after executing the given runnable.
|
||||
*
|
||||
* @param runnable the runnable to execute for setting the orientation.
|
||||
* @param expected whether the runnable is expected to trigger the signal.
|
||||
* @param orientationPortrait whether the orientation is expected to be portrait.
|
||||
*/
|
||||
private void verifyFullscreenMode(
|
||||
Runnable runnable, boolean expected, boolean orientationPortrait)
|
||||
private void verifyFullscreenMode(Runnable runnable, boolean orientationPortrait)
|
||||
throws InterruptedException {
|
||||
CountDownLatch signal = new CountDownLatch(1);
|
||||
mInputMethodService.setCountDownLatchForTesting(signal);
|
||||
@@ -678,12 +379,7 @@ public class InputMethodServiceTest {
|
||||
}
|
||||
// Waits for onConfigurationChanged() to finish.
|
||||
mInstrumentation.waitForIdleSync();
|
||||
boolean completed = signal.await(TIMEOUT_IN_SECONDS, TimeUnit.SECONDS);
|
||||
if (expected && !completed) {
|
||||
fail("Timed out waiting for onConfigurationChanged()");
|
||||
} else if (!expected && completed) {
|
||||
fail("Unexpected call onConfigurationChanged()");
|
||||
}
|
||||
signal.await(TIMEOUT_IN_SECONDS, TimeUnit.SECONDS);
|
||||
|
||||
clickOnEditorText();
|
||||
eventually(() -> assertThat(mInputMethodService.isInputViewShown()).isTrue());
|
||||
@@ -720,21 +416,7 @@ public class InputMethodServiceTest {
|
||||
return mTargetPackageName + "/" + INPUT_METHOD_SERVICE_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of show_ime_with_hard_keyboard, only if it is different to the default value.
|
||||
*
|
||||
* @param enabled the value to be set.
|
||||
*/
|
||||
private void setShowImeWithHardKeyboard(boolean enabled) throws IOException {
|
||||
if (mShowImeWithHardKeyboardEnabled != enabled) {
|
||||
executeShellCommand(enabled
|
||||
? ENABLE_SHOW_IME_WITH_HARD_KEYBOARD_CMD
|
||||
: DISABLE_SHOW_IME_WITH_HARD_KEYBOARD_CMD);
|
||||
mInstrumentation.waitForIdleSync();
|
||||
}
|
||||
}
|
||||
|
||||
private String executeShellCommand(String cmd) throws IOException {
|
||||
private String executeShellCommand(String cmd) throws Exception {
|
||||
Log.i(TAG, "Run command: " + cmd);
|
||||
return UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
||||
.executeShellCommand(cmd);
|
||||
|
||||
@@ -40,6 +40,7 @@ import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.view.Display;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
@@ -76,9 +77,9 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe
|
||||
public void testPerformShowIme() throws Exception {
|
||||
synchronized (ImfLock.class) {
|
||||
mVisibilityApplier.performShowIme(new Binder() /* showInputToken */,
|
||||
null /* statsToken */, 0 /* showFlags */, null, SHOW_SOFT_INPUT);
|
||||
null /* statsToken */, InputMethodManager.SHOW_IMPLICIT, null, SHOW_SOFT_INPUT);
|
||||
}
|
||||
verifyShowSoftInput(false, true, 0 /* showFlags */);
|
||||
verifyShowSoftInput(false, true, InputMethodManager.SHOW_IMPLICIT);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -125,7 +126,7 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe
|
||||
@Test
|
||||
public void testApplyImeVisibility_showImeImplicit() throws Exception {
|
||||
mVisibilityApplier.applyImeVisibility(mWindowToken, null, STATE_SHOW_IME_IMPLICIT);
|
||||
verifyShowSoftInput(true, true, 0 /* showFlags */);
|
||||
verifyShowSoftInput(true, true, InputMethodManager.SHOW_IMPLICIT);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -106,7 +106,7 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes
|
||||
@Test
|
||||
public void testRequestImeVisibility_showExplicit() {
|
||||
initImeTargetWindowState(mWindowToken);
|
||||
boolean res = mComputer.onImeShowFlags(null, 0 /* showFlags */);
|
||||
boolean res = mComputer.onImeShowFlags(null, 0 /* show explicit */);
|
||||
mComputer.requestImeVisibility(mWindowToken, res);
|
||||
|
||||
final ImeTargetWindowState state = mComputer.getWindowStateOrNull(mWindowToken);
|
||||
@@ -118,34 +118,6 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes
|
||||
assertThat(mComputer.mRequestedShowExplicitly).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* This checks that the state after an explicit show request does not get reset during
|
||||
* a subsequent implicit show request, without an intermediary hide request.
|
||||
*/
|
||||
@Test
|
||||
public void testRequestImeVisibility_showExplicit_thenShowImplicit() {
|
||||
initImeTargetWindowState(mWindowToken);
|
||||
mComputer.onImeShowFlags(null, 0 /* showFlags */);
|
||||
assertThat(mComputer.mRequestedShowExplicitly).isTrue();
|
||||
|
||||
mComputer.onImeShowFlags(null, InputMethodManager.SHOW_IMPLICIT);
|
||||
assertThat(mComputer.mRequestedShowExplicitly).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* This checks that the state after a forced show request does not get reset during
|
||||
* a subsequent explicit show request, without an intermediary hide request.
|
||||
*/
|
||||
@Test
|
||||
public void testRequestImeVisibility_showForced_thenShowExplicit() {
|
||||
initImeTargetWindowState(mWindowToken);
|
||||
mComputer.onImeShowFlags(null, InputMethodManager.SHOW_FORCED);
|
||||
assertThat(mComputer.mShowForced).isTrue();
|
||||
|
||||
mComputer.onImeShowFlags(null, 0 /* showFlags */);
|
||||
assertThat(mComputer.mShowForced).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestImeVisibility_showImplicit_a11yNoImePolicy() {
|
||||
// Precondition: set AccessibilityService#SHOW_MODE_HIDDEN policy
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.android.server.inputmethod;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
@@ -163,10 +162,7 @@ public class InputMethodBindingControllerTest extends InputMethodManagerServiceT
|
||||
assertThat(mBindingController.getCurToken()).isNotNull();
|
||||
}
|
||||
// Wait for onServiceConnected()
|
||||
boolean completed = mCountDownLatch.await(TIMEOUT_IN_SECONDS, TimeUnit.SECONDS);
|
||||
if (!completed) {
|
||||
fail("Timed out waiting for onServiceConnected()");
|
||||
}
|
||||
mCountDownLatch.await(TIMEOUT_IN_SECONDS, TimeUnit.SECONDS);
|
||||
|
||||
// Verify onServiceConnected() is called and bound successfully.
|
||||
synchronized (ImfLock.class) {
|
||||
|
||||
@@ -43,8 +43,6 @@ android_test_helper_app {
|
||||
},
|
||||
export_package_resources: true,
|
||||
sdk_version: "current",
|
||||
|
||||
certificate: "platform",
|
||||
}
|
||||
|
||||
android_library {
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.apps.inputmethod.simpleime">
|
||||
|
||||
<uses-sdk android:targetSdkVersion="31" />
|
||||
|
||||
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
|
||||
|
||||
<application android:debuggable="true"
|
||||
|
||||
Reference in New Issue
Block a user