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