• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.cts.mockime;
18 
19 import static java.lang.annotation.RetentionPolicy.SOURCE;
20 
21 import android.os.Bundle;
22 import android.os.PersistableBundle;
23 import android.os.Process;
24 import android.os.RemoteCallback;
25 import android.os.UserHandle;
26 import android.view.inputmethod.InputMethodSubtype;
27 
28 import androidx.annotation.ColorInt;
29 import androidx.annotation.IntDef;
30 import androidx.annotation.NonNull;
31 import androidx.annotation.Nullable;
32 import androidx.window.extensions.layout.WindowLayoutInfo;
33 
34 import java.lang.annotation.Retention;
35 import java.util.Objects;
36 
37 /**
38  * An immutable data store to control the behavior of {@link MockIme}.
39  */
40 public class ImeSettings {
41 
42     @NonNull
43     private final String mClientPackageName;
44 
45     @NonNull
46     private final String mEventCallbackActionName;
47 
48     private static final String EVENT_CALLBACK_INTENT_ACTION_KEY = "eventCallbackActionName";
49     private static final String CHANNEL_KEY = "channel";
50     private static final String DATA_KEY = "data";
51 
52     private static final String BACKGROUND_COLOR_KEY = "BackgroundColor";
53     private static final String NAVIGATION_BAR_COLOR_KEY = "NavigationBarColor";
54     private static final String INPUT_VIEW_HEIGHT =
55             "InputViewHeightWithoutSystemWindowInset";
56     private static final String DRAWS_BEHIND_NAV_BAR = "drawsBehindNavBar";
57     private static final String WINDOW_FLAGS = "WindowFlags";
58     private static final String WINDOW_FLAGS_MASK = "WindowFlagsMask";
59     private static final String FULLSCREEN_MODE_POLICY = "FullscreenModePolicy";
60     private static final String INPUT_VIEW_SYSTEM_UI_VISIBILITY = "InputViewSystemUiVisibility";
61     private static final String WATERMARK_ENABLED = "WatermarkEnabled";
62     private static final String WATERMARK_GRAVITY = "WatermarkGravity";
63     private static final String HARD_KEYBOARD_CONFIGURATION_BEHAVIOR_ALLOWED =
64             "HardKeyboardConfigurationBehaviorAllowed";
65     private static final String INLINE_SUGGESTIONS_ENABLED = "InlineSuggestionsEnabled";
66     private static final String INLINE_SUGGESTION_VIEW_CONTENT_DESC =
67             "InlineSuggestionViewContentDesc";
68     private static final String STRICT_MODE_ENABLED = "StrictModeEnabled";
69     private static final String VERIFY_CONTEXT_APIS_IN_ON_CREATE = "VerifyContextApisInOnCreate";
70     private static final String WINDOW_LAYOUT_INFO_CALLBACK_ENABLED =
71             "WindowLayoutInfoCallbackEnabled";
72     private static final String CONNECTIONLESS_HANDWRITING_ENABLED =
73             "ConnectionlessHandwritingEnabled";
74 
75     /**
76      * Simulate the manifest flag enableOnBackInvokedCallback being true for the IME.
77      */
78     private static final String ON_BACK_CALLBACK_ENABLED = "onBackCallbackEnabled";
79 
80     private static final String USE_CUSTOM_EXTRACT_TEXT_VIEW = "useCustomExtractTextView";
81 
82     private static final String ZERO_INSETS = "zeroInsets";
83 
84     @NonNull
85     private final PersistableBundle mBundle;
86     private final SessionChannel mChannel;
87 
88     @Retention(SOURCE)
89     @IntDef(value = {
90             FullscreenModePolicy.NO_FULLSCREEN,
91             FullscreenModePolicy.FORCE_FULLSCREEN,
92             FullscreenModePolicy.OS_DEFAULT,
93     })
94     public @interface FullscreenModePolicy {
95         /**
96          * Let {@link MockIme} always return {@code false} from
97          * {@link android.inputmethodservice.InputMethodService#onEvaluateFullscreenMode()}.
98          *
99          * <p>This is chosen to be the default behavior of {@link MockIme} to make CTS tests most
100          * deterministic.</p>
101          */
102         int NO_FULLSCREEN = 0;
103 
104         /**
105          * Let {@link MockIme} always return {@code true} from
106          * {@link android.inputmethodservice.InputMethodService#onEvaluateFullscreenMode()}.
107          *
108          * <p>This can be used to test the behaviors when a full-screen IME is running.</p>
109          */
110         int FORCE_FULLSCREEN = 1;
111 
112         /**
113          * Let {@link MockIme} always return the default behavior of
114          * {@link android.inputmethodservice.InputMethodService#onEvaluateFullscreenMode()}.
115          *
116          * <p>This can be used to test the default behavior of that public API.</p>
117          */
118         int OS_DEFAULT = 2;
119     }
120 
ImeSettings(@onNull String clientPackageName, @NonNull Bundle bundle)121     ImeSettings(@NonNull String clientPackageName, @NonNull Bundle bundle) {
122         mClientPackageName = clientPackageName;
123         mEventCallbackActionName = bundle.getString(EVENT_CALLBACK_INTENT_ACTION_KEY);
124         mBundle = bundle.getParcelable(DATA_KEY);
125         mChannel = new SessionChannel(bundle.getParcelable(CHANNEL_KEY, RemoteCallback.class));
126     }
127 
128     @Nullable
getEventCallbackActionName()129     String getEventCallbackActionName() {
130         return mEventCallbackActionName;
131     }
132 
getChannel()133     SessionChannel getChannel() {
134         return mChannel;
135     }
136 
137     @NonNull
getClientPackageName()138     String getClientPackageName() {
139         return mClientPackageName;
140     }
141 
142     @FullscreenModePolicy
fullscreenModePolicy()143     public int fullscreenModePolicy() {
144         return mBundle.getInt(FULLSCREEN_MODE_POLICY);
145     }
146 
147     @ColorInt
getBackgroundColor(@olorInt int defaultColor)148     public int getBackgroundColor(@ColorInt int defaultColor) {
149         return mBundle.getInt(BACKGROUND_COLOR_KEY, defaultColor);
150     }
151 
hasNavigationBarColor()152     public boolean hasNavigationBarColor() {
153         return mBundle.keySet().contains(NAVIGATION_BAR_COLOR_KEY);
154     }
155 
156     @ColorInt
getNavigationBarColor()157     public int getNavigationBarColor() {
158         return mBundle.getInt(NAVIGATION_BAR_COLOR_KEY);
159     }
160 
getInputViewHeight(int defaultHeight)161     public int getInputViewHeight(int defaultHeight) {
162         return mBundle.getInt(INPUT_VIEW_HEIGHT, defaultHeight);
163     }
164 
getDrawsBehindNavBar()165     public boolean getDrawsBehindNavBar() {
166         return mBundle.getBoolean(DRAWS_BEHIND_NAV_BAR, false);
167     }
168 
getWindowFlags(int defaultFlags)169     public int getWindowFlags(int defaultFlags) {
170         return mBundle.getInt(WINDOW_FLAGS, defaultFlags);
171     }
172 
getWindowFlagsMask(int defaultFlags)173     public int getWindowFlagsMask(int defaultFlags) {
174         return mBundle.getInt(WINDOW_FLAGS_MASK, defaultFlags);
175     }
176 
getInputViewSystemUiVisibility(int defaultFlags)177     public int getInputViewSystemUiVisibility(int defaultFlags) {
178         return mBundle.getInt(INPUT_VIEW_SYSTEM_UI_VISIBILITY, defaultFlags);
179     }
180 
isWatermarkEnabled(boolean defaultValue)181     public boolean isWatermarkEnabled(boolean defaultValue) {
182         return mBundle.getBoolean(WATERMARK_ENABLED, defaultValue);
183     }
184 
getWatermarkGravity(int defaultValue)185     public int getWatermarkGravity(int defaultValue) {
186         return mBundle.getInt(WATERMARK_GRAVITY, defaultValue);
187     }
188 
getHardKeyboardConfigurationBehaviorAllowed(boolean defaultValue)189     public boolean getHardKeyboardConfigurationBehaviorAllowed(boolean defaultValue) {
190         return mBundle.getBoolean(HARD_KEYBOARD_CONFIGURATION_BEHAVIOR_ALLOWED, defaultValue);
191     }
192 
getInlineSuggestionsEnabled()193     public boolean getInlineSuggestionsEnabled() {
194         return mBundle.getBoolean(INLINE_SUGGESTIONS_ENABLED);
195     }
196 
197     @Nullable
getInlineSuggestionViewContentDesc(@ullable String defaultValue)198     public String getInlineSuggestionViewContentDesc(@Nullable String defaultValue) {
199         return mBundle.getString(INLINE_SUGGESTION_VIEW_CONTENT_DESC, defaultValue);
200     }
201 
isStrictModeEnabled()202     public boolean isStrictModeEnabled() {
203         return mBundle.getBoolean(STRICT_MODE_ENABLED, false);
204     }
205 
isVerifyContextApisInOnCreate()206     public boolean isVerifyContextApisInOnCreate() {
207         return mBundle.getBoolean(VERIFY_CONTEXT_APIS_IN_ON_CREATE, false);
208     }
209 
isWindowLayoutInfoCallbackEnabled()210     public boolean isWindowLayoutInfoCallbackEnabled() {
211         return mBundle.getBoolean(WINDOW_LAYOUT_INFO_CALLBACK_ENABLED, false);
212     }
213 
isConnectionlessHandwritingEnabled()214     public boolean isConnectionlessHandwritingEnabled() {
215         return mBundle.getBoolean(CONNECTIONLESS_HANDWRITING_ENABLED, false);
216     }
217 
isOnBackCallbackEnabled()218     public boolean isOnBackCallbackEnabled() {
219         return mBundle.getBoolean(ON_BACK_CALLBACK_ENABLED, false);
220     }
221 
close()222     public void close() {
223         if (mChannel != null) {
224             mChannel.close();
225         }
226     }
227 
228     /** Whether or not custom extract view hierarchy should be used. */
isCustomExtractTextViewEnabled()229     public boolean isCustomExtractTextViewEnabled() {
230         return mBundle.getBoolean(USE_CUSTOM_EXTRACT_TEXT_VIEW, false);
231     }
232 
233     /** Whether the IME should provide zero insets when shown. */
isZeroInsetsEnabled()234     public boolean isZeroInsetsEnabled() {
235         return mBundle.getBoolean(ZERO_INSETS, false);
236     }
237 
serializeToBundle(@onNull String eventCallbackActionName, @Nullable Builder builder, @NonNull RemoteCallback channel)238     static Bundle serializeToBundle(@NonNull String eventCallbackActionName,
239             @Nullable Builder builder, @NonNull RemoteCallback channel) {
240         final Bundle result = new Bundle();
241         result.putString(EVENT_CALLBACK_INTENT_ACTION_KEY, eventCallbackActionName);
242         result.putParcelable(DATA_KEY, builder != null ? builder.mBundle : PersistableBundle.EMPTY);
243         result.putParcelable(CHANNEL_KEY, channel);
244         return result;
245     }
246 
247     /**
248      * The builder class for {@link ImeSettings}.
249      */
250     public static final class Builder {
251         private final PersistableBundle mBundle = new PersistableBundle();
252 
253         @MockImePackageNames
254         @NonNull
255         String mMockImePackageName = MockImePackageNames.MockIme1;
256 
257         /**
258          * Specifies a non-default {@link MockIme} package name, which is by default
259          * {@code com.android.cts.mockime}.
260          *
261          * <p>You can use this to interact with multiple {@link MockIme} sessions at the same time.
262          * </p>
263          *
264          * @param packageName One of {@link MockImePackageNames}.
265          * @return this {@link Builder} object
266          */
setMockImePackageName(@ockImePackageNames String packageName)267         public Builder setMockImePackageName(@MockImePackageNames String packageName) {
268             mMockImePackageName = packageName;
269             return this;
270         }
271 
272         @NonNull
273         UserHandle mTargetUser = Process.myUserHandle();
274 
275         /**
276          * Specifies a different user than the current user.
277          *
278          * @param targetUser The user whose {@link MockIme} will be connected to.
279          * @return this {@link Builder} object
280          */
setTargetUser(@onNull UserHandle targetUser)281         public Builder setTargetUser(@NonNull UserHandle targetUser) {
282             mTargetUser = Objects.requireNonNull(targetUser);
283             return this;
284         }
285 
286         /**
287          * Whether the IME should only be initialized and enabled, but not set as the current IME.
288          */
289         boolean mSuppressSetIme = false;
290 
291         /**
292          * Sets whether the IME should only be initialized and enabled, but not set as
293          * the current IME.
294          */
setSuppressSetIme(boolean suppressSetIme)295         public Builder setSuppressSetIme(boolean suppressSetIme) {
296             mSuppressSetIme = suppressSetIme;
297             return this;
298         }
299 
300         boolean mSuppressResetIme = false;
301 
302         /**
303          * Specifies whether {@code adb shell ime reset} should be suppressed or not on
304          * {@link MockImeSession#create(android.content.Context)} and
305          * {@link MockImeSession#close()}.
306          *
307          * <p>The default value is {@code false}.</p>
308          *
309          * @param suppressResetIme {@code true} to suppress {@code adb shell ime reset} upon
310          *                         initialize and cleanup processes of {@link MockImeSession}.
311          * @return this {@link Builder} object
312          */
setSuppressResetIme(boolean suppressResetIme)313         public Builder setSuppressResetIme(boolean suppressResetIme) {
314             mSuppressResetIme = suppressResetIme;
315             return this;
316         }
317 
318         boolean mSuppressDeleteSettings = false;
319 
320         /**
321          * Specifies whether deleting the IME settings should be suppressed or not on {@link
322          * MockImeSession#close()}.
323          *
324          * <p>The default value is {@code false}.
325          *
326          * @param suppressDeleteSettings {@code true} to suppress IME settings deletion upon cleanup
327          *     of {@link MockImeSession}.
328          * @return this {@link Builder} object.
329          */
setSuppressDeleteSettings(boolean suppressDeleteSettings)330         public Builder setSuppressDeleteSettings(boolean suppressDeleteSettings) {
331             mSuppressDeleteSettings = suppressDeleteSettings;
332             return this;
333         }
334 
335         @Nullable
336         InputMethodSubtype[] mAdditionalSubtypes;
337 
338         /**
339          * Specifies additional {@link InputMethodSubtype}s to be set before launching
340          * {@link MockIme} by using
341          * {@link android.view.inputmethod.InputMethodManager#setAdditionalInputMethodSubtypes(
342          * String, InputMethodSubtype[])}.
343          *
344          * @param subtypes An array of {@link InputMethodSubtype}.
345          * @return this {@link Builder} object
346          */
setAdditionalSubtypes(InputMethodSubtype... subtypes)347         public Builder setAdditionalSubtypes(InputMethodSubtype... subtypes) {
348             mAdditionalSubtypes = subtypes;
349             return this;
350         }
351 
352         /**
353          * Controls how MockIme reacts to
354          * {@link android.inputmethodservice.InputMethodService#onEvaluateFullscreenMode()}.
355          *
356          * @param policy one of {@link FullscreenModePolicy}
357          * @see MockIme#onEvaluateFullscreenMode()
358          */
setFullscreenModePolicy(@ullscreenModePolicy int policy)359         public Builder setFullscreenModePolicy(@FullscreenModePolicy int policy) {
360             mBundle.putInt(FULLSCREEN_MODE_POLICY, policy);
361             return this;
362         }
363 
364         /**
365          * Sets the background color of the {@link MockIme}.
366          * @param color background color to be used
367          */
setBackgroundColor(@olorInt int color)368         public Builder setBackgroundColor(@ColorInt int color) {
369             mBundle.putInt(BACKGROUND_COLOR_KEY, color);
370             return this;
371         }
372 
373         /**
374          * Sets the color to be passed to {@link android.view.Window#setNavigationBarColor(int)}.
375          *
376          * @param color color to be passed to {@link android.view.Window#setNavigationBarColor(int)}
377          * @see android.view.View
378          */
setNavigationBarColor(@olorInt int color)379         public Builder setNavigationBarColor(@ColorInt int color) {
380             mBundle.putInt(NAVIGATION_BAR_COLOR_KEY, color);
381             return this;
382         }
383 
384         /**
385          * Sets the input view height measured from the bottom of the screen.
386          *
387          * @param height height of the soft input view. This includes the system window inset such
388          *               as navigation bar.
389          */
setInputViewHeight(int height)390         public Builder setInputViewHeight(int height) {
391             mBundle.putInt(INPUT_VIEW_HEIGHT, height);
392             return this;
393         }
394 
395         /**
396          * Sets whether IME draws behind navigation bar.
397          */
setDrawsBehindNavBar(boolean drawsBehindNavBar)398         public Builder setDrawsBehindNavBar(boolean drawsBehindNavBar) {
399             mBundle.putBoolean(DRAWS_BEHIND_NAV_BAR, drawsBehindNavBar);
400             return this;
401         }
402 
403         /**
404          * Sets window flags to be specified to {@link android.view.Window#setFlags(int, int)} of
405          * the main {@link MockIme} window.
406          *
407          * <p>When {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_OVERSCAN} is set,
408          * {@link MockIme} tries to render the navigation bar by itself.</p>
409          *
410          * @param flags flags to be specified
411          * @param flagsMask mask bits that specify what bits need to be cleared before setting
412          *                  {@code flags}
413          * @see android.view.WindowManager
414          */
setWindowFlags(int flags, int flagsMask)415         public Builder setWindowFlags(int flags, int flagsMask) {
416             mBundle.putInt(WINDOW_FLAGS, flags);
417             mBundle.putInt(WINDOW_FLAGS_MASK, flagsMask);
418             return this;
419         }
420 
421         /**
422          * Sets flags to be specified to {@link android.view.View#setSystemUiVisibility(int)} of
423          * the main soft input view (the returned view from {@link MockIme#onCreateInputView()}).
424          *
425          * @param visibilityFlags flags to be specified
426          * @see android.view.View
427          */
setInputViewSystemUiVisibility(int visibilityFlags)428         public Builder setInputViewSystemUiVisibility(int visibilityFlags) {
429             mBundle.putInt(INPUT_VIEW_SYSTEM_UI_VISIBILITY, visibilityFlags);
430             return this;
431         }
432 
433         /**
434          * Sets whether a unique watermark image needs to be shown on the software keyboard or not.
435          *
436          * <p>This needs to be enabled to use</p>
437          *
438          * @param enabled {@code true} when such a watermark image is requested.
439          */
setWatermarkEnabled(boolean enabled)440         public Builder setWatermarkEnabled(boolean enabled) {
441             mBundle.putBoolean(WATERMARK_ENABLED, enabled);
442             return this;
443         }
444 
445         /**
446          * Sets the {@link android.view.Gravity} flags for the watermark image.
447          *
448          * <p>{@link android.view.Gravity#CENTER} will be used if not set.</p>
449          *
450          * @param gravity {@code true} {@link android.view.Gravity} flags to be set.
451          */
setWatermarkGravity(int gravity)452         public Builder setWatermarkGravity(int gravity) {
453             mBundle.putInt(WATERMARK_GRAVITY, gravity);
454             return this;
455         }
456 
457         /**
458          * Controls whether {@link MockIme} is allowed to change the behavior based on
459          * {@link android.content.res.Configuration#keyboard} and
460          * {@link android.content.res.Configuration#hardKeyboardHidden}.
461          *
462          * <p>Methods in {@link android.inputmethodservice.InputMethodService} such as
463          * {@link android.inputmethodservice.InputMethodService#onEvaluateInputViewShown()} and
464          * {@link android.inputmethodservice.InputMethodService#onShowInputRequested(int, boolean)}
465          * change their behaviors when a hardware keyboard is attached.  This is confusing when
466          * writing tests so by default {@link MockIme} tries to cancel those behaviors.  This
467          * settings re-enables such a behavior.</p>
468          *
469          * @param allowed {@code true} when {@link MockIme} is allowed to change the behavior when
470          *                a hardware keyboard is attached
471          *
472          * @see android.inputmethodservice.InputMethodService#onEvaluateInputViewShown()
473          * @see android.inputmethodservice.InputMethodService#onShowInputRequested(int, boolean)
474          */
setHardKeyboardConfigurationBehaviorAllowed(boolean allowed)475         public Builder setHardKeyboardConfigurationBehaviorAllowed(boolean allowed) {
476             mBundle.putBoolean(HARD_KEYBOARD_CONFIGURATION_BEHAVIOR_ALLOWED, allowed);
477             return this;
478         }
479 
480         /**
481          * Controls whether inline suggestions are enabled for {@link MockIme}. If enabled, a
482          * suggestion strip will be rendered at the top of the keyboard.
483          *
484          * @param enabled {@code true} when {@link MockIme} is enabled to show inline suggestions.
485          */
setInlineSuggestionsEnabled(boolean enabled)486         public Builder setInlineSuggestionsEnabled(boolean enabled) {
487             mBundle.putBoolean(INLINE_SUGGESTIONS_ENABLED, enabled);
488             return this;
489         }
490 
491         /**
492          * Controls whether inline suggestions are enabled for {@link MockIme}. If enabled, a
493          * suggestion strip will be rendered at the top of the keyboard.
494          *
495          * @param contentDesc content description to be set to the inline suggestion View.
496          */
setInlineSuggestionViewContentDesc(@onNull String contentDesc)497         public Builder setInlineSuggestionViewContentDesc(@NonNull String contentDesc) {
498             mBundle.putString(INLINE_SUGGESTION_VIEW_CONTENT_DESC, contentDesc);
499             return this;
500         }
501 
502         /** Sets whether to enable {@link android.os.StrictMode} or not. */
setStrictModeEnabled(boolean enabled)503         public Builder setStrictModeEnabled(boolean enabled) {
504             mBundle.putBoolean(STRICT_MODE_ENABLED, enabled);
505             return this;
506         }
507 
508         /**
509          * Sets whether to verify below {@link android.content.Context} APIs or not:
510          * <ul>
511          *     <li>{@link android.inputmethodservice.InputMethodService#getDisplay}</li>
512          *     <li>{@link android.inputmethodservice.InputMethodService#isUiContext}</li>
513          * </ul>
514          */
setVerifyUiContextApisInOnCreate(boolean enabled)515         public Builder setVerifyUiContextApisInOnCreate(boolean enabled) {
516             mBundle.putBoolean(VERIFY_CONTEXT_APIS_IN_ON_CREATE, enabled);
517             return this;
518         }
519 
520         /**
521          * Sets whether to enable {@link WindowLayoutInfo} callbacks for {@link MockIme}.
522          */
setWindowLayoutInfoCallbackEnabled(boolean enabled)523         public Builder setWindowLayoutInfoCallbackEnabled(boolean enabled) {
524             mBundle.putBoolean(WINDOW_LAYOUT_INFO_CALLBACK_ENABLED, enabled);
525             return this;
526         }
527 
528         /**
529          * Sets whether to enable {@link
530          * android.inputmethodservice.InputMethodService#onStartConnectionlessStylusHandwriting}.
531          */
setConnectionlessHandwritingEnabled(boolean enabled)532         public Builder setConnectionlessHandwritingEnabled(boolean enabled) {
533             mBundle.putBoolean(CONNECTIONLESS_HANDWRITING_ENABLED, enabled);
534             return this;
535         }
536 
537         /**
538          * Sets whether the IME's
539          * {@link android.content.pm.ApplicationInfo#isOnBackInvokedCallbackEnabled()}
540          * should be set to {@code true}.
541          */
setOnBackCallbackEnabled(boolean enabled)542         public Builder setOnBackCallbackEnabled(boolean enabled) {
543             mBundle.putBoolean(ON_BACK_CALLBACK_ENABLED, enabled);
544             return this;
545         }
546 
547         /** Sets whether or not custom extract view hierarchy should be used. */
setCustomExtractTextViewEnabled(boolean enabled)548         public Builder setCustomExtractTextViewEnabled(boolean enabled) {
549             mBundle.putBoolean(USE_CUSTOM_EXTRACT_TEXT_VIEW, enabled);
550             return this;
551         }
552 
553         /**
554          * Sets whether {@link android.inputmethodservice.InputMethodService#onComputeInsets}
555          * should return zero insets.
556          */
setZeroInsets(boolean enabled)557         public Builder setZeroInsets(boolean enabled) {
558             mBundle.putBoolean(ZERO_INSETS, enabled);
559             return this;
560         }
561     }
562 }
563