Home | History | Annotate | Download | only in res
      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 */
    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 */
    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      */
    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      */
    585     public Configuration() {
    586         setToDefaults();
    587     }
    588 
    589     /**
    590      * Makes a deep copy suitable for modification.
    591      */
    592     public Configuration(Configuration o) {
    593         setTo(o);
    594     }
    595 
    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 
    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      */
    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} */
    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      */
    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      */
    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      */
   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      */
   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      */
   1085     public int describeContents() {
   1086         return 0;
   1087     }
   1088 
   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 
   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      */
   1167     private Configuration(Parcel source) {
   1168         readFromParcel(source);
   1169     }
   1170 
   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 
   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 
   1228     public boolean equals(Object that) {
   1229         try {
   1230             return equals((Configuration)that);
   1231         } catch (ClassCastException e) {
   1232         }
   1233         return false;
   1234     }
   1235 
   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      */
   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      */
   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      */
   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 
   1300     private static int getScreenLayoutNoDirection(int screenLayout) {
   1301         return screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK;
   1302     }
   1303 }
   1304