2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package android.content.res;
19 import com.android.internal.util.XmlUtils;
21 import org.xmlpull.v1.XmlPullParser;
22 import org.xmlpull.v1.XmlPullParserException;
23 import org.xmlpull.v1.XmlSerializer;
25 import android.annotation.IntDef;
26 import android.annotation.NonNull;
27 import android.annotation.Nullable;
28 import android.content.pm.ActivityInfo;
29 import android.content.pm.ActivityInfo.Config;
30 import android.os.Build;
31 import android.os.LocaleList;
32 import android.os.Parcel;
33 import android.os.Parcelable;
34 import android.text.TextUtils;
35 import android.view.View;
37 import java.io.IOException;
38 import java.lang.annotation.Retention;
39 import java.lang.annotation.RetentionPolicy;
40 import java.util.ArrayList;
41 import java.util.Locale;
44 * This class describes all device configuration information that can
45 * impact the resources the application retrieves. This includes both
46 * user-specified configuration options (locale list and scaling) as well
47 * as device configurations (such as input modes, screen size and screen orientation).
48 * <p>You can acquire this object from {@link Resources}, using {@link
49 * Resources#getConfiguration}. Thus, from an activity, you can get it by chaining the request
50 * with {@link android.app.Activity#getResources}:</p>
51 * <pre>Configuration config = getResources().getConfiguration();</pre>
53 public final class Configuration implements Parcelable, Comparable<Configuration> {
55 public static final Configuration EMPTY = new Configuration();
58 * Current user preference for the scaling factor for fonts, relative
59 * to the base density scaling.
61 public float fontScale;
64 * IMSI MCC (Mobile Country Code), corresponding to
65 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#MccQualifier">mcc</a>
66 * resource qualifier. 0 if undefined.
71 * IMSI MNC (Mobile Network Code), corresponding to
72 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#MccQualifier">mnc</a>
73 * resource qualifier. 0 if undefined. Note that the actual MNC may be 0; in order to check
74 * for this use the {@link #MNC_ZERO} symbol.
79 * Constant used to to represent MNC (Mobile Network Code) zero.
80 * 0 cannot be used, since it is used to represent an undefined MNC.
82 public static final int MNC_ZERO = 0xffff;
85 * Current user preference for the locale, corresponding to
86 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#LocaleQualifier">locale</a>
89 * @deprecated Do not set or read this directly. Use {@link #getLocales()} and
90 * {@link #setLocales(LocaleList)}. If only the primary locale is needed,
91 * <code>getLocales().get(0)</code> is now the preferred accessor.
93 @Deprecated public Locale locale;
95 private LocaleList mLocaleList;
98 * Locale should persist on setting. This is hidden because it is really
99 * questionable whether this is the right way to expose the functionality.
102 public boolean userSetLocale;
104 /** Constant for {@link #screenLayout}: bits that encode the size. */
105 public static final int SCREENLAYOUT_SIZE_MASK = 0x0f;
106 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
107 * value indicating that no size has been set. */
108 public static final int SCREENLAYOUT_SIZE_UNDEFINED = 0x00;
109 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
110 * value indicating the screen is at least approximately 320x426 dp units,
112 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">small</a>
113 * resource qualifier.
114 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
115 * Multiple Screens</a> for more information. */
116 public static final int SCREENLAYOUT_SIZE_SMALL = 0x01;
117 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
118 * value indicating the screen is at least approximately 320x470 dp units,
120 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">normal</a>
121 * resource qualifier.
122 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
123 * Multiple Screens</a> for more information. */
124 public static final int SCREENLAYOUT_SIZE_NORMAL = 0x02;
125 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
126 * value indicating the screen is at least approximately 480x640 dp units,
128 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">large</a>
129 * resource qualifier.
130 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
131 * Multiple Screens</a> for more information. */
132 public static final int SCREENLAYOUT_SIZE_LARGE = 0x03;
133 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
134 * value indicating the screen is at least approximately 720x960 dp units,
136 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">xlarge</a>
137 * resource qualifier.
138 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
139 * Multiple Screens</a> for more information.*/
140 public static final int SCREENLAYOUT_SIZE_XLARGE = 0x04;
142 /** Constant for {@link #screenLayout}: bits that encode the aspect ratio. */
143 public static final int SCREENLAYOUT_LONG_MASK = 0x30;
144 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
145 * value indicating that no size has been set. */
146 public static final int SCREENLAYOUT_LONG_UNDEFINED = 0x00;
147 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
148 * value that corresponds to the
149 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenAspectQualifier">notlong</a>
150 * resource qualifier. */
151 public static final int SCREENLAYOUT_LONG_NO = 0x10;
152 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
153 * value that corresponds to the
154 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenAspectQualifier">long</a>
155 * resource qualifier. */
156 public static final int SCREENLAYOUT_LONG_YES = 0x20;
158 /** Constant for {@link #screenLayout}: bits that encode the layout direction. */
159 public static final int SCREENLAYOUT_LAYOUTDIR_MASK = 0xC0;
160 /** Constant for {@link #screenLayout}: bits shift to get the layout direction. */
161 public static final int SCREENLAYOUT_LAYOUTDIR_SHIFT = 6;
162 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
163 * value indicating that no layout dir has been set. */
164 public static final int SCREENLAYOUT_LAYOUTDIR_UNDEFINED = 0x00;
165 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
166 * value indicating that a layout dir has been set to LTR. */
167 public static final int SCREENLAYOUT_LAYOUTDIR_LTR = 0x01 << SCREENLAYOUT_LAYOUTDIR_SHIFT;
168 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
169 * value indicating that a layout dir has been set to RTL. */
170 public static final int SCREENLAYOUT_LAYOUTDIR_RTL = 0x02 << SCREENLAYOUT_LAYOUTDIR_SHIFT;
172 /** Constant for {@link #screenLayout}: bits that encode roundness of the screen. */
173 public static final int SCREENLAYOUT_ROUND_MASK = 0x300;
174 /** @hide Constant for {@link #screenLayout}: bit shift to get to screen roundness bits */
175 public static final int SCREENLAYOUT_ROUND_SHIFT = 8;
177 * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating
178 * that it is unknown whether or not the screen has a round shape.
180 public static final int SCREENLAYOUT_ROUND_UNDEFINED = 0x00;
182 * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating
183 * that the screen does not have a rounded shape.
185 public static final int SCREENLAYOUT_ROUND_NO = 0x1 << SCREENLAYOUT_ROUND_SHIFT;
187 * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating
188 * that the screen has a rounded shape. Corners may not be visible to the user;
189 * developers should pay special attention to the {@link android.view.WindowInsets} delivered
190 * to views for more information about ensuring content is not obscured.
192 * <p>Corresponds to the <code>-round</code> resource qualifier.</p>
194 public static final int SCREENLAYOUT_ROUND_YES = 0x2 << SCREENLAYOUT_ROUND_SHIFT;
196 /** Constant for {@link #screenLayout}: a value indicating that screenLayout is undefined */
197 public static final int SCREENLAYOUT_UNDEFINED = SCREENLAYOUT_SIZE_UNDEFINED |
198 SCREENLAYOUT_LONG_UNDEFINED | SCREENLAYOUT_LAYOUTDIR_UNDEFINED |
199 SCREENLAYOUT_ROUND_UNDEFINED;
202 * Special flag we generate to indicate that the screen layout requires
203 * us to use a compatibility mode for apps that are not modern layout
207 public static final int SCREENLAYOUT_COMPAT_NEEDED = 0x10000000;
210 * Bit mask of overall layout of the screen. Currently there are four
212 * <p>The {@link #SCREENLAYOUT_SIZE_MASK} bits define the overall size
213 * of the screen. They may be one of
214 * {@link #SCREENLAYOUT_SIZE_SMALL}, {@link #SCREENLAYOUT_SIZE_NORMAL},
215 * {@link #SCREENLAYOUT_SIZE_LARGE}, or {@link #SCREENLAYOUT_SIZE_XLARGE}.</p>
217 * <p>The {@link #SCREENLAYOUT_LONG_MASK} defines whether the screen
218 * is wider/taller than normal. They may be one of
219 * {@link #SCREENLAYOUT_LONG_NO} or {@link #SCREENLAYOUT_LONG_YES}.</p>
221 * <p>The {@link #SCREENLAYOUT_LAYOUTDIR_MASK} defines whether the screen layout
222 * is either LTR or RTL. They may be one of
223 * {@link #SCREENLAYOUT_LAYOUTDIR_LTR} or {@link #SCREENLAYOUT_LAYOUTDIR_RTL}.</p>
225 * <p>The {@link #SCREENLAYOUT_ROUND_MASK} defines whether the screen has a rounded
226 * shape. They may be one of {@link #SCREENLAYOUT_ROUND_NO} or {@link #SCREENLAYOUT_ROUND_YES}.
229 * <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
230 * Multiple Screens</a> for more information.</p>
232 public int screenLayout;
235 static public int resetScreenLayout(int curLayout) {
236 return (curLayout&~(SCREENLAYOUT_LONG_MASK | SCREENLAYOUT_SIZE_MASK
237 | SCREENLAYOUT_COMPAT_NEEDED))
238 | (SCREENLAYOUT_LONG_YES | SCREENLAYOUT_SIZE_XLARGE);
242 static public int reduceScreenLayout(int curLayout, int longSizeDp, int shortSizeDp) {
243 int screenLayoutSize;
244 boolean screenLayoutLong;
245 boolean screenLayoutCompatNeeded;
247 // These semi-magic numbers define our compatibility modes for
248 // applications with different screens. These are guarantees to
249 // app developers about the space they can expect for a particular
250 // configuration. DO NOT CHANGE!
251 if (longSizeDp < 470) {
252 // This is shorter than an HVGA normal density screen (which
253 // is 480 pixels on its long side).
254 screenLayoutSize = SCREENLAYOUT_SIZE_SMALL;
255 screenLayoutLong = false;
256 screenLayoutCompatNeeded = false;
258 // What size is this screen screen?
259 if (longSizeDp >= 960 && shortSizeDp >= 720) {
260 // 1.5xVGA or larger screens at medium density are the point
261 // at which we consider it to be an extra large screen.
262 screenLayoutSize = SCREENLAYOUT_SIZE_XLARGE;
263 } else if (longSizeDp >= 640 && shortSizeDp >= 480) {
264 // VGA or larger screens at medium density are the point
265 // at which we consider it to be a large screen.
266 screenLayoutSize = SCREENLAYOUT_SIZE_LARGE;
268 screenLayoutSize = SCREENLAYOUT_SIZE_NORMAL;
271 // If this screen is wider than normal HVGA, or taller
272 // than FWVGA, then for old apps we want to run in size
273 // compatibility mode.
274 if (shortSizeDp > 321 || longSizeDp > 570) {
275 screenLayoutCompatNeeded = true;
277 screenLayoutCompatNeeded = false;
280 // Is this a long screen?
281 if (((longSizeDp*3)/5) >= (shortSizeDp-1)) {
282 // Anything wider than WVGA (5:3) is considering to be long.
283 screenLayoutLong = true;
285 screenLayoutLong = false;
289 // Now reduce the last screenLayout to not be better than what we
291 if (!screenLayoutLong) {
292 curLayout = (curLayout&~SCREENLAYOUT_LONG_MASK) | SCREENLAYOUT_LONG_NO;
294 if (screenLayoutCompatNeeded) {
295 curLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
297 int curSize = curLayout&SCREENLAYOUT_SIZE_MASK;
298 if (screenLayoutSize < curSize) {
299 curLayout = (curLayout&~SCREENLAYOUT_SIZE_MASK) | screenLayoutSize;
305 public static String configurationDiffToString(int diff) {
306 ArrayList<String> list = new ArrayList<>();
307 if ((diff & ActivityInfo.CONFIG_MCC) != 0) {
308 list.add("CONFIG_MCC");
310 if ((diff & ActivityInfo.CONFIG_MNC) != 0) {
311 list.add("CONFIG_MNC");
313 if ((diff & ActivityInfo.CONFIG_LOCALE) != 0) {
314 list.add("CONFIG_LOCALE");
316 if ((diff & ActivityInfo.CONFIG_TOUCHSCREEN) != 0) {
317 list.add("CONFIG_TOUCHSCREEN");
319 if ((diff & ActivityInfo.CONFIG_KEYBOARD) != 0) {
320 list.add("CONFIG_KEYBOARD");
322 if ((diff & ActivityInfo.CONFIG_KEYBOARD_HIDDEN) != 0) {
323 list.add("CONFIG_KEYBOARD_HIDDEN");
325 if ((diff & ActivityInfo.CONFIG_NAVIGATION) != 0) {
326 list.add("CONFIG_NAVIGATION");
328 if ((diff & ActivityInfo.CONFIG_ORIENTATION) != 0) {
329 list.add("CONFIG_ORIENTATION");
331 if ((diff & ActivityInfo.CONFIG_SCREEN_LAYOUT) != 0) {
332 list.add("CONFIG_SCREEN_LAYOUT");
334 if ((diff & ActivityInfo.CONFIG_UI_MODE) != 0) {
335 list.add("CONFIG_UI_MODE");
337 if ((diff & ActivityInfo.CONFIG_SCREEN_SIZE) != 0) {
338 list.add("CONFIG_SCREEN_SIZE");
340 if ((diff & ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE) != 0) {
341 list.add("CONFIG_SMALLEST_SCREEN_SIZE");
343 if ((diff & ActivityInfo.CONFIG_LAYOUT_DIRECTION) != 0) {
344 list.add("CONFIG_LAYOUT_DIRECTION");
346 if ((diff & ActivityInfo.CONFIG_FONT_SCALE) != 0) {
347 list.add("CONFIG_FONT_SCALE");
349 StringBuilder builder = new StringBuilder("{");
350 for (int i = 0, n = list.size(); i < n; i++) {
351 builder.append(list.get(i));
353 builder.append(", ");
357 return builder.toString();
361 * Check if the Configuration's current {@link #screenLayout} is at
362 * least the given size.
364 * @param size The desired size, either {@link #SCREENLAYOUT_SIZE_SMALL},
365 * {@link #SCREENLAYOUT_SIZE_NORMAL}, {@link #SCREENLAYOUT_SIZE_LARGE}, or
366 * {@link #SCREENLAYOUT_SIZE_XLARGE}.
367 * @return Returns true if the current screen layout size is at least
370 public boolean isLayoutSizeAtLeast(int size) {
371 int cur = screenLayout&SCREENLAYOUT_SIZE_MASK;
372 if (cur == SCREENLAYOUT_SIZE_UNDEFINED) return false;
376 /** Constant for {@link #touchscreen}: a value indicating that no value has been set. */
377 public static final int TOUCHSCREEN_UNDEFINED = 0;
378 /** Constant for {@link #touchscreen}, value corresponding to the
379 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#TouchscreenQualifier">notouch</a>
380 * resource qualifier. */
381 public static final int TOUCHSCREEN_NOTOUCH = 1;
382 /** @deprecated Not currently supported or used. */
383 @Deprecated public static final int TOUCHSCREEN_STYLUS = 2;
384 /** Constant for {@link #touchscreen}, value corresponding to the
385 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#TouchscreenQualifier">finger</a>
386 * resource qualifier. */
387 public static final int TOUCHSCREEN_FINGER = 3;
390 * The kind of touch screen attached to the device.
391 * One of: {@link #TOUCHSCREEN_NOTOUCH}, {@link #TOUCHSCREEN_FINGER}.
393 public int touchscreen;
395 /** Constant for {@link #keyboard}: a value indicating that no value has been set. */
396 public static final int KEYBOARD_UNDEFINED = 0;
397 /** Constant for {@link #keyboard}, value corresponding to the
398 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">nokeys</a>
399 * resource qualifier. */
400 public static final int KEYBOARD_NOKEYS = 1;
401 /** Constant for {@link #keyboard}, value corresponding to the
402 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">qwerty</a>
403 * resource qualifier. */
404 public static final int KEYBOARD_QWERTY = 2;
405 /** Constant for {@link #keyboard}, value corresponding to the
406 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">12key</a>
407 * resource qualifier. */
408 public static final int KEYBOARD_12KEY = 3;
411 * The kind of keyboard attached to the device.
412 * One of: {@link #KEYBOARD_NOKEYS}, {@link #KEYBOARD_QWERTY},
413 * {@link #KEYBOARD_12KEY}.
417 /** Constant for {@link #keyboardHidden}: a value indicating that no value has been set. */
418 public static final int KEYBOARDHIDDEN_UNDEFINED = 0;
419 /** Constant for {@link #keyboardHidden}, value corresponding to the
420 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keysexposed</a>
421 * resource qualifier. */
422 public static final int KEYBOARDHIDDEN_NO = 1;
423 /** Constant for {@link #keyboardHidden}, value corresponding to the
424 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keyshidden</a>
425 * resource qualifier. */
426 public static final int KEYBOARDHIDDEN_YES = 2;
427 /** Constant matching actual resource implementation. {@hide} */
428 public static final int KEYBOARDHIDDEN_SOFT = 3;
431 * A flag indicating whether any keyboard is available. Unlike
432 * {@link #hardKeyboardHidden}, this also takes into account a soft
433 * keyboard, so if the hard keyboard is hidden but there is soft
434 * keyboard available, it will be set to NO. Value is one of:
435 * {@link #KEYBOARDHIDDEN_NO}, {@link #KEYBOARDHIDDEN_YES}.
437 public int keyboardHidden;
439 /** Constant for {@link #hardKeyboardHidden}: a value indicating that no value has been set. */
440 public static final int HARDKEYBOARDHIDDEN_UNDEFINED = 0;
441 /** Constant for {@link #hardKeyboardHidden}, value corresponding to the
442 * physical keyboard being exposed. */
443 public static final int HARDKEYBOARDHIDDEN_NO = 1;
444 /** Constant for {@link #hardKeyboardHidden}, value corresponding to the
445 * physical keyboard being hidden. */
446 public static final int HARDKEYBOARDHIDDEN_YES = 2;
449 * A flag indicating whether the hard keyboard has been hidden. This will
450 * be set on a device with a mechanism to hide the keyboard from the
451 * user, when that mechanism is closed. One of:
452 * {@link #HARDKEYBOARDHIDDEN_NO}, {@link #HARDKEYBOARDHIDDEN_YES}.
454 public int hardKeyboardHidden;
456 /** Constant for {@link #navigation}: a value indicating that no value has been set. */
457 public static final int NAVIGATION_UNDEFINED = 0;
458 /** Constant for {@link #navigation}, value corresponding to the
459 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">nonav</a>
460 * resource qualifier. */
461 public static final int NAVIGATION_NONAV = 1;
462 /** Constant for {@link #navigation}, value corresponding to the
463 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">dpad</a>
464 * resource qualifier. */
465 public static final int NAVIGATION_DPAD = 2;
466 /** Constant for {@link #navigation}, value corresponding to the
467 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">trackball</a>
468 * resource qualifier. */
469 public static final int NAVIGATION_TRACKBALL = 3;
470 /** Constant for {@link #navigation}, value corresponding to the
471 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">wheel</a>
472 * resource qualifier. */
473 public static final int NAVIGATION_WHEEL = 4;
476 * The kind of navigation method available on the device.
477 * One of: {@link #NAVIGATION_NONAV}, {@link #NAVIGATION_DPAD},
478 * {@link #NAVIGATION_TRACKBALL}, {@link #NAVIGATION_WHEEL}.
480 public int navigation;
482 /** Constant for {@link #navigationHidden}: a value indicating that no value has been set. */
483 public static final int NAVIGATIONHIDDEN_UNDEFINED = 0;
484 /** Constant for {@link #navigationHidden}, value corresponding to the
485 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavAvailQualifier">navexposed</a>
486 * resource qualifier. */
487 public static final int NAVIGATIONHIDDEN_NO = 1;
488 /** Constant for {@link #navigationHidden}, value corresponding to the
489 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavAvailQualifier">navhidden</a>
490 * resource qualifier. */
491 public static final int NAVIGATIONHIDDEN_YES = 2;
494 * A flag indicating whether any 5-way or DPAD navigation available.
495 * This will be set on a device with a mechanism to hide the navigation
496 * controls from the user, when that mechanism is closed. One of:
497 * {@link #NAVIGATIONHIDDEN_NO}, {@link #NAVIGATIONHIDDEN_YES}.
499 public int navigationHidden;
501 /** Constant for {@link #orientation}: a value indicating that no value has been set. */
502 public static final int ORIENTATION_UNDEFINED = 0;
503 /** Constant for {@link #orientation}, value corresponding to the
504 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#OrientationQualifier">port</a>
505 * resource qualifier. */
506 public static final int ORIENTATION_PORTRAIT = 1;
507 /** Constant for {@link #orientation}, value corresponding to the
508 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#OrientationQualifier">land</a>
509 * resource qualifier. */
510 public static final int ORIENTATION_LANDSCAPE = 2;
511 /** @deprecated Not currently supported or used. */
512 @Deprecated public static final int ORIENTATION_SQUARE = 3;
515 * Overall orientation of the screen. May be one of
516 * {@link #ORIENTATION_LANDSCAPE}, {@link #ORIENTATION_PORTRAIT}.
518 public int orientation;
520 /** Constant for {@link #uiMode}: bits that encode the mode type. */
521 public static final int UI_MODE_TYPE_MASK = 0x0f;
522 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
523 * value indicating that no mode type has been set. */
524 public static final int UI_MODE_TYPE_UNDEFINED = 0x00;
525 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
526 * value that corresponds to
527 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">no
528 * UI mode</a> resource qualifier specified. */
529 public static final int UI_MODE_TYPE_NORMAL = 0x01;
530 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
531 * value that corresponds to the
532 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">desk</a>
533 * resource qualifier. */
534 public static final int UI_MODE_TYPE_DESK = 0x02;
535 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
536 * value that corresponds to the
537 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">car</a>
538 * resource qualifier. */
539 public static final int UI_MODE_TYPE_CAR = 0x03;
540 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
541 * value that corresponds to the
542 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">television</a>
543 * resource qualifier. */
544 public static final int UI_MODE_TYPE_TELEVISION = 0x04;
545 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
546 * value that corresponds to the
547 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">appliance</a>
548 * resource qualifier. */
549 public static final int UI_MODE_TYPE_APPLIANCE = 0x05;
550 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
551 * value that corresponds to the
552 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">watch</a>
553 * resource qualifier. */
554 public static final int UI_MODE_TYPE_WATCH = 0x06;
556 /** Constant for {@link #uiMode}: bits that encode the night mode. */
557 public static final int UI_MODE_NIGHT_MASK = 0x30;
558 /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
559 * value indicating that no mode type has been set. */
560 public static final int UI_MODE_NIGHT_UNDEFINED = 0x00;
561 /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
562 * value that corresponds to the
563 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NightQualifier">notnight</a>
564 * resource qualifier. */
565 public static final int UI_MODE_NIGHT_NO = 0x10;
566 /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
567 * value that corresponds to the
568 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NightQualifier">night</a>
569 * resource qualifier. */
570 public static final int UI_MODE_NIGHT_YES = 0x20;
573 * Bit mask of the ui mode. Currently there are two fields:
574 * <p>The {@link #UI_MODE_TYPE_MASK} bits define the overall ui mode of the
575 * device. They may be one of {@link #UI_MODE_TYPE_UNDEFINED},
576 * {@link #UI_MODE_TYPE_NORMAL}, {@link #UI_MODE_TYPE_DESK},
577 * {@link #UI_MODE_TYPE_CAR}, {@link #UI_MODE_TYPE_TELEVISION},
578 * {@link #UI_MODE_TYPE_APPLIANCE}, or {@link #UI_MODE_TYPE_WATCH}.
580 * <p>The {@link #UI_MODE_NIGHT_MASK} defines whether the screen
581 * is in a special mode. They may be one of {@link #UI_MODE_NIGHT_UNDEFINED},
582 * {@link #UI_MODE_NIGHT_NO} or {@link #UI_MODE_NIGHT_YES}.
587 * Default value for {@link #screenWidthDp} indicating that no width
588 * has been specified.
590 public static final int SCREEN_WIDTH_DP_UNDEFINED = 0;
593 * The current width of the available screen space, in dp units,
595 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenWidthQualifier">screen
596 * width</a> resource qualifier. Set to
597 * {@link #SCREEN_WIDTH_DP_UNDEFINED} if no width is specified.
599 public int screenWidthDp;
602 * Default value for {@link #screenHeightDp} indicating that no width
603 * has been specified.
605 public static final int SCREEN_HEIGHT_DP_UNDEFINED = 0;
608 * The current height of the available screen space, in dp units,
610 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenHeightQualifier">screen
611 * height</a> resource qualifier. Set to
612 * {@link #SCREEN_HEIGHT_DP_UNDEFINED} if no height is specified.
614 public int screenHeightDp;
617 * Default value for {@link #smallestScreenWidthDp} indicating that no width
618 * has been specified.
620 public static final int SMALLEST_SCREEN_WIDTH_DP_UNDEFINED = 0;
623 * The smallest screen size an application will see in normal operation,
625 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#SmallestScreenWidthQualifier">smallest
626 * screen width</a> resource qualifier.
627 * This is the smallest value of both screenWidthDp and screenHeightDp
628 * in both portrait and landscape. Set to
629 * {@link #SMALLEST_SCREEN_WIDTH_DP_UNDEFINED} if no width is specified.
631 public int smallestScreenWidthDp;
634 * Default value for {@link #densityDpi} indicating that no width
635 * has been specified.
637 public static final int DENSITY_DPI_UNDEFINED = 0;
640 * Value for {@link #densityDpi} for resources that scale to any density (vector drawables).
643 public static final int DENSITY_DPI_ANY = 0xfffe;
646 * Value for {@link #densityDpi} for resources that are not meant to be scaled.
649 public static final int DENSITY_DPI_NONE = 0xffff;
652 * The target screen density being rendered to,
654 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#DensityQualifier">density</a>
655 * resource qualifier. Set to
656 * {@link #DENSITY_DPI_UNDEFINED} if no density is specified.
658 public int densityDpi;
660 /** @hide Hack to get this information from WM to app running in compat mode. */
661 public int compatScreenWidthDp;
662 /** @hide Hack to get this information from WM to app running in compat mode. */
663 public int compatScreenHeightDp;
664 /** @hide Hack to get this information from WM to app running in compat mode. */
665 public int compatSmallestScreenWidthDp;
668 * @hide Internal book-keeping.
677 NATIVE_CONFIG_LOCALE,
678 NATIVE_CONFIG_TOUCHSCREEN,
679 NATIVE_CONFIG_KEYBOARD,
680 NATIVE_CONFIG_KEYBOARD_HIDDEN,
681 NATIVE_CONFIG_NAVIGATION,
682 NATIVE_CONFIG_ORIENTATION,
683 NATIVE_CONFIG_DENSITY,
684 NATIVE_CONFIG_SCREEN_SIZE,
685 NATIVE_CONFIG_VERSION,
686 NATIVE_CONFIG_SCREEN_LAYOUT,
687 NATIVE_CONFIG_UI_MODE,
688 NATIVE_CONFIG_SMALLEST_SCREEN_SIZE,
689 NATIVE_CONFIG_LAYOUTDIR,
691 @Retention(RetentionPolicy.SOURCE)
692 public @interface NativeConfig {}
694 /** @hide Native-specific bit mask for MCC config; DO NOT USE UNLESS YOU ARE SURE. */
695 public static final int NATIVE_CONFIG_MCC = 0x0001;
696 /** @hide Native-specific bit mask for MNC config; DO NOT USE UNLESS YOU ARE SURE. */
697 public static final int NATIVE_CONFIG_MNC = 0x0002;
698 /** @hide Native-specific bit mask for LOCALE config; DO NOT USE UNLESS YOU ARE SURE. */
699 public static final int NATIVE_CONFIG_LOCALE = 0x0004;
700 /** @hide Native-specific bit mask for TOUCHSCREEN config; DO NOT USE UNLESS YOU ARE SURE. */
701 public static final int NATIVE_CONFIG_TOUCHSCREEN = 0x0008;
702 /** @hide Native-specific bit mask for KEYBOARD config; DO NOT USE UNLESS YOU ARE SURE. */
703 public static final int NATIVE_CONFIG_KEYBOARD = 0x0010;
704 /** @hide Native-specific bit mask for KEYBOARD_HIDDEN config; DO NOT USE UNLESS YOU
706 public static final int NATIVE_CONFIG_KEYBOARD_HIDDEN = 0x0020;
707 /** @hide Native-specific bit mask for NAVIGATION config; DO NOT USE UNLESS YOU ARE SURE. */
708 public static final int NATIVE_CONFIG_NAVIGATION = 0x0040;
709 /** @hide Native-specific bit mask for ORIENTATION config; DO NOT USE UNLESS YOU ARE SURE. */
710 public static final int NATIVE_CONFIG_ORIENTATION = 0x0080;
711 /** @hide Native-specific bit mask for DENSITY config; DO NOT USE UNLESS YOU ARE SURE. */
712 public static final int NATIVE_CONFIG_DENSITY = 0x0100;
713 /** @hide Native-specific bit mask for SCREEN_SIZE config; DO NOT USE UNLESS YOU ARE SURE. */
714 public static final int NATIVE_CONFIG_SCREEN_SIZE = 0x0200;
715 /** @hide Native-specific bit mask for VERSION config; DO NOT USE UNLESS YOU ARE SURE. */
716 public static final int NATIVE_CONFIG_VERSION = 0x0400;
717 /** @hide Native-specific bit mask for SCREEN_LAYOUT config; DO NOT USE UNLESS YOU ARE SURE. */
718 public static final int NATIVE_CONFIG_SCREEN_LAYOUT = 0x0800;
719 /** @hide Native-specific bit mask for UI_MODE config; DO NOT USE UNLESS YOU ARE SURE. */
720 public static final int NATIVE_CONFIG_UI_MODE = 0x1000;
721 /** @hide Native-specific bit mask for SMALLEST_SCREEN_SIZE config; DO NOT USE UNLESS YOU
723 public static final int NATIVE_CONFIG_SMALLEST_SCREEN_SIZE = 0x2000;
724 /** @hide Native-specific bit mask for LAYOUTDIR config ; DO NOT USE UNLESS YOU ARE SURE.*/
725 public static final int NATIVE_CONFIG_LAYOUTDIR = 0x4000;
728 * Construct an invalid Configuration. You must call {@link #setToDefaults}
729 * for this object to be valid. {@more}
731 public Configuration() {
736 * Makes a deep copy suitable for modification.
738 public Configuration(Configuration o) {
742 /* This brings mLocaleList in sync with locale in case a user of the older API who doesn't know
743 * about setLocales() has changed locale directly. */
744 private void fixUpLocaleList() {
745 if ((locale == null && !mLocaleList.isEmpty()) ||
746 (locale != null && !locale.equals(mLocaleList.get(0)))) {
747 mLocaleList = locale == null ? LocaleList.getEmptyLocaleList() : new LocaleList(locale);
751 public void setTo(Configuration o) {
752 fontScale = o.fontScale;
755 locale = o.locale == null ? null : (Locale) o.locale.clone();
757 mLocaleList = o.mLocaleList;
758 userSetLocale = o.userSetLocale;
759 touchscreen = o.touchscreen;
760 keyboard = o.keyboard;
761 keyboardHidden = o.keyboardHidden;
762 hardKeyboardHidden = o.hardKeyboardHidden;
763 navigation = o.navigation;
764 navigationHidden = o.navigationHidden;
765 orientation = o.orientation;
766 screenLayout = o.screenLayout;
768 screenWidthDp = o.screenWidthDp;
769 screenHeightDp = o.screenHeightDp;
770 smallestScreenWidthDp = o.smallestScreenWidthDp;
771 densityDpi = o.densityDpi;
772 compatScreenWidthDp = o.compatScreenWidthDp;
773 compatScreenHeightDp = o.compatScreenHeightDp;
774 compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp;
778 public String toString() {
779 StringBuilder sb = new StringBuilder(128);
781 sb.append(fontScale);
796 if (!mLocaleList.isEmpty()) {
798 sb.append(mLocaleList);
800 sb.append(" ?localeList");
802 int layoutDir = (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK);
804 case SCREENLAYOUT_LAYOUTDIR_UNDEFINED: sb.append(" ?layoutDir"); break;
805 case SCREENLAYOUT_LAYOUTDIR_LTR: sb.append(" ldltr"); break;
806 case SCREENLAYOUT_LAYOUTDIR_RTL: sb.append(" ldrtl"); break;
807 default: sb.append(" layoutDir=");
808 sb.append(layoutDir >> SCREENLAYOUT_LAYOUTDIR_SHIFT); break;
810 if (smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
811 sb.append(" sw"); sb.append(smallestScreenWidthDp); sb.append("dp");
815 if (screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
816 sb.append(" w"); sb.append(screenWidthDp); sb.append("dp");
820 if (screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
821 sb.append(" h"); sb.append(screenHeightDp); sb.append("dp");
825 if (densityDpi != DENSITY_DPI_UNDEFINED) {
826 sb.append(" "); sb.append(densityDpi); sb.append("dpi");
828 sb.append(" ?density");
830 switch ((screenLayout&SCREENLAYOUT_SIZE_MASK)) {
831 case SCREENLAYOUT_SIZE_UNDEFINED: sb.append(" ?lsize"); break;
832 case SCREENLAYOUT_SIZE_SMALL: sb.append(" smll"); break;
833 case SCREENLAYOUT_SIZE_NORMAL: sb.append(" nrml"); break;
834 case SCREENLAYOUT_SIZE_LARGE: sb.append(" lrg"); break;
835 case SCREENLAYOUT_SIZE_XLARGE: sb.append(" xlrg"); break;
836 default: sb.append(" layoutSize=");
837 sb.append(screenLayout&SCREENLAYOUT_SIZE_MASK); break;
839 switch ((screenLayout&SCREENLAYOUT_LONG_MASK)) {
840 case SCREENLAYOUT_LONG_UNDEFINED: sb.append(" ?long"); break;
841 case SCREENLAYOUT_LONG_NO: /* not-long is not interesting to print */ break;
842 case SCREENLAYOUT_LONG_YES: sb.append(" long"); break;
843 default: sb.append(" layoutLong=");
844 sb.append(screenLayout&SCREENLAYOUT_LONG_MASK); break;
846 switch (orientation) {
847 case ORIENTATION_UNDEFINED: sb.append(" ?orien"); break;
848 case ORIENTATION_LANDSCAPE: sb.append(" land"); break;
849 case ORIENTATION_PORTRAIT: sb.append(" port"); break;
850 default: sb.append(" orien="); sb.append(orientation); break;
852 switch ((uiMode&UI_MODE_TYPE_MASK)) {
853 case UI_MODE_TYPE_UNDEFINED: sb.append(" ?uimode"); break;
854 case UI_MODE_TYPE_NORMAL: /* normal is not interesting to print */ break;
855 case UI_MODE_TYPE_DESK: sb.append(" desk"); break;
856 case UI_MODE_TYPE_CAR: sb.append(" car"); break;
857 case UI_MODE_TYPE_TELEVISION: sb.append(" television"); break;
858 case UI_MODE_TYPE_APPLIANCE: sb.append(" appliance"); break;
859 case UI_MODE_TYPE_WATCH: sb.append(" watch"); break;
860 default: sb.append(" uimode="); sb.append(uiMode&UI_MODE_TYPE_MASK); break;
862 switch ((uiMode&UI_MODE_NIGHT_MASK)) {
863 case UI_MODE_NIGHT_UNDEFINED: sb.append(" ?night"); break;
864 case UI_MODE_NIGHT_NO: /* not-night is not interesting to print */ break;
865 case UI_MODE_NIGHT_YES: sb.append(" night"); break;
866 default: sb.append(" night="); sb.append(uiMode&UI_MODE_NIGHT_MASK); break;
868 switch (touchscreen) {
869 case TOUCHSCREEN_UNDEFINED: sb.append(" ?touch"); break;
870 case TOUCHSCREEN_NOTOUCH: sb.append(" -touch"); break;
871 case TOUCHSCREEN_STYLUS: sb.append(" stylus"); break;
872 case TOUCHSCREEN_FINGER: sb.append(" finger"); break;
873 default: sb.append(" touch="); sb.append(touchscreen); break;
876 case KEYBOARD_UNDEFINED: sb.append(" ?keyb"); break;
877 case KEYBOARD_NOKEYS: sb.append(" -keyb"); break;
878 case KEYBOARD_QWERTY: sb.append(" qwerty"); break;
879 case KEYBOARD_12KEY: sb.append(" 12key"); break;
880 default: sb.append(" keys="); sb.append(keyboard); break;
882 switch (keyboardHidden) {
883 case KEYBOARDHIDDEN_UNDEFINED: sb.append("/?"); break;
884 case KEYBOARDHIDDEN_NO: sb.append("/v"); break;
885 case KEYBOARDHIDDEN_YES: sb.append("/h"); break;
886 case KEYBOARDHIDDEN_SOFT: sb.append("/s"); break;
887 default: sb.append("/"); sb.append(keyboardHidden); break;
889 switch (hardKeyboardHidden) {
890 case HARDKEYBOARDHIDDEN_UNDEFINED: sb.append("/?"); break;
891 case HARDKEYBOARDHIDDEN_NO: sb.append("/v"); break;
892 case HARDKEYBOARDHIDDEN_YES: sb.append("/h"); break;
893 default: sb.append("/"); sb.append(hardKeyboardHidden); break;
895 switch (navigation) {
896 case NAVIGATION_UNDEFINED: sb.append(" ?nav"); break;
897 case NAVIGATION_NONAV: sb.append(" -nav"); break;
898 case NAVIGATION_DPAD: sb.append(" dpad"); break;
899 case NAVIGATION_TRACKBALL: sb.append(" tball"); break;
900 case NAVIGATION_WHEEL: sb.append(" wheel"); break;
901 default: sb.append(" nav="); sb.append(navigation); break;
903 switch (navigationHidden) {
904 case NAVIGATIONHIDDEN_UNDEFINED: sb.append("/?"); break;
905 case NAVIGATIONHIDDEN_NO: sb.append("/v"); break;
906 case NAVIGATIONHIDDEN_YES: sb.append("/h"); break;
907 default: sb.append("/"); sb.append(navigationHidden); break;
914 return sb.toString();
918 * Set this object to the system defaults.
920 public void setToDefaults() {
923 mLocaleList = LocaleList.getEmptyLocaleList();
925 userSetLocale = false;
926 touchscreen = TOUCHSCREEN_UNDEFINED;
927 keyboard = KEYBOARD_UNDEFINED;
928 keyboardHidden = KEYBOARDHIDDEN_UNDEFINED;
929 hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED;
930 navigation = NAVIGATION_UNDEFINED;
931 navigationHidden = NAVIGATIONHIDDEN_UNDEFINED;
932 orientation = ORIENTATION_UNDEFINED;
933 screenLayout = SCREENLAYOUT_UNDEFINED;
934 uiMode = UI_MODE_TYPE_UNDEFINED;
935 screenWidthDp = compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED;
936 screenHeightDp = compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED;
937 smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
938 densityDpi = DENSITY_DPI_UNDEFINED;
943 @Deprecated public void makeDefault() {
948 * Copies the fields from delta into this Configuration object, keeping
949 * track of which ones have changed. Any undefined fields in {@code delta}
950 * are ignored and not copied in to the current Configuration.
952 * @return a bit mask of the changed fields, as per {@link #diff}
954 public @Config int updateFrom(@NonNull Configuration delta) {
956 if (delta.fontScale > 0 && fontScale != delta.fontScale) {
957 changed |= ActivityInfo.CONFIG_FONT_SCALE;
958 fontScale = delta.fontScale;
960 if (delta.mcc != 0 && mcc != delta.mcc) {
961 changed |= ActivityInfo.CONFIG_MCC;
964 if (delta.mnc != 0 && mnc != delta.mnc) {
965 changed |= ActivityInfo.CONFIG_MNC;
969 delta.fixUpLocaleList();
970 if (!delta.mLocaleList.isEmpty() && !mLocaleList.equals(delta.mLocaleList)) {
971 changed |= ActivityInfo.CONFIG_LOCALE;
972 mLocaleList = delta.mLocaleList;
973 // delta.locale can't be null, since delta.mLocaleList is not empty.
974 if (!delta.locale.equals(locale)) {
975 locale = (Locale) delta.locale.clone();
976 // If locale has changed, then layout direction is also changed ...
977 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
978 // ... and we need to update the layout direction (represented by the first
979 // 2 most significant bits in screenLayout).
980 setLayoutDirection(locale);
983 final int deltaScreenLayoutDir = delta.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
984 if (deltaScreenLayoutDir != SCREENLAYOUT_LAYOUTDIR_UNDEFINED &&
985 deltaScreenLayoutDir != (screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) {
986 screenLayout = (screenLayout & ~SCREENLAYOUT_LAYOUTDIR_MASK) | deltaScreenLayoutDir;
987 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
989 if (delta.userSetLocale && (!userSetLocale || ((changed & ActivityInfo.CONFIG_LOCALE) != 0)))
991 changed |= ActivityInfo.CONFIG_LOCALE;
992 userSetLocale = true;
994 if (delta.touchscreen != TOUCHSCREEN_UNDEFINED
995 && touchscreen != delta.touchscreen) {
996 changed |= ActivityInfo.CONFIG_TOUCHSCREEN;
997 touchscreen = delta.touchscreen;
999 if (delta.keyboard != KEYBOARD_UNDEFINED
1000 && keyboard != delta.keyboard) {
1001 changed |= ActivityInfo.CONFIG_KEYBOARD;
1002 keyboard = delta.keyboard;
1004 if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED
1005 && keyboardHidden != delta.keyboardHidden) {
1006 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1007 keyboardHidden = delta.keyboardHidden;
1009 if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED
1010 && hardKeyboardHidden != delta.hardKeyboardHidden) {
1011 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1012 hardKeyboardHidden = delta.hardKeyboardHidden;
1014 if (delta.navigation != NAVIGATION_UNDEFINED
1015 && navigation != delta.navigation) {
1016 changed |= ActivityInfo.CONFIG_NAVIGATION;
1017 navigation = delta.navigation;
1019 if (delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED
1020 && navigationHidden != delta.navigationHidden) {
1021 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1022 navigationHidden = delta.navigationHidden;
1024 if (delta.orientation != ORIENTATION_UNDEFINED
1025 && orientation != delta.orientation) {
1026 changed |= ActivityInfo.CONFIG_ORIENTATION;
1027 orientation = delta.orientation;
1029 if (getScreenLayoutNoDirection(delta.screenLayout) !=
1030 (SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED)
1031 && (getScreenLayoutNoDirection(screenLayout) !=
1032 getScreenLayoutNoDirection(delta.screenLayout))) {
1033 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
1034 // We need to preserve the previous layout dir bits if they were defined
1035 if ((delta.screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK) == 0) {
1036 screenLayout = (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK)|delta.screenLayout;
1038 screenLayout = delta.screenLayout;
1041 if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)
1042 && uiMode != delta.uiMode) {
1043 changed |= ActivityInfo.CONFIG_UI_MODE;
1044 if ((delta.uiMode&UI_MODE_TYPE_MASK) != UI_MODE_TYPE_UNDEFINED) {
1045 uiMode = (uiMode&~UI_MODE_TYPE_MASK)
1046 | (delta.uiMode&UI_MODE_TYPE_MASK);
1048 if ((delta.uiMode&UI_MODE_NIGHT_MASK) != UI_MODE_NIGHT_UNDEFINED) {
1049 uiMode = (uiMode&~UI_MODE_NIGHT_MASK)
1050 | (delta.uiMode&UI_MODE_NIGHT_MASK);
1053 if (delta.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED
1054 && screenWidthDp != delta.screenWidthDp) {
1055 changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1056 screenWidthDp = delta.screenWidthDp;
1058 if (delta.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED
1059 && screenHeightDp != delta.screenHeightDp) {
1060 changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1061 screenHeightDp = delta.screenHeightDp;
1063 if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
1064 && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
1065 changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
1066 smallestScreenWidthDp = delta.smallestScreenWidthDp;
1068 if (delta.densityDpi != DENSITY_DPI_UNDEFINED &&
1069 densityDpi != delta.densityDpi) {
1070 changed |= ActivityInfo.CONFIG_DENSITY;
1071 densityDpi = delta.densityDpi;
1073 if (delta.compatScreenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
1074 compatScreenWidthDp = delta.compatScreenWidthDp;
1076 if (delta.compatScreenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
1077 compatScreenHeightDp = delta.compatScreenHeightDp;
1079 if (delta.compatSmallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
1080 compatSmallestScreenWidthDp = delta.compatSmallestScreenWidthDp;
1082 if (delta.seq != 0) {
1090 * Return a bit mask of the differences between this Configuration
1091 * object and the given one. Does not change the values of either. Any
1092 * undefined fields in <var>delta</var> are ignored.
1093 * @return Returns a bit mask indicating which configuration
1094 * values has changed, containing any combination of
1095 * {@link android.content.pm.ActivityInfo#CONFIG_FONT_SCALE
1096 * PackageManager.ActivityInfo.CONFIG_FONT_SCALE},
1097 * {@link android.content.pm.ActivityInfo#CONFIG_MCC
1098 * PackageManager.ActivityInfo.CONFIG_MCC},
1099 * {@link android.content.pm.ActivityInfo#CONFIG_MNC
1100 * PackageManager.ActivityInfo.CONFIG_MNC},
1101 * {@link android.content.pm.ActivityInfo#CONFIG_LOCALE
1102 * PackageManager.ActivityInfo.CONFIG_LOCALE},
1103 * {@link android.content.pm.ActivityInfo#CONFIG_TOUCHSCREEN
1104 * PackageManager.ActivityInfo.CONFIG_TOUCHSCREEN},
1105 * {@link android.content.pm.ActivityInfo#CONFIG_KEYBOARD
1106 * PackageManager.ActivityInfo.CONFIG_KEYBOARD},
1107 * {@link android.content.pm.ActivityInfo#CONFIG_NAVIGATION
1108 * PackageManager.ActivityInfo.CONFIG_NAVIGATION},
1109 * {@link android.content.pm.ActivityInfo#CONFIG_ORIENTATION
1110 * PackageManager.ActivityInfo.CONFIG_ORIENTATION},
1111 * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_LAYOUT
1112 * PackageManager.ActivityInfo.CONFIG_SCREEN_LAYOUT}, or
1113 * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_SIZE
1114 * PackageManager.ActivityInfo.CONFIG_SCREEN_SIZE}, or
1115 * {@link android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE
1116 * PackageManager.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE}.
1117 * {@link android.content.pm.ActivityInfo#CONFIG_LAYOUT_DIRECTION
1118 * PackageManager.ActivityInfo.CONFIG_LAYOUT_DIRECTION}.
1120 public int diff(Configuration delta) {
1122 if (delta.fontScale > 0 && fontScale != delta.fontScale) {
1123 changed |= ActivityInfo.CONFIG_FONT_SCALE;
1125 if (delta.mcc != 0 && mcc != delta.mcc) {
1126 changed |= ActivityInfo.CONFIG_MCC;
1128 if (delta.mnc != 0 && mnc != delta.mnc) {
1129 changed |= ActivityInfo.CONFIG_MNC;
1132 delta.fixUpLocaleList();
1133 if (!delta.mLocaleList.isEmpty() && !mLocaleList.equals(delta.mLocaleList)) {
1134 changed |= ActivityInfo.CONFIG_LOCALE;
1135 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
1137 final int deltaScreenLayoutDir = delta.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
1138 if (deltaScreenLayoutDir != SCREENLAYOUT_LAYOUTDIR_UNDEFINED &&
1139 deltaScreenLayoutDir != (screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) {
1140 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
1142 if (delta.touchscreen != TOUCHSCREEN_UNDEFINED
1143 && touchscreen != delta.touchscreen) {
1144 changed |= ActivityInfo.CONFIG_TOUCHSCREEN;
1146 if (delta.keyboard != KEYBOARD_UNDEFINED
1147 && keyboard != delta.keyboard) {
1148 changed |= ActivityInfo.CONFIG_KEYBOARD;
1150 if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED
1151 && keyboardHidden != delta.keyboardHidden) {
1152 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1154 if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED
1155 && hardKeyboardHidden != delta.hardKeyboardHidden) {
1156 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1158 if (delta.navigation != NAVIGATION_UNDEFINED
1159 && navigation != delta.navigation) {
1160 changed |= ActivityInfo.CONFIG_NAVIGATION;
1162 if (delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED
1163 && navigationHidden != delta.navigationHidden) {
1164 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1166 if (delta.orientation != ORIENTATION_UNDEFINED
1167 && orientation != delta.orientation) {
1168 changed |= ActivityInfo.CONFIG_ORIENTATION;
1170 if (getScreenLayoutNoDirection(delta.screenLayout) !=
1171 (SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED)
1172 && getScreenLayoutNoDirection(screenLayout) !=
1173 getScreenLayoutNoDirection(delta.screenLayout)) {
1174 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
1176 if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)
1177 && uiMode != delta.uiMode) {
1178 changed |= ActivityInfo.CONFIG_UI_MODE;
1180 if (delta.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED
1181 && screenWidthDp != delta.screenWidthDp) {
1182 changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1184 if (delta.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED
1185 && screenHeightDp != delta.screenHeightDp) {
1186 changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1188 if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
1189 && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
1190 changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
1192 if (delta.densityDpi != DENSITY_DPI_UNDEFINED
1193 && densityDpi != delta.densityDpi) {
1194 changed |= ActivityInfo.CONFIG_DENSITY;
1201 * Determines if a new resource needs to be loaded from the bit set of
1202 * configuration changes returned by {@link #updateFrom(Configuration)}.
1204 * @param configChanges the mask of changes configurations as returned by
1205 * {@link #updateFrom(Configuration)}
1206 * @param interestingChanges the configuration changes that the resource
1207 * can handle as given in
1208 * {@link android.util.TypedValue#changingConfigurations}
1209 * @return {@code true} if the resource needs to be loaded, {@code false}
1212 public static boolean needNewResources(@Config int configChanges,
1213 @Config int interestingChanges) {
1214 return (configChanges & (interestingChanges|ActivityInfo.CONFIG_FONT_SCALE)) != 0;
1218 * @hide Return true if the sequence of 'other' is better than this. Assumes
1219 * that 'this' is your current sequence and 'other' is a new one you have
1220 * received some how and want to compare with what you have.
1222 public boolean isOtherSeqNewer(Configuration other) {
1223 if (other == null) {
1227 if (other.seq == 0) {
1228 // If the other sequence is not specified, then we must assume
1229 // it is newer since we don't know any better.
1233 // If this sequence is not specified, then we also consider the
1234 // other is better. Yes we have a preference for other. Sue us.
1237 int diff = other.seq - seq;
1238 if (diff > 0x10000) {
1239 // If there has been a sufficiently large jump, assume the
1240 // sequence has wrapped around.
1247 * Parcelable methods
1249 public int describeContents() {
1253 public void writeToParcel(Parcel dest, int flags) {
1254 dest.writeFloat(fontScale);
1259 final int localeListSize = mLocaleList.size();
1260 dest.writeInt(localeListSize);
1261 for (int i = 0; i < localeListSize; ++i) {
1262 final Locale l = mLocaleList.get(i);
1263 dest.writeString(l.toLanguageTag());
1271 dest.writeInt(touchscreen);
1272 dest.writeInt(keyboard);
1273 dest.writeInt(keyboardHidden);
1274 dest.writeInt(hardKeyboardHidden);
1275 dest.writeInt(navigation);
1276 dest.writeInt(navigationHidden);
1277 dest.writeInt(orientation);
1278 dest.writeInt(screenLayout);
1279 dest.writeInt(uiMode);
1280 dest.writeInt(screenWidthDp);
1281 dest.writeInt(screenHeightDp);
1282 dest.writeInt(smallestScreenWidthDp);
1283 dest.writeInt(densityDpi);
1284 dest.writeInt(compatScreenWidthDp);
1285 dest.writeInt(compatScreenHeightDp);
1286 dest.writeInt(compatSmallestScreenWidthDp);
1290 public void readFromParcel(Parcel source) {
1291 fontScale = source.readFloat();
1292 mcc = source.readInt();
1293 mnc = source.readInt();
1295 final int localeListSize = source.readInt();
1296 final Locale[] localeArray = new Locale[localeListSize];
1297 for (int i = 0; i < localeListSize; ++i) {
1298 localeArray[i] = Locale.forLanguageTag(source.readString());
1300 mLocaleList = new LocaleList(localeArray);
1301 locale = mLocaleList.get(0);
1303 userSetLocale = (source.readInt()==1);
1304 touchscreen = source.readInt();
1305 keyboard = source.readInt();
1306 keyboardHidden = source.readInt();
1307 hardKeyboardHidden = source.readInt();
1308 navigation = source.readInt();
1309 navigationHidden = source.readInt();
1310 orientation = source.readInt();
1311 screenLayout = source.readInt();
1312 uiMode = source.readInt();
1313 screenWidthDp = source.readInt();
1314 screenHeightDp = source.readInt();
1315 smallestScreenWidthDp = source.readInt();
1316 densityDpi = source.readInt();
1317 compatScreenWidthDp = source.readInt();
1318 compatScreenHeightDp = source.readInt();
1319 compatSmallestScreenWidthDp = source.readInt();
1320 seq = source.readInt();
1323 public static final Parcelable.Creator<Configuration> CREATOR
1324 = new Parcelable.Creator<Configuration>() {
1325 public Configuration createFromParcel(Parcel source) {
1326 return new Configuration(source);
1329 public Configuration[] newArray(int size) {
1330 return new Configuration[size];
1335 * Construct this Configuration object, reading from the Parcel.
1337 private Configuration(Parcel source) {
1338 readFromParcel(source);
1341 public int compareTo(Configuration that) {
1343 float a = this.fontScale;
1344 float b = that.fontScale;
1345 if (a < b) return -1;
1346 if (a > b) return 1;
1347 n = this.mcc - that.mcc;
1348 if (n != 0) return n;
1349 n = this.mnc - that.mnc;
1350 if (n != 0) return n;
1353 that.fixUpLocaleList();
1354 // for backward compatibility, we consider an empty locale list to be greater
1355 // than any non-empty locale list.
1356 if (this.mLocaleList.isEmpty()) {
1357 if (!that.mLocaleList.isEmpty()) return 1;
1358 } else if (that.mLocaleList.isEmpty()) {
1361 final int minSize = Math.min(this.mLocaleList.size(), that.mLocaleList.size());
1362 for (int i = 0; i < minSize; ++i) {
1363 final Locale thisLocale = this.mLocaleList.get(i);
1364 final Locale thatLocale = that.mLocaleList.get(i);
1365 n = thisLocale.getLanguage().compareTo(thatLocale.getLanguage());
1366 if (n != 0) return n;
1367 n = thisLocale.getCountry().compareTo(thatLocale.getCountry());
1368 if (n != 0) return n;
1369 n = thisLocale.getVariant().compareTo(thatLocale.getVariant());
1370 if (n != 0) return n;
1371 n = thisLocale.toLanguageTag().compareTo(thatLocale.toLanguageTag());
1372 if (n != 0) return n;
1374 n = this.mLocaleList.size() - that.mLocaleList.size();
1375 if (n != 0) return n;
1378 n = this.touchscreen - that.touchscreen;
1379 if (n != 0) return n;
1380 n = this.keyboard - that.keyboard;
1381 if (n != 0) return n;
1382 n = this.keyboardHidden - that.keyboardHidden;
1383 if (n != 0) return n;
1384 n = this.hardKeyboardHidden - that.hardKeyboardHidden;
1385 if (n != 0) return n;
1386 n = this.navigation - that.navigation;
1387 if (n != 0) return n;
1388 n = this.navigationHidden - that.navigationHidden;
1389 if (n != 0) return n;
1390 n = this.orientation - that.orientation;
1391 if (n != 0) return n;
1392 n = this.screenLayout - that.screenLayout;
1393 if (n != 0) return n;
1394 n = this.uiMode - that.uiMode;
1395 if (n != 0) return n;
1396 n = this.screenWidthDp - that.screenWidthDp;
1397 if (n != 0) return n;
1398 n = this.screenHeightDp - that.screenHeightDp;
1399 if (n != 0) return n;
1400 n = this.smallestScreenWidthDp - that.smallestScreenWidthDp;
1401 if (n != 0) return n;
1402 n = this.densityDpi - that.densityDpi;
1403 //if (n != 0) return n;
1407 public boolean equals(Configuration that) {
1408 if (that == null) return false;
1409 if (that == this) return true;
1410 return this.compareTo(that) == 0;
1413 public boolean equals(Object that) {
1415 return equals((Configuration)that);
1416 } catch (ClassCastException e) {
1421 public int hashCode() {
1423 result = 31 * result + Float.floatToIntBits(fontScale);
1424 result = 31 * result + mcc;
1425 result = 31 * result + mnc;
1426 result = 31 * result + mLocaleList.hashCode();
1427 result = 31 * result + touchscreen;
1428 result = 31 * result + keyboard;
1429 result = 31 * result + keyboardHidden;
1430 result = 31 * result + hardKeyboardHidden;
1431 result = 31 * result + navigation;
1432 result = 31 * result + navigationHidden;
1433 result = 31 * result + orientation;
1434 result = 31 * result + screenLayout;
1435 result = 31 * result + uiMode;
1436 result = 31 * result + screenWidthDp;
1437 result = 31 * result + screenHeightDp;
1438 result = 31 * result + smallestScreenWidthDp;
1439 result = 31 * result + densityDpi;
1444 * Get the locale list. This is the preferred way for getting the locales (instead of using
1445 * the direct accessor to {@link #locale}, which would only provide the primary locale).
1447 * @return The locale list.
1449 public @NonNull LocaleList getLocales() {
1455 * Set the locale list. This is the preferred way for setting up the locales (instead of using
1456 * the direct accessor or {@link #setLocale(Locale)}). This will also set the layout direction
1457 * according to the first locale in the list.
1459 * Note that the layout direction will always come from the first locale in the locale list,
1460 * even if the locale is not supported by the resources (the resources may only support
1461 * another locale further down the list which has a different direction).
1463 * @param locales The locale list. If null, an empty LocaleList will be assigned.
1465 public void setLocales(@Nullable LocaleList locales) {
1466 mLocaleList = locales == null ? LocaleList.getEmptyLocaleList() : locales;
1467 locale = mLocaleList.get(0);
1468 setLayoutDirection(locale);
1472 * Set the locale list to a list of just one locale. This will also set the layout direction
1473 * according to the locale.
1475 * Note that after this is run, calling <code>.equals()</code> on the input locale and the
1476 * {@link #locale} attribute would return <code>true</code> if they are not null, but there is
1477 * no guarantee that they would be the same object.
1479 * See also the note about layout direction in {@link #setLocales(LocaleList)}.
1481 * @param loc The locale. Can be null.
1483 public void setLocale(@Nullable Locale loc) {
1484 setLocales(loc == null ? LocaleList.getEmptyLocaleList() : new LocaleList(loc));
1490 * Clears the locale without changing layout direction.
1492 public void clearLocales() {
1493 mLocaleList = LocaleList.getEmptyLocaleList();
1498 * Return the layout direction. Will be either {@link View#LAYOUT_DIRECTION_LTR} or
1499 * {@link View#LAYOUT_DIRECTION_RTL}.
1501 * @return Returns {@link View#LAYOUT_DIRECTION_RTL} if the configuration
1502 * is {@link #SCREENLAYOUT_LAYOUTDIR_RTL}, otherwise {@link View#LAYOUT_DIRECTION_LTR}.
1504 public int getLayoutDirection() {
1505 return (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK) == SCREENLAYOUT_LAYOUTDIR_RTL
1506 ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
1510 * Set the layout direction from a Locale.
1512 * @param loc The Locale. If null will set the layout direction to
1513 * {@link View#LAYOUT_DIRECTION_LTR}. If not null will set it to the layout direction
1514 * corresponding to the Locale.
1516 * @see View#LAYOUT_DIRECTION_LTR
1517 * @see View#LAYOUT_DIRECTION_RTL
1519 public void setLayoutDirection(Locale loc) {
1520 // There is a "1" difference between the configuration values for
1521 // layout direction and View constants for layout direction, just add "1".
1522 final int layoutDirection = 1 + TextUtils.getLayoutDirectionFromLocale(loc);
1523 screenLayout = (screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK)|
1524 (layoutDirection << SCREENLAYOUT_LAYOUTDIR_SHIFT);
1527 private static int getScreenLayoutNoDirection(int screenLayout) {
1528 return screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK;
1532 * Return whether the screen has a round shape. Apps may choose to change styling based
1533 * on this property, such as the alignment or layout of text or informational icons.
1535 * @return true if the screen is rounded, false otherwise
1537 public boolean isScreenRound() {
1538 return (screenLayout & SCREENLAYOUT_ROUND_MASK) == SCREENLAYOUT_ROUND_YES;
1545 public static String localesToResourceQualifier(LocaleList locs) {
1546 StringBuilder sb = new StringBuilder();
1547 for (int i = 0; i < locs.size(); i++) {
1548 Locale loc = locs.get(i);
1549 boolean l = (loc.getLanguage().length() != 0);
1550 boolean c = (loc.getCountry().length() != 0);
1551 boolean s = (loc.getScript().length() != 0);
1552 boolean v = (loc.getVariant().length() != 0);
1553 // TODO: take script and extensions into account
1555 if (sb.length() != 0) {
1558 sb.append(loc.getLanguage());
1560 sb.append("-r").append(loc.getCountry());
1562 sb.append("-s").append(loc.getScript());
1564 sb.append("-v").append(loc.getVariant());
1570 return sb.toString();
1575 * Returns a string representation of the configuration that can be parsed
1576 * by build tools (like AAPT).
1580 public static String resourceQualifierString(Configuration config) {
1581 ArrayList<String> parts = new ArrayList<String>();
1583 if (config.mcc != 0) {
1584 parts.add("mcc" + config.mcc);
1585 if (config.mnc != 0) {
1586 parts.add("mnc" + config.mnc);
1590 if (!config.mLocaleList.isEmpty()) {
1591 final String resourceQualifier = localesToResourceQualifier(config.mLocaleList);
1592 if (!resourceQualifier.isEmpty()) {
1593 parts.add(resourceQualifier);
1597 switch (config.screenLayout & Configuration.SCREENLAYOUT_LAYOUTDIR_MASK) {
1598 case Configuration.SCREENLAYOUT_LAYOUTDIR_LTR:
1601 case Configuration.SCREENLAYOUT_LAYOUTDIR_RTL:
1608 if (config.smallestScreenWidthDp != 0) {
1609 parts.add("sw" + config.smallestScreenWidthDp + "dp");
1612 if (config.screenWidthDp != 0) {
1613 parts.add("w" + config.screenWidthDp + "dp");
1616 if (config.screenHeightDp != 0) {
1617 parts.add("h" + config.screenHeightDp + "dp");
1620 switch (config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) {
1621 case Configuration.SCREENLAYOUT_SIZE_SMALL:
1624 case Configuration.SCREENLAYOUT_SIZE_NORMAL:
1625 parts.add("normal");
1627 case Configuration.SCREENLAYOUT_SIZE_LARGE:
1630 case Configuration.SCREENLAYOUT_SIZE_XLARGE:
1631 parts.add("xlarge");
1637 switch (config.screenLayout & Configuration.SCREENLAYOUT_LONG_MASK) {
1638 case Configuration.SCREENLAYOUT_LONG_YES:
1641 case Configuration.SCREENLAYOUT_LONG_NO:
1642 parts.add("notlong");
1648 switch (config.screenLayout & Configuration.SCREENLAYOUT_ROUND_MASK) {
1649 case Configuration.SCREENLAYOUT_ROUND_YES:
1652 case Configuration.SCREENLAYOUT_ROUND_NO:
1653 parts.add("notround");
1659 switch (config.orientation) {
1660 case Configuration.ORIENTATION_LANDSCAPE:
1663 case Configuration.ORIENTATION_PORTRAIT:
1670 switch (config.uiMode & Configuration.UI_MODE_TYPE_MASK) {
1671 case Configuration.UI_MODE_TYPE_APPLIANCE:
1672 parts.add("appliance");
1674 case Configuration.UI_MODE_TYPE_DESK:
1677 case Configuration.UI_MODE_TYPE_TELEVISION:
1678 parts.add("television");
1680 case Configuration.UI_MODE_TYPE_CAR:
1683 case Configuration.UI_MODE_TYPE_WATCH:
1690 switch (config.uiMode & Configuration.UI_MODE_NIGHT_MASK) {
1691 case Configuration.UI_MODE_NIGHT_YES:
1694 case Configuration.UI_MODE_NIGHT_NO:
1695 parts.add("notnight");
1701 switch (config.densityDpi) {
1702 case DENSITY_DPI_UNDEFINED:
1720 parts.add("xxhdpi");
1723 parts.add("xxxhdpi");
1725 case DENSITY_DPI_ANY:
1726 parts.add("anydpi");
1728 case DENSITY_DPI_NONE:
1731 parts.add(config.densityDpi + "dpi");
1735 switch (config.touchscreen) {
1736 case Configuration.TOUCHSCREEN_NOTOUCH:
1737 parts.add("notouch");
1739 case Configuration.TOUCHSCREEN_FINGER:
1740 parts.add("finger");
1746 switch (config.keyboardHidden) {
1747 case Configuration.KEYBOARDHIDDEN_NO:
1748 parts.add("keysexposed");
1750 case Configuration.KEYBOARDHIDDEN_YES:
1751 parts.add("keyshidden");
1753 case Configuration.KEYBOARDHIDDEN_SOFT:
1754 parts.add("keyssoft");
1760 switch (config.keyboard) {
1761 case Configuration.KEYBOARD_NOKEYS:
1762 parts.add("nokeys");
1764 case Configuration.KEYBOARD_QWERTY:
1765 parts.add("qwerty");
1767 case Configuration.KEYBOARD_12KEY:
1774 switch (config.navigationHidden) {
1775 case Configuration.NAVIGATIONHIDDEN_NO:
1776 parts.add("navexposed");
1778 case Configuration.NAVIGATIONHIDDEN_YES:
1779 parts.add("navhidden");
1785 switch (config.navigation) {
1786 case Configuration.NAVIGATION_NONAV:
1789 case Configuration.NAVIGATION_DPAD:
1792 case Configuration.NAVIGATION_TRACKBALL:
1793 parts.add("trackball");
1795 case Configuration.NAVIGATION_WHEEL:
1802 parts.add("v" + Build.VERSION.RESOURCES_SDK_INT);
1803 return TextUtils.join("-", parts);
1807 * Generate a delta Configuration between <code>base</code> and <code>change</code>. The
1808 * resulting delta can be used with {@link #updateFrom(Configuration)}.
1810 * Caveat: If the any of the Configuration's members becomes undefined, then
1811 * {@link #updateFrom(Configuration)} will treat it as a no-op and not update that member.
1813 * This is fine for device configurations as no member is ever undefined.
1816 public static Configuration generateDelta(Configuration base, Configuration change) {
1817 final Configuration delta = new Configuration();
1818 if (base.fontScale != change.fontScale) {
1819 delta.fontScale = change.fontScale;
1822 if (base.mcc != change.mcc) {
1823 delta.mcc = change.mcc;
1826 if (base.mnc != change.mnc) {
1827 delta.mnc = change.mnc;
1830 base.fixUpLocaleList();
1831 change.fixUpLocaleList();
1832 if (!base.mLocaleList.equals(change.mLocaleList)) {
1833 delta.mLocaleList = change.mLocaleList;
1834 delta.locale = change.locale;
1837 if (base.touchscreen != change.touchscreen) {
1838 delta.touchscreen = change.touchscreen;
1841 if (base.keyboard != change.keyboard) {
1842 delta.keyboard = change.keyboard;
1845 if (base.keyboardHidden != change.keyboardHidden) {
1846 delta.keyboardHidden = change.keyboardHidden;
1849 if (base.navigation != change.navigation) {
1850 delta.navigation = change.navigation;
1853 if (base.navigationHidden != change.navigationHidden) {
1854 delta.navigationHidden = change.navigationHidden;
1857 if (base.orientation != change.orientation) {
1858 delta.orientation = change.orientation;
1861 if ((base.screenLayout & SCREENLAYOUT_SIZE_MASK) !=
1862 (change.screenLayout & SCREENLAYOUT_SIZE_MASK)) {
1863 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_SIZE_MASK;
1866 if ((base.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK) !=
1867 (change.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) {
1868 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
1871 if ((base.screenLayout & SCREENLAYOUT_LONG_MASK) !=
1872 (change.screenLayout & SCREENLAYOUT_LONG_MASK)) {
1873 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_LONG_MASK;
1876 if ((base.screenLayout & SCREENLAYOUT_ROUND_MASK) !=
1877 (change.screenLayout & SCREENLAYOUT_ROUND_MASK)) {
1878 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_ROUND_MASK;
1881 if ((base.uiMode & UI_MODE_TYPE_MASK) != (change.uiMode & UI_MODE_TYPE_MASK)) {
1882 delta.uiMode |= change.uiMode & UI_MODE_TYPE_MASK;
1885 if ((base.uiMode & UI_MODE_NIGHT_MASK) != (change.uiMode & UI_MODE_NIGHT_MASK)) {
1886 delta.uiMode |= change.uiMode & UI_MODE_NIGHT_MASK;
1889 if (base.screenWidthDp != change.screenWidthDp) {
1890 delta.screenWidthDp = change.screenWidthDp;
1893 if (base.screenHeightDp != change.screenHeightDp) {
1894 delta.screenHeightDp = change.screenHeightDp;
1897 if (base.smallestScreenWidthDp != change.smallestScreenWidthDp) {
1898 delta.smallestScreenWidthDp = change.smallestScreenWidthDp;
1901 if (base.densityDpi != change.densityDpi) {
1902 delta.densityDpi = change.densityDpi;
1907 private static final String XML_ATTR_FONT_SCALE = "fs";
1908 private static final String XML_ATTR_MCC = "mcc";
1909 private static final String XML_ATTR_MNC = "mnc";
1910 private static final String XML_ATTR_LOCALES = "locales";
1911 private static final String XML_ATTR_TOUCHSCREEN = "touch";
1912 private static final String XML_ATTR_KEYBOARD = "key";
1913 private static final String XML_ATTR_KEYBOARD_HIDDEN = "keyHid";
1914 private static final String XML_ATTR_HARD_KEYBOARD_HIDDEN = "hardKeyHid";
1915 private static final String XML_ATTR_NAVIGATION = "nav";
1916 private static final String XML_ATTR_NAVIGATION_HIDDEN = "navHid";
1917 private static final String XML_ATTR_ORIENTATION = "ori";
1918 private static final String XML_ATTR_SCREEN_LAYOUT = "scrLay";
1919 private static final String XML_ATTR_UI_MODE = "ui";
1920 private static final String XML_ATTR_SCREEN_WIDTH = "width";
1921 private static final String XML_ATTR_SCREEN_HEIGHT = "height";
1922 private static final String XML_ATTR_SMALLEST_WIDTH = "sw";
1923 private static final String XML_ATTR_DENSITY = "density";
1926 * Reads the attributes corresponding to Configuration member fields from the Xml parser.
1927 * The parser is expected to be on a tag which has Configuration attributes.
1929 * @param parser The Xml parser from which to read attributes.
1930 * @param configOut The Configuration to populate from the Xml attributes.
1933 public static void readXmlAttrs(XmlPullParser parser, Configuration configOut)
1934 throws XmlPullParserException, IOException {
1935 configOut.fontScale = Float.intBitsToFloat(
1936 XmlUtils.readIntAttribute(parser, XML_ATTR_FONT_SCALE, 0));
1937 configOut.mcc = XmlUtils.readIntAttribute(parser, XML_ATTR_MCC, 0);
1938 configOut.mnc = XmlUtils.readIntAttribute(parser, XML_ATTR_MNC, 0);
1940 final String localesStr = XmlUtils.readStringAttribute(parser, XML_ATTR_LOCALES);
1941 configOut.mLocaleList = LocaleList.forLanguageTags(localesStr);
1942 configOut.locale = configOut.mLocaleList.get(0);
1944 configOut.touchscreen = XmlUtils.readIntAttribute(parser, XML_ATTR_TOUCHSCREEN,
1945 TOUCHSCREEN_UNDEFINED);
1946 configOut.keyboard = XmlUtils.readIntAttribute(parser, XML_ATTR_KEYBOARD,
1947 KEYBOARD_UNDEFINED);
1948 configOut.keyboardHidden = XmlUtils.readIntAttribute(parser, XML_ATTR_KEYBOARD_HIDDEN,
1949 KEYBOARDHIDDEN_UNDEFINED);
1950 configOut.hardKeyboardHidden =
1951 XmlUtils.readIntAttribute(parser, XML_ATTR_HARD_KEYBOARD_HIDDEN,
1952 HARDKEYBOARDHIDDEN_UNDEFINED);
1953 configOut.navigation = XmlUtils.readIntAttribute(parser, XML_ATTR_NAVIGATION,
1954 NAVIGATION_UNDEFINED);
1955 configOut.navigationHidden = XmlUtils.readIntAttribute(parser, XML_ATTR_NAVIGATION_HIDDEN,
1956 NAVIGATIONHIDDEN_UNDEFINED);
1957 configOut.orientation = XmlUtils.readIntAttribute(parser, XML_ATTR_ORIENTATION,
1958 ORIENTATION_UNDEFINED);
1959 configOut.screenLayout = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_LAYOUT,
1960 SCREENLAYOUT_UNDEFINED);
1961 configOut.uiMode = XmlUtils.readIntAttribute(parser, XML_ATTR_UI_MODE, 0);
1962 configOut.screenWidthDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_WIDTH,
1963 SCREEN_WIDTH_DP_UNDEFINED);
1964 configOut.screenHeightDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_HEIGHT,
1965 SCREEN_HEIGHT_DP_UNDEFINED);
1966 configOut.smallestScreenWidthDp =
1967 XmlUtils.readIntAttribute(parser, XML_ATTR_SMALLEST_WIDTH,
1968 SMALLEST_SCREEN_WIDTH_DP_UNDEFINED);
1969 configOut.densityDpi = XmlUtils.readIntAttribute(parser, XML_ATTR_DENSITY,
1970 DENSITY_DPI_UNDEFINED);
1975 * Writes the Configuration's member fields as attributes into the XmlSerializer.
1976 * The serializer is expected to have already started a tag so that attributes can be
1977 * immediately written.
1979 * @param xml The serializer to which to write the attributes.
1980 * @param config The Configuration whose member fields to write.
1983 public static void writeXmlAttrs(XmlSerializer xml, Configuration config) throws IOException {
1984 XmlUtils.writeIntAttribute(xml, XML_ATTR_FONT_SCALE,
1985 Float.floatToIntBits(config.fontScale));
1986 if (config.mcc != 0) {
1987 XmlUtils.writeIntAttribute(xml, XML_ATTR_MCC, config.mcc);
1989 if (config.mnc != 0) {
1990 XmlUtils.writeIntAttribute(xml, XML_ATTR_MNC, config.mnc);
1992 config.fixUpLocaleList();
1993 if (!config.mLocaleList.isEmpty()) {
1994 XmlUtils.writeStringAttribute(xml, XML_ATTR_LOCALES, config.mLocaleList.toLanguageTags());
1996 if (config.touchscreen != TOUCHSCREEN_UNDEFINED) {
1997 XmlUtils.writeIntAttribute(xml, XML_ATTR_TOUCHSCREEN, config.touchscreen);
1999 if (config.keyboard != KEYBOARD_UNDEFINED) {
2000 XmlUtils.writeIntAttribute(xml, XML_ATTR_KEYBOARD, config.keyboard);
2002 if (config.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED) {
2003 XmlUtils.writeIntAttribute(xml, XML_ATTR_KEYBOARD_HIDDEN, config.keyboardHidden);
2005 if (config.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED) {
2006 XmlUtils.writeIntAttribute(xml, XML_ATTR_HARD_KEYBOARD_HIDDEN,
2007 config.hardKeyboardHidden);
2009 if (config.navigation != NAVIGATION_UNDEFINED) {
2010 XmlUtils.writeIntAttribute(xml, XML_ATTR_NAVIGATION, config.navigation);
2012 if (config.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED) {
2013 XmlUtils.writeIntAttribute(xml, XML_ATTR_NAVIGATION_HIDDEN, config.navigationHidden);
2015 if (config.orientation != ORIENTATION_UNDEFINED) {
2016 XmlUtils.writeIntAttribute(xml, XML_ATTR_ORIENTATION, config.orientation);
2018 if (config.screenLayout != SCREENLAYOUT_UNDEFINED) {
2019 XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_LAYOUT, config.screenLayout);
2021 if (config.uiMode != 0) {
2022 XmlUtils.writeIntAttribute(xml, XML_ATTR_UI_MODE, config.uiMode);
2024 if (config.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
2025 XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_WIDTH, config.screenWidthDp);
2027 if (config.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
2028 XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_HEIGHT, config.screenHeightDp);
2030 if (config.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
2031 XmlUtils.writeIntAttribute(xml, XML_ATTR_SMALLEST_WIDTH, config.smallestScreenWidthDp);
2033 if (config.densityDpi != DENSITY_DPI_UNDEFINED) {
2034 XmlUtils.writeIntAttribute(xml, XML_ATTR_DENSITY, config.densityDpi);