blob: ac1cbd4619df920ebc08e8cf309c9de8c6557597 [file] [log] [blame]
Kenny Root15a4d2f2010-03-11 18:20:12 -08001/*
2 * Copyright (C) 2008 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017package android.content.res;
18
Dianne Hackborn337e01a2018-02-27 17:16:37 -080019import static android.content.ConfigurationProto.COLOR_MODE;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070020import static android.content.ConfigurationProto.DENSITY_DPI;
21import static android.content.ConfigurationProto.FONT_SCALE;
Dianne Hackbornbf5ba6b2018-02-20 10:31:02 -080022import static android.content.ConfigurationProto.HARD_KEYBOARD_HIDDEN;
Dianne Hackborn337e01a2018-02-27 17:16:37 -080023import static android.content.ConfigurationProto.KEYBOARD;
Dianne Hackbornbf5ba6b2018-02-20 10:31:02 -080024import static android.content.ConfigurationProto.KEYBOARD_HIDDEN;
25import static android.content.ConfigurationProto.LOCALES;
Varun Shah5e674622019-09-10 14:41:00 -040026import static android.content.ConfigurationProto.LOCALE_LIST;
Dianne Hackbornbf5ba6b2018-02-20 10:31:02 -080027import static android.content.ConfigurationProto.MCC;
28import static android.content.ConfigurationProto.MNC;
29import static android.content.ConfigurationProto.NAVIGATION;
30import static android.content.ConfigurationProto.NAVIGATION_HIDDEN;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070031import static android.content.ConfigurationProto.ORIENTATION;
32import static android.content.ConfigurationProto.SCREEN_HEIGHT_DP;
33import static android.content.ConfigurationProto.SCREEN_LAYOUT;
34import static android.content.ConfigurationProto.SCREEN_WIDTH_DP;
35import static android.content.ConfigurationProto.SMALLEST_SCREEN_WIDTH_DP;
Dianne Hackbornbf5ba6b2018-02-20 10:31:02 -080036import static android.content.ConfigurationProto.TOUCHSCREEN;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070037import static android.content.ConfigurationProto.UI_MODE;
38import static android.content.ConfigurationProto.WINDOW_CONFIGURATION;
Dianne Hackbornbf5ba6b2018-02-20 10:31:02 -080039import static android.content.ResourcesConfigurationProto.CONFIGURATION;
40import static android.content.ResourcesConfigurationProto.SCREEN_HEIGHT_PX;
41import static android.content.ResourcesConfigurationProto.SCREEN_WIDTH_PX;
42import static android.content.ResourcesConfigurationProto.SDK_VERSION;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070043
Alan Viveretteac85f902016-03-11 15:15:51 -050044import android.annotation.IntDef;
45import android.annotation.NonNull;
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -070046import android.annotation.Nullable;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070047import android.annotation.TestApi;
Mathew Inwood5c0d3542018-08-14 13:54:31 +010048import android.annotation.UnsupportedAppUsage;
Wale Ogunwale822e5122017-07-26 06:02:24 -070049import android.app.WindowConfiguration;
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -070050import android.content.LocaleProto;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051import android.content.pm.ActivityInfo;
Alan Viveretteac85f902016-03-11 15:15:51 -050052import android.content.pm.ActivityInfo.Config;
Adam Lesinski2c749d22014-06-04 13:00:29 -070053import android.os.Build;
Yohei Yukawa23cbe852016-05-17 16:42:58 -070054import android.os.LocaleList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.os.Parcel;
56import android.os.Parcelable;
Fabrice Di Megliod3d9f3f2012-09-18 12:55:32 -070057import android.text.TextUtils;
Dianne Hackbornbf5ba6b2018-02-20 10:31:02 -080058import android.util.DisplayMetrics;
Varun Shah95fabaf2019-05-01 12:45:37 -070059import android.util.Slog;
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -070060import android.util.proto.ProtoInputStream;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070061import android.util.proto.ProtoOutputStream;
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -070062import android.util.proto.WireTypeMismatchException;
Fabrice Di Meglio3fb824b2012-02-28 17:58:31 -080063import android.view.View;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064
Romain Guye89d0bb2017-06-20 12:23:42 -070065import com.android.internal.util.XmlUtils;
66
67import org.xmlpull.v1.XmlPullParser;
68import org.xmlpull.v1.XmlPullParserException;
69import org.xmlpull.v1.XmlSerializer;
70
Adam Lesinski7f61e962014-09-02 16:43:52 -070071import java.io.IOException;
Alan Viveretteac85f902016-03-11 15:15:51 -050072import java.lang.annotation.Retention;
73import java.lang.annotation.RetentionPolicy;
Adam Lesinski2c749d22014-06-04 13:00:29 -070074import java.util.ArrayList;
Varun Shah95fabaf2019-05-01 12:45:37 -070075import java.util.IllformedLocaleException;
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -070076import java.util.List;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077import java.util.Locale;
78
79/**
80 * This class describes all device configuration information that can
81 * impact the resources the application retrieves. This includes both
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -070082 * user-specified configuration options (locale list and scaling) as well
Scott Main63848e32011-04-20 22:20:46 -070083 * as device configurations (such as input modes, screen size and screen orientation).
84 * <p>You can acquire this object from {@link Resources}, using {@link
85 * Resources#getConfiguration}. Thus, from an activity, you can get it by chaining the request
86 * with {@link android.app.Activity#getResources}:</p>
87 * <pre>Configuration config = getResources().getConfiguration();</pre>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088 */
89public final class Configuration implements Parcelable, Comparable<Configuration> {
Dianne Hackborn756220b2012-08-14 16:45:30 -070090 /** @hide */
91 public static final Configuration EMPTY = new Configuration();
92
Varun Shah95fabaf2019-05-01 12:45:37 -070093 private static final String TAG = "Configuration";
94
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095 /**
96 * Current user preference for the scaling factor for fonts, relative
97 * to the base density scaling.
98 */
99 public float fontScale;
100
101 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700102 * IMSI MCC (Mobile Country Code), corresponding to
103 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#MccQualifier">mcc</a>
104 * resource qualifier. 0 if undefined.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105 */
106 public int mcc;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700107
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700109 * IMSI MNC (Mobile Network Code), corresponding to
110 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#MccQualifier">mnc</a>
Mattias Petersson1d766b52011-10-07 09:33:52 +0200111 * resource qualifier. 0 if undefined. Note that the actual MNC may be 0; in order to check
112 * for this use the {@link #MNC_ZERO} symbol.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113 */
114 public int mnc;
Mattias Petersson1d766b52011-10-07 09:33:52 +0200115
116 /**
117 * Constant used to to represent MNC (Mobile Network Code) zero.
118 * 0 cannot be used, since it is used to represent an undefined MNC.
119 */
120 public static final int MNC_ZERO = 0xffff;
121
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700123 * Current user preference for the locale, corresponding to
124 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#LocaleQualifier">locale</a>
125 * resource qualifier.
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700126 *
127 * @deprecated Do not set or read this directly. Use {@link #getLocales()} and
Raph Levienb1638702016-04-27 11:02:12 -0700128 * {@link #setLocales(LocaleList)}. If only the primary locale is needed,
129 * <code>getLocales().get(0)</code> is now the preferred accessor.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800130 */
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700131 @Deprecated public Locale locale;
132
133 private LocaleList mLocaleList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134
135 /**
Andy Stadlerf8a7cea2009-04-10 16:24:47 -0700136 * Locale should persist on setting. This is hidden because it is really
137 * questionable whether this is the right way to expose the functionality.
138 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100140 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141 public boolean userSetLocale;
142
Romain Guyc9ba5592017-01-18 16:34:42 -0800143
Romain Guy48327452017-01-23 17:03:35 -0800144 /** Constant for {@link #colorMode}: bits that encode whether the screen is wide gamut. */
145 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_MASK = 0x3;
Romain Guyc9ba5592017-01-18 16:34:42 -0800146 /**
Romain Guy48327452017-01-23 17:03:35 -0800147 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800148 * indicating that it is unknown whether or not the screen is wide gamut.
149 */
Romain Guy48327452017-01-23 17:03:35 -0800150 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED = 0x0;
Romain Guyc9ba5592017-01-18 16:34:42 -0800151 /**
Romain Guy48327452017-01-23 17:03:35 -0800152 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800153 * indicating that the screen is not wide gamut.
154 * <p>Corresponds to the <code>-nowidecg</code> resource qualifier.</p>
155 */
Romain Guy48327452017-01-23 17:03:35 -0800156 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_NO = 0x1;
Romain Guyc9ba5592017-01-18 16:34:42 -0800157 /**
Romain Guy48327452017-01-23 17:03:35 -0800158 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800159 * indicating that the screen is wide gamut.
160 * <p>Corresponds to the <code>-widecg</code> resource qualifier.</p>
161 */
Romain Guy48327452017-01-23 17:03:35 -0800162 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_YES = 0x2;
Romain Guyc9ba5592017-01-18 16:34:42 -0800163
Romain Guyb3f69262017-04-13 20:06:41 -0700164 /** Constant for {@link #colorMode}: bits that encode the dynamic range of the screen. */
Romain Guy48327452017-01-23 17:03:35 -0800165 public static final int COLOR_MODE_HDR_MASK = 0xc;
166 /** Constant for {@link #colorMode}: bits shift to get the screen dynamic range. */
167 public static final int COLOR_MODE_HDR_SHIFT = 2;
Romain Guyc9ba5592017-01-18 16:34:42 -0800168 /**
Romain Guy48327452017-01-23 17:03:35 -0800169 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_HDR_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800170 * indicating that it is unknown whether or not the screen is HDR.
171 */
Romain Guy48327452017-01-23 17:03:35 -0800172 public static final int COLOR_MODE_HDR_UNDEFINED = 0x0;
Romain Guyc9ba5592017-01-18 16:34:42 -0800173 /**
Romain Guy48327452017-01-23 17:03:35 -0800174 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_HDR_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800175 * indicating that the screen is not HDR (low/standard dynamic range).
176 * <p>Corresponds to the <code>-lowdr</code> resource qualifier.</p>
177 */
Romain Guy48327452017-01-23 17:03:35 -0800178 public static final int COLOR_MODE_HDR_NO = 0x1 << COLOR_MODE_HDR_SHIFT;
Romain Guyc9ba5592017-01-18 16:34:42 -0800179 /**
Romain Guy48327452017-01-23 17:03:35 -0800180 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_HDR_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800181 * indicating that the screen is HDR (dynamic range).
182 * <p>Corresponds to the <code>-highdr</code> resource qualifier.</p>
183 */
Romain Guy48327452017-01-23 17:03:35 -0800184 public static final int COLOR_MODE_HDR_YES = 0x2 << COLOR_MODE_HDR_SHIFT;
Romain Guyc9ba5592017-01-18 16:34:42 -0800185
Romain Guy48327452017-01-23 17:03:35 -0800186 /** Constant for {@link #colorMode}: a value indicating that the color mode is undefined */
Romain Guyc9ba5592017-01-18 16:34:42 -0800187 @SuppressWarnings("PointlessBitwiseExpression")
Romain Guy48327452017-01-23 17:03:35 -0800188 public static final int COLOR_MODE_UNDEFINED = COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED |
189 COLOR_MODE_HDR_UNDEFINED;
Romain Guyc9ba5592017-01-18 16:34:42 -0800190
191 /**
Romain Guyb3f69262017-04-13 20:06:41 -0700192 * Bit mask of color capabilities of the screen. Currently there are two fields:
Romain Guy48327452017-01-23 17:03:35 -0800193 * <p>The {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} bits define the color gamut of
Romain Guyc9ba5592017-01-18 16:34:42 -0800194 * the screen. They may be one of
Romain Guy48327452017-01-23 17:03:35 -0800195 * {@link #COLOR_MODE_WIDE_COLOR_GAMUT_NO} or {@link #COLOR_MODE_WIDE_COLOR_GAMUT_YES}.</p>
Romain Guyc9ba5592017-01-18 16:34:42 -0800196 *
Romain Guy48327452017-01-23 17:03:35 -0800197 * <p>The {@link #COLOR_MODE_HDR_MASK} defines the dynamic range of the screen. They may be
198 * one of {@link #COLOR_MODE_HDR_NO} or {@link #COLOR_MODE_HDR_YES}.</p>
Romain Guyc9ba5592017-01-18 16:34:42 -0800199 *
200 * <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
201 * Multiple Screens</a> for more information.</p>
202 */
Romain Guy48327452017-01-23 17:03:35 -0800203 public int colorMode;
Romain Guyc9ba5592017-01-18 16:34:42 -0800204
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700205 /** Constant for {@link #screenLayout}: bits that encode the size. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700206 public static final int SCREENLAYOUT_SIZE_MASK = 0x0f;
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700207 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
208 * value indicating that no size has been set. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700209 public static final int SCREENLAYOUT_SIZE_UNDEFINED = 0x00;
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700210 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700211 * value indicating the screen is at least approximately 320x426 dp units,
212 * corresponds to the
213 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">small</a>
214 * resource qualifier.
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700215 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
216 * Multiple Screens</a> for more information. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700217 public static final int SCREENLAYOUT_SIZE_SMALL = 0x01;
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700218 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700219 * value indicating the screen is at least approximately 320x470 dp units,
220 * corresponds to the
221 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">normal</a>
222 * resource qualifier.
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700223 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
224 * Multiple Screens</a> for more information. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700225 public static final int SCREENLAYOUT_SIZE_NORMAL = 0x02;
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700226 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700227 * value indicating the screen is at least approximately 480x640 dp units,
228 * corresponds to the
229 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">large</a>
230 * resource qualifier.
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700231 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
232 * Multiple Screens</a> for more information. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700233 public static final int SCREENLAYOUT_SIZE_LARGE = 0x03;
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700234 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700235 * value indicating the screen is at least approximately 720x960 dp units,
236 * corresponds to the
237 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">xlarge</a>
238 * resource qualifier.
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700239 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
240 * Multiple Screens</a> for more information.*/
Dianne Hackborn14cee9f2010-04-23 17:51:26 -0700241 public static final int SCREENLAYOUT_SIZE_XLARGE = 0x04;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700242
243 /** Constant for {@link #screenLayout}: bits that encode the aspect ratio. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700244 public static final int SCREENLAYOUT_LONG_MASK = 0x30;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700245 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
246 * value indicating that no size has been set. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700247 public static final int SCREENLAYOUT_LONG_UNDEFINED = 0x00;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700248 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
249 * value that corresponds to the
250 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenAspectQualifier">notlong</a>
251 * resource qualifier. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700252 public static final int SCREENLAYOUT_LONG_NO = 0x10;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700253 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
254 * value that corresponds to the
255 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenAspectQualifier">long</a>
256 * resource qualifier. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700257 public static final int SCREENLAYOUT_LONG_YES = 0x20;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700258
259 /** Constant for {@link #screenLayout}: bits that encode the layout direction. */
260 public static final int SCREENLAYOUT_LAYOUTDIR_MASK = 0xC0;
261 /** Constant for {@link #screenLayout}: bits shift to get the layout direction. */
262 public static final int SCREENLAYOUT_LAYOUTDIR_SHIFT = 6;
263 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
264 * value indicating that no layout dir has been set. */
265 public static final int SCREENLAYOUT_LAYOUTDIR_UNDEFINED = 0x00;
266 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
267 * value indicating that a layout dir has been set to LTR. */
268 public static final int SCREENLAYOUT_LAYOUTDIR_LTR = 0x01 << SCREENLAYOUT_LAYOUTDIR_SHIFT;
269 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
270 * value indicating that a layout dir has been set to RTL. */
271 public static final int SCREENLAYOUT_LAYOUTDIR_RTL = 0x02 << SCREENLAYOUT_LAYOUTDIR_SHIFT;
272
Adam Powell49e7ff92015-05-14 16:18:53 -0700273 /** Constant for {@link #screenLayout}: bits that encode roundness of the screen. */
274 public static final int SCREENLAYOUT_ROUND_MASK = 0x300;
275 /** @hide Constant for {@link #screenLayout}: bit shift to get to screen roundness bits */
276 public static final int SCREENLAYOUT_ROUND_SHIFT = 8;
277 /**
278 * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating
279 * that it is unknown whether or not the screen has a round shape.
280 */
281 public static final int SCREENLAYOUT_ROUND_UNDEFINED = 0x00;
282 /**
283 * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating
284 * that the screen does not have a rounded shape.
285 */
286 public static final int SCREENLAYOUT_ROUND_NO = 0x1 << SCREENLAYOUT_ROUND_SHIFT;
287 /**
288 * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating
289 * that the screen has a rounded shape. Corners may not be visible to the user;
290 * developers should pay special attention to the {@link android.view.WindowInsets} delivered
291 * to views for more information about ensuring content is not obscured.
292 *
293 * <p>Corresponds to the <code>-round</code> resource qualifier.</p>
294 */
295 public static final int SCREENLAYOUT_ROUND_YES = 0x2 << SCREENLAYOUT_ROUND_SHIFT;
296
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700297 /** Constant for {@link #screenLayout}: a value indicating that screenLayout is undefined */
298 public static final int SCREENLAYOUT_UNDEFINED = SCREENLAYOUT_SIZE_UNDEFINED |
Adam Powell49e7ff92015-05-14 16:18:53 -0700299 SCREENLAYOUT_LONG_UNDEFINED | SCREENLAYOUT_LAYOUTDIR_UNDEFINED |
300 SCREENLAYOUT_ROUND_UNDEFINED;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700301
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700302 /**
303 * Special flag we generate to indicate that the screen layout requires
304 * us to use a compatibility mode for apps that are not modern layout
305 * aware.
306 * @hide
307 */
308 public static final int SCREENLAYOUT_COMPAT_NEEDED = 0x10000000;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700309
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700310 /**
Andrii Kulianf12fce12016-05-27 17:30:16 -0700311 * Bit mask of overall layout of the screen. Currently there are four
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700312 * fields:
313 * <p>The {@link #SCREENLAYOUT_SIZE_MASK} bits define the overall size
314 * of the screen. They may be one of
315 * {@link #SCREENLAYOUT_SIZE_SMALL}, {@link #SCREENLAYOUT_SIZE_NORMAL},
Adam Powell49e7ff92015-05-14 16:18:53 -0700316 * {@link #SCREENLAYOUT_SIZE_LARGE}, or {@link #SCREENLAYOUT_SIZE_XLARGE}.</p>
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700317 *
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700318 * <p>The {@link #SCREENLAYOUT_LONG_MASK} defines whether the screen
319 * is wider/taller than normal. They may be one of
Adam Powell49e7ff92015-05-14 16:18:53 -0700320 * {@link #SCREENLAYOUT_LONG_NO} or {@link #SCREENLAYOUT_LONG_YES}.</p>
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700321 *
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700322 * <p>The {@link #SCREENLAYOUT_LAYOUTDIR_MASK} defines whether the screen layout
323 * is either LTR or RTL. They may be one of
Adam Powell49e7ff92015-05-14 16:18:53 -0700324 * {@link #SCREENLAYOUT_LAYOUTDIR_LTR} or {@link #SCREENLAYOUT_LAYOUTDIR_RTL}.</p>
325 *
326 * <p>The {@link #SCREENLAYOUT_ROUND_MASK} defines whether the screen has a rounded
327 * shape. They may be one of {@link #SCREENLAYOUT_ROUND_NO} or {@link #SCREENLAYOUT_ROUND_YES}.
328 * </p>
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700329 *
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700330 * <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
Adam Powell49e7ff92015-05-14 16:18:53 -0700331 * Multiple Screens</a> for more information.</p>
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700332 */
333 public int screenLayout;
Dianne Hackbornfe37f8f2012-09-30 12:24:33 -0700334
Bryce Lee7566d762017-03-30 09:34:15 -0700335 /**
Wale Ogunwale822e5122017-07-26 06:02:24 -0700336 * Configuration relating to the windowing state of the object associated with this
337 * Configuration. Contents of this field are not intended to affect resources, but need to be
338 * communicated and propagated at the same time as the rest of Configuration.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -0700339 * @hide
Bryce Lee7566d762017-03-30 09:34:15 -0700340 */
Wale Ogunwale0d5609b2017-09-13 05:55:07 -0700341 @TestApi
Wale Ogunwale822e5122017-07-26 06:02:24 -0700342 public final WindowConfiguration windowConfiguration = new WindowConfiguration();
Bryce Lee7566d762017-03-30 09:34:15 -0700343
Dianne Hackbornfe37f8f2012-09-30 12:24:33 -0700344 /** @hide */
345 static public int resetScreenLayout(int curLayout) {
346 return (curLayout&~(SCREENLAYOUT_LONG_MASK | SCREENLAYOUT_SIZE_MASK
347 | SCREENLAYOUT_COMPAT_NEEDED))
348 | (SCREENLAYOUT_LONG_YES | SCREENLAYOUT_SIZE_XLARGE);
349 }
350
351 /** @hide */
352 static public int reduceScreenLayout(int curLayout, int longSizeDp, int shortSizeDp) {
353 int screenLayoutSize;
354 boolean screenLayoutLong;
355 boolean screenLayoutCompatNeeded;
356
357 // These semi-magic numbers define our compatibility modes for
358 // applications with different screens. These are guarantees to
359 // app developers about the space they can expect for a particular
360 // configuration. DO NOT CHANGE!
361 if (longSizeDp < 470) {
362 // This is shorter than an HVGA normal density screen (which
363 // is 480 pixels on its long side).
364 screenLayoutSize = SCREENLAYOUT_SIZE_SMALL;
365 screenLayoutLong = false;
366 screenLayoutCompatNeeded = false;
367 } else {
368 // What size is this screen screen?
369 if (longSizeDp >= 960 && shortSizeDp >= 720) {
370 // 1.5xVGA or larger screens at medium density are the point
371 // at which we consider it to be an extra large screen.
372 screenLayoutSize = SCREENLAYOUT_SIZE_XLARGE;
373 } else if (longSizeDp >= 640 && shortSizeDp >= 480) {
374 // VGA or larger screens at medium density are the point
375 // at which we consider it to be a large screen.
376 screenLayoutSize = SCREENLAYOUT_SIZE_LARGE;
377 } else {
378 screenLayoutSize = SCREENLAYOUT_SIZE_NORMAL;
379 }
380
381 // If this screen is wider than normal HVGA, or taller
382 // than FWVGA, then for old apps we want to run in size
383 // compatibility mode.
384 if (shortSizeDp > 321 || longSizeDp > 570) {
385 screenLayoutCompatNeeded = true;
386 } else {
387 screenLayoutCompatNeeded = false;
388 }
389
390 // Is this a long screen?
391 if (((longSizeDp*3)/5) >= (shortSizeDp-1)) {
392 // Anything wider than WVGA (5:3) is considering to be long.
393 screenLayoutLong = true;
394 } else {
395 screenLayoutLong = false;
396 }
397 }
398
399 // Now reduce the last screenLayout to not be better than what we
400 // have found.
401 if (!screenLayoutLong) {
402 curLayout = (curLayout&~SCREENLAYOUT_LONG_MASK) | SCREENLAYOUT_LONG_NO;
403 }
404 if (screenLayoutCompatNeeded) {
405 curLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
406 }
407 int curSize = curLayout&SCREENLAYOUT_SIZE_MASK;
408 if (screenLayoutSize < curSize) {
409 curLayout = (curLayout&~SCREENLAYOUT_SIZE_MASK) | screenLayoutSize;
410 }
411 return curLayout;
412 }
413
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700414 /** @hide */
415 public static String configurationDiffToString(int diff) {
416 ArrayList<String> list = new ArrayList<>();
417 if ((diff & ActivityInfo.CONFIG_MCC) != 0) {
418 list.add("CONFIG_MCC");
419 }
420 if ((diff & ActivityInfo.CONFIG_MNC) != 0) {
421 list.add("CONFIG_MNC");
422 }
423 if ((diff & ActivityInfo.CONFIG_LOCALE) != 0) {
424 list.add("CONFIG_LOCALE");
425 }
426 if ((diff & ActivityInfo.CONFIG_TOUCHSCREEN) != 0) {
427 list.add("CONFIG_TOUCHSCREEN");
428 }
429 if ((diff & ActivityInfo.CONFIG_KEYBOARD) != 0) {
430 list.add("CONFIG_KEYBOARD");
431 }
432 if ((diff & ActivityInfo.CONFIG_KEYBOARD_HIDDEN) != 0) {
433 list.add("CONFIG_KEYBOARD_HIDDEN");
434 }
435 if ((diff & ActivityInfo.CONFIG_NAVIGATION) != 0) {
436 list.add("CONFIG_NAVIGATION");
437 }
438 if ((diff & ActivityInfo.CONFIG_ORIENTATION) != 0) {
439 list.add("CONFIG_ORIENTATION");
440 }
441 if ((diff & ActivityInfo.CONFIG_SCREEN_LAYOUT) != 0) {
442 list.add("CONFIG_SCREEN_LAYOUT");
443 }
Romain Guy48327452017-01-23 17:03:35 -0800444 if ((diff & ActivityInfo.CONFIG_COLOR_MODE) != 0) {
445 list.add("CONFIG_COLOR_MODE");
Romain Guyc9ba5592017-01-18 16:34:42 -0800446 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700447 if ((diff & ActivityInfo.CONFIG_UI_MODE) != 0) {
448 list.add("CONFIG_UI_MODE");
449 }
450 if ((diff & ActivityInfo.CONFIG_SCREEN_SIZE) != 0) {
451 list.add("CONFIG_SCREEN_SIZE");
452 }
453 if ((diff & ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE) != 0) {
454 list.add("CONFIG_SMALLEST_SCREEN_SIZE");
455 }
456 if ((diff & ActivityInfo.CONFIG_LAYOUT_DIRECTION) != 0) {
457 list.add("CONFIG_LAYOUT_DIRECTION");
458 }
459 if ((diff & ActivityInfo.CONFIG_FONT_SCALE) != 0) {
460 list.add("CONFIG_FONT_SCALE");
461 }
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +0100462 if ((diff & ActivityInfo.CONFIG_ASSETS_PATHS) != 0) {
463 list.add("CONFIG_ASSETS_PATHS");
464 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700465 StringBuilder builder = new StringBuilder("{");
466 for (int i = 0, n = list.size(); i < n; i++) {
467 builder.append(list.get(i));
468 if (i != n - 1) {
469 builder.append(", ");
470 }
471 }
472 builder.append("}");
473 return builder.toString();
474 }
475
Dianne Hackborn711e62a2010-11-29 16:38:22 -0800476 /**
477 * Check if the Configuration's current {@link #screenLayout} is at
478 * least the given size.
479 *
480 * @param size The desired size, either {@link #SCREENLAYOUT_SIZE_SMALL},
481 * {@link #SCREENLAYOUT_SIZE_NORMAL}, {@link #SCREENLAYOUT_SIZE_LARGE}, or
482 * {@link #SCREENLAYOUT_SIZE_XLARGE}.
483 * @return Returns true if the current screen layout size is at least
484 * the given size.
485 */
486 public boolean isLayoutSizeAtLeast(int size) {
487 int cur = screenLayout&SCREENLAYOUT_SIZE_MASK;
488 if (cur == SCREENLAYOUT_SIZE_UNDEFINED) return false;
Dianne Hackborn7d3a5bc2010-11-29 22:52:12 -0800489 return cur >= size;
Dianne Hackborn711e62a2010-11-29 16:38:22 -0800490 }
491
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700492 /** Constant for {@link #touchscreen}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800493 public static final int TOUCHSCREEN_UNDEFINED = 0;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700494 /** Constant for {@link #touchscreen}, value corresponding to the
495 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#TouchscreenQualifier">notouch</a>
496 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 public static final int TOUCHSCREEN_NOTOUCH = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700498 /** @deprecated Not currently supported or used. */
499 @Deprecated public static final int TOUCHSCREEN_STYLUS = 2;
500 /** Constant for {@link #touchscreen}, value corresponding to the
501 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#TouchscreenQualifier">finger</a>
502 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 public static final int TOUCHSCREEN_FINGER = 3;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700504
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800505 /**
506 * The kind of touch screen attached to the device.
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700507 * One of: {@link #TOUCHSCREEN_NOTOUCH}, {@link #TOUCHSCREEN_FINGER}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800508 */
509 public int touchscreen;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700510
511 /** Constant for {@link #keyboard}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800512 public static final int KEYBOARD_UNDEFINED = 0;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700513 /** Constant for {@link #keyboard}, value corresponding to the
514 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">nokeys</a>
515 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800516 public static final int KEYBOARD_NOKEYS = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700517 /** Constant for {@link #keyboard}, value corresponding to the
518 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">qwerty</a>
519 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800520 public static final int KEYBOARD_QWERTY = 2;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700521 /** Constant for {@link #keyboard}, value corresponding to the
522 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">12key</a>
523 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800524 public static final int KEYBOARD_12KEY = 3;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800526 /**
527 * The kind of keyboard attached to the device.
Kenny Root507f8ed2009-06-09 11:21:11 -0500528 * One of: {@link #KEYBOARD_NOKEYS}, {@link #KEYBOARD_QWERTY},
529 * {@link #KEYBOARD_12KEY}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800530 */
531 public int keyboard;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700532
533 /** Constant for {@link #keyboardHidden}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800534 public static final int KEYBOARDHIDDEN_UNDEFINED = 0;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700535 /** Constant for {@link #keyboardHidden}, value corresponding to the
536 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keysexposed</a>
537 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800538 public static final int KEYBOARDHIDDEN_NO = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700539 /** Constant for {@link #keyboardHidden}, value corresponding to the
540 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keyshidden</a>
541 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800542 public static final int KEYBOARDHIDDEN_YES = 2;
543 /** Constant matching actual resource implementation. {@hide} */
544 public static final int KEYBOARDHIDDEN_SOFT = 3;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700545
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546 /**
547 * A flag indicating whether any keyboard is available. Unlike
548 * {@link #hardKeyboardHidden}, this also takes into account a soft
549 * keyboard, so if the hard keyboard is hidden but there is soft
550 * keyboard available, it will be set to NO. Value is one of:
551 * {@link #KEYBOARDHIDDEN_NO}, {@link #KEYBOARDHIDDEN_YES}.
552 */
553 public int keyboardHidden;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700554
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700555 /** Constant for {@link #hardKeyboardHidden}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 public static final int HARDKEYBOARDHIDDEN_UNDEFINED = 0;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700557 /** Constant for {@link #hardKeyboardHidden}, value corresponding to the
558 * physical keyboard being exposed. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800559 public static final int HARDKEYBOARDHIDDEN_NO = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700560 /** Constant for {@link #hardKeyboardHidden}, value corresponding to the
561 * physical keyboard being hidden. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800562 public static final int HARDKEYBOARDHIDDEN_YES = 2;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700563
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800564 /**
565 * A flag indicating whether the hard keyboard has been hidden. This will
566 * be set on a device with a mechanism to hide the keyboard from the
567 * user, when that mechanism is closed. One of:
568 * {@link #HARDKEYBOARDHIDDEN_NO}, {@link #HARDKEYBOARDHIDDEN_YES}.
569 */
570 public int hardKeyboardHidden;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700571
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700572 /** Constant for {@link #navigation}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800573 public static final int NAVIGATION_UNDEFINED = 0;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700574 /** Constant for {@link #navigation}, value corresponding to the
575 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">nonav</a>
576 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800577 public static final int NAVIGATION_NONAV = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700578 /** Constant for {@link #navigation}, value corresponding to the
579 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">dpad</a>
580 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800581 public static final int NAVIGATION_DPAD = 2;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700582 /** Constant for {@link #navigation}, value corresponding to the
583 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">trackball</a>
584 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800585 public static final int NAVIGATION_TRACKBALL = 3;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700586 /** Constant for {@link #navigation}, value corresponding to the
587 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">wheel</a>
588 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800589 public static final int NAVIGATION_WHEEL = 4;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700590
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800591 /**
592 * The kind of navigation method available on the device.
Kenny Root507f8ed2009-06-09 11:21:11 -0500593 * One of: {@link #NAVIGATION_NONAV}, {@link #NAVIGATION_DPAD},
594 * {@link #NAVIGATION_TRACKBALL}, {@link #NAVIGATION_WHEEL}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595 */
596 public int navigation;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700597
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700598 /** Constant for {@link #navigationHidden}: a value indicating that no value has been set. */
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700599 public static final int NAVIGATIONHIDDEN_UNDEFINED = 0;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700600 /** Constant for {@link #navigationHidden}, value corresponding to the
601 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavAvailQualifier">navexposed</a>
602 * resource qualifier. */
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700603 public static final int NAVIGATIONHIDDEN_NO = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700604 /** Constant for {@link #navigationHidden}, value corresponding to the
605 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavAvailQualifier">navhidden</a>
606 * resource qualifier. */
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700607 public static final int NAVIGATIONHIDDEN_YES = 2;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700608
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700609 /**
610 * A flag indicating whether any 5-way or DPAD navigation available.
611 * This will be set on a device with a mechanism to hide the navigation
612 * controls from the user, when that mechanism is closed. One of:
613 * {@link #NAVIGATIONHIDDEN_NO}, {@link #NAVIGATIONHIDDEN_YES}.
614 */
615 public int navigationHidden;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700616
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700617 /** Constant for {@link #orientation}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800618 public static final int ORIENTATION_UNDEFINED = 0;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700619 /** Constant for {@link #orientation}, value corresponding to the
620 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#OrientationQualifier">port</a>
621 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800622 public static final int ORIENTATION_PORTRAIT = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700623 /** Constant for {@link #orientation}, value corresponding to the
624 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#OrientationQualifier">land</a>
625 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800626 public static final int ORIENTATION_LANDSCAPE = 2;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700627 /** @deprecated Not currently supported or used. */
628 @Deprecated public static final int ORIENTATION_SQUARE = 3;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700629
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800630 /**
631 * Overall orientation of the screen. May be one of
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700632 * {@link #ORIENTATION_LANDSCAPE}, {@link #ORIENTATION_PORTRAIT}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800633 */
634 public int orientation;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100635
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700636 /** Constant for {@link #uiMode}: bits that encode the mode type. */
Tobias Haamel27b28b32010-02-09 23:09:17 +0100637 public static final int UI_MODE_TYPE_MASK = 0x0f;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700638 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
639 * value indicating that no mode type has been set. */
Dianne Hackbornef05e072010-03-01 17:43:39 -0800640 public static final int UI_MODE_TYPE_UNDEFINED = 0x00;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700641 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
642 * value that corresponds to
643 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">no
644 * UI mode</a> resource qualifier specified. */
Dianne Hackbornef05e072010-03-01 17:43:39 -0800645 public static final int UI_MODE_TYPE_NORMAL = 0x01;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700646 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
647 * value that corresponds to the
648 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">desk</a>
649 * resource qualifier. */
Dianne Hackborn7299c412010-03-04 18:41:49 -0800650 public static final int UI_MODE_TYPE_DESK = 0x02;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700651 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
652 * value that corresponds to the
653 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">car</a>
654 * resource qualifier. */
Dianne Hackborn7299c412010-03-04 18:41:49 -0800655 public static final int UI_MODE_TYPE_CAR = 0x03;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700656 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
657 * value that corresponds to the
658 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">television</a>
659 * resource qualifier. */
Dianne Hackborne360bb62011-05-20 16:11:04 -0700660 public static final int UI_MODE_TYPE_TELEVISION = 0x04;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700661 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
662 * value that corresponds to the
663 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">appliance</a>
664 * resource qualifier. */
Joe Onorato44fcb832011-12-14 20:59:30 -0800665 public static final int UI_MODE_TYPE_APPLIANCE = 0x05;
John Spurlock6c191292014-04-03 16:37:27 -0400666 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
667 * value that corresponds to the
668 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">watch</a>
669 * resource qualifier. */
670 public static final int UI_MODE_TYPE_WATCH = 0x06;
Zak Cohen1a6acdb2016-12-12 15:21:21 -0800671 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
672 * value that corresponds to the
673 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">vrheadset</a>
674 * resource qualifier. */
675 public static final int UI_MODE_TYPE_VR_HEADSET = 0x07;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100676
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700677 /** Constant for {@link #uiMode}: bits that encode the night mode. */
Tobias Haamel27b28b32010-02-09 23:09:17 +0100678 public static final int UI_MODE_NIGHT_MASK = 0x30;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700679 /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
680 * value indicating that no mode type has been set. */
Tobias Haamel27b28b32010-02-09 23:09:17 +0100681 public static final int UI_MODE_NIGHT_UNDEFINED = 0x00;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700682 /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
683 * value that corresponds to the
684 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NightQualifier">notnight</a>
685 * resource qualifier. */
Tobias Haamel27b28b32010-02-09 23:09:17 +0100686 public static final int UI_MODE_NIGHT_NO = 0x10;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700687 /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
688 * value that corresponds to the
689 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NightQualifier">night</a>
690 * resource qualifier. */
Tobias Haamel27b28b32010-02-09 23:09:17 +0100691 public static final int UI_MODE_NIGHT_YES = 0x20;
692
693 /**
694 * Bit mask of the ui mode. Currently there are two fields:
695 * <p>The {@link #UI_MODE_TYPE_MASK} bits define the overall ui mode of the
Dianne Hackborn7299c412010-03-04 18:41:49 -0800696 * device. They may be one of {@link #UI_MODE_TYPE_UNDEFINED},
697 * {@link #UI_MODE_TYPE_NORMAL}, {@link #UI_MODE_TYPE_DESK},
John Spurlock6c191292014-04-03 16:37:27 -0400698 * {@link #UI_MODE_TYPE_CAR}, {@link #UI_MODE_TYPE_TELEVISION},
Zak Cohen1a6acdb2016-12-12 15:21:21 -0800699 * {@link #UI_MODE_TYPE_APPLIANCE}, {@link #UI_MODE_TYPE_WATCH},
700 * or {@link #UI_MODE_TYPE_VR_HEADSET}.
Tobias Haamel27b28b32010-02-09 23:09:17 +0100701 *
702 * <p>The {@link #UI_MODE_NIGHT_MASK} defines whether the screen
Dianne Hackborn7299c412010-03-04 18:41:49 -0800703 * is in a special mode. They may be one of {@link #UI_MODE_NIGHT_UNDEFINED},
Tobias Haamel27b28b32010-02-09 23:09:17 +0100704 * {@link #UI_MODE_NIGHT_NO} or {@link #UI_MODE_NIGHT_YES}.
Tobias Haamel27b28b32010-02-09 23:09:17 +0100705 */
706 public int uiMode;
707
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700708 /**
709 * Default value for {@link #screenWidthDp} indicating that no width
710 * has been specified.
711 */
Dianne Hackbornebff8f92011-05-12 18:07:47 -0700712 public static final int SCREEN_WIDTH_DP_UNDEFINED = 0;
713
714 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700715 * The current width of the available screen space, in dp units,
716 * corresponding to
717 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenWidthQualifier">screen
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700718 * width</a> resource qualifier. Set to
719 * {@link #SCREEN_WIDTH_DP_UNDEFINED} if no width is specified.
Dianne Hackbornebff8f92011-05-12 18:07:47 -0700720 */
721 public int screenWidthDp;
722
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700723 /**
724 * Default value for {@link #screenHeightDp} indicating that no width
725 * has been specified.
726 */
Dianne Hackbornebff8f92011-05-12 18:07:47 -0700727 public static final int SCREEN_HEIGHT_DP_UNDEFINED = 0;
728
729 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700730 * The current height of the available screen space, in dp units,
731 * corresponding to
732 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenHeightQualifier">screen
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700733 * height</a> resource qualifier. Set to
734 * {@link #SCREEN_HEIGHT_DP_UNDEFINED} if no height is specified.
Dianne Hackbornebff8f92011-05-12 18:07:47 -0700735 */
736 public int screenHeightDp;
737
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700738 /**
739 * Default value for {@link #smallestScreenWidthDp} indicating that no width
740 * has been specified.
741 */
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700742 public static final int SMALLEST_SCREEN_WIDTH_DP_UNDEFINED = 0;
743
744 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700745 * The smallest screen size an application will see in normal operation,
746 * corresponding to
747 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#SmallestScreenWidthQualifier">smallest
748 * screen width</a> resource qualifier.
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700749 * This is the smallest value of both screenWidthDp and screenHeightDp
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700750 * in both portrait and landscape. Set to
751 * {@link #SMALLEST_SCREEN_WIDTH_DP_UNDEFINED} if no width is specified.
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700752 */
753 public int smallestScreenWidthDp;
754
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700755 /**
756 * Default value for {@link #densityDpi} indicating that no width
757 * has been specified.
758 */
759 public static final int DENSITY_DPI_UNDEFINED = 0;
760
761 /**
Adam Lesinski31245b42014-08-22 19:10:56 -0700762 * Value for {@link #densityDpi} for resources that scale to any density (vector drawables).
763 * {@hide}
764 */
765 public static final int DENSITY_DPI_ANY = 0xfffe;
766
767 /**
768 * Value for {@link #densityDpi} for resources that are not meant to be scaled.
769 * {@hide}
770 */
771 public static final int DENSITY_DPI_NONE = 0xffff;
772
773 /**
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700774 * The target screen density being rendered to,
775 * corresponding to
776 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#DensityQualifier">density</a>
777 * resource qualifier. Set to
778 * {@link #DENSITY_DPI_UNDEFINED} if no density is specified.
779 */
780 public int densityDpi;
781
Dianne Hackborn5fd21692011-06-07 14:09:47 -0700782 /** @hide Hack to get this information from WM to app running in compat mode. */
783 public int compatScreenWidthDp;
784 /** @hide Hack to get this information from WM to app running in compat mode. */
785 public int compatScreenHeightDp;
786 /** @hide Hack to get this information from WM to app running in compat mode. */
787 public int compatSmallestScreenWidthDp;
788
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800789 /**
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +0100790 * An undefined assetsSeq. This will not override an existing assetsSeq.
791 * @hide
792 */
793 public static final int ASSETS_SEQ_UNDEFINED = 0;
794
795 /**
796 * Internal counter that allows us to piggyback off the configuration change mechanism to
797 * signal to apps that the the assets for an Application have changed. A difference in these
798 * between two Configurations will yield a diff flag of
799 * {@link ActivityInfo#CONFIG_ASSETS_PATHS}.
800 * @hide
801 */
Riddle Hsue716d722019-01-09 15:56:46 +0800802 @TestApi
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +0100803 public int assetsSeq;
804
805 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800806 * @hide Internal book-keeping.
807 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100808 @UnsupportedAppUsage
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800809 public int seq;
Dianne Hackborn1d0b1772013-09-06 14:02:54 -0700810
Alan Viveretteac85f902016-03-11 15:15:51 -0500811 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700812 @IntDef(flag = true, prefix = { "NATIVE_CONFIG_" }, value = {
813 NATIVE_CONFIG_MCC,
814 NATIVE_CONFIG_MNC,
815 NATIVE_CONFIG_LOCALE,
816 NATIVE_CONFIG_TOUCHSCREEN,
817 NATIVE_CONFIG_KEYBOARD,
818 NATIVE_CONFIG_KEYBOARD_HIDDEN,
819 NATIVE_CONFIG_NAVIGATION,
820 NATIVE_CONFIG_ORIENTATION,
821 NATIVE_CONFIG_DENSITY,
822 NATIVE_CONFIG_SCREEN_SIZE,
823 NATIVE_CONFIG_VERSION,
824 NATIVE_CONFIG_SCREEN_LAYOUT,
825 NATIVE_CONFIG_UI_MODE,
826 NATIVE_CONFIG_SMALLEST_SCREEN_SIZE,
827 NATIVE_CONFIG_LAYOUTDIR,
828 NATIVE_CONFIG_COLOR_MODE,
829 })
Alan Viveretteac85f902016-03-11 15:15:51 -0500830 @Retention(RetentionPolicy.SOURCE)
831 public @interface NativeConfig {}
832
Dianne Hackborn1d0b1772013-09-06 14:02:54 -0700833 /** @hide Native-specific bit mask for MCC config; DO NOT USE UNLESS YOU ARE SURE. */
834 public static final int NATIVE_CONFIG_MCC = 0x0001;
835 /** @hide Native-specific bit mask for MNC config; DO NOT USE UNLESS YOU ARE SURE. */
836 public static final int NATIVE_CONFIG_MNC = 0x0002;
837 /** @hide Native-specific bit mask for LOCALE config; DO NOT USE UNLESS YOU ARE SURE. */
838 public static final int NATIVE_CONFIG_LOCALE = 0x0004;
839 /** @hide Native-specific bit mask for TOUCHSCREEN config; DO NOT USE UNLESS YOU ARE SURE. */
840 public static final int NATIVE_CONFIG_TOUCHSCREEN = 0x0008;
841 /** @hide Native-specific bit mask for KEYBOARD config; DO NOT USE UNLESS YOU ARE SURE. */
842 public static final int NATIVE_CONFIG_KEYBOARD = 0x0010;
843 /** @hide Native-specific bit mask for KEYBOARD_HIDDEN config; DO NOT USE UNLESS YOU
844 * ARE SURE. */
845 public static final int NATIVE_CONFIG_KEYBOARD_HIDDEN = 0x0020;
846 /** @hide Native-specific bit mask for NAVIGATION config; DO NOT USE UNLESS YOU ARE SURE. */
847 public static final int NATIVE_CONFIG_NAVIGATION = 0x0040;
848 /** @hide Native-specific bit mask for ORIENTATION config; DO NOT USE UNLESS YOU ARE SURE. */
849 public static final int NATIVE_CONFIG_ORIENTATION = 0x0080;
850 /** @hide Native-specific bit mask for DENSITY config; DO NOT USE UNLESS YOU ARE SURE. */
851 public static final int NATIVE_CONFIG_DENSITY = 0x0100;
852 /** @hide Native-specific bit mask for SCREEN_SIZE config; DO NOT USE UNLESS YOU ARE SURE. */
853 public static final int NATIVE_CONFIG_SCREEN_SIZE = 0x0200;
854 /** @hide Native-specific bit mask for VERSION config; DO NOT USE UNLESS YOU ARE SURE. */
855 public static final int NATIVE_CONFIG_VERSION = 0x0400;
856 /** @hide Native-specific bit mask for SCREEN_LAYOUT config; DO NOT USE UNLESS YOU ARE SURE. */
857 public static final int NATIVE_CONFIG_SCREEN_LAYOUT = 0x0800;
858 /** @hide Native-specific bit mask for UI_MODE config; DO NOT USE UNLESS YOU ARE SURE. */
859 public static final int NATIVE_CONFIG_UI_MODE = 0x1000;
860 /** @hide Native-specific bit mask for SMALLEST_SCREEN_SIZE config; DO NOT USE UNLESS YOU
861 * ARE SURE. */
862 public static final int NATIVE_CONFIG_SMALLEST_SCREEN_SIZE = 0x2000;
863 /** @hide Native-specific bit mask for LAYOUTDIR config ; DO NOT USE UNLESS YOU ARE SURE.*/
864 public static final int NATIVE_CONFIG_LAYOUTDIR = 0x4000;
Romain Guy48327452017-01-23 17:03:35 -0800865 /** @hide Native-specific bit mask for COLOR_MODE config ; DO NOT USE UNLESS YOU ARE SURE.*/
866 public static final int NATIVE_CONFIG_COLOR_MODE = 0x10000;
Dianne Hackborn1d0b1772013-09-06 14:02:54 -0700867
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800868 /**
Adam Lesinskibad43fc2016-07-19 13:35:01 -0700869 * <p>Construct an invalid Configuration. This state is only suitable for constructing a
870 * Configuration delta that will be applied to some valid Configuration object. In order to
871 * create a valid standalone Configuration, you must call {@link #setToDefaults}. </p>
872 *
873 * <p>Example:</p>
874 * <pre class="prettyprint">
875 * Configuration validConfig = new Configuration();
876 * validConfig.setToDefaults();
877 *
878 * Configuration deltaOnlyConfig = new Configuration();
879 * deltaOnlyConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
880 *
881 * validConfig.updateFrom(deltaOnlyConfig);
882 * </pre>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 */
884 public Configuration() {
Adam Lesinskibad43fc2016-07-19 13:35:01 -0700885 unset();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886 }
887
888 /**
889 * Makes a deep copy suitable for modification.
890 */
891 public Configuration(Configuration o) {
Dianne Hackborn694f79b2010-03-17 19:44:59 -0700892 setTo(o);
893 }
894
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700895 /* This brings mLocaleList in sync with locale in case a user of the older API who doesn't know
896 * about setLocales() has changed locale directly. */
897 private void fixUpLocaleList() {
898 if ((locale == null && !mLocaleList.isEmpty()) ||
Roozbeh Pournaderfee44842016-02-04 15:24:24 -0800899 (locale != null && !locale.equals(mLocaleList.get(0)))) {
Raph Levien10ea92a2016-05-02 12:56:01 -0700900 mLocaleList = locale == null ? LocaleList.getEmptyLocaleList() : new LocaleList(locale);
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700901 }
902 }
903
Chet Haased30149e2017-01-13 12:55:16 -0800904 /**
905 * Sets the fields in this object to those in the given Configuration.
906 *
907 * @param o The Configuration object used to set the values of this Configuration's fields.
908 */
Dianne Hackborn694f79b2010-03-17 19:44:59 -0700909 public void setTo(Configuration o) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800910 fontScale = o.fontScale;
911 mcc = o.mcc;
912 mnc = o.mnc;
Roozbeh Pournader8a412e02015-12-02 18:39:50 -0800913 locale = o.locale == null ? null : (Locale) o.locale.clone();
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700914 o.fixUpLocaleList();
915 mLocaleList = o.mLocaleList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800916 userSetLocale = o.userSetLocale;
917 touchscreen = o.touchscreen;
918 keyboard = o.keyboard;
919 keyboardHidden = o.keyboardHidden;
920 hardKeyboardHidden = o.hardKeyboardHidden;
921 navigation = o.navigation;
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700922 navigationHidden = o.navigationHidden;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800923 orientation = o.orientation;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700924 screenLayout = o.screenLayout;
Romain Guy48327452017-01-23 17:03:35 -0800925 colorMode = o.colorMode;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100926 uiMode = o.uiMode;
Dianne Hackbornebff8f92011-05-12 18:07:47 -0700927 screenWidthDp = o.screenWidthDp;
928 screenHeightDp = o.screenHeightDp;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700929 smallestScreenWidthDp = o.smallestScreenWidthDp;
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700930 densityDpi = o.densityDpi;
Dianne Hackborn5fd21692011-06-07 14:09:47 -0700931 compatScreenWidthDp = o.compatScreenWidthDp;
932 compatScreenHeightDp = o.compatScreenHeightDp;
933 compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp;
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +0100934 assetsSeq = o.assetsSeq;
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800935 seq = o.seq;
Wale Ogunwale822e5122017-07-26 06:02:24 -0700936 windowConfiguration.setTo(o.windowConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800937 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700938
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700940 StringBuilder sb = new StringBuilder(128);
Dianne Hackborn29735682011-04-21 17:26:39 -0700941 sb.append("{");
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700942 sb.append(fontScale);
Dianne Hackborn5be8de32011-05-24 18:11:57 -0700943 sb.append(" ");
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700944 if (mcc != 0) {
945 sb.append(mcc);
946 sb.append("mcc");
947 } else {
948 sb.append("?mcc");
949 }
950 if (mnc != 0) {
951 sb.append(mnc);
952 sb.append("mnc");
953 } else {
954 sb.append("?mnc");
955 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700956 fixUpLocaleList();
957 if (!mLocaleList.isEmpty()) {
Dianne Hackborn9a849832011-04-07 15:11:57 -0700958 sb.append(" ");
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700959 sb.append(mLocaleList);
Dianne Hackborn9a849832011-04-07 15:11:57 -0700960 } else {
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700961 sb.append(" ?localeList");
Daniel Sandler7d6bddc2010-07-22 16:11:55 -0400962 }
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700963 int layoutDir = (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK);
964 switch (layoutDir) {
965 case SCREENLAYOUT_LAYOUTDIR_UNDEFINED: sb.append(" ?layoutDir"); break;
Fabrice Di Meglio8a802db2012-09-05 13:12:02 -0700966 case SCREENLAYOUT_LAYOUTDIR_LTR: sb.append(" ldltr"); break;
967 case SCREENLAYOUT_LAYOUTDIR_RTL: sb.append(" ldrtl"); break;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700968 default: sb.append(" layoutDir=");
969 sb.append(layoutDir >> SCREENLAYOUT_LAYOUTDIR_SHIFT); break;
Fabrice Di Meglio7a736fb2011-06-09 20:20:36 -0700970 }
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700971 if (smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
972 sb.append(" sw"); sb.append(smallestScreenWidthDp); sb.append("dp");
973 } else {
Dianne Hackborn2f0b1752011-05-31 17:59:49 -0700974 sb.append(" ?swdp");
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700975 }
976 if (screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
977 sb.append(" w"); sb.append(screenWidthDp); sb.append("dp");
978 } else {
Dianne Hackborn2f0b1752011-05-31 17:59:49 -0700979 sb.append(" ?wdp");
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700980 }
981 if (screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
982 sb.append(" h"); sb.append(screenHeightDp); sb.append("dp");
983 } else {
Dianne Hackborn2f0b1752011-05-31 17:59:49 -0700984 sb.append(" ?hdp");
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700985 }
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700986 if (densityDpi != DENSITY_DPI_UNDEFINED) {
987 sb.append(" "); sb.append(densityDpi); sb.append("dpi");
988 } else {
989 sb.append(" ?density");
990 }
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700991 switch ((screenLayout&SCREENLAYOUT_SIZE_MASK)) {
992 case SCREENLAYOUT_SIZE_UNDEFINED: sb.append(" ?lsize"); break;
993 case SCREENLAYOUT_SIZE_SMALL: sb.append(" smll"); break;
994 case SCREENLAYOUT_SIZE_NORMAL: sb.append(" nrml"); break;
995 case SCREENLAYOUT_SIZE_LARGE: sb.append(" lrg"); break;
996 case SCREENLAYOUT_SIZE_XLARGE: sb.append(" xlrg"); break;
997 default: sb.append(" layoutSize=");
998 sb.append(screenLayout&SCREENLAYOUT_SIZE_MASK); break;
999 }
1000 switch ((screenLayout&SCREENLAYOUT_LONG_MASK)) {
1001 case SCREENLAYOUT_LONG_UNDEFINED: sb.append(" ?long"); break;
1002 case SCREENLAYOUT_LONG_NO: /* not-long is not interesting to print */ break;
1003 case SCREENLAYOUT_LONG_YES: sb.append(" long"); break;
1004 default: sb.append(" layoutLong=");
1005 sb.append(screenLayout&SCREENLAYOUT_LONG_MASK); break;
1006 }
Romain Guy48327452017-01-23 17:03:35 -08001007 switch ((colorMode &COLOR_MODE_HDR_MASK)) {
1008 case COLOR_MODE_HDR_UNDEFINED: sb.append(" ?ldr"); break; // most likely not HDR
1009 case COLOR_MODE_HDR_NO: /* ldr is not interesting to print */ break;
1010 case COLOR_MODE_HDR_YES: sb.append(" hdr"); break;
Romain Guyc9ba5592017-01-18 16:34:42 -08001011 default: sb.append(" dynamicRange=");
Romain Guy48327452017-01-23 17:03:35 -08001012 sb.append(colorMode &COLOR_MODE_HDR_MASK); break;
Romain Guyc9ba5592017-01-18 16:34:42 -08001013 }
Romain Guy48327452017-01-23 17:03:35 -08001014 switch ((colorMode &COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) {
1015 case COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED: sb.append(" ?wideColorGamut"); break;
1016 case COLOR_MODE_WIDE_COLOR_GAMUT_NO: /* not wide is not interesting to print */ break;
1017 case COLOR_MODE_WIDE_COLOR_GAMUT_YES: sb.append(" widecg"); break;
Romain Guyc9ba5592017-01-18 16:34:42 -08001018 default: sb.append(" wideColorGamut=");
Romain Guy48327452017-01-23 17:03:35 -08001019 sb.append(colorMode &COLOR_MODE_WIDE_COLOR_GAMUT_MASK); break;
Romain Guyc9ba5592017-01-18 16:34:42 -08001020 }
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001021 switch (orientation) {
1022 case ORIENTATION_UNDEFINED: sb.append(" ?orien"); break;
1023 case ORIENTATION_LANDSCAPE: sb.append(" land"); break;
1024 case ORIENTATION_PORTRAIT: sb.append(" port"); break;
1025 default: sb.append(" orien="); sb.append(orientation); break;
1026 }
1027 switch ((uiMode&UI_MODE_TYPE_MASK)) {
1028 case UI_MODE_TYPE_UNDEFINED: sb.append(" ?uimode"); break;
1029 case UI_MODE_TYPE_NORMAL: /* normal is not interesting to print */ break;
1030 case UI_MODE_TYPE_DESK: sb.append(" desk"); break;
1031 case UI_MODE_TYPE_CAR: sb.append(" car"); break;
Dianne Hackborne360bb62011-05-20 16:11:04 -07001032 case UI_MODE_TYPE_TELEVISION: sb.append(" television"); break;
Joe Onorato44fcb832011-12-14 20:59:30 -08001033 case UI_MODE_TYPE_APPLIANCE: sb.append(" appliance"); break;
John Spurlock6c191292014-04-03 16:37:27 -04001034 case UI_MODE_TYPE_WATCH: sb.append(" watch"); break;
Zak Cohen1a6acdb2016-12-12 15:21:21 -08001035 case UI_MODE_TYPE_VR_HEADSET: sb.append(" vrheadset"); break;
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001036 default: sb.append(" uimode="); sb.append(uiMode&UI_MODE_TYPE_MASK); break;
1037 }
1038 switch ((uiMode&UI_MODE_NIGHT_MASK)) {
1039 case UI_MODE_NIGHT_UNDEFINED: sb.append(" ?night"); break;
1040 case UI_MODE_NIGHT_NO: /* not-night is not interesting to print */ break;
1041 case UI_MODE_NIGHT_YES: sb.append(" night"); break;
1042 default: sb.append(" night="); sb.append(uiMode&UI_MODE_NIGHT_MASK); break;
1043 }
Dianne Hackborn9a849832011-04-07 15:11:57 -07001044 switch (touchscreen) {
1045 case TOUCHSCREEN_UNDEFINED: sb.append(" ?touch"); break;
1046 case TOUCHSCREEN_NOTOUCH: sb.append(" -touch"); break;
1047 case TOUCHSCREEN_STYLUS: sb.append(" stylus"); break;
1048 case TOUCHSCREEN_FINGER: sb.append(" finger"); break;
1049 default: sb.append(" touch="); sb.append(touchscreen); break;
1050 }
1051 switch (keyboard) {
1052 case KEYBOARD_UNDEFINED: sb.append(" ?keyb"); break;
1053 case KEYBOARD_NOKEYS: sb.append(" -keyb"); break;
1054 case KEYBOARD_QWERTY: sb.append(" qwerty"); break;
1055 case KEYBOARD_12KEY: sb.append(" 12key"); break;
1056 default: sb.append(" keys="); sb.append(keyboard); break;
1057 }
1058 switch (keyboardHidden) {
1059 case KEYBOARDHIDDEN_UNDEFINED: sb.append("/?"); break;
1060 case KEYBOARDHIDDEN_NO: sb.append("/v"); break;
1061 case KEYBOARDHIDDEN_YES: sb.append("/h"); break;
1062 case KEYBOARDHIDDEN_SOFT: sb.append("/s"); break;
1063 default: sb.append("/"); sb.append(keyboardHidden); break;
1064 }
1065 switch (hardKeyboardHidden) {
1066 case HARDKEYBOARDHIDDEN_UNDEFINED: sb.append("/?"); break;
1067 case HARDKEYBOARDHIDDEN_NO: sb.append("/v"); break;
1068 case HARDKEYBOARDHIDDEN_YES: sb.append("/h"); break;
1069 default: sb.append("/"); sb.append(hardKeyboardHidden); break;
1070 }
1071 switch (navigation) {
1072 case NAVIGATION_UNDEFINED: sb.append(" ?nav"); break;
1073 case NAVIGATION_NONAV: sb.append(" -nav"); break;
1074 case NAVIGATION_DPAD: sb.append(" dpad"); break;
1075 case NAVIGATION_TRACKBALL: sb.append(" tball"); break;
1076 case NAVIGATION_WHEEL: sb.append(" wheel"); break;
1077 default: sb.append(" nav="); sb.append(navigation); break;
1078 }
1079 switch (navigationHidden) {
1080 case NAVIGATIONHIDDEN_UNDEFINED: sb.append("/?"); break;
1081 case NAVIGATIONHIDDEN_NO: sb.append("/v"); break;
1082 case NAVIGATIONHIDDEN_YES: sb.append("/h"); break;
1083 default: sb.append("/"); sb.append(navigationHidden); break;
1084 }
Wale Ogunwale822e5122017-07-26 06:02:24 -07001085 sb.append(" winConfig="); sb.append(windowConfiguration);
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001086 if (assetsSeq != 0) {
1087 sb.append(" as.").append(assetsSeq);
1088 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001089 if (seq != 0) {
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001090 sb.append(" s.").append(seq);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001091 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001092 sb.append('}');
1093 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094 }
1095
1096 /**
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001097 * Write to a protocol buffer output stream.
1098 * Protocol buffer message definition at {@link android.content.ConfigurationProto}
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -07001099 * Has the option to ignore fields that don't need to be persisted to disk.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001100 *
1101 * @param protoOutputStream Stream to write the Configuration object to.
1102 * @param fieldId Field Id of the Configuration as defined in the parent message
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -07001103 * @param persisted Note if this proto will be persisted to disk
Nataniel Borges023ecb52019-01-16 14:15:43 -08001104 * @param critical If true, reduce amount of data written.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001105 * @hide
1106 */
Nataniel Borges023ecb52019-01-16 14:15:43 -08001107 public void writeToProto(ProtoOutputStream protoOutputStream, long fieldId, boolean persisted,
1108 boolean critical) {
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001109 final long token = protoOutputStream.start(fieldId);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001110 if (!critical) {
1111 protoOutputStream.write(FONT_SCALE, fontScale);
1112 protoOutputStream.write(MCC, mcc);
1113 protoOutputStream.write(MNC, mnc);
1114 if (mLocaleList != null) {
Varun Shah5e674622019-09-10 14:41:00 -04001115 protoOutputStream.write(LOCALE_LIST, mLocaleList.toLanguageTags());
Nataniel Borges023ecb52019-01-16 14:15:43 -08001116 }
1117 protoOutputStream.write(SCREEN_LAYOUT, screenLayout);
1118 protoOutputStream.write(COLOR_MODE, colorMode);
1119 protoOutputStream.write(TOUCHSCREEN, touchscreen);
1120 protoOutputStream.write(KEYBOARD, keyboard);
1121 protoOutputStream.write(KEYBOARD_HIDDEN, keyboardHidden);
1122 protoOutputStream.write(HARD_KEYBOARD_HIDDEN, hardKeyboardHidden);
1123 protoOutputStream.write(NAVIGATION, navigation);
1124 protoOutputStream.write(NAVIGATION_HIDDEN, navigationHidden);
1125 protoOutputStream.write(UI_MODE, uiMode);
1126 protoOutputStream.write(SMALLEST_SCREEN_WIDTH_DP, smallestScreenWidthDp);
1127 protoOutputStream.write(DENSITY_DPI, densityDpi);
1128 // For persistence, we do not care about window configuration
1129 if (!persisted && windowConfiguration != null) {
1130 windowConfiguration.writeToProto(protoOutputStream, WINDOW_CONFIGURATION);
1131 }
Kweku Adams15afdeb2018-09-04 11:54:46 -07001132 }
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001133 protoOutputStream.write(ORIENTATION, orientation);
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001134 protoOutputStream.write(SCREEN_WIDTH_DP, screenWidthDp);
1135 protoOutputStream.write(SCREEN_HEIGHT_DP, screenHeightDp);
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001136 protoOutputStream.end(token);
1137 }
1138
1139 /**
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -07001140 * Write to a protocol buffer output stream.
1141 * Protocol buffer message definition at {@link android.content.ConfigurationProto}
1142 *
1143 * @param protoOutputStream Stream to write the Configuration object to.
1144 * @param fieldId Field Id of the Configuration as defined in the parent message
1145 * @hide
1146 */
1147 public void writeToProto(ProtoOutputStream protoOutputStream, long fieldId) {
Nataniel Borges023ecb52019-01-16 14:15:43 -08001148 writeToProto(protoOutputStream, fieldId, false /* persisted */, false /* critical */);
1149 }
1150
1151 /**
1152 * Write to a protocol buffer output stream.
1153 * Protocol buffer message definition at {@link android.content.ConfigurationProto}
1154 *
1155 * @param protoOutputStream Stream to write the Configuration object to.
1156 * @param fieldId Field Id of the Configuration as defined in the parent message
1157 * @param critical If true, reduce amount of data written.
1158 * @hide
1159 */
1160 public void writeToProto(ProtoOutputStream protoOutputStream, long fieldId, boolean critical) {
1161 writeToProto(protoOutputStream, fieldId, false /* persisted */, critical);
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -07001162 }
1163
1164 /**
1165 * Read from a protocol buffer output stream.
1166 * Protocol buffer message definition at {@link android.content.ConfigurationProto}
1167 *
1168 * @param protoInputStream Stream to read the Configuration object from.
1169 * @param fieldId Field Id of the Configuration as defined in the parent message
1170 * @hide
1171 */
1172 public void readFromProto(ProtoInputStream protoInputStream, long fieldId) throws IOException {
1173 final long token = protoInputStream.start(fieldId);
1174 final List<Locale> list = new ArrayList();
1175 try {
1176 while (protoInputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
1177 switch (protoInputStream.getFieldNumber()) {
1178 case (int) FONT_SCALE:
1179 fontScale = protoInputStream.readFloat(FONT_SCALE);
1180 break;
1181 case (int) MCC:
1182 mcc = protoInputStream.readInt(MCC);
1183 break;
1184 case (int) MNC:
1185 mnc = protoInputStream.readInt(MNC);
1186 break;
1187 case (int) LOCALES:
1188 // Parse the Locale here to handle all the repeated Locales
1189 // The LocaleList will be created when the message is completed
1190 final long localeToken = protoInputStream.start(LOCALES);
1191 String language = "";
1192 String country = "";
1193 String variant = "";
Varun Shah95fabaf2019-05-01 12:45:37 -07001194 String script = "";
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -07001195 try {
1196 while (protoInputStream.nextField()
1197 != ProtoInputStream.NO_MORE_FIELDS) {
1198 switch (protoInputStream.getFieldNumber()) {
1199 case (int) LocaleProto.LANGUAGE:
1200 language = protoInputStream.readString(
1201 LocaleProto.LANGUAGE);
1202 break;
1203 case (int) LocaleProto.COUNTRY:
1204 country = protoInputStream.readString(LocaleProto.COUNTRY);
1205 break;
1206 case (int) LocaleProto.VARIANT:
1207 variant = protoInputStream.readString(LocaleProto.VARIANT);
1208 break;
Varun Shah95fabaf2019-05-01 12:45:37 -07001209 case (int) LocaleProto.SCRIPT:
1210 script = protoInputStream.readString(LocaleProto.SCRIPT);
1211 break;
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -07001212 }
1213 }
1214 } catch (WireTypeMismatchException wtme) {
1215 // rethrow for caller deal with
1216 throw wtme;
1217 } finally {
1218 protoInputStream.end(localeToken);
Varun Shah95fabaf2019-05-01 12:45:37 -07001219 try {
1220 final Locale locale = new Locale.Builder()
1221 .setLanguage(language)
1222 .setRegion(country)
1223 .setVariant(variant)
1224 .setScript(script)
1225 .build();
Varun Shah669d8862019-09-04 12:04:02 -07001226 // Log a WTF here if a repeated locale is found to avoid throwing an
1227 // exception in system server when LocaleList is created below
1228 final int inListIndex = list.indexOf(locale);
1229 if (inListIndex != -1) {
1230 Slog.wtf(TAG, "Repeated locale (" + list.get(inListIndex) + ")"
1231 + " found when trying to add: " + locale.toString());
1232 } else {
1233 list.add(locale);
1234 }
Varun Shah95fabaf2019-05-01 12:45:37 -07001235 } catch (IllformedLocaleException e) {
1236 Slog.e(TAG, "readFromProto error building locale with: "
1237 + "language-" + language + ";country-" + country
1238 + ";variant-" + variant + ";script-" + script);
1239 }
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -07001240 }
1241 break;
1242 case (int) SCREEN_LAYOUT:
1243 screenLayout = protoInputStream.readInt(SCREEN_LAYOUT);
1244 break;
1245 case (int) COLOR_MODE:
1246 colorMode = protoInputStream.readInt(COLOR_MODE);
1247 break;
1248 case (int) TOUCHSCREEN:
1249 touchscreen = protoInputStream.readInt(TOUCHSCREEN);
1250 break;
1251 case (int) KEYBOARD:
1252 keyboard = protoInputStream.readInt(KEYBOARD);
1253 break;
1254 case (int) KEYBOARD_HIDDEN:
1255 keyboardHidden = protoInputStream.readInt(KEYBOARD_HIDDEN);
1256 break;
1257 case (int) HARD_KEYBOARD_HIDDEN:
1258 hardKeyboardHidden = protoInputStream.readInt(HARD_KEYBOARD_HIDDEN);
1259 break;
1260 case (int) NAVIGATION:
1261 navigation = protoInputStream.readInt(NAVIGATION);
1262 break;
1263 case (int) NAVIGATION_HIDDEN:
1264 navigationHidden = protoInputStream.readInt(NAVIGATION_HIDDEN);
1265 break;
1266 case (int) ORIENTATION:
1267 orientation = protoInputStream.readInt(ORIENTATION);
1268 break;
1269 case (int) UI_MODE:
1270 uiMode = protoInputStream.readInt(UI_MODE);
1271 break;
1272 case (int) SCREEN_WIDTH_DP:
1273 screenWidthDp = protoInputStream.readInt(SCREEN_WIDTH_DP);
1274 break;
1275 case (int) SCREEN_HEIGHT_DP:
1276 screenHeightDp = protoInputStream.readInt(SCREEN_HEIGHT_DP);
1277 break;
1278 case (int) SMALLEST_SCREEN_WIDTH_DP:
1279 smallestScreenWidthDp = protoInputStream.readInt(SMALLEST_SCREEN_WIDTH_DP);
1280 break;
1281 case (int) DENSITY_DPI:
1282 densityDpi = protoInputStream.readInt(DENSITY_DPI);
1283 break;
1284 case (int) WINDOW_CONFIGURATION:
1285 windowConfiguration.readFromProto(protoInputStream, WINDOW_CONFIGURATION);
1286 break;
Varun Shah5e674622019-09-10 14:41:00 -04001287 case (int) LOCALE_LIST:
1288 try {
1289 setLocales(LocaleList.forLanguageTags(protoInputStream.readString(
1290 LOCALE_LIST)));
1291 } catch (Exception e) {
1292 Slog.e(TAG, "error parsing locale list in configuration.", e);
1293 }
1294 break;
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -07001295 }
1296 }
1297 } finally {
1298 // Let caller handle any exceptions
1299 if (list.size() > 0) {
1300 //Create the LocaleList from the collected Locales
1301 setLocales(new LocaleList(list.toArray(new Locale[list.size()])));
1302 }
1303 protoInputStream.end(token);
1304 }
1305 }
1306
1307 /**
Dianne Hackbornbf5ba6b2018-02-20 10:31:02 -08001308 * Write full {@link android.content.ResourcesConfigurationProto} to protocol buffer output
1309 * stream.
1310 *
1311 * @param protoOutputStream Stream to write the Configuration object to.
1312 * @param fieldId Field Id of the Configuration as defined in the parent message
1313 * @param metrics Current display information
1314 * @hide
1315 */
1316 public void writeResConfigToProto(ProtoOutputStream protoOutputStream, long fieldId,
1317 DisplayMetrics metrics) {
1318 final int width, height;
1319 if (metrics.widthPixels >= metrics.heightPixels) {
1320 width = metrics.widthPixels;
1321 height = metrics.heightPixels;
1322 } else {
1323 //noinspection SuspiciousNameCombination
1324 width = metrics.heightPixels;
1325 //noinspection SuspiciousNameCombination
1326 height = metrics.widthPixels;
1327 }
1328
1329 final long token = protoOutputStream.start(fieldId);
1330 writeToProto(protoOutputStream, CONFIGURATION);
1331 protoOutputStream.write(SDK_VERSION, Build.VERSION.RESOURCES_SDK_INT);
1332 protoOutputStream.write(SCREEN_WIDTH_PX, width);
1333 protoOutputStream.write(SCREEN_HEIGHT_PX, height);
1334 protoOutputStream.end(token);
1335 }
1336
1337 /**
Michael Wright19859762017-09-18 20:57:58 +01001338 * Convert the UI mode to a human readable format.
1339 * @hide
1340 */
1341 public static String uiModeToString(int uiMode) {
1342 switch (uiMode) {
1343 case UI_MODE_TYPE_UNDEFINED:
1344 return "UI_MODE_TYPE_UNDEFINED";
1345 case UI_MODE_TYPE_NORMAL:
1346 return "UI_MODE_TYPE_NORMAL";
1347 case UI_MODE_TYPE_DESK:
1348 return "UI_MODE_TYPE_DESK";
1349 case UI_MODE_TYPE_CAR:
1350 return "UI_MODE_TYPE_CAR";
1351 case UI_MODE_TYPE_TELEVISION:
1352 return "UI_MODE_TYPE_TELEVISION";
1353 case UI_MODE_TYPE_APPLIANCE:
1354 return "UI_MODE_TYPE_APPLIANCE";
1355 case UI_MODE_TYPE_WATCH:
1356 return "UI_MODE_TYPE_WATCH";
1357 case UI_MODE_TYPE_VR_HEADSET:
1358 return "UI_MODE_TYPE_VR_HEADSET";
1359 default:
1360 return Integer.toString(uiMode);
1361 }
1362 }
1363
1364 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001365 * Set this object to the system defaults.
1366 */
1367 public void setToDefaults() {
1368 fontScale = 1;
1369 mcc = mnc = 0;
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001370 mLocaleList = LocaleList.getEmptyLocaleList();
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001371 locale = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001372 userSetLocale = false;
1373 touchscreen = TOUCHSCREEN_UNDEFINED;
1374 keyboard = KEYBOARD_UNDEFINED;
1375 keyboardHidden = KEYBOARDHIDDEN_UNDEFINED;
1376 hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED;
1377 navigation = NAVIGATION_UNDEFINED;
Dianne Hackborn93e462b2009-09-15 22:50:40 -07001378 navigationHidden = NAVIGATIONHIDDEN_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001379 orientation = ORIENTATION_UNDEFINED;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001380 screenLayout = SCREENLAYOUT_UNDEFINED;
Romain Guy48327452017-01-23 17:03:35 -08001381 colorMode = COLOR_MODE_UNDEFINED;
Dianne Hackborn7299c412010-03-04 18:41:49 -08001382 uiMode = UI_MODE_TYPE_UNDEFINED;
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001383 screenWidthDp = compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED;
1384 screenHeightDp = compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED;
1385 smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001386 densityDpi = DENSITY_DPI_UNDEFINED;
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001387 assetsSeq = ASSETS_SEQ_UNDEFINED;
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001388 seq = 0;
Wale Ogunwale822e5122017-07-26 06:02:24 -07001389 windowConfiguration.setToDefaults();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001390 }
1391
Adam Lesinskibad43fc2016-07-19 13:35:01 -07001392 /**
1393 * Set this object to completely undefined.
1394 * @hide
1395 */
1396 public void unset() {
1397 setToDefaults();
1398 fontScale = 0;
1399 }
1400
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001401 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001402 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001403 @Deprecated public void makeDefault() {
1404 setToDefaults();
1405 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -07001406
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001407 /**
Alan Viveretteac85f902016-03-11 15:15:51 -05001408 * Copies the fields from delta into this Configuration object, keeping
1409 * track of which ones have changed. Any undefined fields in {@code delta}
1410 * are ignored and not copied in to the current Configuration.
1411 *
1412 * @return a bit mask of the changed fields, as per {@link #diff}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001413 */
Alan Viveretteac85f902016-03-11 15:15:51 -05001414 public @Config int updateFrom(@NonNull Configuration delta) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001415 int changed = 0;
1416 if (delta.fontScale > 0 && fontScale != delta.fontScale) {
1417 changed |= ActivityInfo.CONFIG_FONT_SCALE;
1418 fontScale = delta.fontScale;
1419 }
1420 if (delta.mcc != 0 && mcc != delta.mcc) {
1421 changed |= ActivityInfo.CONFIG_MCC;
1422 mcc = delta.mcc;
1423 }
1424 if (delta.mnc != 0 && mnc != delta.mnc) {
1425 changed |= ActivityInfo.CONFIG_MNC;
1426 mnc = delta.mnc;
1427 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001428 fixUpLocaleList();
1429 delta.fixUpLocaleList();
1430 if (!delta.mLocaleList.isEmpty() && !mLocaleList.equals(delta.mLocaleList)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001431 changed |= ActivityInfo.CONFIG_LOCALE;
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001432 mLocaleList = delta.mLocaleList;
1433 // delta.locale can't be null, since delta.mLocaleList is not empty.
1434 if (!delta.locale.equals(locale)) {
1435 locale = (Locale) delta.locale.clone();
1436 // If locale has changed, then layout direction is also changed ...
1437 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
1438 // ... and we need to update the layout direction (represented by the first
1439 // 2 most significant bits in screenLayout).
1440 setLayoutDirection(locale);
1441 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442 }
Craig Mautner31678b52013-08-12 17:56:34 -07001443 final int deltaScreenLayoutDir = delta.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
1444 if (deltaScreenLayoutDir != SCREENLAYOUT_LAYOUTDIR_UNDEFINED &&
1445 deltaScreenLayoutDir != (screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) {
1446 screenLayout = (screenLayout & ~SCREENLAYOUT_LAYOUTDIR_MASK) | deltaScreenLayoutDir;
Amith Yamasanid8415f42013-08-07 20:15:10 -07001447 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
Amith Yamasanid8415f42013-08-07 20:15:10 -07001448 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 if (delta.userSetLocale && (!userSetLocale || ((changed & ActivityInfo.CONFIG_LOCALE) != 0)))
1450 {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001451 changed |= ActivityInfo.CONFIG_LOCALE;
Amith Yamasanid8415f42013-08-07 20:15:10 -07001452 userSetLocale = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001453 }
1454 if (delta.touchscreen != TOUCHSCREEN_UNDEFINED
1455 && touchscreen != delta.touchscreen) {
1456 changed |= ActivityInfo.CONFIG_TOUCHSCREEN;
1457 touchscreen = delta.touchscreen;
1458 }
1459 if (delta.keyboard != KEYBOARD_UNDEFINED
1460 && keyboard != delta.keyboard) {
1461 changed |= ActivityInfo.CONFIG_KEYBOARD;
1462 keyboard = delta.keyboard;
1463 }
1464 if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED
1465 && keyboardHidden != delta.keyboardHidden) {
1466 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1467 keyboardHidden = delta.keyboardHidden;
1468 }
1469 if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED
1470 && hardKeyboardHidden != delta.hardKeyboardHidden) {
1471 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1472 hardKeyboardHidden = delta.hardKeyboardHidden;
1473 }
1474 if (delta.navigation != NAVIGATION_UNDEFINED
1475 && navigation != delta.navigation) {
1476 changed |= ActivityInfo.CONFIG_NAVIGATION;
1477 navigation = delta.navigation;
1478 }
Dianne Hackborn93e462b2009-09-15 22:50:40 -07001479 if (delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED
1480 && navigationHidden != delta.navigationHidden) {
1481 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1482 navigationHidden = delta.navigationHidden;
1483 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001484 if (delta.orientation != ORIENTATION_UNDEFINED
1485 && orientation != delta.orientation) {
1486 changed |= ActivityInfo.CONFIG_ORIENTATION;
1487 orientation = delta.orientation;
1488 }
Robert Carrdf259d32016-12-05 20:33:10 -08001489 if (((delta.screenLayout & SCREENLAYOUT_SIZE_MASK) != SCREENLAYOUT_SIZE_UNDEFINED)
1490 && (delta.screenLayout & SCREENLAYOUT_SIZE_MASK)
1491 != (screenLayout & SCREENLAYOUT_SIZE_MASK)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07001492 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
Robert Carrdf259d32016-12-05 20:33:10 -08001493 screenLayout = (screenLayout & ~SCREENLAYOUT_SIZE_MASK)
1494 | (delta.screenLayout & SCREENLAYOUT_SIZE_MASK);
Dianne Hackborn723738c2009-06-25 19:48:04 -07001495 }
Robert Carrdf259d32016-12-05 20:33:10 -08001496 if (((delta.screenLayout & SCREENLAYOUT_LONG_MASK) != SCREENLAYOUT_LONG_UNDEFINED)
1497 && (delta.screenLayout & SCREENLAYOUT_LONG_MASK)
1498 != (screenLayout & SCREENLAYOUT_LONG_MASK)) {
1499 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
1500 screenLayout = (screenLayout & ~SCREENLAYOUT_LONG_MASK)
1501 | (delta.screenLayout & SCREENLAYOUT_LONG_MASK);
1502 }
1503 if (((delta.screenLayout & SCREENLAYOUT_ROUND_MASK) != SCREENLAYOUT_ROUND_UNDEFINED)
1504 && (delta.screenLayout & SCREENLAYOUT_ROUND_MASK)
1505 != (screenLayout & SCREENLAYOUT_ROUND_MASK)) {
1506 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
1507 screenLayout = (screenLayout & ~SCREENLAYOUT_ROUND_MASK)
1508 | (delta.screenLayout & SCREENLAYOUT_ROUND_MASK);
1509 }
1510 if ((delta.screenLayout & SCREENLAYOUT_COMPAT_NEEDED)
1511 != (screenLayout & SCREENLAYOUT_COMPAT_NEEDED)
1512 && delta.screenLayout != 0) {
1513 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
1514 screenLayout = (screenLayout & ~SCREENLAYOUT_COMPAT_NEEDED)
1515 | (delta.screenLayout & SCREENLAYOUT_COMPAT_NEEDED);
1516 }
1517
Romain Guy48327452017-01-23 17:03:35 -08001518 if (((delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) !=
1519 COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED)
1520 && (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK)
1521 != (colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) {
1522 changed |= ActivityInfo.CONFIG_COLOR_MODE;
1523 colorMode = (colorMode & ~COLOR_MODE_WIDE_COLOR_GAMUT_MASK)
1524 | (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK);
Romain Guyc9ba5592017-01-18 16:34:42 -08001525 }
1526
Romain Guy48327452017-01-23 17:03:35 -08001527 if (((delta.colorMode & COLOR_MODE_HDR_MASK) != COLOR_MODE_HDR_UNDEFINED)
1528 && (delta.colorMode & COLOR_MODE_HDR_MASK)
1529 != (colorMode & COLOR_MODE_HDR_MASK)) {
1530 changed |= ActivityInfo.CONFIG_COLOR_MODE;
1531 colorMode = (colorMode & ~COLOR_MODE_HDR_MASK)
1532 | (delta.colorMode & COLOR_MODE_HDR_MASK);
Romain Guyc9ba5592017-01-18 16:34:42 -08001533 }
1534
Dianne Hackborn7299c412010-03-04 18:41:49 -08001535 if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)
Tobias Haamel27b28b32010-02-09 23:09:17 +01001536 && uiMode != delta.uiMode) {
1537 changed |= ActivityInfo.CONFIG_UI_MODE;
Dianne Hackborn7299c412010-03-04 18:41:49 -08001538 if ((delta.uiMode&UI_MODE_TYPE_MASK) != UI_MODE_TYPE_UNDEFINED) {
1539 uiMode = (uiMode&~UI_MODE_TYPE_MASK)
1540 | (delta.uiMode&UI_MODE_TYPE_MASK);
1541 }
1542 if ((delta.uiMode&UI_MODE_NIGHT_MASK) != UI_MODE_NIGHT_UNDEFINED) {
1543 uiMode = (uiMode&~UI_MODE_NIGHT_MASK)
1544 | (delta.uiMode&UI_MODE_NIGHT_MASK);
1545 }
Tobias Haamel27b28b32010-02-09 23:09:17 +01001546 }
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001547 if (delta.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED
1548 && screenWidthDp != delta.screenWidthDp) {
1549 changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1550 screenWidthDp = delta.screenWidthDp;
1551 }
1552 if (delta.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED
1553 && screenHeightDp != delta.screenHeightDp) {
1554 changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1555 screenHeightDp = delta.screenHeightDp;
1556 }
Danny Baumanne7123a62013-05-15 10:21:40 +02001557 if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
1558 && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
1559 changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001560 smallestScreenWidthDp = delta.smallestScreenWidthDp;
1561 }
Danny Baumanne7123a62013-05-15 10:21:40 +02001562 if (delta.densityDpi != DENSITY_DPI_UNDEFINED &&
1563 densityDpi != delta.densityDpi) {
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001564 changed |= ActivityInfo.CONFIG_DENSITY;
1565 densityDpi = delta.densityDpi;
1566 }
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001567 if (delta.compatScreenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
1568 compatScreenWidthDp = delta.compatScreenWidthDp;
1569 }
1570 if (delta.compatScreenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
1571 compatScreenHeightDp = delta.compatScreenHeightDp;
1572 }
1573 if (delta.compatSmallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
1574 compatSmallestScreenWidthDp = delta.compatSmallestScreenWidthDp;
1575 }
Adam Lesinski4eb41292017-07-06 12:06:13 -07001576 if (delta.assetsSeq != ASSETS_SEQ_UNDEFINED && delta.assetsSeq != assetsSeq) {
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001577 changed |= ActivityInfo.CONFIG_ASSETS_PATHS;
1578 assetsSeq = delta.assetsSeq;
1579 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001580 if (delta.seq != 0) {
1581 seq = delta.seq;
1582 }
Wale Ogunwale822e5122017-07-26 06:02:24 -07001583 if (windowConfiguration.updateFrom(delta.windowConfiguration) != 0) {
1584 changed |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
1585 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -07001586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001587 return changed;
1588 }
1589
1590 /**
1591 * Return a bit mask of the differences between this Configuration
1592 * object and the given one. Does not change the values of either. Any
1593 * undefined fields in <var>delta</var> are ignored.
1594 * @return Returns a bit mask indicating which configuration
1595 * values has changed, containing any combination of
1596 * {@link android.content.pm.ActivityInfo#CONFIG_FONT_SCALE
1597 * PackageManager.ActivityInfo.CONFIG_FONT_SCALE},
1598 * {@link android.content.pm.ActivityInfo#CONFIG_MCC
1599 * PackageManager.ActivityInfo.CONFIG_MCC},
1600 * {@link android.content.pm.ActivityInfo#CONFIG_MNC
1601 * PackageManager.ActivityInfo.CONFIG_MNC},
1602 * {@link android.content.pm.ActivityInfo#CONFIG_LOCALE
1603 * PackageManager.ActivityInfo.CONFIG_LOCALE},
1604 * {@link android.content.pm.ActivityInfo#CONFIG_TOUCHSCREEN
1605 * PackageManager.ActivityInfo.CONFIG_TOUCHSCREEN},
1606 * {@link android.content.pm.ActivityInfo#CONFIG_KEYBOARD
1607 * PackageManager.ActivityInfo.CONFIG_KEYBOARD},
1608 * {@link android.content.pm.ActivityInfo#CONFIG_NAVIGATION
Dianne Hackborn723738c2009-06-25 19:48:04 -07001609 * PackageManager.ActivityInfo.CONFIG_NAVIGATION},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001610 * {@link android.content.pm.ActivityInfo#CONFIG_ORIENTATION
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001611 * PackageManager.ActivityInfo.CONFIG_ORIENTATION},
Dianne Hackborn723738c2009-06-25 19:48:04 -07001612 * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_LAYOUT
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001613 * PackageManager.ActivityInfo.CONFIG_SCREEN_LAYOUT}, or
1614 * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_SIZE
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001615 * PackageManager.ActivityInfo.CONFIG_SCREEN_SIZE}, or
1616 * {@link android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE
1617 * PackageManager.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE}.
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001618 * {@link android.content.pm.ActivityInfo#CONFIG_LAYOUT_DIRECTION
1619 * PackageManager.ActivityInfo.CONFIG_LAYOUT_DIRECTION}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001620 */
1621 public int diff(Configuration delta) {
Bryce Lee658d9842017-07-28 08:33:36 -07001622 return diff(delta, false /* compareUndefined */, false /* publicOnly */);
1623 }
1624
1625 /**
1626 * Returns the diff against the provided {@link Configuration} excluding values that would
1627 * publicly be equivalent, such as appBounds.
1628 * @param delta {@link Configuration} to compare to.
1629 *
1630 * TODO(b/36812336): Remove once appBounds has been moved out of Configuration.
1631 * {@hide}
1632 */
1633 public int diffPublicOnly(Configuration delta) {
1634 return diff(delta, false /* compareUndefined */, true /* publicOnly */);
Andrii Kulianb10330d2016-09-16 13:51:46 -07001635 }
1636
1637 /**
1638 * Variation of {@link #diff(Configuration)} with an option to skip checks for undefined values.
1639 *
1640 * @hide
1641 */
Bryce Lee658d9842017-07-28 08:33:36 -07001642 public int diff(Configuration delta, boolean compareUndefined, boolean publicOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 int changed = 0;
Andrii Kulianb10330d2016-09-16 13:51:46 -07001644 if ((compareUndefined || delta.fontScale > 0) && fontScale != delta.fontScale) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001645 changed |= ActivityInfo.CONFIG_FONT_SCALE;
1646 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001647 if ((compareUndefined || delta.mcc != 0) && mcc != delta.mcc) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001648 changed |= ActivityInfo.CONFIG_MCC;
1649 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001650 if ((compareUndefined || delta.mnc != 0) && mnc != delta.mnc) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001651 changed |= ActivityInfo.CONFIG_MNC;
1652 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001653 fixUpLocaleList();
1654 delta.fixUpLocaleList();
Andrii Kulianb10330d2016-09-16 13:51:46 -07001655 if ((compareUndefined || !delta.mLocaleList.isEmpty())
1656 && !mLocaleList.equals(delta.mLocaleList)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001657 changed |= ActivityInfo.CONFIG_LOCALE;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001658 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001659 }
Craig Mautner31678b52013-08-12 17:56:34 -07001660 final int deltaScreenLayoutDir = delta.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
Andrii Kulianb10330d2016-09-16 13:51:46 -07001661 if ((compareUndefined || deltaScreenLayoutDir != SCREENLAYOUT_LAYOUTDIR_UNDEFINED)
1662 && deltaScreenLayoutDir != (screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) {
Amith Yamasanid8415f42013-08-07 20:15:10 -07001663 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
1664 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001665 if ((compareUndefined || delta.touchscreen != TOUCHSCREEN_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001666 && touchscreen != delta.touchscreen) {
1667 changed |= ActivityInfo.CONFIG_TOUCHSCREEN;
1668 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001669 if ((compareUndefined || delta.keyboard != KEYBOARD_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001670 && keyboard != delta.keyboard) {
1671 changed |= ActivityInfo.CONFIG_KEYBOARD;
1672 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001673 if ((compareUndefined || delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001674 && keyboardHidden != delta.keyboardHidden) {
1675 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1676 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001677 if ((compareUndefined || delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001678 && hardKeyboardHidden != delta.hardKeyboardHidden) {
1679 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1680 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001681 if ((compareUndefined || delta.navigation != NAVIGATION_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682 && navigation != delta.navigation) {
1683 changed |= ActivityInfo.CONFIG_NAVIGATION;
1684 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001685 if ((compareUndefined || delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED)
Dianne Hackborn93e462b2009-09-15 22:50:40 -07001686 && navigationHidden != delta.navigationHidden) {
1687 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1688 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001689 if ((compareUndefined || delta.orientation != ORIENTATION_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001690 && orientation != delta.orientation) {
1691 changed |= ActivityInfo.CONFIG_ORIENTATION;
1692 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001693 if ((compareUndefined || getScreenLayoutNoDirection(delta.screenLayout) !=
1694 (SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED))
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001695 && getScreenLayoutNoDirection(screenLayout) !=
Andrii Kulianb10330d2016-09-16 13:51:46 -07001696 getScreenLayoutNoDirection(delta.screenLayout)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07001697 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
1698 }
Romain Guyc9ba5592017-01-18 16:34:42 -08001699 if ((compareUndefined ||
Romain Guy48327452017-01-23 17:03:35 -08001700 (delta.colorMode & COLOR_MODE_HDR_MASK) != COLOR_MODE_HDR_UNDEFINED)
1701 && (colorMode & COLOR_MODE_HDR_MASK) !=
1702 (delta.colorMode & COLOR_MODE_HDR_MASK)) {
1703 changed |= ActivityInfo.CONFIG_COLOR_MODE;
Romain Guyc9ba5592017-01-18 16:34:42 -08001704 }
1705 if ((compareUndefined ||
Romain Guy48327452017-01-23 17:03:35 -08001706 (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) !=
1707 COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED)
1708 && (colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) !=
1709 (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) {
1710 changed |= ActivityInfo.CONFIG_COLOR_MODE;
Romain Guyc9ba5592017-01-18 16:34:42 -08001711 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001712 if ((compareUndefined || delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED))
Tobias Haamel27b28b32010-02-09 23:09:17 +01001713 && uiMode != delta.uiMode) {
1714 changed |= ActivityInfo.CONFIG_UI_MODE;
1715 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001716 if ((compareUndefined || delta.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED)
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001717 && screenWidthDp != delta.screenWidthDp) {
1718 changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1719 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001720 if ((compareUndefined || delta.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED)
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001721 && screenHeightDp != delta.screenHeightDp) {
1722 changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1723 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001724 if ((compareUndefined || delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED)
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001725 && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
1726 changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
1727 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001728 if ((compareUndefined || delta.densityDpi != DENSITY_DPI_UNDEFINED)
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001729 && densityDpi != delta.densityDpi) {
1730 changed |= ActivityInfo.CONFIG_DENSITY;
1731 }
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001732 if ((compareUndefined || delta.assetsSeq != ASSETS_SEQ_UNDEFINED)
1733 && assetsSeq != delta.assetsSeq) {
1734 changed |= ActivityInfo.CONFIG_ASSETS_PATHS;
1735 }
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001736
Wale Ogunwale822e5122017-07-26 06:02:24 -07001737 // WindowConfiguration differences aren't considered public...
1738 if (!publicOnly
1739 && windowConfiguration.diff(delta.windowConfiguration, compareUndefined) != 0) {
1740 changed |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
Bryce Lee7566d762017-03-30 09:34:15 -07001741 }
1742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001743 return changed;
1744 }
1745
1746 /**
Alan Viveretteac85f902016-03-11 15:15:51 -05001747 * Determines if a new resource needs to be loaded from the bit set of
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001748 * configuration changes returned by {@link #updateFrom(Configuration)}.
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -07001749 *
Alan Viveretteac85f902016-03-11 15:15:51 -05001750 * @param configChanges the mask of changes configurations as returned by
1751 * {@link #updateFrom(Configuration)}
1752 * @param interestingChanges the configuration changes that the resource
1753 * can handle as given in
1754 * {@link android.util.TypedValue#changingConfigurations}
1755 * @return {@code true} if the resource needs to be loaded, {@code false}
1756 * otherwise
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001757 */
Alan Viveretteac85f902016-03-11 15:15:51 -05001758 public static boolean needNewResources(@Config int configChanges,
1759 @Config int interestingChanges) {
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001760 // CONFIG_ASSETS_PATHS and CONFIG_FONT_SCALE are higher level configuration changes that
1761 // all resources are subject to change with.
1762 interestingChanges = interestingChanges | ActivityInfo.CONFIG_ASSETS_PATHS
1763 | ActivityInfo.CONFIG_FONT_SCALE;
1764 return (configChanges & interestingChanges) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001765 }
Amith Yamasanid8415f42013-08-07 20:15:10 -07001766
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001767 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001768 * @hide Return true if the sequence of 'other' is better than this. Assumes
1769 * that 'this' is your current sequence and 'other' is a new one you have
1770 * received some how and want to compare with what you have.
1771 */
1772 public boolean isOtherSeqNewer(Configuration other) {
1773 if (other == null) {
1774 // Sanity check.
1775 return false;
1776 }
1777 if (other.seq == 0) {
1778 // If the other sequence is not specified, then we must assume
1779 // it is newer since we don't know any better.
1780 return true;
1781 }
1782 if (seq == 0) {
1783 // If this sequence is not specified, then we also consider the
1784 // other is better. Yes we have a preference for other. Sue us.
1785 return true;
1786 }
1787 int diff = other.seq - seq;
1788 if (diff > 0x10000) {
1789 // If there has been a sufficiently large jump, assume the
1790 // sequence has wrapped around.
1791 return false;
1792 }
1793 return diff > 0;
1794 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -07001795
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001796 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001797 * Parcelable methods
1798 */
1799 public int describeContents() {
1800 return 0;
1801 }
1802
1803 public void writeToParcel(Parcel dest, int flags) {
1804 dest.writeFloat(fontScale);
1805 dest.writeInt(mcc);
1806 dest.writeInt(mnc);
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001807
1808 fixUpLocaleList();
Siyamed Sinir27ddd8a2018-02-27 13:07:22 -08001809 dest.writeParcelable(mLocaleList, flags);
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001811 if(userSetLocale) {
1812 dest.writeInt(1);
1813 } else {
1814 dest.writeInt(0);
1815 }
1816 dest.writeInt(touchscreen);
1817 dest.writeInt(keyboard);
1818 dest.writeInt(keyboardHidden);
1819 dest.writeInt(hardKeyboardHidden);
1820 dest.writeInt(navigation);
Dianne Hackborn93e462b2009-09-15 22:50:40 -07001821 dest.writeInt(navigationHidden);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001822 dest.writeInt(orientation);
Dianne Hackborn723738c2009-06-25 19:48:04 -07001823 dest.writeInt(screenLayout);
Romain Guy48327452017-01-23 17:03:35 -08001824 dest.writeInt(colorMode);
Tobias Haamel27b28b32010-02-09 23:09:17 +01001825 dest.writeInt(uiMode);
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001826 dest.writeInt(screenWidthDp);
1827 dest.writeInt(screenHeightDp);
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001828 dest.writeInt(smallestScreenWidthDp);
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001829 dest.writeInt(densityDpi);
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001830 dest.writeInt(compatScreenWidthDp);
1831 dest.writeInt(compatScreenHeightDp);
1832 dest.writeInt(compatSmallestScreenWidthDp);
Wale Ogunwale822e5122017-07-26 06:02:24 -07001833 dest.writeValue(windowConfiguration);
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001834 dest.writeInt(assetsSeq);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001835 dest.writeInt(seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001836 }
1837
Dianne Hackborn694f79b2010-03-17 19:44:59 -07001838 public void readFromParcel(Parcel source) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001839 fontScale = source.readFloat();
1840 mcc = source.readInt();
1841 mnc = source.readInt();
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001842
Siyamed Sinir27ddd8a2018-02-27 13:07:22 -08001843 mLocaleList = source.readParcelable(LocaleList.class.getClassLoader());
Roozbeh Pournaderfee44842016-02-04 15:24:24 -08001844 locale = mLocaleList.get(0);
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001845
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001846 userSetLocale = (source.readInt()==1);
1847 touchscreen = source.readInt();
1848 keyboard = source.readInt();
1849 keyboardHidden = source.readInt();
1850 hardKeyboardHidden = source.readInt();
1851 navigation = source.readInt();
Dianne Hackborn93e462b2009-09-15 22:50:40 -07001852 navigationHidden = source.readInt();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853 orientation = source.readInt();
Dianne Hackborn723738c2009-06-25 19:48:04 -07001854 screenLayout = source.readInt();
Romain Guy48327452017-01-23 17:03:35 -08001855 colorMode = source.readInt();
Tobias Haamel27b28b32010-02-09 23:09:17 +01001856 uiMode = source.readInt();
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001857 screenWidthDp = source.readInt();
1858 screenHeightDp = source.readInt();
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001859 smallestScreenWidthDp = source.readInt();
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001860 densityDpi = source.readInt();
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001861 compatScreenWidthDp = source.readInt();
1862 compatScreenHeightDp = source.readInt();
1863 compatSmallestScreenWidthDp = source.readInt();
Wale Ogunwale822e5122017-07-26 06:02:24 -07001864 windowConfiguration.setTo((WindowConfiguration) source.readValue(null));
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001865 assetsSeq = source.readInt();
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001866 seq = source.readInt();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001867 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -07001868
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07001869 public static final @android.annotation.NonNull Parcelable.Creator<Configuration> CREATOR
Dianne Hackborn694f79b2010-03-17 19:44:59 -07001870 = new Parcelable.Creator<Configuration>() {
1871 public Configuration createFromParcel(Parcel source) {
1872 return new Configuration(source);
1873 }
1874
1875 public Configuration[] newArray(int size) {
1876 return new Configuration[size];
1877 }
1878 };
1879
1880 /**
1881 * Construct this Configuration object, reading from the Parcel.
1882 */
1883 private Configuration(Parcel source) {
1884 readFromParcel(source);
1885 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001886
1887 public int compareTo(Configuration that) {
1888 int n;
1889 float a = this.fontScale;
1890 float b = that.fontScale;
1891 if (a < b) return -1;
1892 if (a > b) return 1;
1893 n = this.mcc - that.mcc;
1894 if (n != 0) return n;
1895 n = this.mnc - that.mnc;
1896 if (n != 0) return n;
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001897
1898 fixUpLocaleList();
1899 that.fixUpLocaleList();
1900 // for backward compatibility, we consider an empty locale list to be greater
1901 // than any non-empty locale list.
1902 if (this.mLocaleList.isEmpty()) {
1903 if (!that.mLocaleList.isEmpty()) return 1;
1904 } else if (that.mLocaleList.isEmpty()) {
Dianne Hackborna8397032010-03-12 10:52:22 -08001905 return -1;
1906 } else {
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001907 final int minSize = Math.min(this.mLocaleList.size(), that.mLocaleList.size());
1908 for (int i = 0; i < minSize; ++i) {
1909 final Locale thisLocale = this.mLocaleList.get(i);
1910 final Locale thatLocale = that.mLocaleList.get(i);
1911 n = thisLocale.getLanguage().compareTo(thatLocale.getLanguage());
1912 if (n != 0) return n;
1913 n = thisLocale.getCountry().compareTo(thatLocale.getCountry());
1914 if (n != 0) return n;
1915 n = thisLocale.getVariant().compareTo(thatLocale.getVariant());
1916 if (n != 0) return n;
1917 n = thisLocale.toLanguageTag().compareTo(thatLocale.toLanguageTag());
1918 if (n != 0) return n;
1919 }
1920 n = this.mLocaleList.size() - that.mLocaleList.size();
Dianne Hackborna8397032010-03-12 10:52:22 -08001921 if (n != 0) return n;
1922 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001923
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001924 n = this.touchscreen - that.touchscreen;
1925 if (n != 0) return n;
1926 n = this.keyboard - that.keyboard;
1927 if (n != 0) return n;
1928 n = this.keyboardHidden - that.keyboardHidden;
1929 if (n != 0) return n;
1930 n = this.hardKeyboardHidden - that.hardKeyboardHidden;
1931 if (n != 0) return n;
1932 n = this.navigation - that.navigation;
1933 if (n != 0) return n;
Dianne Hackborn93e462b2009-09-15 22:50:40 -07001934 n = this.navigationHidden - that.navigationHidden;
1935 if (n != 0) return n;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001936 n = this.orientation - that.orientation;
Dianne Hackborn723738c2009-06-25 19:48:04 -07001937 if (n != 0) return n;
Romain Guy48327452017-01-23 17:03:35 -08001938 n = this.colorMode - that.colorMode;
Romain Guyc9ba5592017-01-18 16:34:42 -08001939 if (n != 0) return n;
Dianne Hackborn723738c2009-06-25 19:48:04 -07001940 n = this.screenLayout - that.screenLayout;
Tobias Haamel27b28b32010-02-09 23:09:17 +01001941 if (n != 0) return n;
1942 n = this.uiMode - that.uiMode;
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001943 if (n != 0) return n;
1944 n = this.screenWidthDp - that.screenWidthDp;
1945 if (n != 0) return n;
1946 n = this.screenHeightDp - that.screenHeightDp;
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001947 if (n != 0) return n;
1948 n = this.smallestScreenWidthDp - that.smallestScreenWidthDp;
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001949 if (n != 0) return n;
1950 n = this.densityDpi - that.densityDpi;
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001951 if (n != 0) return n;
1952 n = this.assetsSeq - that.assetsSeq;
Bryce Leec5fe0ee2017-06-30 09:03:09 -07001953 if (n != 0) return n;
Wale Ogunwale822e5122017-07-26 06:02:24 -07001954 n = windowConfiguration.compareTo(that.windowConfiguration);
1955 if (n != 0) return n;
Bryce Leec5fe0ee2017-06-30 09:03:09 -07001956
1957 // if (n != 0) return n;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001958 return n;
1959 }
1960
1961 public boolean equals(Configuration that) {
1962 if (that == null) return false;
1963 if (that == this) return true;
1964 return this.compareTo(that) == 0;
1965 }
1966
1967 public boolean equals(Object that) {
1968 try {
1969 return equals((Configuration)that);
1970 } catch (ClassCastException e) {
1971 }
1972 return false;
1973 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001974
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001975 public int hashCode() {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001976 int result = 17;
1977 result = 31 * result + Float.floatToIntBits(fontScale);
1978 result = 31 * result + mcc;
1979 result = 31 * result + mnc;
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001980 result = 31 * result + mLocaleList.hashCode();
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001981 result = 31 * result + touchscreen;
1982 result = 31 * result + keyboard;
1983 result = 31 * result + keyboardHidden;
1984 result = 31 * result + hardKeyboardHidden;
1985 result = 31 * result + navigation;
1986 result = 31 * result + navigationHidden;
1987 result = 31 * result + orientation;
1988 result = 31 * result + screenLayout;
Romain Guy48327452017-01-23 17:03:35 -08001989 result = 31 * result + colorMode;
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001990 result = 31 * result + uiMode;
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001991 result = 31 * result + screenWidthDp;
1992 result = 31 * result + screenHeightDp;
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001993 result = 31 * result + smallestScreenWidthDp;
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001994 result = 31 * result + densityDpi;
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001995 result = 31 * result + assetsSeq;
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001996 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001997 }
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001998
1999 /**
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002000 * Get the locale list. This is the preferred way for getting the locales (instead of using
2001 * the direct accessor to {@link #locale}, which would only provide the primary locale).
2002 *
2003 * @return The locale list.
2004 */
Adam Lesinskib61e4052016-05-19 18:23:05 -07002005 public @NonNull LocaleList getLocales() {
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002006 fixUpLocaleList();
2007 return mLocaleList;
2008 }
2009
2010 /**
2011 * Set the locale list. This is the preferred way for setting up the locales (instead of using
2012 * the direct accessor or {@link #setLocale(Locale)}). This will also set the layout direction
2013 * according to the first locale in the list.
2014 *
2015 * Note that the layout direction will always come from the first locale in the locale list,
2016 * even if the locale is not supported by the resources (the resources may only support
2017 * another locale further down the list which has a different direction).
2018 *
2019 * @param locales The locale list. If null, an empty LocaleList will be assigned.
2020 */
2021 public void setLocales(@Nullable LocaleList locales) {
2022 mLocaleList = locales == null ? LocaleList.getEmptyLocaleList() : locales;
Roozbeh Pournaderfee44842016-02-04 15:24:24 -08002023 locale = mLocaleList.get(0);
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002024 setLayoutDirection(locale);
2025 }
2026
2027 /**
2028 * Set the locale list to a list of just one locale. This will also set the layout direction
2029 * according to the locale.
2030 *
2031 * Note that after this is run, calling <code>.equals()</code> on the input locale and the
2032 * {@link #locale} attribute would return <code>true</code> if they are not null, but there is
2033 * no guarantee that they would be the same object.
2034 *
2035 * See also the note about layout direction in {@link #setLocales(LocaleList)}.
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07002036 *
2037 * @param loc The locale. Can be null.
2038 */
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002039 public void setLocale(@Nullable Locale loc) {
Raph Levien10ea92a2016-05-02 12:56:01 -07002040 setLocales(loc == null ? LocaleList.getEmptyLocaleList() : new LocaleList(loc));
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07002041 }
2042
2043 /**
Seigo Nonakabd5cac62016-05-13 15:11:37 +09002044 * @hide
2045 *
2046 * Clears the locale without changing layout direction.
2047 */
2048 public void clearLocales() {
2049 mLocaleList = LocaleList.getEmptyLocaleList();
2050 locale = null;
2051 }
2052
2053 /**
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07002054 * Return the layout direction. Will be either {@link View#LAYOUT_DIRECTION_LTR} or
2055 * {@link View#LAYOUT_DIRECTION_RTL}.
2056 *
Dianne Hackbornf1ae2692013-04-19 14:09:37 -07002057 * @return Returns {@link View#LAYOUT_DIRECTION_RTL} if the configuration
2058 * is {@link #SCREENLAYOUT_LAYOUTDIR_RTL}, otherwise {@link View#LAYOUT_DIRECTION_LTR}.
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07002059 */
2060 public int getLayoutDirection() {
Dianne Hackbornf1ae2692013-04-19 14:09:37 -07002061 return (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK) == SCREENLAYOUT_LAYOUTDIR_RTL
2062 ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07002063 }
2064
2065 /**
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002066 * Set the layout direction from a Locale.
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07002067 *
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002068 * @param loc The Locale. If null will set the layout direction to
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07002069 * {@link View#LAYOUT_DIRECTION_LTR}. If not null will set it to the layout direction
2070 * corresponding to the Locale.
2071 *
John Spurlockbc4cf002015-03-24 21:51:20 -04002072 * @see View#LAYOUT_DIRECTION_LTR
2073 * @see View#LAYOUT_DIRECTION_RTL
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07002074 */
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002075 public void setLayoutDirection(Locale loc) {
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07002076 // There is a "1" difference between the configuration values for
2077 // layout direction and View constants for layout direction, just add "1".
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002078 final int layoutDirection = 1 + TextUtils.getLayoutDirectionFromLocale(loc);
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07002079 screenLayout = (screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK)|
2080 (layoutDirection << SCREENLAYOUT_LAYOUTDIR_SHIFT);
2081 }
2082
2083 private static int getScreenLayoutNoDirection(int screenLayout) {
2084 return screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK;
2085 }
Adam Lesinski2c749d22014-06-04 13:00:29 -07002086
2087 /**
Adam Powell49e7ff92015-05-14 16:18:53 -07002088 * Return whether the screen has a round shape. Apps may choose to change styling based
2089 * on this property, such as the alignment or layout of text or informational icons.
2090 *
2091 * @return true if the screen is rounded, false otherwise
2092 */
2093 public boolean isScreenRound() {
2094 return (screenLayout & SCREENLAYOUT_ROUND_MASK) == SCREENLAYOUT_ROUND_YES;
2095 }
2096
2097 /**
Romain Guye89d0bb2017-06-20 12:23:42 -07002098 * Return whether the screen has a wide color gamut and wide color gamut rendering
2099 * is supported by this device.
Romain Guyc9ba5592017-01-18 16:34:42 -08002100 *
Chia-I Wu53e86ba2018-05-02 10:13:22 -07002101 * When true, it implies the screen is colorspace aware but not
2102 * necessarily color-managed. The final colors may still be changed by the
2103 * screen depending on user settings.
2104 *
Romain Guye89d0bb2017-06-20 12:23:42 -07002105 * @return true if the screen has a wide color gamut and wide color gamut rendering
2106 * is supported, false otherwise
Romain Guyc9ba5592017-01-18 16:34:42 -08002107 */
2108 public boolean isScreenWideColorGamut() {
Romain Guy48327452017-01-23 17:03:35 -08002109 return (colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) == COLOR_MODE_WIDE_COLOR_GAMUT_YES;
Romain Guyc9ba5592017-01-18 16:34:42 -08002110 }
2111
2112 /**
2113 * Return whether the screen has a high dynamic range.
2114 *
2115 * @return true if the screen has a high dynamic range, false otherwise
2116 */
2117 public boolean isScreenHdr() {
Romain Guy48327452017-01-23 17:03:35 -08002118 return (colorMode & COLOR_MODE_HDR_MASK) == COLOR_MODE_HDR_YES;
Romain Guyc9ba5592017-01-18 16:34:42 -08002119 }
2120
2121 /**
Adam Lesinski2c749d22014-06-04 13:00:29 -07002122 *
2123 * @hide
2124 */
Roozbeh Pournader47f71a62015-11-07 11:55:38 -08002125 public static String localesToResourceQualifier(LocaleList locs) {
Roozbeh Pournader309ebd62016-06-17 22:13:12 -07002126 final StringBuilder sb = new StringBuilder();
Roozbeh Pournader47f71a62015-11-07 11:55:38 -08002127 for (int i = 0; i < locs.size(); i++) {
Roozbeh Pournader309ebd62016-06-17 22:13:12 -07002128 final Locale loc = locs.get(i);
2129 final int l = loc.getLanguage().length();
2130 if (l == 0) {
2131 continue;
2132 }
2133 final int s = loc.getScript().length();
2134 final int c = loc.getCountry().length();
2135 final int v = loc.getVariant().length();
2136 // We ignore locale extensions, since they are not supported by AAPT
2137
2138 if (sb.length() != 0) {
2139 sb.append(",");
2140 }
2141 if (l == 2 && s == 0 && (c == 0 || c == 2) && v == 0) {
2142 // Traditional locale format: xx or xx-rYY
Roozbeh Pournader47f71a62015-11-07 11:55:38 -08002143 sb.append(loc.getLanguage());
Roozbeh Pournader309ebd62016-06-17 22:13:12 -07002144 if (c == 2) {
Roozbeh Pournader47f71a62015-11-07 11:55:38 -08002145 sb.append("-r").append(loc.getCountry());
Roozbeh Pournader309ebd62016-06-17 22:13:12 -07002146 }
2147 } else {
2148 sb.append("b+");
2149 sb.append(loc.getLanguage());
2150 if (s != 0) {
2151 sb.append("+");
2152 sb.append(loc.getScript());
2153 }
2154 if (c != 0) {
2155 sb.append("+");
2156 sb.append(loc.getCountry());
2157 }
2158 if (v != 0) {
2159 sb.append("+");
2160 sb.append(loc.getVariant());
Adam Lesinski2c749d22014-06-04 13:00:29 -07002161 }
2162 }
2163 }
2164 return sb.toString();
2165 }
2166
2167
2168 /**
2169 * Returns a string representation of the configuration that can be parsed
Dianne Hackbornbf5ba6b2018-02-20 10:31:02 -08002170 * by build tools (like AAPT), without display metrics included
Adam Lesinski2c749d22014-06-04 13:00:29 -07002171 *
Adam Lesinski2c749d22014-06-04 13:00:29 -07002172 * @hide
2173 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01002174 @UnsupportedAppUsage
Adam Lesinski2c749d22014-06-04 13:00:29 -07002175 public static String resourceQualifierString(Configuration config) {
Dianne Hackbornbf5ba6b2018-02-20 10:31:02 -08002176 return resourceQualifierString(config, null);
2177 }
2178
2179 /**
2180 * Returns a string representation of the configuration that can be parsed
2181 * by build tools (like AAPT).
2182 *
2183 * @hide
2184 */
2185 public static String resourceQualifierString(Configuration config, DisplayMetrics metrics) {
Adam Lesinski2c749d22014-06-04 13:00:29 -07002186 ArrayList<String> parts = new ArrayList<String>();
2187
2188 if (config.mcc != 0) {
Adam Lesinski90865622014-10-16 18:18:10 -07002189 parts.add("mcc" + config.mcc);
Adam Lesinski2c749d22014-06-04 13:00:29 -07002190 if (config.mnc != 0) {
Adam Lesinski90865622014-10-16 18:18:10 -07002191 parts.add("mnc" + config.mnc);
Adam Lesinski2c749d22014-06-04 13:00:29 -07002192 }
2193 }
2194
Roozbeh Pournader47f71a62015-11-07 11:55:38 -08002195 if (!config.mLocaleList.isEmpty()) {
Roozbeh Pournader417bbe02015-11-09 17:09:15 -08002196 final String resourceQualifier = localesToResourceQualifier(config.mLocaleList);
2197 if (!resourceQualifier.isEmpty()) {
2198 parts.add(resourceQualifier);
2199 }
Adam Lesinski2c749d22014-06-04 13:00:29 -07002200 }
2201
2202 switch (config.screenLayout & Configuration.SCREENLAYOUT_LAYOUTDIR_MASK) {
2203 case Configuration.SCREENLAYOUT_LAYOUTDIR_LTR:
2204 parts.add("ldltr");
2205 break;
2206 case Configuration.SCREENLAYOUT_LAYOUTDIR_RTL:
2207 parts.add("ldrtl");
2208 break;
2209 default:
2210 break;
2211 }
2212
2213 if (config.smallestScreenWidthDp != 0) {
2214 parts.add("sw" + config.smallestScreenWidthDp + "dp");
2215 }
2216
2217 if (config.screenWidthDp != 0) {
2218 parts.add("w" + config.screenWidthDp + "dp");
2219 }
2220
2221 if (config.screenHeightDp != 0) {
2222 parts.add("h" + config.screenHeightDp + "dp");
2223 }
2224
2225 switch (config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) {
2226 case Configuration.SCREENLAYOUT_SIZE_SMALL:
2227 parts.add("small");
2228 break;
2229 case Configuration.SCREENLAYOUT_SIZE_NORMAL:
2230 parts.add("normal");
2231 break;
2232 case Configuration.SCREENLAYOUT_SIZE_LARGE:
2233 parts.add("large");
2234 break;
2235 case Configuration.SCREENLAYOUT_SIZE_XLARGE:
2236 parts.add("xlarge");
2237 break;
2238 default:
2239 break;
2240 }
2241
2242 switch (config.screenLayout & Configuration.SCREENLAYOUT_LONG_MASK) {
2243 case Configuration.SCREENLAYOUT_LONG_YES:
2244 parts.add("long");
2245 break;
2246 case Configuration.SCREENLAYOUT_LONG_NO:
2247 parts.add("notlong");
2248 break;
2249 default:
2250 break;
2251 }
2252
Adam Powell49e7ff92015-05-14 16:18:53 -07002253 switch (config.screenLayout & Configuration.SCREENLAYOUT_ROUND_MASK) {
2254 case Configuration.SCREENLAYOUT_ROUND_YES:
2255 parts.add("round");
2256 break;
2257 case Configuration.SCREENLAYOUT_ROUND_NO:
2258 parts.add("notround");
2259 break;
2260 default:
2261 break;
2262 }
2263
Romain Guy48327452017-01-23 17:03:35 -08002264 switch (config.colorMode & Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_MASK) {
2265 case Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_YES:
Romain Guyc9ba5592017-01-18 16:34:42 -08002266 parts.add("widecg");
2267 break;
Romain Guy48327452017-01-23 17:03:35 -08002268 case Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_NO:
Romain Guyc9ba5592017-01-18 16:34:42 -08002269 parts.add("nowidecg");
2270 break;
2271 default:
2272 break;
2273 }
2274
Chia-I Wu0d8acf52018-05-09 12:08:05 -07002275 switch (config.colorMode & Configuration.COLOR_MODE_HDR_MASK) {
2276 case Configuration.COLOR_MODE_HDR_YES:
2277 parts.add("highdr");
2278 break;
2279 case Configuration.COLOR_MODE_HDR_NO:
2280 parts.add("lowdr");
2281 break;
2282 default:
2283 break;
2284 }
2285
Adam Lesinski2c749d22014-06-04 13:00:29 -07002286 switch (config.orientation) {
2287 case Configuration.ORIENTATION_LANDSCAPE:
2288 parts.add("land");
2289 break;
2290 case Configuration.ORIENTATION_PORTRAIT:
2291 parts.add("port");
2292 break;
2293 default:
2294 break;
2295 }
2296
2297 switch (config.uiMode & Configuration.UI_MODE_TYPE_MASK) {
2298 case Configuration.UI_MODE_TYPE_APPLIANCE:
2299 parts.add("appliance");
2300 break;
2301 case Configuration.UI_MODE_TYPE_DESK:
2302 parts.add("desk");
2303 break;
2304 case Configuration.UI_MODE_TYPE_TELEVISION:
2305 parts.add("television");
2306 break;
2307 case Configuration.UI_MODE_TYPE_CAR:
2308 parts.add("car");
2309 break;
2310 case Configuration.UI_MODE_TYPE_WATCH:
2311 parts.add("watch");
2312 break;
Zak Cohen1a6acdb2016-12-12 15:21:21 -08002313 case Configuration.UI_MODE_TYPE_VR_HEADSET:
2314 parts.add("vrheadset");
2315 break;
Adam Lesinski2c749d22014-06-04 13:00:29 -07002316 default:
2317 break;
2318 }
2319
2320 switch (config.uiMode & Configuration.UI_MODE_NIGHT_MASK) {
2321 case Configuration.UI_MODE_NIGHT_YES:
2322 parts.add("night");
2323 break;
2324 case Configuration.UI_MODE_NIGHT_NO:
2325 parts.add("notnight");
2326 break;
2327 default:
2328 break;
2329 }
2330
2331 switch (config.densityDpi) {
Adam Lesinski31245b42014-08-22 19:10:56 -07002332 case DENSITY_DPI_UNDEFINED:
Adam Lesinski2c749d22014-06-04 13:00:29 -07002333 break;
2334 case 120:
2335 parts.add("ldpi");
2336 break;
2337 case 160:
2338 parts.add("mdpi");
2339 break;
2340 case 213:
2341 parts.add("tvdpi");
2342 break;
2343 case 240:
2344 parts.add("hdpi");
2345 break;
2346 case 320:
2347 parts.add("xhdpi");
2348 break;
Adam Lesinskiebc3e4c2014-08-21 12:21:45 -07002349 case 480:
2350 parts.add("xxhdpi");
2351 break;
2352 case 640:
2353 parts.add("xxxhdpi");
2354 break;
Adam Lesinski31245b42014-08-22 19:10:56 -07002355 case DENSITY_DPI_ANY:
2356 parts.add("anydpi");
2357 break;
2358 case DENSITY_DPI_NONE:
2359 parts.add("nodpi");
Christian Williamsb709f3c2017-11-02 17:19:27 -07002360 break;
Adam Lesinski2c749d22014-06-04 13:00:29 -07002361 default:
2362 parts.add(config.densityDpi + "dpi");
2363 break;
2364 }
2365
2366 switch (config.touchscreen) {
2367 case Configuration.TOUCHSCREEN_NOTOUCH:
2368 parts.add("notouch");
2369 break;
2370 case Configuration.TOUCHSCREEN_FINGER:
2371 parts.add("finger");
2372 break;
2373 default:
2374 break;
2375 }
2376
2377 switch (config.keyboardHidden) {
2378 case Configuration.KEYBOARDHIDDEN_NO:
2379 parts.add("keysexposed");
2380 break;
2381 case Configuration.KEYBOARDHIDDEN_YES:
2382 parts.add("keyshidden");
2383 break;
2384 case Configuration.KEYBOARDHIDDEN_SOFT:
2385 parts.add("keyssoft");
2386 break;
2387 default:
2388 break;
2389 }
2390
2391 switch (config.keyboard) {
2392 case Configuration.KEYBOARD_NOKEYS:
2393 parts.add("nokeys");
2394 break;
2395 case Configuration.KEYBOARD_QWERTY:
2396 parts.add("qwerty");
2397 break;
2398 case Configuration.KEYBOARD_12KEY:
2399 parts.add("12key");
2400 break;
2401 default:
2402 break;
2403 }
2404
2405 switch (config.navigationHidden) {
2406 case Configuration.NAVIGATIONHIDDEN_NO:
2407 parts.add("navexposed");
2408 break;
2409 case Configuration.NAVIGATIONHIDDEN_YES:
2410 parts.add("navhidden");
2411 break;
2412 default:
2413 break;
2414 }
2415
2416 switch (config.navigation) {
2417 case Configuration.NAVIGATION_NONAV:
2418 parts.add("nonav");
2419 break;
2420 case Configuration.NAVIGATION_DPAD:
2421 parts.add("dpad");
2422 break;
2423 case Configuration.NAVIGATION_TRACKBALL:
2424 parts.add("trackball");
2425 break;
2426 case Configuration.NAVIGATION_WHEEL:
2427 parts.add("wheel");
2428 break;
2429 default:
2430 break;
2431 }
2432
Dianne Hackbornbf5ba6b2018-02-20 10:31:02 -08002433 if (metrics != null) {
2434 final int width, height;
2435 if (metrics.widthPixels >= metrics.heightPixels) {
2436 width = metrics.widthPixels;
2437 height = metrics.heightPixels;
2438 } else {
2439 //noinspection SuspiciousNameCombination
2440 width = metrics.heightPixels;
2441 //noinspection SuspiciousNameCombination
2442 height = metrics.widthPixels;
2443 }
2444 parts.add(width + "x" + height);
2445 }
2446
Adam Lesinskiebc3e4c2014-08-21 12:21:45 -07002447 parts.add("v" + Build.VERSION.RESOURCES_SDK_INT);
Adam Lesinski2c749d22014-06-04 13:00:29 -07002448 return TextUtils.join("-", parts);
2449 }
Adam Lesinski7f61e962014-09-02 16:43:52 -07002450
2451 /**
2452 * Generate a delta Configuration between <code>base</code> and <code>change</code>. The
2453 * resulting delta can be used with {@link #updateFrom(Configuration)}.
2454 * <p />
2455 * Caveat: If the any of the Configuration's members becomes undefined, then
2456 * {@link #updateFrom(Configuration)} will treat it as a no-op and not update that member.
2457 *
2458 * This is fine for device configurations as no member is ever undefined.
2459 * {@hide}
2460 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01002461 @UnsupportedAppUsage
Adam Lesinski7f61e962014-09-02 16:43:52 -07002462 public static Configuration generateDelta(Configuration base, Configuration change) {
2463 final Configuration delta = new Configuration();
2464 if (base.fontScale != change.fontScale) {
2465 delta.fontScale = change.fontScale;
2466 }
2467
2468 if (base.mcc != change.mcc) {
2469 delta.mcc = change.mcc;
2470 }
2471
2472 if (base.mnc != change.mnc) {
2473 delta.mnc = change.mnc;
2474 }
2475
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002476 base.fixUpLocaleList();
2477 change.fixUpLocaleList();
2478 if (!base.mLocaleList.equals(change.mLocaleList)) {
2479 delta.mLocaleList = change.mLocaleList;
Adam Lesinski7f61e962014-09-02 16:43:52 -07002480 delta.locale = change.locale;
2481 }
2482
2483 if (base.touchscreen != change.touchscreen) {
2484 delta.touchscreen = change.touchscreen;
2485 }
2486
2487 if (base.keyboard != change.keyboard) {
2488 delta.keyboard = change.keyboard;
2489 }
2490
2491 if (base.keyboardHidden != change.keyboardHidden) {
2492 delta.keyboardHidden = change.keyboardHidden;
2493 }
2494
2495 if (base.navigation != change.navigation) {
2496 delta.navigation = change.navigation;
2497 }
2498
2499 if (base.navigationHidden != change.navigationHidden) {
2500 delta.navigationHidden = change.navigationHidden;
2501 }
2502
2503 if (base.orientation != change.orientation) {
2504 delta.orientation = change.orientation;
2505 }
2506
2507 if ((base.screenLayout & SCREENLAYOUT_SIZE_MASK) !=
2508 (change.screenLayout & SCREENLAYOUT_SIZE_MASK)) {
2509 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_SIZE_MASK;
2510 }
2511
2512 if ((base.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK) !=
2513 (change.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) {
2514 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
2515 }
2516
2517 if ((base.screenLayout & SCREENLAYOUT_LONG_MASK) !=
2518 (change.screenLayout & SCREENLAYOUT_LONG_MASK)) {
2519 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_LONG_MASK;
2520 }
2521
Adam Powell49e7ff92015-05-14 16:18:53 -07002522 if ((base.screenLayout & SCREENLAYOUT_ROUND_MASK) !=
2523 (change.screenLayout & SCREENLAYOUT_ROUND_MASK)) {
2524 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_ROUND_MASK;
2525 }
2526
Romain Guy48327452017-01-23 17:03:35 -08002527 if ((base.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) !=
2528 (change.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) {
2529 delta.colorMode |= change.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK;
Romain Guyc9ba5592017-01-18 16:34:42 -08002530 }
2531
Romain Guy48327452017-01-23 17:03:35 -08002532 if ((base.colorMode & COLOR_MODE_HDR_MASK) !=
2533 (change.colorMode & COLOR_MODE_HDR_MASK)) {
2534 delta.colorMode |= change.colorMode & COLOR_MODE_HDR_MASK;
Romain Guyc9ba5592017-01-18 16:34:42 -08002535 }
2536
Adam Lesinski7f61e962014-09-02 16:43:52 -07002537 if ((base.uiMode & UI_MODE_TYPE_MASK) != (change.uiMode & UI_MODE_TYPE_MASK)) {
2538 delta.uiMode |= change.uiMode & UI_MODE_TYPE_MASK;
2539 }
2540
2541 if ((base.uiMode & UI_MODE_NIGHT_MASK) != (change.uiMode & UI_MODE_NIGHT_MASK)) {
2542 delta.uiMode |= change.uiMode & UI_MODE_NIGHT_MASK;
2543 }
2544
2545 if (base.screenWidthDp != change.screenWidthDp) {
2546 delta.screenWidthDp = change.screenWidthDp;
2547 }
2548
2549 if (base.screenHeightDp != change.screenHeightDp) {
2550 delta.screenHeightDp = change.screenHeightDp;
2551 }
2552
2553 if (base.smallestScreenWidthDp != change.smallestScreenWidthDp) {
2554 delta.smallestScreenWidthDp = change.smallestScreenWidthDp;
2555 }
2556
2557 if (base.densityDpi != change.densityDpi) {
2558 delta.densityDpi = change.densityDpi;
2559 }
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01002560
2561 if (base.assetsSeq != change.assetsSeq) {
2562 delta.assetsSeq = change.assetsSeq;
2563 }
Wale Ogunwale822e5122017-07-26 06:02:24 -07002564
2565 if (!base.windowConfiguration.equals(change.windowConfiguration)) {
2566 delta.windowConfiguration.setTo(change.windowConfiguration);
2567 }
Adam Lesinski7f61e962014-09-02 16:43:52 -07002568 return delta;
2569 }
2570
2571 private static final String XML_ATTR_FONT_SCALE = "fs";
2572 private static final String XML_ATTR_MCC = "mcc";
2573 private static final String XML_ATTR_MNC = "mnc";
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002574 private static final String XML_ATTR_LOCALES = "locales";
Adam Lesinski7f61e962014-09-02 16:43:52 -07002575 private static final String XML_ATTR_TOUCHSCREEN = "touch";
2576 private static final String XML_ATTR_KEYBOARD = "key";
2577 private static final String XML_ATTR_KEYBOARD_HIDDEN = "keyHid";
2578 private static final String XML_ATTR_HARD_KEYBOARD_HIDDEN = "hardKeyHid";
2579 private static final String XML_ATTR_NAVIGATION = "nav";
2580 private static final String XML_ATTR_NAVIGATION_HIDDEN = "navHid";
2581 private static final String XML_ATTR_ORIENTATION = "ori";
Bryce Leec1f2f2a2017-06-22 15:29:42 -07002582 private static final String XML_ATTR_ROTATION = "rot";
Adam Lesinski7f61e962014-09-02 16:43:52 -07002583 private static final String XML_ATTR_SCREEN_LAYOUT = "scrLay";
Romain Guy48327452017-01-23 17:03:35 -08002584 private static final String XML_ATTR_COLOR_MODE = "clrMod";
Adam Lesinski7f61e962014-09-02 16:43:52 -07002585 private static final String XML_ATTR_UI_MODE = "ui";
2586 private static final String XML_ATTR_SCREEN_WIDTH = "width";
2587 private static final String XML_ATTR_SCREEN_HEIGHT = "height";
2588 private static final String XML_ATTR_SMALLEST_WIDTH = "sw";
2589 private static final String XML_ATTR_DENSITY = "density";
Bryce Lee7566d762017-03-30 09:34:15 -07002590 private static final String XML_ATTR_APP_BOUNDS = "app_bounds";
Adam Lesinski7f61e962014-09-02 16:43:52 -07002591
2592 /**
2593 * Reads the attributes corresponding to Configuration member fields from the Xml parser.
2594 * The parser is expected to be on a tag which has Configuration attributes.
2595 *
2596 * @param parser The Xml parser from which to read attributes.
2597 * @param configOut The Configuration to populate from the Xml attributes.
2598 * {@hide}
2599 */
2600 public static void readXmlAttrs(XmlPullParser parser, Configuration configOut)
2601 throws XmlPullParserException, IOException {
2602 configOut.fontScale = Float.intBitsToFloat(
2603 XmlUtils.readIntAttribute(parser, XML_ATTR_FONT_SCALE, 0));
2604 configOut.mcc = XmlUtils.readIntAttribute(parser, XML_ATTR_MCC, 0);
2605 configOut.mnc = XmlUtils.readIntAttribute(parser, XML_ATTR_MNC, 0);
2606
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002607 final String localesStr = XmlUtils.readStringAttribute(parser, XML_ATTR_LOCALES);
2608 configOut.mLocaleList = LocaleList.forLanguageTags(localesStr);
Roozbeh Pournaderfee44842016-02-04 15:24:24 -08002609 configOut.locale = configOut.mLocaleList.get(0);
Adam Lesinski7f61e962014-09-02 16:43:52 -07002610
2611 configOut.touchscreen = XmlUtils.readIntAttribute(parser, XML_ATTR_TOUCHSCREEN,
2612 TOUCHSCREEN_UNDEFINED);
2613 configOut.keyboard = XmlUtils.readIntAttribute(parser, XML_ATTR_KEYBOARD,
2614 KEYBOARD_UNDEFINED);
2615 configOut.keyboardHidden = XmlUtils.readIntAttribute(parser, XML_ATTR_KEYBOARD_HIDDEN,
2616 KEYBOARDHIDDEN_UNDEFINED);
2617 configOut.hardKeyboardHidden =
2618 XmlUtils.readIntAttribute(parser, XML_ATTR_HARD_KEYBOARD_HIDDEN,
2619 HARDKEYBOARDHIDDEN_UNDEFINED);
2620 configOut.navigation = XmlUtils.readIntAttribute(parser, XML_ATTR_NAVIGATION,
2621 NAVIGATION_UNDEFINED);
2622 configOut.navigationHidden = XmlUtils.readIntAttribute(parser, XML_ATTR_NAVIGATION_HIDDEN,
2623 NAVIGATIONHIDDEN_UNDEFINED);
2624 configOut.orientation = XmlUtils.readIntAttribute(parser, XML_ATTR_ORIENTATION,
2625 ORIENTATION_UNDEFINED);
2626 configOut.screenLayout = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_LAYOUT,
2627 SCREENLAYOUT_UNDEFINED);
Romain Guy48327452017-01-23 17:03:35 -08002628 configOut.colorMode = XmlUtils.readIntAttribute(parser, XML_ATTR_COLOR_MODE,
2629 COLOR_MODE_UNDEFINED);
Adam Lesinski7f61e962014-09-02 16:43:52 -07002630 configOut.uiMode = XmlUtils.readIntAttribute(parser, XML_ATTR_UI_MODE, 0);
2631 configOut.screenWidthDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_WIDTH,
2632 SCREEN_WIDTH_DP_UNDEFINED);
2633 configOut.screenHeightDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_HEIGHT,
2634 SCREEN_HEIGHT_DP_UNDEFINED);
2635 configOut.smallestScreenWidthDp =
2636 XmlUtils.readIntAttribute(parser, XML_ATTR_SMALLEST_WIDTH,
2637 SMALLEST_SCREEN_WIDTH_DP_UNDEFINED);
2638 configOut.densityDpi = XmlUtils.readIntAttribute(parser, XML_ATTR_DENSITY,
2639 DENSITY_DPI_UNDEFINED);
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01002640
Wale Ogunwale822e5122017-07-26 06:02:24 -07002641 // For persistence, we don't care about assetsSeq and WindowConfiguration, so do not read it
2642 // out.
Adam Lesinski7f61e962014-09-02 16:43:52 -07002643 }
2644
2645
2646 /**
2647 * Writes the Configuration's member fields as attributes into the XmlSerializer.
2648 * The serializer is expected to have already started a tag so that attributes can be
2649 * immediately written.
2650 *
2651 * @param xml The serializer to which to write the attributes.
2652 * @param config The Configuration whose member fields to write.
2653 * {@hide}
2654 */
2655 public static void writeXmlAttrs(XmlSerializer xml, Configuration config) throws IOException {
2656 XmlUtils.writeIntAttribute(xml, XML_ATTR_FONT_SCALE,
2657 Float.floatToIntBits(config.fontScale));
2658 if (config.mcc != 0) {
2659 XmlUtils.writeIntAttribute(xml, XML_ATTR_MCC, config.mcc);
2660 }
2661 if (config.mnc != 0) {
2662 XmlUtils.writeIntAttribute(xml, XML_ATTR_MNC, config.mnc);
2663 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002664 config.fixUpLocaleList();
2665 if (!config.mLocaleList.isEmpty()) {
2666 XmlUtils.writeStringAttribute(xml, XML_ATTR_LOCALES, config.mLocaleList.toLanguageTags());
Adam Lesinski7f61e962014-09-02 16:43:52 -07002667 }
2668 if (config.touchscreen != TOUCHSCREEN_UNDEFINED) {
2669 XmlUtils.writeIntAttribute(xml, XML_ATTR_TOUCHSCREEN, config.touchscreen);
2670 }
2671 if (config.keyboard != KEYBOARD_UNDEFINED) {
2672 XmlUtils.writeIntAttribute(xml, XML_ATTR_KEYBOARD, config.keyboard);
2673 }
2674 if (config.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED) {
2675 XmlUtils.writeIntAttribute(xml, XML_ATTR_KEYBOARD_HIDDEN, config.keyboardHidden);
2676 }
2677 if (config.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED) {
2678 XmlUtils.writeIntAttribute(xml, XML_ATTR_HARD_KEYBOARD_HIDDEN,
2679 config.hardKeyboardHidden);
2680 }
2681 if (config.navigation != NAVIGATION_UNDEFINED) {
2682 XmlUtils.writeIntAttribute(xml, XML_ATTR_NAVIGATION, config.navigation);
2683 }
2684 if (config.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED) {
2685 XmlUtils.writeIntAttribute(xml, XML_ATTR_NAVIGATION_HIDDEN, config.navigationHidden);
2686 }
2687 if (config.orientation != ORIENTATION_UNDEFINED) {
2688 XmlUtils.writeIntAttribute(xml, XML_ATTR_ORIENTATION, config.orientation);
2689 }
2690 if (config.screenLayout != SCREENLAYOUT_UNDEFINED) {
2691 XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_LAYOUT, config.screenLayout);
2692 }
Romain Guy48327452017-01-23 17:03:35 -08002693 if (config.colorMode != COLOR_MODE_UNDEFINED) {
2694 XmlUtils.writeIntAttribute(xml, XML_ATTR_COLOR_MODE, config.colorMode);
Romain Guyc9ba5592017-01-18 16:34:42 -08002695 }
Adam Lesinski7f61e962014-09-02 16:43:52 -07002696 if (config.uiMode != 0) {
2697 XmlUtils.writeIntAttribute(xml, XML_ATTR_UI_MODE, config.uiMode);
2698 }
2699 if (config.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
2700 XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_WIDTH, config.screenWidthDp);
2701 }
2702 if (config.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
2703 XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_HEIGHT, config.screenHeightDp);
2704 }
2705 if (config.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
2706 XmlUtils.writeIntAttribute(xml, XML_ATTR_SMALLEST_WIDTH, config.smallestScreenWidthDp);
2707 }
2708 if (config.densityDpi != DENSITY_DPI_UNDEFINED) {
2709 XmlUtils.writeIntAttribute(xml, XML_ATTR_DENSITY, config.densityDpi);
2710 }
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01002711
Wale Ogunwale822e5122017-07-26 06:02:24 -07002712 // For persistence, we do not care about assetsSeq and window configuration, so do not write
2713 // it out.
Adam Lesinski7f61e962014-09-02 16:43:52 -07002714 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002715}