1 /*
2  * Copyright (C) 2022 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 android.hardware.input;
18 
19 import android.annotation.NonNull;
20 import android.annotation.SystemApi;
21 import android.icu.util.ULocale;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 
25 import java.util.Objects;
26 
27 
28 /**
29  * Configurations to create virtual keyboard.
30  *
31  * @hide
32  */
33 @SystemApi
34 public final class VirtualKeyboardConfig extends VirtualInputDeviceConfig implements Parcelable {
35     /**
36      * Default language tag when creating virtual keyboard. Used when the language tag is not set.
37      */
38     public static final String DEFAULT_LANGUAGE_TAG = "en-Latn-US";
39     /** Default layout type when creating virtual keyboard. Used when the layout type is not set. */
40     public static final String DEFAULT_LAYOUT_TYPE = "qwerty";
41 
42     @NonNull
43     private final String mLanguageTag;
44 
45     @NonNull
46     private final String mLayoutType;
47 
48     @NonNull
49     public static final Creator<VirtualKeyboardConfig> CREATOR =
50             new Creator<VirtualKeyboardConfig>() {
51                 @Override
52                 public VirtualKeyboardConfig createFromParcel(Parcel in) {
53                     return new VirtualKeyboardConfig(in);
54                 }
55 
56                 @Override
57                 public VirtualKeyboardConfig[] newArray(int size) {
58                     return new VirtualKeyboardConfig[size];
59                 }
60             };
61 
VirtualKeyboardConfig(@onNull Builder builder)62     private VirtualKeyboardConfig(@NonNull Builder builder) {
63         super(builder);
64         mLanguageTag = builder.mLanguageTag;
65         mLayoutType = builder.mLayoutType;
66     }
67 
VirtualKeyboardConfig(@onNull Parcel in)68     private VirtualKeyboardConfig(@NonNull Parcel in) {
69         super(in);
70         mLanguageTag = in.readString8();
71         mLayoutType = in.readString8();
72     }
73 
74     /**
75      * @see Builder#setLanguageTag().
76      */
77     @NonNull
getLanguageTag()78     public String getLanguageTag() {
79         return mLanguageTag;
80     }
81 
82     /**
83      * @see Builder#setLayoutType().
84      */
85     @NonNull
getLayoutType()86     public String getLayoutType() {
87         return mLayoutType;
88     }
89 
90     @Override
describeContents()91     public int describeContents() {
92         return 0;
93     }
94 
95     @Override
writeToParcel(@onNull Parcel dest, int flags)96     public void writeToParcel(@NonNull Parcel dest, int flags) {
97         super.writeToParcel(dest, flags);
98         dest.writeString8(mLanguageTag);
99         dest.writeString8(mLayoutType);
100     }
101 
102     /**
103      * Builder for creating a {@link VirtualKeyboardConfig}.
104      */
105     public static final class Builder extends VirtualInputDeviceConfig.Builder<Builder> {
106         @NonNull
107         private String mLanguageTag = DEFAULT_LANGUAGE_TAG;
108         @NonNull
109         private String mLayoutType = DEFAULT_LAYOUT_TYPE;
110 
111         /**
112          * Sets the preferred input language of the virtual keyboard using an IETF
113          * <a href="https://tools.ietf.org/html/bcp47">BCP-47</a>  conformant tag.
114          *
115          * The passed in {@code languageTag} will be canonized using {@link
116          * ULocale} and used by the system as a hint to configure the keyboard layout.
117          *
118          * If {@code languageTag} is not specified, the virtual keyboard will be created with {@link
119          * #DEFAULT_LANGUAGE_TAG}.
120          *
121          * Note that the preferred layout is not guaranteed. If the specified language is
122          * well-formed but not supported, the keyboard will be using English US QWERTY layout.
123          *
124          * In case where the owning Virtual Device has created multiple virtual keyboards, only the
125          * {@code languageTag} of the most recent virtual keyboard will be kept to hint the locale
126          * of the Virtual Device.
127          *
128          *  @throws IllegalArgumentException if either of the language or country is not present in
129          *  the language tag.
130          */
131         @NonNull
setLanguageTag(@onNull String languageTag)132         public Builder setLanguageTag(@NonNull String languageTag) {
133             Objects.requireNonNull(languageTag, "languageTag cannot be null");
134             ULocale locale = ULocale.forLanguageTag(languageTag);
135             if (locale.getLanguage().isEmpty()) {
136                 throw new IllegalArgumentException("The language tag is not valid.");
137             }
138             mLanguageTag = ULocale.createCanonical(locale).toLanguageTag();
139             return this;
140         }
141 
142         /**
143          * Sets the preferred layout type of the virtual keyboard. See {@code keyboardLayoutType}
144          * attribute in frameworks/base/core/res/res/values/attrs.xml for a list of supported
145          * layout types.
146          *
147          * Note that the preferred layout is not guaranteed. If the specified layout type is
148          * well-formed but not supported, the keyboard will be using English US QWERTY layout.
149          *
150          * If not specified, the virtual keyboard will be created with {@link #DEFAULT_LAYOUT_TYPE}.
151          */
152         @NonNull
setLayoutType(@onNull String layoutType)153         public Builder setLayoutType(@NonNull String layoutType) {
154             Objects.requireNonNull(layoutType, "layoutType cannot be null");
155             mLayoutType = layoutType;
156             return this;
157         }
158 
159         /**
160          * Builds the {@link VirtualKeyboardConfig} instance.
161          */
162         @NonNull
build()163         public VirtualKeyboardConfig build() {
164             return new VirtualKeyboardConfig(this);
165         }
166     }
167 }
168