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 android.os.Bundle; 20 import android.os.PersistableBundle; 21 22 import androidx.annotation.ColorInt; 23 import androidx.annotation.NonNull; 24 import androidx.annotation.Nullable; 25 26 /** 27 * An immutable data store to control the behavior of {@link MockIme}. 28 */ 29 public class ImeSettings { 30 31 @NonNull 32 private final String mClientPackageName; 33 34 @NonNull 35 private final String mEventCallbackActionName; 36 37 private static final String EVENT_CALLBACK_INTENT_ACTION_KEY = "eventCallbackActionName"; 38 private static final String DATA_KEY = "data"; 39 40 private static final String BACKGROUND_COLOR_KEY = "BackgroundColor"; 41 private static final String NAVIGATION_BAR_COLOR_KEY = "NavigationBarColor"; 42 private static final String INPUT_VIEW_HEIGHT = 43 "InputViewHeightWithoutSystemWindowInset"; 44 private static final String DRAWS_BEHIND_NAV_BAR = "drawsBehindNavBar"; 45 private static final String WINDOW_FLAGS = "WindowFlags"; 46 private static final String WINDOW_FLAGS_MASK = "WindowFlagsMask"; 47 private static final String FULLSCREEN_MODE_ALLOWED = "FullscreenModeAllowed"; 48 private static final String INPUT_VIEW_SYSTEM_UI_VISIBILITY = "InputViewSystemUiVisibility"; 49 private static final String WATERMARK_ENABLED = "WatermarkEnabled"; 50 private static final String HARD_KEYBOARD_CONFIGURATION_BEHAVIOR_ALLOWED = 51 "HardKeyboardConfigurationBehaviorAllowed"; 52 private static final String INLINE_SUGGESTIONS_ENABLED = "InlineSuggestionsEnabled"; 53 private static final String INLINE_SUGGESTION_VIEW_CONTENT_DESC = 54 "InlineSuggestionViewContentDesc"; 55 private static final String STRICT_MODE_ENABLED = "StrictModeEnabled"; 56 private static final String VERIFY_GET_DISPLAY_ON_CREATE = "VerifyGetDisplayOnCreate"; 57 58 @NonNull 59 private final PersistableBundle mBundle; 60 ImeSettings(@onNull String clientPackageName, @NonNull Bundle bundle)61 ImeSettings(@NonNull String clientPackageName, @NonNull Bundle bundle) { 62 mClientPackageName = clientPackageName; 63 mEventCallbackActionName = bundle.getString(EVENT_CALLBACK_INTENT_ACTION_KEY); 64 mBundle = bundle.getParcelable(DATA_KEY); 65 } 66 67 @Nullable getEventCallbackActionName()68 String getEventCallbackActionName() { 69 return mEventCallbackActionName; 70 } 71 72 @NonNull getClientPackageName()73 String getClientPackageName() { 74 return mClientPackageName; 75 } 76 fullscreenModeAllowed(boolean defaultValue)77 public boolean fullscreenModeAllowed(boolean defaultValue) { 78 return mBundle.getBoolean(FULLSCREEN_MODE_ALLOWED, defaultValue); 79 } 80 81 @ColorInt getBackgroundColor(@olorInt int defaultColor)82 public int getBackgroundColor(@ColorInt int defaultColor) { 83 return mBundle.getInt(BACKGROUND_COLOR_KEY, defaultColor); 84 } 85 hasNavigationBarColor()86 public boolean hasNavigationBarColor() { 87 return mBundle.keySet().contains(NAVIGATION_BAR_COLOR_KEY); 88 } 89 90 @ColorInt getNavigationBarColor()91 public int getNavigationBarColor() { 92 return mBundle.getInt(NAVIGATION_BAR_COLOR_KEY); 93 } 94 getInputViewHeight(int defaultHeight)95 public int getInputViewHeight(int defaultHeight) { 96 return mBundle.getInt(INPUT_VIEW_HEIGHT, defaultHeight); 97 } 98 getDrawsBehindNavBar()99 public boolean getDrawsBehindNavBar() { 100 return mBundle.getBoolean(DRAWS_BEHIND_NAV_BAR, false); 101 } 102 getWindowFlags(int defaultFlags)103 public int getWindowFlags(int defaultFlags) { 104 return mBundle.getInt(WINDOW_FLAGS, defaultFlags); 105 } 106 getWindowFlagsMask(int defaultFlags)107 public int getWindowFlagsMask(int defaultFlags) { 108 return mBundle.getInt(WINDOW_FLAGS_MASK, defaultFlags); 109 } 110 getInputViewSystemUiVisibility(int defaultFlags)111 public int getInputViewSystemUiVisibility(int defaultFlags) { 112 return mBundle.getInt(INPUT_VIEW_SYSTEM_UI_VISIBILITY, defaultFlags); 113 } 114 isWatermarkEnabled(boolean defaultValue)115 public boolean isWatermarkEnabled(boolean defaultValue) { 116 return mBundle.getBoolean(WATERMARK_ENABLED, defaultValue); 117 } 118 getHardKeyboardConfigurationBehaviorAllowed(boolean defaultValue)119 public boolean getHardKeyboardConfigurationBehaviorAllowed(boolean defaultValue) { 120 return mBundle.getBoolean(HARD_KEYBOARD_CONFIGURATION_BEHAVIOR_ALLOWED, defaultValue); 121 } 122 getInlineSuggestionsEnabled()123 public boolean getInlineSuggestionsEnabled() { 124 return mBundle.getBoolean(INLINE_SUGGESTIONS_ENABLED); 125 } 126 127 @Nullable getInlineSuggestionViewContentDesc(@ullable String defaultValue)128 public String getInlineSuggestionViewContentDesc(@Nullable String defaultValue) { 129 return mBundle.getString(INLINE_SUGGESTION_VIEW_CONTENT_DESC, defaultValue); 130 } 131 isStrictModeEnabled()132 public boolean isStrictModeEnabled() { 133 return mBundle.getBoolean(STRICT_MODE_ENABLED, false); 134 } 135 isVerifyGetDisplayOnCreate()136 public boolean isVerifyGetDisplayOnCreate() { 137 return mBundle.getBoolean(VERIFY_GET_DISPLAY_ON_CREATE, false); 138 } 139 serializeToBundle(@onNull String eventCallbackActionName, @Nullable Builder builder)140 static Bundle serializeToBundle(@NonNull String eventCallbackActionName, 141 @Nullable Builder builder) { 142 final Bundle result = new Bundle(); 143 result.putString(EVENT_CALLBACK_INTENT_ACTION_KEY, eventCallbackActionName); 144 result.putParcelable(DATA_KEY, builder != null ? builder.mBundle : PersistableBundle.EMPTY); 145 return result; 146 } 147 148 /** 149 * The builder class for {@link ImeSettings}. 150 */ 151 public static final class Builder { 152 private final PersistableBundle mBundle = new PersistableBundle(); 153 154 /** 155 * Controls whether fullscreen mode is allowed or not. 156 * 157 * <p>By default, fullscreen mode is not allowed in {@link MockIme}.</p> 158 * 159 * @param allowed {@code true} if fullscreen mode is allowed 160 * @see MockIme#onEvaluateFullscreenMode() 161 */ setFullscreenModeAllowed(boolean allowed)162 public Builder setFullscreenModeAllowed(boolean allowed) { 163 mBundle.putBoolean(FULLSCREEN_MODE_ALLOWED, allowed); 164 return this; 165 } 166 167 /** 168 * Sets the background color of the {@link MockIme}. 169 * @param color background color to be used 170 */ setBackgroundColor(@olorInt int color)171 public Builder setBackgroundColor(@ColorInt int color) { 172 mBundle.putInt(BACKGROUND_COLOR_KEY, color); 173 return this; 174 } 175 176 /** 177 * Sets the color to be passed to {@link android.view.Window#setNavigationBarColor(int)}. 178 * 179 * @param color color to be passed to {@link android.view.Window#setNavigationBarColor(int)} 180 * @see android.view.View 181 */ setNavigationBarColor(@olorInt int color)182 public Builder setNavigationBarColor(@ColorInt int color) { 183 mBundle.putInt(NAVIGATION_BAR_COLOR_KEY, color); 184 return this; 185 } 186 187 /** 188 * Sets the input view height measured from the bottom of the screen. 189 * 190 * @param height height of the soft input view. This includes the system window inset such 191 * as navigation bar. 192 */ setInputViewHeight(int height)193 public Builder setInputViewHeight(int height) { 194 mBundle.putInt(INPUT_VIEW_HEIGHT, height); 195 return this; 196 } 197 198 /** 199 * Sets whether IME draws behind navigation bar. 200 */ setDrawsBehindNavBar(boolean drawsBehindNavBar)201 public Builder setDrawsBehindNavBar(boolean drawsBehindNavBar) { 202 mBundle.putBoolean(DRAWS_BEHIND_NAV_BAR, drawsBehindNavBar); 203 return this; 204 } 205 206 /** 207 * Sets window flags to be specified to {@link android.view.Window#setFlags(int, int)} of 208 * the main {@link MockIme} window. 209 * 210 * <p>When {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_OVERSCAN} is set, 211 * {@link MockIme} tries to render the navigation bar by itself.</p> 212 * 213 * @param flags flags to be specified 214 * @param flagsMask mask bits that specify what bits need to be cleared before setting 215 * {@code flags} 216 * @see android.view.WindowManager 217 */ setWindowFlags(int flags, int flagsMask)218 public Builder setWindowFlags(int flags, int flagsMask) { 219 mBundle.putInt(WINDOW_FLAGS, flags); 220 mBundle.putInt(WINDOW_FLAGS_MASK, flagsMask); 221 return this; 222 } 223 224 /** 225 * Sets flags to be specified to {@link android.view.View#setSystemUiVisibility(int)} of 226 * the main soft input view (the returned view from {@link MockIme#onCreateInputView()}). 227 * 228 * @param visibilityFlags flags to be specified 229 * @see android.view.View 230 */ setInputViewSystemUiVisibility(int visibilityFlags)231 public Builder setInputViewSystemUiVisibility(int visibilityFlags) { 232 mBundle.putInt(INPUT_VIEW_SYSTEM_UI_VISIBILITY, visibilityFlags); 233 return this; 234 } 235 236 /** 237 * Sets whether a unique watermark image needs to be shown on the software keyboard or not. 238 * 239 * <p>This needs to be enabled to use</p> 240 * 241 * @param enabled {@code true} when such a watermark image is requested. 242 */ setWatermarkEnabled(boolean enabled)243 public Builder setWatermarkEnabled(boolean enabled) { 244 mBundle.putBoolean(WATERMARK_ENABLED, enabled); 245 return this; 246 } 247 248 /** 249 * Controls whether {@link MockIme} is allowed to change the behavior based on 250 * {@link android.content.res.Configuration#keyboard} and 251 * {@link android.content.res.Configuration#hardKeyboardHidden}. 252 * 253 * <p>Methods in {@link android.inputmethodservice.InputMethodService} such as 254 * {@link android.inputmethodservice.InputMethodService#onEvaluateInputViewShown()} and 255 * {@link android.inputmethodservice.InputMethodService#onShowInputRequested(int, boolean)} 256 * change their behaviors when a hardware keyboard is attached. This is confusing when 257 * writing tests so by default {@link MockIme} tries to cancel those behaviors. This 258 * settings re-enables such a behavior.</p> 259 * 260 * @param allowed {@code true} when {@link MockIme} is allowed to change the behavior when 261 * a hardware keyboard is attached 262 * 263 * @see android.inputmethodservice.InputMethodService#onEvaluateInputViewShown() 264 * @see android.inputmethodservice.InputMethodService#onShowInputRequested(int, boolean) 265 */ setHardKeyboardConfigurationBehaviorAllowed(boolean allowed)266 public Builder setHardKeyboardConfigurationBehaviorAllowed(boolean allowed) { 267 mBundle.putBoolean(HARD_KEYBOARD_CONFIGURATION_BEHAVIOR_ALLOWED, allowed); 268 return this; 269 } 270 271 /** 272 * Controls whether inline suggestions are enabled for {@link MockIme}. If enabled, a 273 * suggestion strip will be rendered at the top of the keyboard. 274 * 275 * @param enabled {@code true} when {@link MockIme} is enabled to show inline suggestions. 276 */ setInlineSuggestionsEnabled(boolean enabled)277 public Builder setInlineSuggestionsEnabled(boolean enabled) { 278 mBundle.putBoolean(INLINE_SUGGESTIONS_ENABLED, enabled); 279 return this; 280 } 281 282 /** 283 * Controls whether inline suggestions are enabled for {@link MockIme}. If enabled, a 284 * suggestion strip will be rendered at the top of the keyboard. 285 * 286 * @param contentDesc content description to be set to the inline suggestion View. 287 */ setInlineSuggestionViewContentDesc(@onNull String contentDesc)288 public Builder setInlineSuggestionViewContentDesc(@NonNull String contentDesc) { 289 mBundle.putString(INLINE_SUGGESTION_VIEW_CONTENT_DESC, contentDesc); 290 return this; 291 } 292 293 /** Sets whether to enable {@link android.os.StrictMode} or not. */ setStrictModeEnabled(boolean enabled)294 public Builder setStrictModeEnabled(boolean enabled) { 295 mBundle.putBoolean(STRICT_MODE_ENABLED, enabled); 296 return this; 297 } 298 299 /** 300 * Sets whether to verify {@link android.inputmethodservice.InputMethodService#getDisplay()} 301 * or not. 302 */ setVerifyGetDisplayOnCreate(boolean enabled)303 public Builder setVerifyGetDisplayOnCreate(boolean enabled) { 304 mBundle.putBoolean(VERIFY_GET_DISPLAY_ON_CREATE, enabled); 305 return this; 306 } 307 } 308 } 309