• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package android.content.res;
18 
19 import com.android.internal.util.XmlUtils;
20 
21 import org.xmlpull.v1.XmlPullParser;
22 import org.xmlpull.v1.XmlPullParserException;
23 import org.xmlpull.v1.XmlSerializer;
24 
25 import android.content.pm.ActivityInfo;
26 import android.os.Build;
27 import android.os.Parcel;
28 import android.os.Parcelable;
29 import android.text.TextUtils;
30 import android.view.View;
31 
32 import java.io.IOException;
33 import java.util.ArrayList;
34 import java.util.Locale;
35 
36 /**
37  * This class describes all device configuration information that can
38  * impact the resources the application retrieves.  This includes both
39  * user-specified configuration options (locale and scaling) as well
40  * as device configurations (such as input modes, screen size and screen orientation).
41  * <p>You can acquire this object from {@link Resources}, using {@link
42  * Resources#getConfiguration}. Thus, from an activity, you can get it by chaining the request
43  * with {@link android.app.Activity#getResources}:</p>
44  * <pre>Configuration config = getResources().getConfiguration();</pre>
45  */
46 public final class Configuration implements Parcelable, Comparable<Configuration> {
47     /** @hide */
48     public static final Configuration EMPTY = new Configuration();
49 
50     /**
51      * Current user preference for the scaling factor for fonts, relative
52      * to the base density scaling.
53      */
54     public float fontScale;
55 
56     /**
57      * IMSI MCC (Mobile Country Code), corresponding to
58      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#MccQualifier">mcc</a>
59      * resource qualifier.  0 if undefined.
60      */
61     public int mcc;
62 
63     /**
64      * IMSI MNC (Mobile Network Code), corresponding to
65      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#MccQualifier">mnc</a>
66      * resource qualifier.  0 if undefined. Note that the actual MNC may be 0; in order to check
67      * for this use the {@link #MNC_ZERO} symbol.
68      */
69     public int mnc;
70 
71     /**
72      * Constant used to to represent MNC (Mobile Network Code) zero.
73      * 0 cannot be used, since it is used to represent an undefined MNC.
74      */
75     public static final int MNC_ZERO = 0xffff;
76 
77     /**
78      * Current user preference for the locale, corresponding to
79      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#LocaleQualifier">locale</a>
80      * resource qualifier.
81      */
82     public Locale locale;
83 
84     /**
85      * Locale should persist on setting.  This is hidden because it is really
86      * questionable whether this is the right way to expose the functionality.
87      * @hide
88      */
89     public boolean userSetLocale;
90 
91     /** Constant for {@link #screenLayout}: bits that encode the size. */
92     public static final int SCREENLAYOUT_SIZE_MASK = 0x0f;
93     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
94      * value indicating that no size has been set. */
95     public static final int SCREENLAYOUT_SIZE_UNDEFINED = 0x00;
96     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
97      * value indicating the screen is at least approximately 320x426 dp units,
98      * corresponds to the
99      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">small</a>
100      * resource qualifier.
101      * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
102      * Multiple Screens</a> for more information. */
103     public static final int SCREENLAYOUT_SIZE_SMALL = 0x01;
104     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
105      * value indicating the screen is at least approximately 320x470 dp units,
106      * corresponds to the
107      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">normal</a>
108      * resource qualifier.
109      * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
110      * Multiple Screens</a> for more information. */
111     public static final int SCREENLAYOUT_SIZE_NORMAL = 0x02;
112     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
113      * value indicating the screen is at least approximately 480x640 dp units,
114      * corresponds to the
115      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">large</a>
116      * resource qualifier.
117      * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
118      * Multiple Screens</a> for more information. */
119     public static final int SCREENLAYOUT_SIZE_LARGE = 0x03;
120     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
121      * value indicating the screen is at least approximately 720x960 dp units,
122      * corresponds to the
123      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">xlarge</a>
124      * resource qualifier.
125      * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
126      * Multiple Screens</a> for more information.*/
127     public static final int SCREENLAYOUT_SIZE_XLARGE = 0x04;
128 
129     /** Constant for {@link #screenLayout}: bits that encode the aspect ratio. */
130     public static final int SCREENLAYOUT_LONG_MASK = 0x30;
131     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
132      * value indicating that no size has been set. */
133     public static final int SCREENLAYOUT_LONG_UNDEFINED = 0x00;
134     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
135      * value that corresponds to the
136      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenAspectQualifier">notlong</a>
137      * resource qualifier. */
138     public static final int SCREENLAYOUT_LONG_NO = 0x10;
139     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
140      * value that corresponds to the
141      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenAspectQualifier">long</a>
142      * resource qualifier. */
143     public static final int SCREENLAYOUT_LONG_YES = 0x20;
144 
145     /** Constant for {@link #screenLayout}: bits that encode the layout direction. */
146     public static final int SCREENLAYOUT_LAYOUTDIR_MASK = 0xC0;
147     /** Constant for {@link #screenLayout}: bits shift to get the layout direction. */
148     public static final int SCREENLAYOUT_LAYOUTDIR_SHIFT = 6;
149     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
150      * value indicating that no layout dir has been set. */
151     public static final int SCREENLAYOUT_LAYOUTDIR_UNDEFINED = 0x00;
152     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
153      * value indicating that a layout dir has been set to LTR. */
154     public static final int SCREENLAYOUT_LAYOUTDIR_LTR = 0x01 << SCREENLAYOUT_LAYOUTDIR_SHIFT;
155     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
156      * value indicating that a layout dir has been set to RTL. */
157     public static final int SCREENLAYOUT_LAYOUTDIR_RTL = 0x02 << SCREENLAYOUT_LAYOUTDIR_SHIFT;
158 
159     /** Constant for {@link #screenLayout}: a value indicating that screenLayout is undefined */
160     public static final int SCREENLAYOUT_UNDEFINED = SCREENLAYOUT_SIZE_UNDEFINED |
161             SCREENLAYOUT_LONG_UNDEFINED | SCREENLAYOUT_LAYOUTDIR_UNDEFINED;
162 
163     /**
164      * Special flag we generate to indicate that the screen layout requires
165      * us to use a compatibility mode for apps that are not modern layout
166      * aware.
167      * @hide
168      */
169     public static final int SCREENLAYOUT_COMPAT_NEEDED = 0x10000000;
170 
171     /**
172      * Bit mask of overall layout of the screen.  Currently there are two
173      * fields:
174      * <p>The {@link #SCREENLAYOUT_SIZE_MASK} bits define the overall size
175      * of the screen.  They may be one of
176      * {@link #SCREENLAYOUT_SIZE_SMALL}, {@link #SCREENLAYOUT_SIZE_NORMAL},
177      * {@link #SCREENLAYOUT_SIZE_LARGE}, or {@link #SCREENLAYOUT_SIZE_XLARGE}.
178      *
179      * <p>The {@link #SCREENLAYOUT_LONG_MASK} defines whether the screen
180      * is wider/taller than normal.  They may be one of
181      * {@link #SCREENLAYOUT_LONG_NO} or {@link #SCREENLAYOUT_LONG_YES}.
182      *
183      * <p>The {@link #SCREENLAYOUT_LAYOUTDIR_MASK} defines whether the screen layout
184      * is either LTR or RTL.  They may be one of
185      * {@link #SCREENLAYOUT_LAYOUTDIR_LTR} or {@link #SCREENLAYOUT_LAYOUTDIR_RTL}.
186      *
187      * <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
188      * Multiple Screens</a> for more information.
189      */
190     public int screenLayout;
191 
192     /** @hide */
resetScreenLayout(int curLayout)193     static public int resetScreenLayout(int curLayout) {
194         return (curLayout&~(SCREENLAYOUT_LONG_MASK | SCREENLAYOUT_SIZE_MASK
195                         | SCREENLAYOUT_COMPAT_NEEDED))
196                 | (SCREENLAYOUT_LONG_YES | SCREENLAYOUT_SIZE_XLARGE);
197     }
198 
199     /** @hide */
reduceScreenLayout(int curLayout, int longSizeDp, int shortSizeDp)200     static public int reduceScreenLayout(int curLayout, int longSizeDp, int shortSizeDp) {
201         int screenLayoutSize;
202         boolean screenLayoutLong;
203         boolean screenLayoutCompatNeeded;
204 
205         // These semi-magic numbers define our compatibility modes for
206         // applications with different screens.  These are guarantees to
207         // app developers about the space they can expect for a particular
208         // configuration.  DO NOT CHANGE!
209         if (longSizeDp < 470) {
210             // This is shorter than an HVGA normal density screen (which
211             // is 480 pixels on its long side).
212             screenLayoutSize = SCREENLAYOUT_SIZE_SMALL;
213             screenLayoutLong = false;
214             screenLayoutCompatNeeded = false;
215         } else {
216             // What size is this screen screen?
217             if (longSizeDp >= 960 && shortSizeDp >= 720) {
218                 // 1.5xVGA or larger screens at medium density are the point
219                 // at which we consider it to be an extra large screen.
220                 screenLayoutSize = SCREENLAYOUT_SIZE_XLARGE;
221             } else if (longSizeDp >= 640 && shortSizeDp >= 480) {
222                 // VGA or larger screens at medium density are the point
223                 // at which we consider it to be a large screen.
224                 screenLayoutSize = SCREENLAYOUT_SIZE_LARGE;
225             } else {
226                 screenLayoutSize = SCREENLAYOUT_SIZE_NORMAL;
227             }
228 
229             // If this screen is wider than normal HVGA, or taller
230             // than FWVGA, then for old apps we want to run in size
231             // compatibility mode.
232             if (shortSizeDp > 321 || longSizeDp > 570) {
233                 screenLayoutCompatNeeded = true;
234             } else {
235                 screenLayoutCompatNeeded = false;
236             }
237 
238             // Is this a long screen?
239             if (((longSizeDp*3)/5) >= (shortSizeDp-1)) {
240                 // Anything wider than WVGA (5:3) is considering to be long.
241                 screenLayoutLong = true;
242             } else {
243                 screenLayoutLong = false;
244             }
245         }
246 
247         // Now reduce the last screenLayout to not be better than what we
248         // have found.
249         if (!screenLayoutLong) {
250             curLayout = (curLayout&~SCREENLAYOUT_LONG_MASK) | SCREENLAYOUT_LONG_NO;
251         }
252         if (screenLayoutCompatNeeded) {
253             curLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
254         }
255         int curSize = curLayout&SCREENLAYOUT_SIZE_MASK;
256         if (screenLayoutSize < curSize) {
257             curLayout = (curLayout&~SCREENLAYOUT_SIZE_MASK) | screenLayoutSize;
258         }
259         return curLayout;
260     }
261 
262     /**
263      * Check if the Configuration's current {@link #screenLayout} is at
264      * least the given size.
265      *
266      * @param size The desired size, either {@link #SCREENLAYOUT_SIZE_SMALL},
267      * {@link #SCREENLAYOUT_SIZE_NORMAL}, {@link #SCREENLAYOUT_SIZE_LARGE}, or
268      * {@link #SCREENLAYOUT_SIZE_XLARGE}.
269      * @return Returns true if the current screen layout size is at least
270      * the given size.
271      */
isLayoutSizeAtLeast(int size)272     public boolean isLayoutSizeAtLeast(int size) {
273         int cur = screenLayout&SCREENLAYOUT_SIZE_MASK;
274         if (cur == SCREENLAYOUT_SIZE_UNDEFINED) return false;
275         return cur >= size;
276     }
277 
278     /** Constant for {@link #touchscreen}: a value indicating that no value has been set. */
279     public static final int TOUCHSCREEN_UNDEFINED = 0;
280     /** Constant for {@link #touchscreen}, value corresponding to the
281      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#TouchscreenQualifier">notouch</a>
282      * resource qualifier. */
283     public static final int TOUCHSCREEN_NOTOUCH = 1;
284     /** @deprecated Not currently supported or used. */
285     @Deprecated public static final int TOUCHSCREEN_STYLUS = 2;
286     /** Constant for {@link #touchscreen}, value corresponding to the
287      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#TouchscreenQualifier">finger</a>
288      * resource qualifier. */
289     public static final int TOUCHSCREEN_FINGER = 3;
290 
291     /**
292      * The kind of touch screen attached to the device.
293      * One of: {@link #TOUCHSCREEN_NOTOUCH}, {@link #TOUCHSCREEN_FINGER}.
294      */
295     public int touchscreen;
296 
297     /** Constant for {@link #keyboard}: a value indicating that no value has been set. */
298     public static final int KEYBOARD_UNDEFINED = 0;
299     /** Constant for {@link #keyboard}, value corresponding to the
300      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">nokeys</a>
301      * resource qualifier. */
302     public static final int KEYBOARD_NOKEYS = 1;
303     /** Constant for {@link #keyboard}, value corresponding to the
304      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">qwerty</a>
305      * resource qualifier. */
306     public static final int KEYBOARD_QWERTY = 2;
307     /** Constant for {@link #keyboard}, value corresponding to the
308      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">12key</a>
309      * resource qualifier. */
310     public static final int KEYBOARD_12KEY = 3;
311 
312     /**
313      * The kind of keyboard attached to the device.
314      * One of: {@link #KEYBOARD_NOKEYS}, {@link #KEYBOARD_QWERTY},
315      * {@link #KEYBOARD_12KEY}.
316      */
317     public int keyboard;
318 
319     /** Constant for {@link #keyboardHidden}: a value indicating that no value has been set. */
320     public static final int KEYBOARDHIDDEN_UNDEFINED = 0;
321     /** Constant for {@link #keyboardHidden}, value corresponding to the
322      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keysexposed</a>
323      * resource qualifier. */
324     public static final int KEYBOARDHIDDEN_NO = 1;
325     /** Constant for {@link #keyboardHidden}, value corresponding to the
326      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keyshidden</a>
327      * resource qualifier. */
328     public static final int KEYBOARDHIDDEN_YES = 2;
329     /** Constant matching actual resource implementation. {@hide} */
330     public static final int KEYBOARDHIDDEN_SOFT = 3;
331 
332     /**
333      * A flag indicating whether any keyboard is available.  Unlike
334      * {@link #hardKeyboardHidden}, this also takes into account a soft
335      * keyboard, so if the hard keyboard is hidden but there is soft
336      * keyboard available, it will be set to NO.  Value is one of:
337      * {@link #KEYBOARDHIDDEN_NO}, {@link #KEYBOARDHIDDEN_YES}.
338      */
339     public int keyboardHidden;
340 
341     /** Constant for {@link #hardKeyboardHidden}: a value indicating that no value has been set. */
342     public static final int HARDKEYBOARDHIDDEN_UNDEFINED = 0;
343     /** Constant for {@link #hardKeyboardHidden}, value corresponding to the
344      * physical keyboard being exposed. */
345     public static final int HARDKEYBOARDHIDDEN_NO = 1;
346     /** Constant for {@link #hardKeyboardHidden}, value corresponding to the
347      * physical keyboard being hidden. */
348     public static final int HARDKEYBOARDHIDDEN_YES = 2;
349 
350     /**
351      * A flag indicating whether the hard keyboard has been hidden.  This will
352      * be set on a device with a mechanism to hide the keyboard from the
353      * user, when that mechanism is closed.  One of:
354      * {@link #HARDKEYBOARDHIDDEN_NO}, {@link #HARDKEYBOARDHIDDEN_YES}.
355      */
356     public int hardKeyboardHidden;
357 
358     /** Constant for {@link #navigation}: a value indicating that no value has been set. */
359     public static final int NAVIGATION_UNDEFINED = 0;
360     /** Constant for {@link #navigation}, value corresponding to the
361      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">nonav</a>
362      * resource qualifier. */
363     public static final int NAVIGATION_NONAV = 1;
364     /** Constant for {@link #navigation}, value corresponding to the
365      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">dpad</a>
366      * resource qualifier. */
367     public static final int NAVIGATION_DPAD = 2;
368     /** Constant for {@link #navigation}, value corresponding to the
369      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">trackball</a>
370      * resource qualifier. */
371     public static final int NAVIGATION_TRACKBALL = 3;
372     /** Constant for {@link #navigation}, value corresponding to the
373      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">wheel</a>
374      * resource qualifier. */
375     public static final int NAVIGATION_WHEEL = 4;
376 
377     /**
378      * The kind of navigation method available on the device.
379      * One of: {@link #NAVIGATION_NONAV}, {@link #NAVIGATION_DPAD},
380      * {@link #NAVIGATION_TRACKBALL}, {@link #NAVIGATION_WHEEL}.
381      */
382     public int navigation;
383 
384     /** Constant for {@link #navigationHidden}: a value indicating that no value has been set. */
385     public static final int NAVIGATIONHIDDEN_UNDEFINED = 0;
386     /** Constant for {@link #navigationHidden}, value corresponding to the
387      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavAvailQualifier">navexposed</a>
388      * resource qualifier. */
389     public static final int NAVIGATIONHIDDEN_NO = 1;
390     /** Constant for {@link #navigationHidden}, value corresponding to the
391      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavAvailQualifier">navhidden</a>
392      * resource qualifier. */
393     public static final int NAVIGATIONHIDDEN_YES = 2;
394 
395     /**
396      * A flag indicating whether any 5-way or DPAD navigation available.
397      * This will be set on a device with a mechanism to hide the navigation
398      * controls from the user, when that mechanism is closed.  One of:
399      * {@link #NAVIGATIONHIDDEN_NO}, {@link #NAVIGATIONHIDDEN_YES}.
400      */
401     public int navigationHidden;
402 
403     /** Constant for {@link #orientation}: a value indicating that no value has been set. */
404     public static final int ORIENTATION_UNDEFINED = 0;
405     /** Constant for {@link #orientation}, value corresponding to the
406      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#OrientationQualifier">port</a>
407      * resource qualifier. */
408     public static final int ORIENTATION_PORTRAIT = 1;
409     /** Constant for {@link #orientation}, value corresponding to the
410      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#OrientationQualifier">land</a>
411      * resource qualifier. */
412     public static final int ORIENTATION_LANDSCAPE = 2;
413     /** @deprecated Not currently supported or used. */
414     @Deprecated public static final int ORIENTATION_SQUARE = 3;
415 
416     /**
417      * Overall orientation of the screen.  May be one of
418      * {@link #ORIENTATION_LANDSCAPE}, {@link #ORIENTATION_PORTRAIT}.
419      */
420     public int orientation;
421 
422     /** Constant for {@link #uiMode}: bits that encode the mode type. */
423     public static final int UI_MODE_TYPE_MASK = 0x0f;
424     /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
425      * value indicating that no mode type has been set. */
426     public static final int UI_MODE_TYPE_UNDEFINED = 0x00;
427     /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
428      * value that corresponds to
429      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">no
430      * UI mode</a> resource qualifier specified. */
431     public static final int UI_MODE_TYPE_NORMAL = 0x01;
432     /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
433      * value that corresponds to the
434      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">desk</a>
435      * resource qualifier. */
436     public static final int UI_MODE_TYPE_DESK = 0x02;
437     /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
438      * value that corresponds to the
439      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">car</a>
440      * resource qualifier. */
441     public static final int UI_MODE_TYPE_CAR = 0x03;
442     /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
443      * value that corresponds to the
444      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">television</a>
445      * resource qualifier. */
446     public static final int UI_MODE_TYPE_TELEVISION = 0x04;
447     /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
448      * value that corresponds to the
449      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">appliance</a>
450      * resource qualifier. */
451     public static final int UI_MODE_TYPE_APPLIANCE = 0x05;
452     /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
453      * value that corresponds to the
454      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">watch</a>
455      * resource qualifier. */
456     public static final int UI_MODE_TYPE_WATCH = 0x06;
457 
458     /** Constant for {@link #uiMode}: bits that encode the night mode. */
459     public static final int UI_MODE_NIGHT_MASK = 0x30;
460     /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
461      * value indicating that no mode type has been set. */
462     public static final int UI_MODE_NIGHT_UNDEFINED = 0x00;
463     /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
464      * value that corresponds to the
465      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NightQualifier">notnight</a>
466      * resource qualifier. */
467     public static final int UI_MODE_NIGHT_NO = 0x10;
468     /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
469      * value that corresponds to the
470      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NightQualifier">night</a>
471      * resource qualifier. */
472     public static final int UI_MODE_NIGHT_YES = 0x20;
473 
474     /**
475      * Bit mask of the ui mode.  Currently there are two fields:
476      * <p>The {@link #UI_MODE_TYPE_MASK} bits define the overall ui mode of the
477      * device. They may be one of {@link #UI_MODE_TYPE_UNDEFINED},
478      * {@link #UI_MODE_TYPE_NORMAL}, {@link #UI_MODE_TYPE_DESK},
479      * {@link #UI_MODE_TYPE_CAR}, {@link #UI_MODE_TYPE_TELEVISION},
480      * {@link #UI_MODE_TYPE_APPLIANCE}, or {@link #UI_MODE_TYPE_WATCH}.
481      *
482      * <p>The {@link #UI_MODE_NIGHT_MASK} defines whether the screen
483      * is in a special mode. They may be one of {@link #UI_MODE_NIGHT_UNDEFINED},
484      * {@link #UI_MODE_NIGHT_NO} or {@link #UI_MODE_NIGHT_YES}.
485      */
486     public int uiMode;
487 
488     /**
489      * Default value for {@link #screenWidthDp} indicating that no width
490      * has been specified.
491      */
492     public static final int SCREEN_WIDTH_DP_UNDEFINED = 0;
493 
494     /**
495      * The current width of the available screen space, in dp units,
496      * corresponding to
497      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenWidthQualifier">screen
498      * width</a> resource qualifier.  Set to
499      * {@link #SCREEN_WIDTH_DP_UNDEFINED} if no width is specified.
500      */
501     public int screenWidthDp;
502 
503     /**
504      * Default value for {@link #screenHeightDp} indicating that no width
505      * has been specified.
506      */
507     public static final int SCREEN_HEIGHT_DP_UNDEFINED = 0;
508 
509     /**
510      * The current height of the available screen space, in dp units,
511      * corresponding to
512      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenHeightQualifier">screen
513      * height</a> resource qualifier.  Set to
514      * {@link #SCREEN_HEIGHT_DP_UNDEFINED} if no height is specified.
515      */
516     public int screenHeightDp;
517 
518     /**
519      * Default value for {@link #smallestScreenWidthDp} indicating that no width
520      * has been specified.
521      */
522     public static final int SMALLEST_SCREEN_WIDTH_DP_UNDEFINED = 0;
523 
524     /**
525      * The smallest screen size an application will see in normal operation,
526      * corresponding to
527      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#SmallestScreenWidthQualifier">smallest
528      * screen width</a> resource qualifier.
529      * This is the smallest value of both screenWidthDp and screenHeightDp
530      * in both portrait and landscape.  Set to
531      * {@link #SMALLEST_SCREEN_WIDTH_DP_UNDEFINED} if no width is specified.
532      */
533     public int smallestScreenWidthDp;
534 
535     /**
536      * Default value for {@link #densityDpi} indicating that no width
537      * has been specified.
538      */
539     public static final int DENSITY_DPI_UNDEFINED = 0;
540 
541     /**
542      * Value for {@link #densityDpi} for resources that scale to any density (vector drawables).
543      * {@hide}
544      */
545     public static final int DENSITY_DPI_ANY = 0xfffe;
546 
547     /**
548      * Value for {@link #densityDpi} for resources that are not meant to be scaled.
549      * {@hide}
550      */
551     public static final int DENSITY_DPI_NONE = 0xffff;
552 
553     /**
554      * The target screen density being rendered to,
555      * corresponding to
556      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#DensityQualifier">density</a>
557      * resource qualifier.  Set to
558      * {@link #DENSITY_DPI_UNDEFINED} if no density is specified.
559      */
560     public int densityDpi;
561 
562     /** @hide Hack to get this information from WM to app running in compat mode. */
563     public int compatScreenWidthDp;
564     /** @hide Hack to get this information from WM to app running in compat mode. */
565     public int compatScreenHeightDp;
566     /** @hide Hack to get this information from WM to app running in compat mode. */
567     public int compatSmallestScreenWidthDp;
568 
569     /**
570      * @hide Internal book-keeping.
571      */
572     public int seq;
573 
574     /** @hide Native-specific bit mask for MCC config; DO NOT USE UNLESS YOU ARE SURE. */
575     public static final int NATIVE_CONFIG_MCC = 0x0001;
576     /** @hide Native-specific bit mask for MNC config; DO NOT USE UNLESS YOU ARE SURE. */
577     public static final int NATIVE_CONFIG_MNC = 0x0002;
578     /** @hide Native-specific bit mask for LOCALE config; DO NOT USE UNLESS YOU ARE SURE. */
579     public static final int NATIVE_CONFIG_LOCALE = 0x0004;
580     /** @hide Native-specific bit mask for TOUCHSCREEN config; DO NOT USE UNLESS YOU ARE SURE. */
581     public static final int NATIVE_CONFIG_TOUCHSCREEN = 0x0008;
582     /** @hide Native-specific bit mask for KEYBOARD config; DO NOT USE UNLESS YOU ARE SURE. */
583     public static final int NATIVE_CONFIG_KEYBOARD = 0x0010;
584     /** @hide Native-specific bit mask for KEYBOARD_HIDDEN config; DO NOT USE UNLESS YOU
585      * ARE SURE. */
586     public static final int NATIVE_CONFIG_KEYBOARD_HIDDEN = 0x0020;
587     /** @hide Native-specific bit mask for NAVIGATION config; DO NOT USE UNLESS YOU ARE SURE. */
588     public static final int NATIVE_CONFIG_NAVIGATION = 0x0040;
589     /** @hide Native-specific bit mask for ORIENTATION config; DO NOT USE UNLESS YOU ARE SURE. */
590     public static final int NATIVE_CONFIG_ORIENTATION = 0x0080;
591     /** @hide Native-specific bit mask for DENSITY config; DO NOT USE UNLESS YOU ARE SURE. */
592     public static final int NATIVE_CONFIG_DENSITY = 0x0100;
593     /** @hide Native-specific bit mask for SCREEN_SIZE config; DO NOT USE UNLESS YOU ARE SURE. */
594     public static final int NATIVE_CONFIG_SCREEN_SIZE = 0x0200;
595     /** @hide Native-specific bit mask for VERSION config; DO NOT USE UNLESS YOU ARE SURE. */
596     public static final int NATIVE_CONFIG_VERSION = 0x0400;
597     /** @hide Native-specific bit mask for SCREEN_LAYOUT config; DO NOT USE UNLESS YOU ARE SURE. */
598     public static final int NATIVE_CONFIG_SCREEN_LAYOUT = 0x0800;
599     /** @hide Native-specific bit mask for UI_MODE config; DO NOT USE UNLESS YOU ARE SURE. */
600     public static final int NATIVE_CONFIG_UI_MODE = 0x1000;
601     /** @hide Native-specific bit mask for SMALLEST_SCREEN_SIZE config; DO NOT USE UNLESS YOU
602      * ARE SURE. */
603     public static final int NATIVE_CONFIG_SMALLEST_SCREEN_SIZE = 0x2000;
604     /** @hide Native-specific bit mask for LAYOUTDIR config ; DO NOT USE UNLESS YOU ARE SURE.*/
605     public static final int NATIVE_CONFIG_LAYOUTDIR = 0x4000;
606 
607     /**
608      * Construct an invalid Configuration.  You must call {@link #setToDefaults}
609      * for this object to be valid.  {@more}
610      */
Configuration()611     public Configuration() {
612         setToDefaults();
613     }
614 
615     /**
616      * Makes a deep copy suitable for modification.
617      */
Configuration(Configuration o)618     public Configuration(Configuration o) {
619         setTo(o);
620     }
621 
setTo(Configuration o)622     public void setTo(Configuration o) {
623         fontScale = o.fontScale;
624         mcc = o.mcc;
625         mnc = o.mnc;
626         if (o.locale != null) {
627             locale = (Locale) o.locale.clone();
628         }
629         userSetLocale = o.userSetLocale;
630         touchscreen = o.touchscreen;
631         keyboard = o.keyboard;
632         keyboardHidden = o.keyboardHidden;
633         hardKeyboardHidden = o.hardKeyboardHidden;
634         navigation = o.navigation;
635         navigationHidden = o.navigationHidden;
636         orientation = o.orientation;
637         screenLayout = o.screenLayout;
638         uiMode = o.uiMode;
639         screenWidthDp = o.screenWidthDp;
640         screenHeightDp = o.screenHeightDp;
641         smallestScreenWidthDp = o.smallestScreenWidthDp;
642         densityDpi = o.densityDpi;
643         compatScreenWidthDp = o.compatScreenWidthDp;
644         compatScreenHeightDp = o.compatScreenHeightDp;
645         compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp;
646         seq = o.seq;
647     }
648 
toString()649     public String toString() {
650         StringBuilder sb = new StringBuilder(128);
651         sb.append("{");
652         sb.append(fontScale);
653         sb.append(" ");
654         if (mcc != 0) {
655             sb.append(mcc);
656             sb.append("mcc");
657         } else {
658             sb.append("?mcc");
659         }
660         if (mnc != 0) {
661             sb.append(mnc);
662             sb.append("mnc");
663         } else {
664             sb.append("?mnc");
665         }
666         if (locale != null) {
667             sb.append(" ");
668             sb.append(locale);
669         } else {
670             sb.append(" ?locale");
671         }
672         int layoutDir = (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK);
673         switch (layoutDir) {
674             case SCREENLAYOUT_LAYOUTDIR_UNDEFINED: sb.append(" ?layoutDir"); break;
675             case SCREENLAYOUT_LAYOUTDIR_LTR: sb.append(" ldltr"); break;
676             case SCREENLAYOUT_LAYOUTDIR_RTL: sb.append(" ldrtl"); break;
677             default: sb.append(" layoutDir=");
678                 sb.append(layoutDir >> SCREENLAYOUT_LAYOUTDIR_SHIFT); break;
679         }
680         if (smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
681             sb.append(" sw"); sb.append(smallestScreenWidthDp); sb.append("dp");
682         } else {
683             sb.append(" ?swdp");
684         }
685         if (screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
686             sb.append(" w"); sb.append(screenWidthDp); sb.append("dp");
687         } else {
688             sb.append(" ?wdp");
689         }
690         if (screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
691             sb.append(" h"); sb.append(screenHeightDp); sb.append("dp");
692         } else {
693             sb.append(" ?hdp");
694         }
695         if (densityDpi != DENSITY_DPI_UNDEFINED) {
696             sb.append(" "); sb.append(densityDpi); sb.append("dpi");
697         } else {
698             sb.append(" ?density");
699         }
700         switch ((screenLayout&SCREENLAYOUT_SIZE_MASK)) {
701             case SCREENLAYOUT_SIZE_UNDEFINED: sb.append(" ?lsize"); break;
702             case SCREENLAYOUT_SIZE_SMALL: sb.append(" smll"); break;
703             case SCREENLAYOUT_SIZE_NORMAL: sb.append(" nrml"); break;
704             case SCREENLAYOUT_SIZE_LARGE: sb.append(" lrg"); break;
705             case SCREENLAYOUT_SIZE_XLARGE: sb.append(" xlrg"); break;
706             default: sb.append(" layoutSize=");
707                     sb.append(screenLayout&SCREENLAYOUT_SIZE_MASK); break;
708         }
709         switch ((screenLayout&SCREENLAYOUT_LONG_MASK)) {
710             case SCREENLAYOUT_LONG_UNDEFINED: sb.append(" ?long"); break;
711             case SCREENLAYOUT_LONG_NO: /* not-long is not interesting to print */ break;
712             case SCREENLAYOUT_LONG_YES: sb.append(" long"); break;
713             default: sb.append(" layoutLong=");
714                     sb.append(screenLayout&SCREENLAYOUT_LONG_MASK); break;
715         }
716         switch (orientation) {
717             case ORIENTATION_UNDEFINED: sb.append(" ?orien"); break;
718             case ORIENTATION_LANDSCAPE: sb.append(" land"); break;
719             case ORIENTATION_PORTRAIT: sb.append(" port"); break;
720             default: sb.append(" orien="); sb.append(orientation); break;
721         }
722         switch ((uiMode&UI_MODE_TYPE_MASK)) {
723             case UI_MODE_TYPE_UNDEFINED: sb.append(" ?uimode"); break;
724             case UI_MODE_TYPE_NORMAL: /* normal is not interesting to print */ break;
725             case UI_MODE_TYPE_DESK: sb.append(" desk"); break;
726             case UI_MODE_TYPE_CAR: sb.append(" car"); break;
727             case UI_MODE_TYPE_TELEVISION: sb.append(" television"); break;
728             case UI_MODE_TYPE_APPLIANCE: sb.append(" appliance"); break;
729             case UI_MODE_TYPE_WATCH: sb.append(" watch"); break;
730             default: sb.append(" uimode="); sb.append(uiMode&UI_MODE_TYPE_MASK); break;
731         }
732         switch ((uiMode&UI_MODE_NIGHT_MASK)) {
733             case UI_MODE_NIGHT_UNDEFINED: sb.append(" ?night"); break;
734             case UI_MODE_NIGHT_NO: /* not-night is not interesting to print */ break;
735             case UI_MODE_NIGHT_YES: sb.append(" night"); break;
736             default: sb.append(" night="); sb.append(uiMode&UI_MODE_NIGHT_MASK); break;
737         }
738         switch (touchscreen) {
739             case TOUCHSCREEN_UNDEFINED: sb.append(" ?touch"); break;
740             case TOUCHSCREEN_NOTOUCH: sb.append(" -touch"); break;
741             case TOUCHSCREEN_STYLUS: sb.append(" stylus"); break;
742             case TOUCHSCREEN_FINGER: sb.append(" finger"); break;
743             default: sb.append(" touch="); sb.append(touchscreen); break;
744         }
745         switch (keyboard) {
746             case KEYBOARD_UNDEFINED: sb.append(" ?keyb"); break;
747             case KEYBOARD_NOKEYS: sb.append(" -keyb"); break;
748             case KEYBOARD_QWERTY: sb.append(" qwerty"); break;
749             case KEYBOARD_12KEY: sb.append(" 12key"); break;
750             default: sb.append(" keys="); sb.append(keyboard); break;
751         }
752         switch (keyboardHidden) {
753             case KEYBOARDHIDDEN_UNDEFINED: sb.append("/?"); break;
754             case KEYBOARDHIDDEN_NO: sb.append("/v"); break;
755             case KEYBOARDHIDDEN_YES: sb.append("/h"); break;
756             case KEYBOARDHIDDEN_SOFT: sb.append("/s"); break;
757             default: sb.append("/"); sb.append(keyboardHidden); break;
758         }
759         switch (hardKeyboardHidden) {
760             case HARDKEYBOARDHIDDEN_UNDEFINED: sb.append("/?"); break;
761             case HARDKEYBOARDHIDDEN_NO: sb.append("/v"); break;
762             case HARDKEYBOARDHIDDEN_YES: sb.append("/h"); break;
763             default: sb.append("/"); sb.append(hardKeyboardHidden); break;
764         }
765         switch (navigation) {
766             case NAVIGATION_UNDEFINED: sb.append(" ?nav"); break;
767             case NAVIGATION_NONAV: sb.append(" -nav"); break;
768             case NAVIGATION_DPAD: sb.append(" dpad"); break;
769             case NAVIGATION_TRACKBALL: sb.append(" tball"); break;
770             case NAVIGATION_WHEEL: sb.append(" wheel"); break;
771             default: sb.append(" nav="); sb.append(navigation); break;
772         }
773         switch (navigationHidden) {
774             case NAVIGATIONHIDDEN_UNDEFINED: sb.append("/?"); break;
775             case NAVIGATIONHIDDEN_NO: sb.append("/v"); break;
776             case NAVIGATIONHIDDEN_YES: sb.append("/h"); break;
777             default: sb.append("/"); sb.append(navigationHidden); break;
778         }
779         if (seq != 0) {
780             sb.append(" s.");
781             sb.append(seq);
782         }
783         sb.append('}');
784         return sb.toString();
785     }
786 
787     /**
788      * Set this object to the system defaults.
789      */
setToDefaults()790     public void setToDefaults() {
791         fontScale = 1;
792         mcc = mnc = 0;
793         locale = null;
794         userSetLocale = false;
795         touchscreen = TOUCHSCREEN_UNDEFINED;
796         keyboard = KEYBOARD_UNDEFINED;
797         keyboardHidden = KEYBOARDHIDDEN_UNDEFINED;
798         hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED;
799         navigation = NAVIGATION_UNDEFINED;
800         navigationHidden = NAVIGATIONHIDDEN_UNDEFINED;
801         orientation = ORIENTATION_UNDEFINED;
802         screenLayout = SCREENLAYOUT_UNDEFINED;
803         uiMode = UI_MODE_TYPE_UNDEFINED;
804         screenWidthDp = compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED;
805         screenHeightDp = compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED;
806         smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
807         densityDpi = DENSITY_DPI_UNDEFINED;
808         seq = 0;
809     }
810 
811     /** {@hide} */
makeDefault()812     @Deprecated public void makeDefault() {
813         setToDefaults();
814     }
815 
816     /**
817      * Copy the fields from delta into this Configuration object, keeping
818      * track of which ones have changed.  Any undefined fields in
819      * <var>delta</var> are ignored and not copied in to the current
820      * Configuration.
821      * @return Returns a bit mask of the changed fields, as per
822      * {@link #diff}.
823      */
updateFrom(Configuration delta)824     public int updateFrom(Configuration delta) {
825         int changed = 0;
826         if (delta.fontScale > 0 && fontScale != delta.fontScale) {
827             changed |= ActivityInfo.CONFIG_FONT_SCALE;
828             fontScale = delta.fontScale;
829         }
830         if (delta.mcc != 0 && mcc != delta.mcc) {
831             changed |= ActivityInfo.CONFIG_MCC;
832             mcc = delta.mcc;
833         }
834         if (delta.mnc != 0 && mnc != delta.mnc) {
835             changed |= ActivityInfo.CONFIG_MNC;
836             mnc = delta.mnc;
837         }
838         if (delta.locale != null
839                 && (locale == null || !locale.equals(delta.locale))) {
840             changed |= ActivityInfo.CONFIG_LOCALE;
841             locale = delta.locale != null
842                     ? (Locale) delta.locale.clone() : null;
843             // If locale has changed, then layout direction is also changed ...
844             changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
845             // ... and we need to update the layout direction (represented by the first
846             // 2 most significant bits in screenLayout).
847             setLayoutDirection(locale);
848         }
849         final int deltaScreenLayoutDir = delta.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
850         if (deltaScreenLayoutDir != SCREENLAYOUT_LAYOUTDIR_UNDEFINED &&
851                 deltaScreenLayoutDir != (screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) {
852             screenLayout = (screenLayout & ~SCREENLAYOUT_LAYOUTDIR_MASK) | deltaScreenLayoutDir;
853             changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
854         }
855         if (delta.userSetLocale && (!userSetLocale || ((changed & ActivityInfo.CONFIG_LOCALE) != 0)))
856         {
857             changed |= ActivityInfo.CONFIG_LOCALE;
858             userSetLocale = true;
859         }
860         if (delta.touchscreen != TOUCHSCREEN_UNDEFINED
861                 && touchscreen != delta.touchscreen) {
862             changed |= ActivityInfo.CONFIG_TOUCHSCREEN;
863             touchscreen = delta.touchscreen;
864         }
865         if (delta.keyboard != KEYBOARD_UNDEFINED
866                 && keyboard != delta.keyboard) {
867             changed |= ActivityInfo.CONFIG_KEYBOARD;
868             keyboard = delta.keyboard;
869         }
870         if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED
871                 && keyboardHidden != delta.keyboardHidden) {
872             changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
873             keyboardHidden = delta.keyboardHidden;
874         }
875         if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED
876                 && hardKeyboardHidden != delta.hardKeyboardHidden) {
877             changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
878             hardKeyboardHidden = delta.hardKeyboardHidden;
879         }
880         if (delta.navigation != NAVIGATION_UNDEFINED
881                 && navigation != delta.navigation) {
882             changed |= ActivityInfo.CONFIG_NAVIGATION;
883             navigation = delta.navigation;
884         }
885         if (delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED
886                 && navigationHidden != delta.navigationHidden) {
887             changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
888             navigationHidden = delta.navigationHidden;
889         }
890         if (delta.orientation != ORIENTATION_UNDEFINED
891                 && orientation != delta.orientation) {
892             changed |= ActivityInfo.CONFIG_ORIENTATION;
893             orientation = delta.orientation;
894         }
895         if (getScreenLayoutNoDirection(delta.screenLayout) !=
896                     (SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED)
897                 && (getScreenLayoutNoDirection(screenLayout) !=
898                     getScreenLayoutNoDirection(delta.screenLayout))) {
899             changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
900             // We need to preserve the previous layout dir bits if they were defined
901             if ((delta.screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK) == 0) {
902                 screenLayout = (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK)|delta.screenLayout;
903             } else {
904                 screenLayout = delta.screenLayout;
905             }
906         }
907         if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)
908                 && uiMode != delta.uiMode) {
909             changed |= ActivityInfo.CONFIG_UI_MODE;
910             if ((delta.uiMode&UI_MODE_TYPE_MASK) != UI_MODE_TYPE_UNDEFINED) {
911                 uiMode = (uiMode&~UI_MODE_TYPE_MASK)
912                         | (delta.uiMode&UI_MODE_TYPE_MASK);
913             }
914             if ((delta.uiMode&UI_MODE_NIGHT_MASK) != UI_MODE_NIGHT_UNDEFINED) {
915                 uiMode = (uiMode&~UI_MODE_NIGHT_MASK)
916                         | (delta.uiMode&UI_MODE_NIGHT_MASK);
917             }
918         }
919         if (delta.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED
920                 && screenWidthDp != delta.screenWidthDp) {
921             changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
922             screenWidthDp = delta.screenWidthDp;
923         }
924         if (delta.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED
925                 && screenHeightDp != delta.screenHeightDp) {
926             changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
927             screenHeightDp = delta.screenHeightDp;
928         }
929         if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
930                 && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
931             changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
932             smallestScreenWidthDp = delta.smallestScreenWidthDp;
933         }
934         if (delta.densityDpi != DENSITY_DPI_UNDEFINED &&
935                 densityDpi != delta.densityDpi) {
936             changed |= ActivityInfo.CONFIG_DENSITY;
937             densityDpi = delta.densityDpi;
938         }
939         if (delta.compatScreenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
940             compatScreenWidthDp = delta.compatScreenWidthDp;
941         }
942         if (delta.compatScreenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
943             compatScreenHeightDp = delta.compatScreenHeightDp;
944         }
945         if (delta.compatSmallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
946             compatSmallestScreenWidthDp = delta.compatSmallestScreenWidthDp;
947         }
948         if (delta.seq != 0) {
949             seq = delta.seq;
950         }
951 
952         return changed;
953     }
954 
955     /**
956      * Return a bit mask of the differences between this Configuration
957      * object and the given one.  Does not change the values of either.  Any
958      * undefined fields in <var>delta</var> are ignored.
959      * @return Returns a bit mask indicating which configuration
960      * values has changed, containing any combination of
961      * {@link android.content.pm.ActivityInfo#CONFIG_FONT_SCALE
962      * PackageManager.ActivityInfo.CONFIG_FONT_SCALE},
963      * {@link android.content.pm.ActivityInfo#CONFIG_MCC
964      * PackageManager.ActivityInfo.CONFIG_MCC},
965      * {@link android.content.pm.ActivityInfo#CONFIG_MNC
966      * PackageManager.ActivityInfo.CONFIG_MNC},
967      * {@link android.content.pm.ActivityInfo#CONFIG_LOCALE
968      * PackageManager.ActivityInfo.CONFIG_LOCALE},
969      * {@link android.content.pm.ActivityInfo#CONFIG_TOUCHSCREEN
970      * PackageManager.ActivityInfo.CONFIG_TOUCHSCREEN},
971      * {@link android.content.pm.ActivityInfo#CONFIG_KEYBOARD
972      * PackageManager.ActivityInfo.CONFIG_KEYBOARD},
973      * {@link android.content.pm.ActivityInfo#CONFIG_NAVIGATION
974      * PackageManager.ActivityInfo.CONFIG_NAVIGATION},
975      * {@link android.content.pm.ActivityInfo#CONFIG_ORIENTATION
976      * PackageManager.ActivityInfo.CONFIG_ORIENTATION},
977      * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_LAYOUT
978      * PackageManager.ActivityInfo.CONFIG_SCREEN_LAYOUT}, or
979      * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_SIZE
980      * PackageManager.ActivityInfo.CONFIG_SCREEN_SIZE}, or
981      * {@link android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE
982      * PackageManager.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE}.
983      * {@link android.content.pm.ActivityInfo#CONFIG_LAYOUT_DIRECTION
984      * PackageManager.ActivityInfo.CONFIG_LAYOUT_DIRECTION}.
985      */
diff(Configuration delta)986     public int diff(Configuration delta) {
987         int changed = 0;
988         if (delta.fontScale > 0 && fontScale != delta.fontScale) {
989             changed |= ActivityInfo.CONFIG_FONT_SCALE;
990         }
991         if (delta.mcc != 0 && mcc != delta.mcc) {
992             changed |= ActivityInfo.CONFIG_MCC;
993         }
994         if (delta.mnc != 0 && mnc != delta.mnc) {
995             changed |= ActivityInfo.CONFIG_MNC;
996         }
997         if (delta.locale != null
998                 && (locale == null || !locale.equals(delta.locale))) {
999             changed |= ActivityInfo.CONFIG_LOCALE;
1000             changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
1001         }
1002         final int deltaScreenLayoutDir = delta.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
1003         if (deltaScreenLayoutDir != SCREENLAYOUT_LAYOUTDIR_UNDEFINED &&
1004                 deltaScreenLayoutDir != (screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) {
1005             changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
1006         }
1007         if (delta.touchscreen != TOUCHSCREEN_UNDEFINED
1008                 && touchscreen != delta.touchscreen) {
1009             changed |= ActivityInfo.CONFIG_TOUCHSCREEN;
1010         }
1011         if (delta.keyboard != KEYBOARD_UNDEFINED
1012                 && keyboard != delta.keyboard) {
1013             changed |= ActivityInfo.CONFIG_KEYBOARD;
1014         }
1015         if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED
1016                 && keyboardHidden != delta.keyboardHidden) {
1017             changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1018         }
1019         if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED
1020                 && hardKeyboardHidden != delta.hardKeyboardHidden) {
1021             changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1022         }
1023         if (delta.navigation != NAVIGATION_UNDEFINED
1024                 && navigation != delta.navigation) {
1025             changed |= ActivityInfo.CONFIG_NAVIGATION;
1026         }
1027         if (delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED
1028                 && navigationHidden != delta.navigationHidden) {
1029             changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1030         }
1031         if (delta.orientation != ORIENTATION_UNDEFINED
1032                 && orientation != delta.orientation) {
1033             changed |= ActivityInfo.CONFIG_ORIENTATION;
1034         }
1035         if (getScreenLayoutNoDirection(delta.screenLayout) !=
1036                     (SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED)
1037                 && getScreenLayoutNoDirection(screenLayout) !=
1038                     getScreenLayoutNoDirection(delta.screenLayout)) {
1039             changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
1040         }
1041         if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)
1042                 && uiMode != delta.uiMode) {
1043             changed |= ActivityInfo.CONFIG_UI_MODE;
1044         }
1045         if (delta.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED
1046                 && screenWidthDp != delta.screenWidthDp) {
1047             changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1048         }
1049         if (delta.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED
1050                 && screenHeightDp != delta.screenHeightDp) {
1051             changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1052         }
1053         if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
1054                 && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
1055             changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
1056         }
1057         if (delta.densityDpi != DENSITY_DPI_UNDEFINED
1058                 && densityDpi != delta.densityDpi) {
1059             changed |= ActivityInfo.CONFIG_DENSITY;
1060         }
1061 
1062         return changed;
1063     }
1064 
1065     /**
1066      * Determine if a new resource needs to be loaded from the bit set of
1067      * configuration changes returned by {@link #updateFrom(Configuration)}.
1068      *
1069      * @param configChanges The mask of changes configurations as returned by
1070      * {@link #updateFrom(Configuration)}.
1071      * @param interestingChanges The configuration changes that the resource
1072      * can handled, as given in {@link android.util.TypedValue#changingConfigurations}.
1073      *
1074      * @return Return true if the resource needs to be loaded, else false.
1075      */
needNewResources(int configChanges, int interestingChanges)1076     public static boolean needNewResources(int configChanges, int interestingChanges) {
1077         return (configChanges & (interestingChanges|ActivityInfo.CONFIG_FONT_SCALE)) != 0;
1078     }
1079 
1080     /**
1081      * @hide Return true if the sequence of 'other' is better than this.  Assumes
1082      * that 'this' is your current sequence and 'other' is a new one you have
1083      * received some how and want to compare with what you have.
1084      */
isOtherSeqNewer(Configuration other)1085     public boolean isOtherSeqNewer(Configuration other) {
1086         if (other == null) {
1087             // Sanity check.
1088             return false;
1089         }
1090         if (other.seq == 0) {
1091             // If the other sequence is not specified, then we must assume
1092             // it is newer since we don't know any better.
1093             return true;
1094         }
1095         if (seq == 0) {
1096             // If this sequence is not specified, then we also consider the
1097             // other is better.  Yes we have a preference for other.  Sue us.
1098             return true;
1099         }
1100         int diff = other.seq - seq;
1101         if (diff > 0x10000) {
1102             // If there has been a sufficiently large jump, assume the
1103             // sequence has wrapped around.
1104             return false;
1105         }
1106         return diff > 0;
1107     }
1108 
1109     /**
1110      * Parcelable methods
1111      */
describeContents()1112     public int describeContents() {
1113         return 0;
1114     }
1115 
writeToParcel(Parcel dest, int flags)1116     public void writeToParcel(Parcel dest, int flags) {
1117         dest.writeFloat(fontScale);
1118         dest.writeInt(mcc);
1119         dest.writeInt(mnc);
1120         if (locale == null) {
1121             dest.writeInt(0);
1122         } else {
1123             dest.writeInt(1);
1124             dest.writeString(locale.getLanguage());
1125             dest.writeString(locale.getCountry());
1126             dest.writeString(locale.getVariant());
1127         }
1128         if(userSetLocale) {
1129             dest.writeInt(1);
1130         } else {
1131             dest.writeInt(0);
1132         }
1133         dest.writeInt(touchscreen);
1134         dest.writeInt(keyboard);
1135         dest.writeInt(keyboardHidden);
1136         dest.writeInt(hardKeyboardHidden);
1137         dest.writeInt(navigation);
1138         dest.writeInt(navigationHidden);
1139         dest.writeInt(orientation);
1140         dest.writeInt(screenLayout);
1141         dest.writeInt(uiMode);
1142         dest.writeInt(screenWidthDp);
1143         dest.writeInt(screenHeightDp);
1144         dest.writeInt(smallestScreenWidthDp);
1145         dest.writeInt(densityDpi);
1146         dest.writeInt(compatScreenWidthDp);
1147         dest.writeInt(compatScreenHeightDp);
1148         dest.writeInt(compatSmallestScreenWidthDp);
1149         dest.writeInt(seq);
1150     }
1151 
readFromParcel(Parcel source)1152     public void readFromParcel(Parcel source) {
1153         fontScale = source.readFloat();
1154         mcc = source.readInt();
1155         mnc = source.readInt();
1156         if (source.readInt() != 0) {
1157             locale = new Locale(source.readString(), source.readString(),
1158                     source.readString());
1159         }
1160         userSetLocale = (source.readInt()==1);
1161         touchscreen = source.readInt();
1162         keyboard = source.readInt();
1163         keyboardHidden = source.readInt();
1164         hardKeyboardHidden = source.readInt();
1165         navigation = source.readInt();
1166         navigationHidden = source.readInt();
1167         orientation = source.readInt();
1168         screenLayout = source.readInt();
1169         uiMode = source.readInt();
1170         screenWidthDp = source.readInt();
1171         screenHeightDp = source.readInt();
1172         smallestScreenWidthDp = source.readInt();
1173         densityDpi = source.readInt();
1174         compatScreenWidthDp = source.readInt();
1175         compatScreenHeightDp = source.readInt();
1176         compatSmallestScreenWidthDp = source.readInt();
1177         seq = source.readInt();
1178     }
1179 
1180     public static final Parcelable.Creator<Configuration> CREATOR
1181             = new Parcelable.Creator<Configuration>() {
1182         public Configuration createFromParcel(Parcel source) {
1183             return new Configuration(source);
1184         }
1185 
1186         public Configuration[] newArray(int size) {
1187             return new Configuration[size];
1188         }
1189     };
1190 
1191     /**
1192      * Construct this Configuration object, reading from the Parcel.
1193      */
Configuration(Parcel source)1194     private Configuration(Parcel source) {
1195         readFromParcel(source);
1196     }
1197 
compareTo(Configuration that)1198     public int compareTo(Configuration that) {
1199         int n;
1200         float a = this.fontScale;
1201         float b = that.fontScale;
1202         if (a < b) return -1;
1203         if (a > b) return 1;
1204         n = this.mcc - that.mcc;
1205         if (n != 0) return n;
1206         n = this.mnc - that.mnc;
1207         if (n != 0) return n;
1208         if (this.locale == null) {
1209             if (that.locale != null) return 1;
1210         } else if (that.locale == null) {
1211             return -1;
1212         } else {
1213             n = this.locale.getLanguage().compareTo(that.locale.getLanguage());
1214             if (n != 0) return n;
1215             n = this.locale.getCountry().compareTo(that.locale.getCountry());
1216             if (n != 0) return n;
1217             n = this.locale.getVariant().compareTo(that.locale.getVariant());
1218             if (n != 0) return n;
1219         }
1220         n = this.touchscreen - that.touchscreen;
1221         if (n != 0) return n;
1222         n = this.keyboard - that.keyboard;
1223         if (n != 0) return n;
1224         n = this.keyboardHidden - that.keyboardHidden;
1225         if (n != 0) return n;
1226         n = this.hardKeyboardHidden - that.hardKeyboardHidden;
1227         if (n != 0) return n;
1228         n = this.navigation - that.navigation;
1229         if (n != 0) return n;
1230         n = this.navigationHidden - that.navigationHidden;
1231         if (n != 0) return n;
1232         n = this.orientation - that.orientation;
1233         if (n != 0) return n;
1234         n = this.screenLayout - that.screenLayout;
1235         if (n != 0) return n;
1236         n = this.uiMode - that.uiMode;
1237         if (n != 0) return n;
1238         n = this.screenWidthDp - that.screenWidthDp;
1239         if (n != 0) return n;
1240         n = this.screenHeightDp - that.screenHeightDp;
1241         if (n != 0) return n;
1242         n = this.smallestScreenWidthDp - that.smallestScreenWidthDp;
1243         if (n != 0) return n;
1244         n = this.densityDpi - that.densityDpi;
1245         //if (n != 0) return n;
1246         return n;
1247     }
1248 
equals(Configuration that)1249     public boolean equals(Configuration that) {
1250         if (that == null) return false;
1251         if (that == this) return true;
1252         return this.compareTo(that) == 0;
1253     }
1254 
equals(Object that)1255     public boolean equals(Object that) {
1256         try {
1257             return equals((Configuration)that);
1258         } catch (ClassCastException e) {
1259         }
1260         return false;
1261     }
1262 
hashCode()1263     public int hashCode() {
1264         int result = 17;
1265         result = 31 * result + Float.floatToIntBits(fontScale);
1266         result = 31 * result + mcc;
1267         result = 31 * result + mnc;
1268         result = 31 * result + (locale != null ? locale.hashCode() : 0);
1269         result = 31 * result + touchscreen;
1270         result = 31 * result + keyboard;
1271         result = 31 * result + keyboardHidden;
1272         result = 31 * result + hardKeyboardHidden;
1273         result = 31 * result + navigation;
1274         result = 31 * result + navigationHidden;
1275         result = 31 * result + orientation;
1276         result = 31 * result + screenLayout;
1277         result = 31 * result + uiMode;
1278         result = 31 * result + screenWidthDp;
1279         result = 31 * result + screenHeightDp;
1280         result = 31 * result + smallestScreenWidthDp;
1281         result = 31 * result + densityDpi;
1282         return result;
1283     }
1284 
1285     /**
1286      * Set the locale. This is the preferred way for setting up the locale (instead of using the
1287      * direct accessor). This will also set the userLocale and layout direction according to
1288      * the locale.
1289      *
1290      * @param loc The locale. Can be null.
1291      */
setLocale(Locale loc)1292     public void setLocale(Locale loc) {
1293         locale = loc;
1294         userSetLocale = true;
1295         setLayoutDirection(locale);
1296     }
1297 
1298     /**
1299      * Return the layout direction. Will be either {@link View#LAYOUT_DIRECTION_LTR} or
1300      * {@link View#LAYOUT_DIRECTION_RTL}.
1301      *
1302      * @return Returns {@link View#LAYOUT_DIRECTION_RTL} if the configuration
1303      * is {@link #SCREENLAYOUT_LAYOUTDIR_RTL}, otherwise {@link View#LAYOUT_DIRECTION_LTR}.
1304      */
getLayoutDirection()1305     public int getLayoutDirection() {
1306         return (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK) == SCREENLAYOUT_LAYOUTDIR_RTL
1307                 ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
1308     }
1309 
1310     /**
1311      * Set the layout direction from the Locale.
1312      *
1313      * @param locale The Locale. If null will set the layout direction to
1314      * {@link View#LAYOUT_DIRECTION_LTR}. If not null will set it to the layout direction
1315      * corresponding to the Locale.
1316      *
1317      * @see {@link View#LAYOUT_DIRECTION_LTR} and {@link View#LAYOUT_DIRECTION_RTL}
1318      */
setLayoutDirection(Locale locale)1319     public void setLayoutDirection(Locale locale) {
1320         // There is a "1" difference between the configuration values for
1321         // layout direction and View constants for layout direction, just add "1".
1322         final int layoutDirection = 1 + TextUtils.getLayoutDirectionFromLocale(locale);
1323         screenLayout = (screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK)|
1324                 (layoutDirection << SCREENLAYOUT_LAYOUTDIR_SHIFT);
1325     }
1326 
getScreenLayoutNoDirection(int screenLayout)1327     private static int getScreenLayoutNoDirection(int screenLayout) {
1328         return screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK;
1329     }
1330 
1331     /**
1332      *
1333      * @hide
1334      */
localeToResourceQualifier(Locale locale)1335     public static String localeToResourceQualifier(Locale locale) {
1336         StringBuilder sb = new StringBuilder();
1337         boolean l = (locale.getLanguage().length() != 0);
1338         boolean c = (locale.getCountry().length() != 0);
1339         boolean s = (locale.getScript().length() != 0);
1340         boolean v = (locale.getVariant().length() != 0);
1341 
1342         if (l) {
1343             sb.append(locale.getLanguage());
1344             if (c) {
1345                 sb.append("-r").append(locale.getCountry());
1346                 if (s) {
1347                     sb.append("-s").append(locale.getScript());
1348                     if (v) {
1349                         sb.append("-v").append(locale.getVariant());
1350                     }
1351                 }
1352             }
1353         }
1354         return sb.toString();
1355     }
1356 
1357 
1358     /**
1359      * Returns a string representation of the configuration that can be parsed
1360      * by build tools (like AAPT).
1361      *
1362      * @hide
1363      */
resourceQualifierString(Configuration config)1364     public static String resourceQualifierString(Configuration config) {
1365         ArrayList<String> parts = new ArrayList<String>();
1366 
1367         if (config.mcc != 0) {
1368             parts.add(config.mcc + "mcc");
1369             if (config.mnc != 0) {
1370                 parts.add(config.mnc + "mnc");
1371             }
1372         }
1373 
1374         if (!config.locale.getLanguage().isEmpty()) {
1375             parts.add(localeToResourceQualifier(config.locale));
1376         }
1377 
1378         switch (config.screenLayout & Configuration.SCREENLAYOUT_LAYOUTDIR_MASK) {
1379             case Configuration.SCREENLAYOUT_LAYOUTDIR_LTR:
1380                 parts.add("ldltr");
1381                 break;
1382             case Configuration.SCREENLAYOUT_LAYOUTDIR_RTL:
1383                 parts.add("ldrtl");
1384                 break;
1385             default:
1386                 break;
1387         }
1388 
1389         if (config.smallestScreenWidthDp != 0) {
1390             parts.add("sw" + config.smallestScreenWidthDp + "dp");
1391         }
1392 
1393         if (config.screenWidthDp != 0) {
1394             parts.add("w" + config.screenWidthDp + "dp");
1395         }
1396 
1397         if (config.screenHeightDp != 0) {
1398             parts.add("h" + config.screenHeightDp + "dp");
1399         }
1400 
1401         switch (config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) {
1402             case Configuration.SCREENLAYOUT_SIZE_SMALL:
1403                 parts.add("small");
1404                 break;
1405             case Configuration.SCREENLAYOUT_SIZE_NORMAL:
1406                 parts.add("normal");
1407                 break;
1408             case Configuration.SCREENLAYOUT_SIZE_LARGE:
1409                 parts.add("large");
1410                 break;
1411             case Configuration.SCREENLAYOUT_SIZE_XLARGE:
1412                 parts.add("xlarge");
1413                 break;
1414             default:
1415                 break;
1416         }
1417 
1418         switch (config.screenLayout & Configuration.SCREENLAYOUT_LONG_MASK) {
1419             case Configuration.SCREENLAYOUT_LONG_YES:
1420                 parts.add("long");
1421                 break;
1422             case Configuration.SCREENLAYOUT_LONG_NO:
1423                 parts.add("notlong");
1424                 break;
1425             default:
1426                 break;
1427         }
1428 
1429         switch (config.orientation) {
1430             case Configuration.ORIENTATION_LANDSCAPE:
1431                 parts.add("land");
1432                 break;
1433             case Configuration.ORIENTATION_PORTRAIT:
1434                 parts.add("port");
1435                 break;
1436             default:
1437                 break;
1438         }
1439 
1440         switch (config.uiMode & Configuration.UI_MODE_TYPE_MASK) {
1441             case Configuration.UI_MODE_TYPE_APPLIANCE:
1442                 parts.add("appliance");
1443                 break;
1444             case Configuration.UI_MODE_TYPE_DESK:
1445                 parts.add("desk");
1446                 break;
1447             case Configuration.UI_MODE_TYPE_TELEVISION:
1448                 parts.add("television");
1449                 break;
1450             case Configuration.UI_MODE_TYPE_CAR:
1451                 parts.add("car");
1452                 break;
1453             case Configuration.UI_MODE_TYPE_WATCH:
1454                 parts.add("watch");
1455                 break;
1456             default:
1457                 break;
1458         }
1459 
1460         switch (config.uiMode & Configuration.UI_MODE_NIGHT_MASK) {
1461             case Configuration.UI_MODE_NIGHT_YES:
1462                 parts.add("night");
1463                 break;
1464             case Configuration.UI_MODE_NIGHT_NO:
1465                 parts.add("notnight");
1466                 break;
1467             default:
1468                 break;
1469         }
1470 
1471         switch (config.densityDpi) {
1472             case DENSITY_DPI_UNDEFINED:
1473                 break;
1474             case 120:
1475                 parts.add("ldpi");
1476                 break;
1477             case 160:
1478                 parts.add("mdpi");
1479                 break;
1480             case 213:
1481                 parts.add("tvdpi");
1482                 break;
1483             case 240:
1484                 parts.add("hdpi");
1485                 break;
1486             case 320:
1487                 parts.add("xhdpi");
1488                 break;
1489             case 480:
1490                 parts.add("xxhdpi");
1491                 break;
1492             case 640:
1493                 parts.add("xxxhdpi");
1494                 break;
1495             case DENSITY_DPI_ANY:
1496                 parts.add("anydpi");
1497                 break;
1498             case DENSITY_DPI_NONE:
1499                 parts.add("nodpi");
1500             default:
1501                 parts.add(config.densityDpi + "dpi");
1502                 break;
1503         }
1504 
1505         switch (config.touchscreen) {
1506             case Configuration.TOUCHSCREEN_NOTOUCH:
1507                 parts.add("notouch");
1508                 break;
1509             case Configuration.TOUCHSCREEN_FINGER:
1510                 parts.add("finger");
1511                 break;
1512             default:
1513                 break;
1514         }
1515 
1516         switch (config.keyboardHidden) {
1517             case Configuration.KEYBOARDHIDDEN_NO:
1518                 parts.add("keysexposed");
1519                 break;
1520             case Configuration.KEYBOARDHIDDEN_YES:
1521                 parts.add("keyshidden");
1522                 break;
1523             case Configuration.KEYBOARDHIDDEN_SOFT:
1524                 parts.add("keyssoft");
1525                 break;
1526             default:
1527                 break;
1528         }
1529 
1530         switch (config.keyboard) {
1531             case Configuration.KEYBOARD_NOKEYS:
1532                 parts.add("nokeys");
1533                 break;
1534             case Configuration.KEYBOARD_QWERTY:
1535                 parts.add("qwerty");
1536                 break;
1537             case Configuration.KEYBOARD_12KEY:
1538                 parts.add("12key");
1539                 break;
1540             default:
1541                 break;
1542         }
1543 
1544         switch (config.navigationHidden) {
1545             case Configuration.NAVIGATIONHIDDEN_NO:
1546                 parts.add("navexposed");
1547                 break;
1548             case Configuration.NAVIGATIONHIDDEN_YES:
1549                 parts.add("navhidden");
1550                 break;
1551             default:
1552                 break;
1553         }
1554 
1555         switch (config.navigation) {
1556             case Configuration.NAVIGATION_NONAV:
1557                 parts.add("nonav");
1558                 break;
1559             case Configuration.NAVIGATION_DPAD:
1560                 parts.add("dpad");
1561                 break;
1562             case Configuration.NAVIGATION_TRACKBALL:
1563                 parts.add("trackball");
1564                 break;
1565             case Configuration.NAVIGATION_WHEEL:
1566                 parts.add("wheel");
1567                 break;
1568             default:
1569                 break;
1570         }
1571 
1572         parts.add("v" + Build.VERSION.RESOURCES_SDK_INT);
1573         return TextUtils.join("-", parts);
1574     }
1575 
1576     /**
1577      * Generate a delta Configuration between <code>base</code> and <code>change</code>. The
1578      * resulting delta can be used with {@link #updateFrom(Configuration)}.
1579      * <p />
1580      * Caveat: If the any of the Configuration's members becomes undefined, then
1581      * {@link #updateFrom(Configuration)} will treat it as a no-op and not update that member.
1582      *
1583      * This is fine for device configurations as no member is ever undefined.
1584      * {@hide}
1585      */
generateDelta(Configuration base, Configuration change)1586     public static Configuration generateDelta(Configuration base, Configuration change) {
1587         final Configuration delta = new Configuration();
1588         if (base.fontScale != change.fontScale) {
1589             delta.fontScale = change.fontScale;
1590         }
1591 
1592         if (base.mcc != change.mcc) {
1593             delta.mcc = change.mcc;
1594         }
1595 
1596         if (base.mnc != change.mnc) {
1597             delta.mnc = change.mnc;
1598         }
1599 
1600         if ((base.locale == null && change.locale != null) ||
1601                 (base.locale != null && !base.locale.equals(change.locale)))  {
1602             delta.locale = change.locale;
1603         }
1604 
1605         if (base.touchscreen != change.touchscreen) {
1606             delta.touchscreen = change.touchscreen;
1607         }
1608 
1609         if (base.keyboard != change.keyboard) {
1610             delta.keyboard = change.keyboard;
1611         }
1612 
1613         if (base.keyboardHidden != change.keyboardHidden) {
1614             delta.keyboardHidden = change.keyboardHidden;
1615         }
1616 
1617         if (base.navigation != change.navigation) {
1618             delta.navigation = change.navigation;
1619         }
1620 
1621         if (base.navigationHidden != change.navigationHidden) {
1622             delta.navigationHidden = change.navigationHidden;
1623         }
1624 
1625         if (base.orientation != change.orientation) {
1626             delta.orientation = change.orientation;
1627         }
1628 
1629         if ((base.screenLayout & SCREENLAYOUT_SIZE_MASK) !=
1630                 (change.screenLayout & SCREENLAYOUT_SIZE_MASK)) {
1631             delta.screenLayout |= change.screenLayout & SCREENLAYOUT_SIZE_MASK;
1632         }
1633 
1634         if ((base.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK) !=
1635                 (change.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) {
1636             delta.screenLayout |= change.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
1637         }
1638 
1639         if ((base.screenLayout & SCREENLAYOUT_LONG_MASK) !=
1640                 (change.screenLayout & SCREENLAYOUT_LONG_MASK)) {
1641             delta.screenLayout |= change.screenLayout & SCREENLAYOUT_LONG_MASK;
1642         }
1643 
1644         if ((base.uiMode & UI_MODE_TYPE_MASK) != (change.uiMode & UI_MODE_TYPE_MASK)) {
1645             delta.uiMode |= change.uiMode & UI_MODE_TYPE_MASK;
1646         }
1647 
1648         if ((base.uiMode & UI_MODE_NIGHT_MASK) != (change.uiMode & UI_MODE_NIGHT_MASK)) {
1649             delta.uiMode |= change.uiMode & UI_MODE_NIGHT_MASK;
1650         }
1651 
1652         if (base.screenWidthDp != change.screenWidthDp) {
1653             delta.screenWidthDp = change.screenWidthDp;
1654         }
1655 
1656         if (base.screenHeightDp != change.screenHeightDp) {
1657             delta.screenHeightDp = change.screenHeightDp;
1658         }
1659 
1660         if (base.smallestScreenWidthDp != change.smallestScreenWidthDp) {
1661             delta.smallestScreenWidthDp = change.smallestScreenWidthDp;
1662         }
1663 
1664         if (base.densityDpi != change.densityDpi) {
1665             delta.densityDpi = change.densityDpi;
1666         }
1667         return delta;
1668     }
1669 
1670     private static final String XML_ATTR_FONT_SCALE = "fs";
1671     private static final String XML_ATTR_MCC = "mcc";
1672     private static final String XML_ATTR_MNC = "mnc";
1673     private static final String XML_ATTR_LOCALE = "locale";
1674     private static final String XML_ATTR_TOUCHSCREEN = "touch";
1675     private static final String XML_ATTR_KEYBOARD = "key";
1676     private static final String XML_ATTR_KEYBOARD_HIDDEN = "keyHid";
1677     private static final String XML_ATTR_HARD_KEYBOARD_HIDDEN = "hardKeyHid";
1678     private static final String XML_ATTR_NAVIGATION = "nav";
1679     private static final String XML_ATTR_NAVIGATION_HIDDEN = "navHid";
1680     private static final String XML_ATTR_ORIENTATION = "ori";
1681     private static final String XML_ATTR_SCREEN_LAYOUT = "scrLay";
1682     private static final String XML_ATTR_UI_MODE = "ui";
1683     private static final String XML_ATTR_SCREEN_WIDTH = "width";
1684     private static final String XML_ATTR_SCREEN_HEIGHT = "height";
1685     private static final String XML_ATTR_SMALLEST_WIDTH = "sw";
1686     private static final String XML_ATTR_DENSITY = "density";
1687 
1688     /**
1689      * Reads the attributes corresponding to Configuration member fields from the Xml parser.
1690      * The parser is expected to be on a tag which has Configuration attributes.
1691      *
1692      * @param parser The Xml parser from which to read attributes.
1693      * @param configOut The Configuration to populate from the Xml attributes.
1694      * {@hide}
1695      */
readXmlAttrs(XmlPullParser parser, Configuration configOut)1696     public static void readXmlAttrs(XmlPullParser parser, Configuration configOut)
1697             throws XmlPullParserException, IOException {
1698         configOut.fontScale = Float.intBitsToFloat(
1699                 XmlUtils.readIntAttribute(parser, XML_ATTR_FONT_SCALE, 0));
1700         configOut.mcc = XmlUtils.readIntAttribute(parser, XML_ATTR_MCC, 0);
1701         configOut.mnc = XmlUtils.readIntAttribute(parser, XML_ATTR_MNC, 0);
1702 
1703         final String localeStr = XmlUtils.readStringAttribute(parser, XML_ATTR_LOCALE);
1704         if (localeStr != null) {
1705             configOut.locale = Locale.forLanguageTag(localeStr);
1706         }
1707 
1708         configOut.touchscreen = XmlUtils.readIntAttribute(parser, XML_ATTR_TOUCHSCREEN,
1709                 TOUCHSCREEN_UNDEFINED);
1710         configOut.keyboard = XmlUtils.readIntAttribute(parser, XML_ATTR_KEYBOARD,
1711                 KEYBOARD_UNDEFINED);
1712         configOut.keyboardHidden = XmlUtils.readIntAttribute(parser, XML_ATTR_KEYBOARD_HIDDEN,
1713                 KEYBOARDHIDDEN_UNDEFINED);
1714         configOut.hardKeyboardHidden =
1715                 XmlUtils.readIntAttribute(parser, XML_ATTR_HARD_KEYBOARD_HIDDEN,
1716                         HARDKEYBOARDHIDDEN_UNDEFINED);
1717         configOut.navigation = XmlUtils.readIntAttribute(parser, XML_ATTR_NAVIGATION,
1718                 NAVIGATION_UNDEFINED);
1719         configOut.navigationHidden = XmlUtils.readIntAttribute(parser, XML_ATTR_NAVIGATION_HIDDEN,
1720                 NAVIGATIONHIDDEN_UNDEFINED);
1721         configOut.orientation = XmlUtils.readIntAttribute(parser, XML_ATTR_ORIENTATION,
1722                 ORIENTATION_UNDEFINED);
1723         configOut.screenLayout = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_LAYOUT,
1724                 SCREENLAYOUT_UNDEFINED);
1725         configOut.uiMode = XmlUtils.readIntAttribute(parser, XML_ATTR_UI_MODE, 0);
1726         configOut.screenWidthDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_WIDTH,
1727                 SCREEN_WIDTH_DP_UNDEFINED);
1728         configOut.screenHeightDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_HEIGHT,
1729                 SCREEN_HEIGHT_DP_UNDEFINED);
1730         configOut.smallestScreenWidthDp =
1731                 XmlUtils.readIntAttribute(parser, XML_ATTR_SMALLEST_WIDTH,
1732                         SMALLEST_SCREEN_WIDTH_DP_UNDEFINED);
1733         configOut.densityDpi = XmlUtils.readIntAttribute(parser, XML_ATTR_DENSITY,
1734                 DENSITY_DPI_UNDEFINED);
1735     }
1736 
1737 
1738     /**
1739      * Writes the Configuration's member fields as attributes into the XmlSerializer.
1740      * The serializer is expected to have already started a tag so that attributes can be
1741      * immediately written.
1742      *
1743      * @param xml The serializer to which to write the attributes.
1744      * @param config The Configuration whose member fields to write.
1745      * {@hide}
1746      */
writeXmlAttrs(XmlSerializer xml, Configuration config)1747     public static void writeXmlAttrs(XmlSerializer xml, Configuration config) throws IOException {
1748         XmlUtils.writeIntAttribute(xml, XML_ATTR_FONT_SCALE,
1749                 Float.floatToIntBits(config.fontScale));
1750         if (config.mcc != 0) {
1751             XmlUtils.writeIntAttribute(xml, XML_ATTR_MCC, config.mcc);
1752         }
1753         if (config.mnc != 0) {
1754             XmlUtils.writeIntAttribute(xml, XML_ATTR_MNC, config.mnc);
1755         }
1756         if (config.locale != null) {
1757             XmlUtils.writeStringAttribute(xml, XML_ATTR_LOCALE, config.locale.toLanguageTag());
1758         }
1759         if (config.touchscreen != TOUCHSCREEN_UNDEFINED) {
1760             XmlUtils.writeIntAttribute(xml, XML_ATTR_TOUCHSCREEN, config.touchscreen);
1761         }
1762         if (config.keyboard != KEYBOARD_UNDEFINED) {
1763             XmlUtils.writeIntAttribute(xml, XML_ATTR_KEYBOARD, config.keyboard);
1764         }
1765         if (config.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED) {
1766             XmlUtils.writeIntAttribute(xml, XML_ATTR_KEYBOARD_HIDDEN, config.keyboardHidden);
1767         }
1768         if (config.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED) {
1769             XmlUtils.writeIntAttribute(xml, XML_ATTR_HARD_KEYBOARD_HIDDEN,
1770                     config.hardKeyboardHidden);
1771         }
1772         if (config.navigation != NAVIGATION_UNDEFINED) {
1773             XmlUtils.writeIntAttribute(xml, XML_ATTR_NAVIGATION, config.navigation);
1774         }
1775         if (config.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED) {
1776             XmlUtils.writeIntAttribute(xml, XML_ATTR_NAVIGATION_HIDDEN, config.navigationHidden);
1777         }
1778         if (config.orientation != ORIENTATION_UNDEFINED) {
1779             XmlUtils.writeIntAttribute(xml, XML_ATTR_ORIENTATION, config.orientation);
1780         }
1781         if (config.screenLayout != SCREENLAYOUT_UNDEFINED) {
1782             XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_LAYOUT, config.screenLayout);
1783         }
1784         if (config.uiMode != 0) {
1785             XmlUtils.writeIntAttribute(xml, XML_ATTR_UI_MODE, config.uiMode);
1786         }
1787         if (config.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
1788             XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_WIDTH, config.screenWidthDp);
1789         }
1790         if (config.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
1791             XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_HEIGHT, config.screenHeightDp);
1792         }
1793         if (config.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
1794             XmlUtils.writeIntAttribute(xml, XML_ATTR_SMALLEST_WIDTH, config.smallestScreenWidthDp);
1795         }
1796         if (config.densityDpi != DENSITY_DPI_UNDEFINED) {
1797             XmlUtils.writeIntAttribute(xml, XML_ATTR_DENSITY, config.densityDpi);
1798         }
1799     }
1800 }
1801