• 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 android.content.pm.ActivityInfo;
20 import android.os.Parcel;
21 import android.os.Parcelable;
22 import android.text.TextUtils;
23 import android.view.View;
24 
25 import java.util.Locale;
26 
27 /**
28  * This class describes all device configuration information that can
29  * impact the resources the application retrieves.  This includes both
30  * user-specified configuration options (locale and scaling) as well
31  * as device configurations (such as input modes, screen size and screen orientation).
32  * <p>You can acquire this object from {@link Resources}, using {@link
33  * Resources#getConfiguration}. Thus, from an activity, you can get it by chaining the request
34  * with {@link android.app.Activity#getResources}:</p>
35  * <pre>Configuration config = getResources().getConfiguration();</pre>
36  */
37 public final class Configuration implements Parcelable, Comparable<Configuration> {
38     /** @hide */
39     public static final Configuration EMPTY = new Configuration();
40 
41     /**
42      * Current user preference for the scaling factor for fonts, relative
43      * to the base density scaling.
44      */
45     public float fontScale;
46 
47     /**
48      * IMSI MCC (Mobile Country Code), corresponding to
49      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#MccQualifier">mcc</a>
50      * resource qualifier.  0 if undefined.
51      */
52     public int mcc;
53 
54     /**
55      * IMSI MNC (Mobile Network Code), corresponding to
56      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#MccQualifier">mnc</a>
57      * resource qualifier.  0 if undefined. Note that the actual MNC may be 0; in order to check
58      * for this use the {@link #MNC_ZERO} symbol.
59      */
60     public int mnc;
61 
62     /**
63      * Constant used to to represent MNC (Mobile Network Code) zero.
64      * 0 cannot be used, since it is used to represent an undefined MNC.
65      */
66     public static final int MNC_ZERO = 0xffff;
67 
68     /**
69      * Current user preference for the locale, corresponding to
70      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#LocaleQualifier">locale</a>
71      * resource qualifier.
72      */
73     public Locale locale;
74 
75     /**
76      * Locale should persist on setting.  This is hidden because it is really
77      * questionable whether this is the right way to expose the functionality.
78      * @hide
79      */
80     public boolean userSetLocale;
81 
82     /** Constant for {@link #screenLayout}: bits that encode the size. */
83     public static final int SCREENLAYOUT_SIZE_MASK = 0x0f;
84     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
85      * value indicating that no size has been set. */
86     public static final int SCREENLAYOUT_SIZE_UNDEFINED = 0x00;
87     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
88      * value indicating the screen is at least approximately 320x426 dp units,
89      * corresponds to the
90      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">small</a>
91      * resource qualifier.
92      * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
93      * Multiple Screens</a> for more information. */
94     public static final int SCREENLAYOUT_SIZE_SMALL = 0x01;
95     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
96      * value indicating the screen is at least approximately 320x470 dp units,
97      * corresponds to the
98      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">normal</a>
99      * resource qualifier.
100      * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
101      * Multiple Screens</a> for more information. */
102     public static final int SCREENLAYOUT_SIZE_NORMAL = 0x02;
103     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
104      * value indicating the screen is at least approximately 480x640 dp units,
105      * corresponds to the
106      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">large</a>
107      * resource qualifier.
108      * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
109      * Multiple Screens</a> for more information. */
110     public static final int SCREENLAYOUT_SIZE_LARGE = 0x03;
111     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
112      * value indicating the screen is at least approximately 720x960 dp units,
113      * corresponds to the
114      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">xlarge</a>
115      * resource qualifier.
116      * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
117      * Multiple Screens</a> for more information.*/
118     public static final int SCREENLAYOUT_SIZE_XLARGE = 0x04;
119 
120     /** Constant for {@link #screenLayout}: bits that encode the aspect ratio. */
121     public static final int SCREENLAYOUT_LONG_MASK = 0x30;
122     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
123      * value indicating that no size has been set. */
124     public static final int SCREENLAYOUT_LONG_UNDEFINED = 0x00;
125     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
126      * value that corresponds to the
127      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenAspectQualifier">notlong</a>
128      * resource qualifier. */
129     public static final int SCREENLAYOUT_LONG_NO = 0x10;
130     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
131      * value that corresponds to the
132      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenAspectQualifier">long</a>
133      * resource qualifier. */
134     public static final int SCREENLAYOUT_LONG_YES = 0x20;
135 
136     /** Constant for {@link #screenLayout}: bits that encode the layout direction. */
137     public static final int SCREENLAYOUT_LAYOUTDIR_MASK = 0xC0;
138     /** Constant for {@link #screenLayout}: bits shift to get the layout direction. */
139     public static final int SCREENLAYOUT_LAYOUTDIR_SHIFT = 6;
140     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
141      * value indicating that no layout dir has been set. */
142     public static final int SCREENLAYOUT_LAYOUTDIR_UNDEFINED = 0x00;
143     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
144      * value indicating that a layout dir has been set to LTR. */
145     public static final int SCREENLAYOUT_LAYOUTDIR_LTR = 0x01 << SCREENLAYOUT_LAYOUTDIR_SHIFT;
146     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
147      * value indicating that a layout dir has been set to RTL. */
148     public static final int SCREENLAYOUT_LAYOUTDIR_RTL = 0x02 << SCREENLAYOUT_LAYOUTDIR_SHIFT;
149 
150     /** Constant for {@link #screenLayout}: a value indicating that screenLayout is undefined */
151     public static final int SCREENLAYOUT_UNDEFINED = SCREENLAYOUT_SIZE_UNDEFINED |
152             SCREENLAYOUT_LONG_UNDEFINED | SCREENLAYOUT_LAYOUTDIR_UNDEFINED;
153 
154     /**
155      * Special flag we generate to indicate that the screen layout requires
156      * us to use a compatibility mode for apps that are not modern layout
157      * aware.
158      * @hide
159      */
160     public static final int SCREENLAYOUT_COMPAT_NEEDED = 0x10000000;
161 
162     /**
163      * Bit mask of overall layout of the screen.  Currently there are two
164      * fields:
165      * <p>The {@link #SCREENLAYOUT_SIZE_MASK} bits define the overall size
166      * of the screen.  They may be one of
167      * {@link #SCREENLAYOUT_SIZE_SMALL}, {@link #SCREENLAYOUT_SIZE_NORMAL},
168      * {@link #SCREENLAYOUT_SIZE_LARGE}, or {@link #SCREENLAYOUT_SIZE_XLARGE}.
169      *
170      * <p>The {@link #SCREENLAYOUT_LONG_MASK} defines whether the screen
171      * is wider/taller than normal.  They may be one of
172      * {@link #SCREENLAYOUT_LONG_NO} or {@link #SCREENLAYOUT_LONG_YES}.
173      *
174      * <p>The {@link #SCREENLAYOUT_LAYOUTDIR_MASK} defines whether the screen layout
175      * is either LTR or RTL.  They may be one of
176      * {@link #SCREENLAYOUT_LAYOUTDIR_LTR} or {@link #SCREENLAYOUT_LAYOUTDIR_RTL}.
177      *
178      * <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
179      * Multiple Screens</a> for more information.
180      */
181     public int screenLayout;
182 
183     /** @hide */
resetScreenLayout(int curLayout)184     static public int resetScreenLayout(int curLayout) {
185         return (curLayout&~(SCREENLAYOUT_LONG_MASK | SCREENLAYOUT_SIZE_MASK
186                         | SCREENLAYOUT_COMPAT_NEEDED))
187                 | (SCREENLAYOUT_LONG_YES | SCREENLAYOUT_SIZE_XLARGE);
188     }
189 
190     /** @hide */
reduceScreenLayout(int curLayout, int longSizeDp, int shortSizeDp)191     static public int reduceScreenLayout(int curLayout, int longSizeDp, int shortSizeDp) {
192         int screenLayoutSize;
193         boolean screenLayoutLong;
194         boolean screenLayoutCompatNeeded;
195 
196         // These semi-magic numbers define our compatibility modes for
197         // applications with different screens.  These are guarantees to
198         // app developers about the space they can expect for a particular
199         // configuration.  DO NOT CHANGE!
200         if (longSizeDp < 470) {
201             // This is shorter than an HVGA normal density screen (which
202             // is 480 pixels on its long side).
203             screenLayoutSize = SCREENLAYOUT_SIZE_SMALL;
204             screenLayoutLong = false;
205             screenLayoutCompatNeeded = false;
206         } else {
207             // What size is this screen screen?
208             if (longSizeDp >= 960 && shortSizeDp >= 720) {
209                 // 1.5xVGA or larger screens at medium density are the point
210                 // at which we consider it to be an extra large screen.
211                 screenLayoutSize = SCREENLAYOUT_SIZE_XLARGE;
212             } else if (longSizeDp >= 640 && shortSizeDp >= 480) {
213                 // VGA or larger screens at medium density are the point
214                 // at which we consider it to be a large screen.
215                 screenLayoutSize = SCREENLAYOUT_SIZE_LARGE;
216             } else {
217                 screenLayoutSize = SCREENLAYOUT_SIZE_NORMAL;
218             }
219 
220             // If this screen is wider than normal HVGA, or taller
221             // than FWVGA, then for old apps we want to run in size
222             // compatibility mode.
223             if (shortSizeDp > 321 || longSizeDp > 570) {
224                 screenLayoutCompatNeeded = true;
225             } else {
226                 screenLayoutCompatNeeded = false;
227             }
228 
229             // Is this a long screen?
230             if (((longSizeDp*3)/5) >= (shortSizeDp-1)) {
231                 // Anything wider than WVGA (5:3) is considering to be long.
232                 screenLayoutLong = true;
233             } else {
234                 screenLayoutLong = false;
235             }
236         }
237 
238         // Now reduce the last screenLayout to not be better than what we
239         // have found.
240         if (!screenLayoutLong) {
241             curLayout = (curLayout&~SCREENLAYOUT_LONG_MASK) | SCREENLAYOUT_LONG_NO;
242         }
243         if (screenLayoutCompatNeeded) {
244             curLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
245         }
246         int curSize = curLayout&SCREENLAYOUT_SIZE_MASK;
247         if (screenLayoutSize < curSize) {
248             curLayout = (curLayout&~SCREENLAYOUT_SIZE_MASK) | screenLayoutSize;
249         }
250         return curLayout;
251     }
252 
253     /**
254      * Check if the Configuration's current {@link #screenLayout} is at
255      * least the given size.
256      *
257      * @param size The desired size, either {@link #SCREENLAYOUT_SIZE_SMALL},
258      * {@link #SCREENLAYOUT_SIZE_NORMAL}, {@link #SCREENLAYOUT_SIZE_LARGE}, or
259      * {@link #SCREENLAYOUT_SIZE_XLARGE}.
260      * @return Returns true if the current screen layout size is at least
261      * the given size.
262      */
isLayoutSizeAtLeast(int size)263     public boolean isLayoutSizeAtLeast(int size) {
264         int cur = screenLayout&SCREENLAYOUT_SIZE_MASK;
265         if (cur == SCREENLAYOUT_SIZE_UNDEFINED) return false;
266         return cur >= size;
267     }
268 
269     /** Constant for {@link #touchscreen}: a value indicating that no value has been set. */
270     public static final int TOUCHSCREEN_UNDEFINED = 0;
271     /** Constant for {@link #touchscreen}, value corresponding to the
272      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#TouchscreenQualifier">notouch</a>
273      * resource qualifier. */
274     public static final int TOUCHSCREEN_NOTOUCH = 1;
275     /** @deprecated Not currently supported or used. */
276     @Deprecated public static final int TOUCHSCREEN_STYLUS = 2;
277     /** Constant for {@link #touchscreen}, value corresponding to the
278      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#TouchscreenQualifier">finger</a>
279      * resource qualifier. */
280     public static final int TOUCHSCREEN_FINGER = 3;
281 
282     /**
283      * The kind of touch screen attached to the device.
284      * One of: {@link #TOUCHSCREEN_NOTOUCH}, {@link #TOUCHSCREEN_FINGER}.
285      */
286     public int touchscreen;
287 
288     /** Constant for {@link #keyboard}: a value indicating that no value has been set. */
289     public static final int KEYBOARD_UNDEFINED = 0;
290     /** Constant for {@link #keyboard}, value corresponding to the
291      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">nokeys</a>
292      * resource qualifier. */
293     public static final int KEYBOARD_NOKEYS = 1;
294     /** Constant for {@link #keyboard}, value corresponding to the
295      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">qwerty</a>
296      * resource qualifier. */
297     public static final int KEYBOARD_QWERTY = 2;
298     /** Constant for {@link #keyboard}, value corresponding to the
299      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">12key</a>
300      * resource qualifier. */
301     public static final int KEYBOARD_12KEY = 3;
302 
303     /**
304      * The kind of keyboard attached to the device.
305      * One of: {@link #KEYBOARD_NOKEYS}, {@link #KEYBOARD_QWERTY},
306      * {@link #KEYBOARD_12KEY}.
307      */
308     public int keyboard;
309 
310     /** Constant for {@link #keyboardHidden}: a value indicating that no value has been set. */
311     public static final int KEYBOARDHIDDEN_UNDEFINED = 0;
312     /** Constant for {@link #keyboardHidden}, value corresponding to the
313      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keysexposed</a>
314      * resource qualifier. */
315     public static final int KEYBOARDHIDDEN_NO = 1;
316     /** Constant for {@link #keyboardHidden}, value corresponding to the
317      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keyshidden</a>
318      * resource qualifier. */
319     public static final int KEYBOARDHIDDEN_YES = 2;
320     /** Constant matching actual resource implementation. {@hide} */
321     public static final int KEYBOARDHIDDEN_SOFT = 3;
322 
323     /**
324      * A flag indicating whether any keyboard is available.  Unlike
325      * {@link #hardKeyboardHidden}, this also takes into account a soft
326      * keyboard, so if the hard keyboard is hidden but there is soft
327      * keyboard available, it will be set to NO.  Value is one of:
328      * {@link #KEYBOARDHIDDEN_NO}, {@link #KEYBOARDHIDDEN_YES}.
329      */
330     public int keyboardHidden;
331 
332     /** Constant for {@link #hardKeyboardHidden}: a value indicating that no value has been set. */
333     public static final int HARDKEYBOARDHIDDEN_UNDEFINED = 0;
334     /** Constant for {@link #hardKeyboardHidden}, value corresponding to the
335      * physical keyboard being exposed. */
336     public static final int HARDKEYBOARDHIDDEN_NO = 1;
337     /** Constant for {@link #hardKeyboardHidden}, value corresponding to the
338      * physical keyboard being hidden. */
339     public static final int HARDKEYBOARDHIDDEN_YES = 2;
340 
341     /**
342      * A flag indicating whether the hard keyboard has been hidden.  This will
343      * be set on a device with a mechanism to hide the keyboard from the
344      * user, when that mechanism is closed.  One of:
345      * {@link #HARDKEYBOARDHIDDEN_NO}, {@link #HARDKEYBOARDHIDDEN_YES}.
346      */
347     public int hardKeyboardHidden;
348 
349     /** Constant for {@link #navigation}: a value indicating that no value has been set. */
350     public static final int NAVIGATION_UNDEFINED = 0;
351     /** Constant for {@link #navigation}, value corresponding to the
352      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">nonav</a>
353      * resource qualifier. */
354     public static final int NAVIGATION_NONAV = 1;
355     /** Constant for {@link #navigation}, value corresponding to the
356      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">dpad</a>
357      * resource qualifier. */
358     public static final int NAVIGATION_DPAD = 2;
359     /** Constant for {@link #navigation}, value corresponding to the
360      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">trackball</a>
361      * resource qualifier. */
362     public static final int NAVIGATION_TRACKBALL = 3;
363     /** Constant for {@link #navigation}, value corresponding to the
364      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">wheel</a>
365      * resource qualifier. */
366     public static final int NAVIGATION_WHEEL = 4;
367 
368     /**
369      * The kind of navigation method available on the device.
370      * One of: {@link #NAVIGATION_NONAV}, {@link #NAVIGATION_DPAD},
371      * {@link #NAVIGATION_TRACKBALL}, {@link #NAVIGATION_WHEEL}.
372      */
373     public int navigation;
374 
375     /** Constant for {@link #navigationHidden}: a value indicating that no value has been set. */
376     public static final int NAVIGATIONHIDDEN_UNDEFINED = 0;
377     /** Constant for {@link #navigationHidden}, value corresponding to the
378      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavAvailQualifier">navexposed</a>
379      * resource qualifier. */
380     public static final int NAVIGATIONHIDDEN_NO = 1;
381     /** Constant for {@link #navigationHidden}, value corresponding to the
382      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavAvailQualifier">navhidden</a>
383      * resource qualifier. */
384     public static final int NAVIGATIONHIDDEN_YES = 2;
385 
386     /**
387      * A flag indicating whether any 5-way or DPAD navigation available.
388      * This will be set on a device with a mechanism to hide the navigation
389      * controls from the user, when that mechanism is closed.  One of:
390      * {@link #NAVIGATIONHIDDEN_NO}, {@link #NAVIGATIONHIDDEN_YES}.
391      */
392     public int navigationHidden;
393 
394     /** Constant for {@link #orientation}: a value indicating that no value has been set. */
395     public static final int ORIENTATION_UNDEFINED = 0;
396     /** Constant for {@link #orientation}, value corresponding to the
397      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#OrientationQualifier">port</a>
398      * resource qualifier. */
399     public static final int ORIENTATION_PORTRAIT = 1;
400     /** Constant for {@link #orientation}, value corresponding to the
401      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#OrientationQualifier">land</a>
402      * resource qualifier. */
403     public static final int ORIENTATION_LANDSCAPE = 2;
404     /** @deprecated Not currently supported or used. */
405     @Deprecated public static final int ORIENTATION_SQUARE = 3;
406 
407     /**
408      * Overall orientation of the screen.  May be one of
409      * {@link #ORIENTATION_LANDSCAPE}, {@link #ORIENTATION_PORTRAIT}.
410      */
411     public int orientation;
412 
413     /** Constant for {@link #uiMode}: bits that encode the mode type. */
414     public static final int UI_MODE_TYPE_MASK = 0x0f;
415     /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
416      * value indicating that no mode type has been set. */
417     public static final int UI_MODE_TYPE_UNDEFINED = 0x00;
418     /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
419      * value that corresponds to
420      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">no
421      * UI mode</a> resource qualifier specified. */
422     public static final int UI_MODE_TYPE_NORMAL = 0x01;
423     /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
424      * value that corresponds to the
425      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">desk</a>
426      * resource qualifier. */
427     public static final int UI_MODE_TYPE_DESK = 0x02;
428     /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
429      * value that corresponds to the
430      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">car</a>
431      * resource qualifier. */
432     public static final int UI_MODE_TYPE_CAR = 0x03;
433     /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
434      * value that corresponds to the
435      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">television</a>
436      * resource qualifier. */
437     public static final int UI_MODE_TYPE_TELEVISION = 0x04;
438     /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
439      * value that corresponds to the
440      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">appliance</a>
441      * resource qualifier. */
442     public static final int UI_MODE_TYPE_APPLIANCE = 0x05;
443 
444     /** Constant for {@link #uiMode}: bits that encode the night mode. */
445     public static final int UI_MODE_NIGHT_MASK = 0x30;
446     /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
447      * value indicating that no mode type has been set. */
448     public static final int UI_MODE_NIGHT_UNDEFINED = 0x00;
449     /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
450      * value that corresponds to the
451      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NightQualifier">notnight</a>
452      * resource qualifier. */
453     public static final int UI_MODE_NIGHT_NO = 0x10;
454     /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
455      * value that corresponds to the
456      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NightQualifier">night</a>
457      * resource qualifier. */
458     public static final int UI_MODE_NIGHT_YES = 0x20;
459 
460     /**
461      * Bit mask of the ui mode.  Currently there are two fields:
462      * <p>The {@link #UI_MODE_TYPE_MASK} bits define the overall ui mode of the
463      * device. They may be one of {@link #UI_MODE_TYPE_UNDEFINED},
464      * {@link #UI_MODE_TYPE_NORMAL}, {@link #UI_MODE_TYPE_DESK},
465      * {@link #UI_MODE_TYPE_CAR}, {@link #UI_MODE_TYPE_TELEVISION}, or
466      * {@link #UI_MODE_TYPE_APPLIANCE}.
467      *
468      * <p>The {@link #UI_MODE_NIGHT_MASK} defines whether the screen
469      * is in a special mode. They may be one of {@link #UI_MODE_NIGHT_UNDEFINED},
470      * {@link #UI_MODE_NIGHT_NO} or {@link #UI_MODE_NIGHT_YES}.
471      */
472     public int uiMode;
473 
474     /**
475      * Default value for {@link #screenWidthDp} indicating that no width
476      * has been specified.
477      */
478     public static final int SCREEN_WIDTH_DP_UNDEFINED = 0;
479 
480     /**
481      * The current width of the available screen space, in dp units,
482      * corresponding to
483      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenWidthQualifier">screen
484      * width</a> resource qualifier.  Set to
485      * {@link #SCREEN_WIDTH_DP_UNDEFINED} if no width is specified.
486      */
487     public int screenWidthDp;
488 
489     /**
490      * Default value for {@link #screenHeightDp} indicating that no width
491      * has been specified.
492      */
493     public static final int SCREEN_HEIGHT_DP_UNDEFINED = 0;
494 
495     /**
496      * The current height of the available screen space, in dp units,
497      * corresponding to
498      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenHeightQualifier">screen
499      * height</a> resource qualifier.  Set to
500      * {@link #SCREEN_HEIGHT_DP_UNDEFINED} if no height is specified.
501      */
502     public int screenHeightDp;
503 
504     /**
505      * Default value for {@link #smallestScreenWidthDp} indicating that no width
506      * has been specified.
507      */
508     public static final int SMALLEST_SCREEN_WIDTH_DP_UNDEFINED = 0;
509 
510     /**
511      * The smallest screen size an application will see in normal operation,
512      * corresponding to
513      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#SmallestScreenWidthQualifier">smallest
514      * screen width</a> resource qualifier.
515      * This is the smallest value of both screenWidthDp and screenHeightDp
516      * in both portrait and landscape.  Set to
517      * {@link #SMALLEST_SCREEN_WIDTH_DP_UNDEFINED} if no width is specified.
518      */
519     public int smallestScreenWidthDp;
520 
521     /**
522      * Default value for {@link #densityDpi} indicating that no width
523      * has been specified.
524      */
525     public static final int DENSITY_DPI_UNDEFINED = 0;
526 
527     /**
528      * The target screen density being rendered to,
529      * corresponding to
530      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#DensityQualifier">density</a>
531      * resource qualifier.  Set to
532      * {@link #DENSITY_DPI_UNDEFINED} if no density is specified.
533      */
534     public int densityDpi;
535 
536     /** @hide Hack to get this information from WM to app running in compat mode. */
537     public int compatScreenWidthDp;
538     /** @hide Hack to get this information from WM to app running in compat mode. */
539     public int compatScreenHeightDp;
540     /** @hide Hack to get this information from WM to app running in compat mode. */
541     public int compatSmallestScreenWidthDp;
542 
543     /**
544      * @hide Internal book-keeping.
545      */
546     public int seq;
547 
548     /** @hide Native-specific bit mask for MCC config; DO NOT USE UNLESS YOU ARE SURE. */
549     public static final int NATIVE_CONFIG_MCC = 0x0001;
550     /** @hide Native-specific bit mask for MNC config; DO NOT USE UNLESS YOU ARE SURE. */
551     public static final int NATIVE_CONFIG_MNC = 0x0002;
552     /** @hide Native-specific bit mask for LOCALE config; DO NOT USE UNLESS YOU ARE SURE. */
553     public static final int NATIVE_CONFIG_LOCALE = 0x0004;
554     /** @hide Native-specific bit mask for TOUCHSCREEN config; DO NOT USE UNLESS YOU ARE SURE. */
555     public static final int NATIVE_CONFIG_TOUCHSCREEN = 0x0008;
556     /** @hide Native-specific bit mask for KEYBOARD config; DO NOT USE UNLESS YOU ARE SURE. */
557     public static final int NATIVE_CONFIG_KEYBOARD = 0x0010;
558     /** @hide Native-specific bit mask for KEYBOARD_HIDDEN config; DO NOT USE UNLESS YOU
559      * ARE SURE. */
560     public static final int NATIVE_CONFIG_KEYBOARD_HIDDEN = 0x0020;
561     /** @hide Native-specific bit mask for NAVIGATION config; DO NOT USE UNLESS YOU ARE SURE. */
562     public static final int NATIVE_CONFIG_NAVIGATION = 0x0040;
563     /** @hide Native-specific bit mask for ORIENTATION config; DO NOT USE UNLESS YOU ARE SURE. */
564     public static final int NATIVE_CONFIG_ORIENTATION = 0x0080;
565     /** @hide Native-specific bit mask for DENSITY config; DO NOT USE UNLESS YOU ARE SURE. */
566     public static final int NATIVE_CONFIG_DENSITY = 0x0100;
567     /** @hide Native-specific bit mask for SCREEN_SIZE config; DO NOT USE UNLESS YOU ARE SURE. */
568     public static final int NATIVE_CONFIG_SCREEN_SIZE = 0x0200;
569     /** @hide Native-specific bit mask for VERSION config; DO NOT USE UNLESS YOU ARE SURE. */
570     public static final int NATIVE_CONFIG_VERSION = 0x0400;
571     /** @hide Native-specific bit mask for SCREEN_LAYOUT config; DO NOT USE UNLESS YOU ARE SURE. */
572     public static final int NATIVE_CONFIG_SCREEN_LAYOUT = 0x0800;
573     /** @hide Native-specific bit mask for UI_MODE config; DO NOT USE UNLESS YOU ARE SURE. */
574     public static final int NATIVE_CONFIG_UI_MODE = 0x1000;
575     /** @hide Native-specific bit mask for SMALLEST_SCREEN_SIZE config; DO NOT USE UNLESS YOU
576      * ARE SURE. */
577     public static final int NATIVE_CONFIG_SMALLEST_SCREEN_SIZE = 0x2000;
578     /** @hide Native-specific bit mask for LAYOUTDIR config ; DO NOT USE UNLESS YOU ARE SURE.*/
579     public static final int NATIVE_CONFIG_LAYOUTDIR = 0x4000;
580 
581     /**
582      * Construct an invalid Configuration.  You must call {@link #setToDefaults}
583      * for this object to be valid.  {@more}
584      */
Configuration()585     public Configuration() {
586         setToDefaults();
587     }
588 
589     /**
590      * Makes a deep copy suitable for modification.
591      */
Configuration(Configuration o)592     public Configuration(Configuration o) {
593         setTo(o);
594     }
595 
setTo(Configuration o)596     public void setTo(Configuration o) {
597         fontScale = o.fontScale;
598         mcc = o.mcc;
599         mnc = o.mnc;
600         if (o.locale != null) {
601             locale = (Locale) o.locale.clone();
602         }
603         userSetLocale = o.userSetLocale;
604         touchscreen = o.touchscreen;
605         keyboard = o.keyboard;
606         keyboardHidden = o.keyboardHidden;
607         hardKeyboardHidden = o.hardKeyboardHidden;
608         navigation = o.navigation;
609         navigationHidden = o.navigationHidden;
610         orientation = o.orientation;
611         screenLayout = o.screenLayout;
612         uiMode = o.uiMode;
613         screenWidthDp = o.screenWidthDp;
614         screenHeightDp = o.screenHeightDp;
615         smallestScreenWidthDp = o.smallestScreenWidthDp;
616         densityDpi = o.densityDpi;
617         compatScreenWidthDp = o.compatScreenWidthDp;
618         compatScreenHeightDp = o.compatScreenHeightDp;
619         compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp;
620         seq = o.seq;
621     }
622 
toString()623     public String toString() {
624         StringBuilder sb = new StringBuilder(128);
625         sb.append("{");
626         sb.append(fontScale);
627         sb.append(" ");
628         if (mcc != 0) {
629             sb.append(mcc);
630             sb.append("mcc");
631         } else {
632             sb.append("?mcc");
633         }
634         if (mnc != 0) {
635             sb.append(mnc);
636             sb.append("mnc");
637         } else {
638             sb.append("?mnc");
639         }
640         if (locale != null) {
641             sb.append(" ");
642             sb.append(locale);
643         } else {
644             sb.append(" ?locale");
645         }
646         int layoutDir = (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK);
647         switch (layoutDir) {
648             case SCREENLAYOUT_LAYOUTDIR_UNDEFINED: sb.append(" ?layoutDir"); break;
649             case SCREENLAYOUT_LAYOUTDIR_LTR: sb.append(" ldltr"); break;
650             case SCREENLAYOUT_LAYOUTDIR_RTL: sb.append(" ldrtl"); break;
651             default: sb.append(" layoutDir=");
652                 sb.append(layoutDir >> SCREENLAYOUT_LAYOUTDIR_SHIFT); break;
653         }
654         if (smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
655             sb.append(" sw"); sb.append(smallestScreenWidthDp); sb.append("dp");
656         } else {
657             sb.append(" ?swdp");
658         }
659         if (screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
660             sb.append(" w"); sb.append(screenWidthDp); sb.append("dp");
661         } else {
662             sb.append(" ?wdp");
663         }
664         if (screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
665             sb.append(" h"); sb.append(screenHeightDp); sb.append("dp");
666         } else {
667             sb.append(" ?hdp");
668         }
669         if (densityDpi != DENSITY_DPI_UNDEFINED) {
670             sb.append(" "); sb.append(densityDpi); sb.append("dpi");
671         } else {
672             sb.append(" ?density");
673         }
674         switch ((screenLayout&SCREENLAYOUT_SIZE_MASK)) {
675             case SCREENLAYOUT_SIZE_UNDEFINED: sb.append(" ?lsize"); break;
676             case SCREENLAYOUT_SIZE_SMALL: sb.append(" smll"); break;
677             case SCREENLAYOUT_SIZE_NORMAL: sb.append(" nrml"); break;
678             case SCREENLAYOUT_SIZE_LARGE: sb.append(" lrg"); break;
679             case SCREENLAYOUT_SIZE_XLARGE: sb.append(" xlrg"); break;
680             default: sb.append(" layoutSize=");
681                     sb.append(screenLayout&SCREENLAYOUT_SIZE_MASK); break;
682         }
683         switch ((screenLayout&SCREENLAYOUT_LONG_MASK)) {
684             case SCREENLAYOUT_LONG_UNDEFINED: sb.append(" ?long"); break;
685             case SCREENLAYOUT_LONG_NO: /* not-long is not interesting to print */ break;
686             case SCREENLAYOUT_LONG_YES: sb.append(" long"); break;
687             default: sb.append(" layoutLong=");
688                     sb.append(screenLayout&SCREENLAYOUT_LONG_MASK); break;
689         }
690         switch (orientation) {
691             case ORIENTATION_UNDEFINED: sb.append(" ?orien"); break;
692             case ORIENTATION_LANDSCAPE: sb.append(" land"); break;
693             case ORIENTATION_PORTRAIT: sb.append(" port"); break;
694             default: sb.append(" orien="); sb.append(orientation); break;
695         }
696         switch ((uiMode&UI_MODE_TYPE_MASK)) {
697             case UI_MODE_TYPE_UNDEFINED: sb.append(" ?uimode"); break;
698             case UI_MODE_TYPE_NORMAL: /* normal is not interesting to print */ break;
699             case UI_MODE_TYPE_DESK: sb.append(" desk"); break;
700             case UI_MODE_TYPE_CAR: sb.append(" car"); break;
701             case UI_MODE_TYPE_TELEVISION: sb.append(" television"); break;
702             case UI_MODE_TYPE_APPLIANCE: sb.append(" appliance"); break;
703             default: sb.append(" uimode="); sb.append(uiMode&UI_MODE_TYPE_MASK); break;
704         }
705         switch ((uiMode&UI_MODE_NIGHT_MASK)) {
706             case UI_MODE_NIGHT_UNDEFINED: sb.append(" ?night"); break;
707             case UI_MODE_NIGHT_NO: /* not-night is not interesting to print */ break;
708             case UI_MODE_NIGHT_YES: sb.append(" night"); break;
709             default: sb.append(" night="); sb.append(uiMode&UI_MODE_NIGHT_MASK); break;
710         }
711         switch (touchscreen) {
712             case TOUCHSCREEN_UNDEFINED: sb.append(" ?touch"); break;
713             case TOUCHSCREEN_NOTOUCH: sb.append(" -touch"); break;
714             case TOUCHSCREEN_STYLUS: sb.append(" stylus"); break;
715             case TOUCHSCREEN_FINGER: sb.append(" finger"); break;
716             default: sb.append(" touch="); sb.append(touchscreen); break;
717         }
718         switch (keyboard) {
719             case KEYBOARD_UNDEFINED: sb.append(" ?keyb"); break;
720             case KEYBOARD_NOKEYS: sb.append(" -keyb"); break;
721             case KEYBOARD_QWERTY: sb.append(" qwerty"); break;
722             case KEYBOARD_12KEY: sb.append(" 12key"); break;
723             default: sb.append(" keys="); sb.append(keyboard); break;
724         }
725         switch (keyboardHidden) {
726             case KEYBOARDHIDDEN_UNDEFINED: sb.append("/?"); break;
727             case KEYBOARDHIDDEN_NO: sb.append("/v"); break;
728             case KEYBOARDHIDDEN_YES: sb.append("/h"); break;
729             case KEYBOARDHIDDEN_SOFT: sb.append("/s"); break;
730             default: sb.append("/"); sb.append(keyboardHidden); break;
731         }
732         switch (hardKeyboardHidden) {
733             case HARDKEYBOARDHIDDEN_UNDEFINED: sb.append("/?"); break;
734             case HARDKEYBOARDHIDDEN_NO: sb.append("/v"); break;
735             case HARDKEYBOARDHIDDEN_YES: sb.append("/h"); break;
736             default: sb.append("/"); sb.append(hardKeyboardHidden); break;
737         }
738         switch (navigation) {
739             case NAVIGATION_UNDEFINED: sb.append(" ?nav"); break;
740             case NAVIGATION_NONAV: sb.append(" -nav"); break;
741             case NAVIGATION_DPAD: sb.append(" dpad"); break;
742             case NAVIGATION_TRACKBALL: sb.append(" tball"); break;
743             case NAVIGATION_WHEEL: sb.append(" wheel"); break;
744             default: sb.append(" nav="); sb.append(navigation); break;
745         }
746         switch (navigationHidden) {
747             case NAVIGATIONHIDDEN_UNDEFINED: sb.append("/?"); break;
748             case NAVIGATIONHIDDEN_NO: sb.append("/v"); break;
749             case NAVIGATIONHIDDEN_YES: sb.append("/h"); break;
750             default: sb.append("/"); sb.append(navigationHidden); break;
751         }
752         if (seq != 0) {
753             sb.append(" s.");
754             sb.append(seq);
755         }
756         sb.append('}');
757         return sb.toString();
758     }
759 
760     /**
761      * Set this object to the system defaults.
762      */
setToDefaults()763     public void setToDefaults() {
764         fontScale = 1;
765         mcc = mnc = 0;
766         locale = null;
767         userSetLocale = false;
768         touchscreen = TOUCHSCREEN_UNDEFINED;
769         keyboard = KEYBOARD_UNDEFINED;
770         keyboardHidden = KEYBOARDHIDDEN_UNDEFINED;
771         hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED;
772         navigation = NAVIGATION_UNDEFINED;
773         navigationHidden = NAVIGATIONHIDDEN_UNDEFINED;
774         orientation = ORIENTATION_UNDEFINED;
775         screenLayout = SCREENLAYOUT_UNDEFINED;
776         uiMode = UI_MODE_TYPE_UNDEFINED;
777         screenWidthDp = compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED;
778         screenHeightDp = compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED;
779         smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
780         densityDpi = DENSITY_DPI_UNDEFINED;
781         seq = 0;
782     }
783 
784     /** {@hide} */
makeDefault()785     @Deprecated public void makeDefault() {
786         setToDefaults();
787     }
788 
789     /**
790      * Copy the fields from delta into this Configuration object, keeping
791      * track of which ones have changed.  Any undefined fields in
792      * <var>delta</var> are ignored and not copied in to the current
793      * Configuration.
794      * @return Returns a bit mask of the changed fields, as per
795      * {@link #diff}.
796      */
updateFrom(Configuration delta)797     public int updateFrom(Configuration delta) {
798         int changed = 0;
799         if (delta.fontScale > 0 && fontScale != delta.fontScale) {
800             changed |= ActivityInfo.CONFIG_FONT_SCALE;
801             fontScale = delta.fontScale;
802         }
803         if (delta.mcc != 0 && mcc != delta.mcc) {
804             changed |= ActivityInfo.CONFIG_MCC;
805             mcc = delta.mcc;
806         }
807         if (delta.mnc != 0 && mnc != delta.mnc) {
808             changed |= ActivityInfo.CONFIG_MNC;
809             mnc = delta.mnc;
810         }
811         if (delta.locale != null
812                 && (locale == null || !locale.equals(delta.locale))) {
813             changed |= ActivityInfo.CONFIG_LOCALE;
814             locale = delta.locale != null
815                     ? (Locale) delta.locale.clone() : null;
816             // If locale has changed, then layout direction is also changed ...
817             changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
818             // ... and we need to update the layout direction (represented by the first
819             // 2 most significant bits in screenLayout).
820             setLayoutDirection(locale);
821         }
822         final int deltaScreenLayoutDir = delta.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
823         if (deltaScreenLayoutDir != SCREENLAYOUT_LAYOUTDIR_UNDEFINED &&
824                 deltaScreenLayoutDir != (screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) {
825             screenLayout = (screenLayout & ~SCREENLAYOUT_LAYOUTDIR_MASK) | deltaScreenLayoutDir;
826             changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
827         }
828         if (delta.userSetLocale && (!userSetLocale || ((changed & ActivityInfo.CONFIG_LOCALE) != 0)))
829         {
830             changed |= ActivityInfo.CONFIG_LOCALE;
831             userSetLocale = true;
832         }
833         if (delta.touchscreen != TOUCHSCREEN_UNDEFINED
834                 && touchscreen != delta.touchscreen) {
835             changed |= ActivityInfo.CONFIG_TOUCHSCREEN;
836             touchscreen = delta.touchscreen;
837         }
838         if (delta.keyboard != KEYBOARD_UNDEFINED
839                 && keyboard != delta.keyboard) {
840             changed |= ActivityInfo.CONFIG_KEYBOARD;
841             keyboard = delta.keyboard;
842         }
843         if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED
844                 && keyboardHidden != delta.keyboardHidden) {
845             changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
846             keyboardHidden = delta.keyboardHidden;
847         }
848         if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED
849                 && hardKeyboardHidden != delta.hardKeyboardHidden) {
850             changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
851             hardKeyboardHidden = delta.hardKeyboardHidden;
852         }
853         if (delta.navigation != NAVIGATION_UNDEFINED
854                 && navigation != delta.navigation) {
855             changed |= ActivityInfo.CONFIG_NAVIGATION;
856             navigation = delta.navigation;
857         }
858         if (delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED
859                 && navigationHidden != delta.navigationHidden) {
860             changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
861             navigationHidden = delta.navigationHidden;
862         }
863         if (delta.orientation != ORIENTATION_UNDEFINED
864                 && orientation != delta.orientation) {
865             changed |= ActivityInfo.CONFIG_ORIENTATION;
866             orientation = delta.orientation;
867         }
868         if (getScreenLayoutNoDirection(delta.screenLayout) !=
869                     (SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED)
870                 && (getScreenLayoutNoDirection(screenLayout) !=
871                     getScreenLayoutNoDirection(delta.screenLayout))) {
872             changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
873             // We need to preserve the previous layout dir bits if they were defined
874             if ((delta.screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK) == 0) {
875                 screenLayout = (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK)|delta.screenLayout;
876             } else {
877                 screenLayout = delta.screenLayout;
878             }
879         }
880         if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)
881                 && uiMode != delta.uiMode) {
882             changed |= ActivityInfo.CONFIG_UI_MODE;
883             if ((delta.uiMode&UI_MODE_TYPE_MASK) != UI_MODE_TYPE_UNDEFINED) {
884                 uiMode = (uiMode&~UI_MODE_TYPE_MASK)
885                         | (delta.uiMode&UI_MODE_TYPE_MASK);
886             }
887             if ((delta.uiMode&UI_MODE_NIGHT_MASK) != UI_MODE_NIGHT_UNDEFINED) {
888                 uiMode = (uiMode&~UI_MODE_NIGHT_MASK)
889                         | (delta.uiMode&UI_MODE_NIGHT_MASK);
890             }
891         }
892         if (delta.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED
893                 && screenWidthDp != delta.screenWidthDp) {
894             changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
895             screenWidthDp = delta.screenWidthDp;
896         }
897         if (delta.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED
898                 && screenHeightDp != delta.screenHeightDp) {
899             changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
900             screenHeightDp = delta.screenHeightDp;
901         }
902         if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
903                 && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
904             changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
905             smallestScreenWidthDp = delta.smallestScreenWidthDp;
906         }
907         if (delta.densityDpi != DENSITY_DPI_UNDEFINED &&
908                 densityDpi != delta.densityDpi) {
909             changed |= ActivityInfo.CONFIG_DENSITY;
910             densityDpi = delta.densityDpi;
911         }
912         if (delta.compatScreenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
913             compatScreenWidthDp = delta.compatScreenWidthDp;
914         }
915         if (delta.compatScreenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
916             compatScreenHeightDp = delta.compatScreenHeightDp;
917         }
918         if (delta.compatSmallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
919             compatSmallestScreenWidthDp = delta.compatSmallestScreenWidthDp;
920         }
921         if (delta.seq != 0) {
922             seq = delta.seq;
923         }
924 
925         return changed;
926     }
927 
928     /**
929      * Return a bit mask of the differences between this Configuration
930      * object and the given one.  Does not change the values of either.  Any
931      * undefined fields in <var>delta</var> are ignored.
932      * @return Returns a bit mask indicating which configuration
933      * values has changed, containing any combination of
934      * {@link android.content.pm.ActivityInfo#CONFIG_FONT_SCALE
935      * PackageManager.ActivityInfo.CONFIG_FONT_SCALE},
936      * {@link android.content.pm.ActivityInfo#CONFIG_MCC
937      * PackageManager.ActivityInfo.CONFIG_MCC},
938      * {@link android.content.pm.ActivityInfo#CONFIG_MNC
939      * PackageManager.ActivityInfo.CONFIG_MNC},
940      * {@link android.content.pm.ActivityInfo#CONFIG_LOCALE
941      * PackageManager.ActivityInfo.CONFIG_LOCALE},
942      * {@link android.content.pm.ActivityInfo#CONFIG_TOUCHSCREEN
943      * PackageManager.ActivityInfo.CONFIG_TOUCHSCREEN},
944      * {@link android.content.pm.ActivityInfo#CONFIG_KEYBOARD
945      * PackageManager.ActivityInfo.CONFIG_KEYBOARD},
946      * {@link android.content.pm.ActivityInfo#CONFIG_NAVIGATION
947      * PackageManager.ActivityInfo.CONFIG_NAVIGATION},
948      * {@link android.content.pm.ActivityInfo#CONFIG_ORIENTATION
949      * PackageManager.ActivityInfo.CONFIG_ORIENTATION},
950      * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_LAYOUT
951      * PackageManager.ActivityInfo.CONFIG_SCREEN_LAYOUT}, or
952      * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_SIZE
953      * PackageManager.ActivityInfo.CONFIG_SCREEN_SIZE}, or
954      * {@link android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE
955      * PackageManager.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE}.
956      * {@link android.content.pm.ActivityInfo#CONFIG_LAYOUT_DIRECTION
957      * PackageManager.ActivityInfo.CONFIG_LAYOUT_DIRECTION}.
958      */
diff(Configuration delta)959     public int diff(Configuration delta) {
960         int changed = 0;
961         if (delta.fontScale > 0 && fontScale != delta.fontScale) {
962             changed |= ActivityInfo.CONFIG_FONT_SCALE;
963         }
964         if (delta.mcc != 0 && mcc != delta.mcc) {
965             changed |= ActivityInfo.CONFIG_MCC;
966         }
967         if (delta.mnc != 0 && mnc != delta.mnc) {
968             changed |= ActivityInfo.CONFIG_MNC;
969         }
970         if (delta.locale != null
971                 && (locale == null || !locale.equals(delta.locale))) {
972             changed |= ActivityInfo.CONFIG_LOCALE;
973             changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
974         }
975         final int deltaScreenLayoutDir = delta.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
976         if (deltaScreenLayoutDir != SCREENLAYOUT_LAYOUTDIR_UNDEFINED &&
977                 deltaScreenLayoutDir != (screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) {
978             changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
979         }
980         if (delta.touchscreen != TOUCHSCREEN_UNDEFINED
981                 && touchscreen != delta.touchscreen) {
982             changed |= ActivityInfo.CONFIG_TOUCHSCREEN;
983         }
984         if (delta.keyboard != KEYBOARD_UNDEFINED
985                 && keyboard != delta.keyboard) {
986             changed |= ActivityInfo.CONFIG_KEYBOARD;
987         }
988         if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED
989                 && keyboardHidden != delta.keyboardHidden) {
990             changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
991         }
992         if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED
993                 && hardKeyboardHidden != delta.hardKeyboardHidden) {
994             changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
995         }
996         if (delta.navigation != NAVIGATION_UNDEFINED
997                 && navigation != delta.navigation) {
998             changed |= ActivityInfo.CONFIG_NAVIGATION;
999         }
1000         if (delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED
1001                 && navigationHidden != delta.navigationHidden) {
1002             changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1003         }
1004         if (delta.orientation != ORIENTATION_UNDEFINED
1005                 && orientation != delta.orientation) {
1006             changed |= ActivityInfo.CONFIG_ORIENTATION;
1007         }
1008         if (getScreenLayoutNoDirection(delta.screenLayout) !=
1009                     (SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED)
1010                 && getScreenLayoutNoDirection(screenLayout) !=
1011                     getScreenLayoutNoDirection(delta.screenLayout)) {
1012             changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
1013         }
1014         if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)
1015                 && uiMode != delta.uiMode) {
1016             changed |= ActivityInfo.CONFIG_UI_MODE;
1017         }
1018         if (delta.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED
1019                 && screenWidthDp != delta.screenWidthDp) {
1020             changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1021         }
1022         if (delta.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED
1023                 && screenHeightDp != delta.screenHeightDp) {
1024             changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1025         }
1026         if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
1027                 && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
1028             changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
1029         }
1030         if (delta.densityDpi != DENSITY_DPI_UNDEFINED
1031                 && densityDpi != delta.densityDpi) {
1032             changed |= ActivityInfo.CONFIG_DENSITY;
1033         }
1034 
1035         return changed;
1036     }
1037 
1038     /**
1039      * Determine if a new resource needs to be loaded from the bit set of
1040      * configuration changes returned by {@link #updateFrom(Configuration)}.
1041      *
1042      * @param configChanges The mask of changes configurations as returned by
1043      * {@link #updateFrom(Configuration)}.
1044      * @param interestingChanges The configuration changes that the resource
1045      * can handled, as given in {@link android.util.TypedValue#changingConfigurations}.
1046      *
1047      * @return Return true if the resource needs to be loaded, else false.
1048      */
needNewResources(int configChanges, int interestingChanges)1049     public static boolean needNewResources(int configChanges, int interestingChanges) {
1050         return (configChanges & (interestingChanges|ActivityInfo.CONFIG_FONT_SCALE)) != 0;
1051     }
1052 
1053     /**
1054      * @hide Return true if the sequence of 'other' is better than this.  Assumes
1055      * that 'this' is your current sequence and 'other' is a new one you have
1056      * received some how and want to compare with what you have.
1057      */
isOtherSeqNewer(Configuration other)1058     public boolean isOtherSeqNewer(Configuration other) {
1059         if (other == null) {
1060             // Sanity check.
1061             return false;
1062         }
1063         if (other.seq == 0) {
1064             // If the other sequence is not specified, then we must assume
1065             // it is newer since we don't know any better.
1066             return true;
1067         }
1068         if (seq == 0) {
1069             // If this sequence is not specified, then we also consider the
1070             // other is better.  Yes we have a preference for other.  Sue us.
1071             return true;
1072         }
1073         int diff = other.seq - seq;
1074         if (diff > 0x10000) {
1075             // If there has been a sufficiently large jump, assume the
1076             // sequence has wrapped around.
1077             return false;
1078         }
1079         return diff > 0;
1080     }
1081 
1082     /**
1083      * Parcelable methods
1084      */
describeContents()1085     public int describeContents() {
1086         return 0;
1087     }
1088 
writeToParcel(Parcel dest, int flags)1089     public void writeToParcel(Parcel dest, int flags) {
1090         dest.writeFloat(fontScale);
1091         dest.writeInt(mcc);
1092         dest.writeInt(mnc);
1093         if (locale == null) {
1094             dest.writeInt(0);
1095         } else {
1096             dest.writeInt(1);
1097             dest.writeString(locale.getLanguage());
1098             dest.writeString(locale.getCountry());
1099             dest.writeString(locale.getVariant());
1100         }
1101         if(userSetLocale) {
1102             dest.writeInt(1);
1103         } else {
1104             dest.writeInt(0);
1105         }
1106         dest.writeInt(touchscreen);
1107         dest.writeInt(keyboard);
1108         dest.writeInt(keyboardHidden);
1109         dest.writeInt(hardKeyboardHidden);
1110         dest.writeInt(navigation);
1111         dest.writeInt(navigationHidden);
1112         dest.writeInt(orientation);
1113         dest.writeInt(screenLayout);
1114         dest.writeInt(uiMode);
1115         dest.writeInt(screenWidthDp);
1116         dest.writeInt(screenHeightDp);
1117         dest.writeInt(smallestScreenWidthDp);
1118         dest.writeInt(densityDpi);
1119         dest.writeInt(compatScreenWidthDp);
1120         dest.writeInt(compatScreenHeightDp);
1121         dest.writeInt(compatSmallestScreenWidthDp);
1122         dest.writeInt(seq);
1123     }
1124 
readFromParcel(Parcel source)1125     public void readFromParcel(Parcel source) {
1126         fontScale = source.readFloat();
1127         mcc = source.readInt();
1128         mnc = source.readInt();
1129         if (source.readInt() != 0) {
1130             locale = new Locale(source.readString(), source.readString(),
1131                     source.readString());
1132         }
1133         userSetLocale = (source.readInt()==1);
1134         touchscreen = source.readInt();
1135         keyboard = source.readInt();
1136         keyboardHidden = source.readInt();
1137         hardKeyboardHidden = source.readInt();
1138         navigation = source.readInt();
1139         navigationHidden = source.readInt();
1140         orientation = source.readInt();
1141         screenLayout = source.readInt();
1142         uiMode = source.readInt();
1143         screenWidthDp = source.readInt();
1144         screenHeightDp = source.readInt();
1145         smallestScreenWidthDp = source.readInt();
1146         densityDpi = source.readInt();
1147         compatScreenWidthDp = source.readInt();
1148         compatScreenHeightDp = source.readInt();
1149         compatSmallestScreenWidthDp = source.readInt();
1150         seq = source.readInt();
1151     }
1152 
1153     public static final Parcelable.Creator<Configuration> CREATOR
1154             = new Parcelable.Creator<Configuration>() {
1155         public Configuration createFromParcel(Parcel source) {
1156             return new Configuration(source);
1157         }
1158 
1159         public Configuration[] newArray(int size) {
1160             return new Configuration[size];
1161         }
1162     };
1163 
1164     /**
1165      * Construct this Configuration object, reading from the Parcel.
1166      */
Configuration(Parcel source)1167     private Configuration(Parcel source) {
1168         readFromParcel(source);
1169     }
1170 
compareTo(Configuration that)1171     public int compareTo(Configuration that) {
1172         int n;
1173         float a = this.fontScale;
1174         float b = that.fontScale;
1175         if (a < b) return -1;
1176         if (a > b) return 1;
1177         n = this.mcc - that.mcc;
1178         if (n != 0) return n;
1179         n = this.mnc - that.mnc;
1180         if (n != 0) return n;
1181         if (this.locale == null) {
1182             if (that.locale != null) return 1;
1183         } else if (that.locale == null) {
1184             return -1;
1185         } else {
1186             n = this.locale.getLanguage().compareTo(that.locale.getLanguage());
1187             if (n != 0) return n;
1188             n = this.locale.getCountry().compareTo(that.locale.getCountry());
1189             if (n != 0) return n;
1190             n = this.locale.getVariant().compareTo(that.locale.getVariant());
1191             if (n != 0) return n;
1192         }
1193         n = this.touchscreen - that.touchscreen;
1194         if (n != 0) return n;
1195         n = this.keyboard - that.keyboard;
1196         if (n != 0) return n;
1197         n = this.keyboardHidden - that.keyboardHidden;
1198         if (n != 0) return n;
1199         n = this.hardKeyboardHidden - that.hardKeyboardHidden;
1200         if (n != 0) return n;
1201         n = this.navigation - that.navigation;
1202         if (n != 0) return n;
1203         n = this.navigationHidden - that.navigationHidden;
1204         if (n != 0) return n;
1205         n = this.orientation - that.orientation;
1206         if (n != 0) return n;
1207         n = this.screenLayout - that.screenLayout;
1208         if (n != 0) return n;
1209         n = this.uiMode - that.uiMode;
1210         if (n != 0) return n;
1211         n = this.screenWidthDp - that.screenWidthDp;
1212         if (n != 0) return n;
1213         n = this.screenHeightDp - that.screenHeightDp;
1214         if (n != 0) return n;
1215         n = this.smallestScreenWidthDp - that.smallestScreenWidthDp;
1216         if (n != 0) return n;
1217         n = this.densityDpi - that.densityDpi;
1218         //if (n != 0) return n;
1219         return n;
1220     }
1221 
equals(Configuration that)1222     public boolean equals(Configuration that) {
1223         if (that == null) return false;
1224         if (that == this) return true;
1225         return this.compareTo(that) == 0;
1226     }
1227 
equals(Object that)1228     public boolean equals(Object that) {
1229         try {
1230             return equals((Configuration)that);
1231         } catch (ClassCastException e) {
1232         }
1233         return false;
1234     }
1235 
hashCode()1236     public int hashCode() {
1237         int result = 17;
1238         result = 31 * result + Float.floatToIntBits(fontScale);
1239         result = 31 * result + mcc;
1240         result = 31 * result + mnc;
1241         result = 31 * result + (locale != null ? locale.hashCode() : 0);
1242         result = 31 * result + touchscreen;
1243         result = 31 * result + keyboard;
1244         result = 31 * result + keyboardHidden;
1245         result = 31 * result + hardKeyboardHidden;
1246         result = 31 * result + navigation;
1247         result = 31 * result + navigationHidden;
1248         result = 31 * result + orientation;
1249         result = 31 * result + screenLayout;
1250         result = 31 * result + uiMode;
1251         result = 31 * result + screenWidthDp;
1252         result = 31 * result + screenHeightDp;
1253         result = 31 * result + smallestScreenWidthDp;
1254         result = 31 * result + densityDpi;
1255         return result;
1256     }
1257 
1258     /**
1259      * Set the locale. This is the preferred way for setting up the locale (instead of using the
1260      * direct accessor). This will also set the userLocale and layout direction according to
1261      * the locale.
1262      *
1263      * @param loc The locale. Can be null.
1264      */
setLocale(Locale loc)1265     public void setLocale(Locale loc) {
1266         locale = loc;
1267         userSetLocale = true;
1268         setLayoutDirection(locale);
1269     }
1270 
1271     /**
1272      * Return the layout direction. Will be either {@link View#LAYOUT_DIRECTION_LTR} or
1273      * {@link View#LAYOUT_DIRECTION_RTL}.
1274      *
1275      * @return Returns {@link View#LAYOUT_DIRECTION_RTL} if the configuration
1276      * is {@link #SCREENLAYOUT_LAYOUTDIR_RTL}, otherwise {@link View#LAYOUT_DIRECTION_LTR}.
1277      */
getLayoutDirection()1278     public int getLayoutDirection() {
1279         return (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK) == SCREENLAYOUT_LAYOUTDIR_RTL
1280                 ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
1281     }
1282 
1283     /**
1284      * Set the layout direction from the Locale.
1285      *
1286      * @param locale The Locale. If null will set the layout direction to
1287      * {@link View#LAYOUT_DIRECTION_LTR}. If not null will set it to the layout direction
1288      * corresponding to the Locale.
1289      *
1290      * @see {@link View#LAYOUT_DIRECTION_LTR} and {@link View#LAYOUT_DIRECTION_RTL}
1291      */
setLayoutDirection(Locale locale)1292     public void setLayoutDirection(Locale locale) {
1293         // There is a "1" difference between the configuration values for
1294         // layout direction and View constants for layout direction, just add "1".
1295         final int layoutDirection = 1 + TextUtils.getLayoutDirectionFromLocale(locale);
1296         screenLayout = (screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK)|
1297                 (layoutDirection << SCREENLAYOUT_LAYOUTDIR_SHIFT);
1298     }
1299 
getScreenLayoutNoDirection(int screenLayout)1300     private static int getScreenLayoutNoDirection(int screenLayout) {
1301         return screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK;
1302     }
1303 }
1304