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.Parcel;
20 import android.os.PersistableBundle;
21 import androidx.annotation.ColorInt;
22 import androidx.annotation.NonNull;
23 import androidx.annotation.Nullable;
24 
25 /**
26  * An immutable data store to control the behavior of {@link MockIme}.
27  */
28 public class ImeSettings {
29 
30     @NonNull
31     private final String mEventCallbackActionName;
32 
33     private static final String BACKGROUND_COLOR_KEY = "BackgroundColor";
34     private static final String NAVIGATION_BAR_COLOR_KEY = "NavigationBarColor";
35     private static final String INPUT_VIEW_HEIGHT_WITHOUT_SYSTEM_WINDOW_INSET =
36             "InputViewHeightWithoutSystemWindowInset";
37     private static final String WINDOW_FLAGS = "WindowFlags";
38     private static final String WINDOW_FLAGS_MASK = "WindowFlagsMask";
39     private static final String FULLSCREEN_MODE_ALLOWED = "FullscreenModeAllowed";
40     private static final String INPUT_VIEW_SYSTEM_UI_VISIBILITY = "InputViewSystemUiVisibility";
41     private static final String HARD_KEYBOARD_CONFIGURATION_BEHAVIOR_ALLOWED =
42             "HardKeyboardConfigurationBehaviorAllowed";
43 
44     @NonNull
45     private final PersistableBundle mBundle;
46 
ImeSettings(@onNull Parcel parcel)47     ImeSettings(@NonNull Parcel parcel) {
48         mEventCallbackActionName = parcel.readString();
49         mBundle = parcel.readPersistableBundle();
50     }
51 
52     @Nullable
getEventCallbackActionName()53     String getEventCallbackActionName() {
54         return mEventCallbackActionName;
55     }
56 
fullscreenModeAllowed(boolean defaultValue)57     public boolean fullscreenModeAllowed(boolean defaultValue) {
58         return mBundle.getBoolean(FULLSCREEN_MODE_ALLOWED, defaultValue);
59     }
60 
61     @ColorInt
getBackgroundColor(@olorInt int defaultColor)62     public int getBackgroundColor(@ColorInt int defaultColor) {
63         return mBundle.getInt(BACKGROUND_COLOR_KEY, defaultColor);
64     }
65 
hasNavigationBarColor()66     public boolean hasNavigationBarColor() {
67         return mBundle.keySet().contains(NAVIGATION_BAR_COLOR_KEY);
68     }
69 
70     @ColorInt
getNavigationBarColor()71     public int getNavigationBarColor() {
72         return mBundle.getInt(NAVIGATION_BAR_COLOR_KEY);
73     }
74 
getInputViewHeightWithoutSystemWindowInset(int defaultHeight)75     public int getInputViewHeightWithoutSystemWindowInset(int defaultHeight) {
76         return mBundle.getInt(INPUT_VIEW_HEIGHT_WITHOUT_SYSTEM_WINDOW_INSET, defaultHeight);
77     }
78 
getWindowFlags(int defaultFlags)79     public int getWindowFlags(int defaultFlags) {
80         return mBundle.getInt(WINDOW_FLAGS, defaultFlags);
81     }
82 
getWindowFlagsMask(int defaultFlags)83     public int getWindowFlagsMask(int defaultFlags) {
84         return mBundle.getInt(WINDOW_FLAGS_MASK, defaultFlags);
85     }
86 
getInputViewSystemUiVisibility(int defaultFlags)87     public int getInputViewSystemUiVisibility(int defaultFlags) {
88         return mBundle.getInt(INPUT_VIEW_SYSTEM_UI_VISIBILITY, defaultFlags);
89     }
90 
getHardKeyboardConfigurationBehaviorAllowed(boolean defaultValue)91     public boolean getHardKeyboardConfigurationBehaviorAllowed(boolean defaultValue) {
92         return mBundle.getBoolean(HARD_KEYBOARD_CONFIGURATION_BEHAVIOR_ALLOWED, defaultValue);
93     }
94 
writeToParcel(@onNull Parcel parcel, @NonNull String eventCallbackActionName, @Nullable Builder builder)95     static void writeToParcel(@NonNull Parcel parcel, @NonNull String eventCallbackActionName,
96             @Nullable Builder builder) {
97         parcel.writeString(eventCallbackActionName);
98         if (builder != null) {
99             parcel.writePersistableBundle(builder.mBundle);
100         } else {
101             parcel.writePersistableBundle(PersistableBundle.EMPTY);
102         }
103     }
104 
105     /**
106      * The builder class for {@link ImeSettings}.
107      */
108     public static final class Builder {
109         private final PersistableBundle mBundle = new PersistableBundle();
110 
111         /**
112          * Controls whether fullscreen mode is allowed or not.
113          *
114          * <p>By default, fullscreen mode is not allowed in {@link MockIme}.</p>
115          *
116          * @param allowed {@code true} if fullscreen mode is allowed
117          * @see MockIme#onEvaluateFullscreenMode()
118          */
setFullscreenModeAllowed(boolean allowed)119         public Builder setFullscreenModeAllowed(boolean allowed) {
120             mBundle.putBoolean(FULLSCREEN_MODE_ALLOWED, allowed);
121             return this;
122         }
123 
124         /**
125          * Sets the background color of the {@link MockIme}.
126          * @param color background color to be used
127          */
setBackgroundColor(@olorInt int color)128         public Builder setBackgroundColor(@ColorInt int color) {
129             mBundle.putInt(BACKGROUND_COLOR_KEY, color);
130             return this;
131         }
132 
133         /**
134          * Sets the color to be passed to {@link android.view.Window#setNavigationBarColor(int)}.
135          *
136          * @param color color to be passed to {@link android.view.Window#setNavigationBarColor(int)}
137          * @see android.view.View
138          */
setNavigationBarColor(@olorInt int color)139         public Builder setNavigationBarColor(@ColorInt int color) {
140             mBundle.putInt(NAVIGATION_BAR_COLOR_KEY, color);
141             return this;
142         }
143 
144         /**
145          * Sets the input view height measured from the bottom system window inset.
146          * @param height height of the soft input view. This does not include the system window
147          *               inset such as navigation bar
148          */
setInputViewHeightWithoutSystemWindowInset(int height)149         public Builder setInputViewHeightWithoutSystemWindowInset(int height) {
150             mBundle.putInt(INPUT_VIEW_HEIGHT_WITHOUT_SYSTEM_WINDOW_INSET, height);
151             return this;
152         }
153 
154         /**
155          * Sets window flags to be specified to {@link android.view.Window#setFlags(int, int)} of
156          * the main {@link MockIme} window.
157          *
158          * <p>When {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_OVERSCAN} is set,
159          * {@link MockIme} tries to render the navigation bar by itself.</p>
160          *
161          * @param flags flags to be specified
162          * @param flagsMask mask bits that specify what bits need to be cleared before setting
163          *                  {@code flags}
164          * @see android.view.WindowManager
165          */
setWindowFlags(int flags, int flagsMask)166         public Builder setWindowFlags(int flags, int flagsMask) {
167             mBundle.putInt(WINDOW_FLAGS, flags);
168             mBundle.putInt(WINDOW_FLAGS_MASK, flagsMask);
169             return this;
170         }
171 
172         /**
173          * Sets flags to be specified to {@link android.view.View#setSystemUiVisibility(int)} of
174          * the main soft input view (the returned view from {@link MockIme#onCreateInputView()}).
175          *
176          * @param visibilityFlags flags to be specified
177          * @see android.view.View
178          */
setInputViewSystemUiVisibility(int visibilityFlags)179         public Builder setInputViewSystemUiVisibility(int visibilityFlags) {
180             mBundle.putInt(INPUT_VIEW_SYSTEM_UI_VISIBILITY, visibilityFlags);
181             return this;
182         }
183 
184         /**
185          * Controls whether {@link MockIme} is allowed to change the behavior based on
186          * {@link android.content.res.Configuration#keyboard} and
187          * {@link android.content.res.Configuration#hardKeyboardHidden}.
188          *
189          * <p>Methods in {@link android.inputmethodservice.InputMethodService} such as
190          * {@link android.inputmethodservice.InputMethodService#onEvaluateInputViewShown()} and
191          * {@link android.inputmethodservice.InputMethodService#onShowInputRequested(int, boolean)}
192          * change their behaviors when a hardware keyboard is attached.  This is confusing when
193          * writing tests so by default {@link MockIme} tries to cancel those behaviors.  This
194          * settings re-enables such a behavior.</p>
195          *
196          * @param allowed {@code true} when {@link MockIme} is allowed to change the behavior when
197          *                a hardware keyboard is attached
198          *
199          * @see android.inputmethodservice.InputMethodService#onEvaluateInputViewShown()
200          * @see android.inputmethodservice.InputMethodService#onShowInputRequested(int, boolean)
201          */
setHardKeyboardConfigurationBehaviorAllowed(boolean allowed)202         public Builder setHardKeyboardConfigurationBehaviorAllowed(boolean allowed) {
203             mBundle.putBoolean(HARD_KEYBOARD_CONFIGURATION_BEHAVIOR_ALLOWED, allowed);
204             return this;
205         }
206     }
207 }
208