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.util.LocaleUtil;
     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     /**
     39      * Current user preference for the scaling factor for fonts, relative
     40      * to the base density scaling.
     41      */
     42     public float fontScale;
     43 
     44     /**
     45      * IMSI MCC (Mobile Country Code), corresponding to
     46      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#MccQualifier">mcc</a>
     47      * resource qualifier.  0 if undefined.
     48      */
     49     public int mcc;
     50 
     51     /**
     52      * IMSI MNC (Mobile Network Code), corresponding to
     53      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#MccQualifier">mnc</a>
     54      * resource qualifier.  0 if undefined.
     55      */
     56     public int mnc;
     57 
     58     /**
     59      * Current user preference for the locale, corresponding to
     60      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#LocaleQualifier">locale</a>
     61      * resource qualifier.
     62      */
     63     public Locale locale;
     64 
     65     /**
     66      * Locale should persist on setting.  This is hidden because it is really
     67      * questionable whether this is the right way to expose the functionality.
     68      * @hide
     69      */
     70     public boolean userSetLocale;
     71 
     72     /** Constant for {@link #screenLayout}: bits that encode the size. */
     73     public static final int SCREENLAYOUT_SIZE_MASK = 0x0f;
     74     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
     75      * value indicating that no size has been set. */
     76     public static final int SCREENLAYOUT_SIZE_UNDEFINED = 0x00;
     77     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
     78      * value indicating the screen is at least approximately 320x426 dp units,
     79      * corresponds to the
     80      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">small</a>
     81      * resource qualifier.
     82      * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
     83      * Multiple Screens</a> for more information. */
     84     public static final int SCREENLAYOUT_SIZE_SMALL = 0x01;
     85     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
     86      * value indicating the screen is at least approximately 320x470 dp units,
     87      * corresponds to the
     88      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">normal</a>
     89      * resource qualifier.
     90      * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
     91      * Multiple Screens</a> for more information. */
     92     public static final int SCREENLAYOUT_SIZE_NORMAL = 0x02;
     93     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
     94      * value indicating the screen is at least approximately 480x640 dp units,
     95      * corresponds to the
     96      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">large</a>
     97      * resource qualifier.
     98      * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
     99      * Multiple Screens</a> for more information. */
    100     public static final int SCREENLAYOUT_SIZE_LARGE = 0x03;
    101     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
    102      * value indicating the screen is at least approximately 720x960 dp units,
    103      * corresponds to the
    104      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">xlarge</a>
    105      * resource qualifier.
    106      * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
    107      * Multiple Screens</a> for more information.*/
    108     public static final int SCREENLAYOUT_SIZE_XLARGE = 0x04;
    109 
    110     /** Constant for {@link #screenLayout}: bits that encode the aspect ratio. */
    111     public static final int SCREENLAYOUT_LONG_MASK = 0x30;
    112     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
    113      * value indicating that no size has been set. */
    114     public static final int SCREENLAYOUT_LONG_UNDEFINED = 0x00;
    115     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
    116      * value that corresponds to the
    117      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenAspectQualifier">notlong</a>
    118      * resource qualifier. */
    119     public static final int SCREENLAYOUT_LONG_NO = 0x10;
    120     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
    121      * value that corresponds to the
    122      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenAspectQualifier">long</a>
    123      * resource qualifier. */
    124     public static final int SCREENLAYOUT_LONG_YES = 0x20;
    125 
    126     /**
    127      * Special flag we generate to indicate that the screen layout requires
    128      * us to use a compatibility mode for apps that are not modern layout
    129      * aware.
    130      * @hide
    131      */
    132     public static final int SCREENLAYOUT_COMPAT_NEEDED = 0x10000000;
    133 
    134     /**
    135      * Bit mask of overall layout of the screen.  Currently there are two
    136      * fields:
    137      * <p>The {@link #SCREENLAYOUT_SIZE_MASK} bits define the overall size
    138      * of the screen.  They may be one of
    139      * {@link #SCREENLAYOUT_SIZE_SMALL}, {@link #SCREENLAYOUT_SIZE_NORMAL},
    140      * {@link #SCREENLAYOUT_SIZE_LARGE}, or {@link #SCREENLAYOUT_SIZE_XLARGE}.
    141      *
    142      * <p>The {@link #SCREENLAYOUT_LONG_MASK} defines whether the screen
    143      * is wider/taller than normal.  They may be one of
    144      * {@link #SCREENLAYOUT_LONG_NO} or {@link #SCREENLAYOUT_LONG_YES}.
    145      *
    146      * <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
    147      * Multiple Screens</a> for more information.
    148      */
    149     public int screenLayout;
    150 
    151     /**
    152      * Check if the Configuration's current {@link #screenLayout} is at
    153      * least the given size.
    154      *
    155      * @param size The desired size, either {@link #SCREENLAYOUT_SIZE_SMALL},
    156      * {@link #SCREENLAYOUT_SIZE_NORMAL}, {@link #SCREENLAYOUT_SIZE_LARGE}, or
    157      * {@link #SCREENLAYOUT_SIZE_XLARGE}.
    158      * @return Returns true if the current screen layout size is at least
    159      * the given size.
    160      */
    161     public boolean isLayoutSizeAtLeast(int size) {
    162         int cur = screenLayout&SCREENLAYOUT_SIZE_MASK;
    163         if (cur == SCREENLAYOUT_SIZE_UNDEFINED) return false;
    164         return cur >= size;
    165     }
    166 
    167     /** Constant for {@link #touchscreen}: a value indicating that no value has been set. */
    168     public static final int TOUCHSCREEN_UNDEFINED = 0;
    169     /** Constant for {@link #touchscreen}, value corresponding to the
    170      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#TouchscreenQualifier">notouch</a>
    171      * resource qualifier. */
    172     public static final int TOUCHSCREEN_NOTOUCH = 1;
    173     /** @deprecated Not currently supported or used. */
    174     @Deprecated public static final int TOUCHSCREEN_STYLUS = 2;
    175     /** Constant for {@link #touchscreen}, value corresponding to the
    176      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#TouchscreenQualifier">finger</a>
    177      * resource qualifier. */
    178     public static final int TOUCHSCREEN_FINGER = 3;
    179 
    180     /**
    181      * The kind of touch screen attached to the device.
    182      * One of: {@link #TOUCHSCREEN_NOTOUCH}, {@link #TOUCHSCREEN_FINGER}.
    183      */
    184     public int touchscreen;
    185 
    186     /** Constant for {@link #keyboard}: a value indicating that no value has been set. */
    187     public static final int KEYBOARD_UNDEFINED = 0;
    188     /** Constant for {@link #keyboard}, value corresponding to the
    189      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">nokeys</a>
    190      * resource qualifier. */
    191     public static final int KEYBOARD_NOKEYS = 1;
    192     /** Constant for {@link #keyboard}, value corresponding to the
    193      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">qwerty</a>
    194      * resource qualifier. */
    195     public static final int KEYBOARD_QWERTY = 2;
    196     /** Constant for {@link #keyboard}, value corresponding to the
    197      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">12key</a>
    198      * resource qualifier. */
    199     public static final int KEYBOARD_12KEY = 3;
    200 
    201     /**
    202      * The kind of keyboard attached to the device.
    203      * One of: {@link #KEYBOARD_NOKEYS}, {@link #KEYBOARD_QWERTY},
    204      * {@link #KEYBOARD_12KEY}.
    205      */
    206     public int keyboard;
    207 
    208     /** Constant for {@link #keyboardHidden}: a value indicating that no value has been set. */
    209     public static final int KEYBOARDHIDDEN_UNDEFINED = 0;
    210     /** Constant for {@link #keyboardHidden}, value corresponding to the
    211      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keysexposed</a>
    212      * resource qualifier. */
    213     public static final int KEYBOARDHIDDEN_NO = 1;
    214     /** Constant for {@link #keyboardHidden}, value corresponding to the
    215      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keyshidden</a>
    216      * resource qualifier. */
    217     public static final int KEYBOARDHIDDEN_YES = 2;
    218     /** Constant matching actual resource implementation. {@hide} */
    219     public static final int KEYBOARDHIDDEN_SOFT = 3;
    220 
    221     /**
    222      * A flag indicating whether any keyboard is available.  Unlike
    223      * {@link #hardKeyboardHidden}, this also takes into account a soft
    224      * keyboard, so if the hard keyboard is hidden but there is soft
    225      * keyboard available, it will be set to NO.  Value is one of:
    226      * {@link #KEYBOARDHIDDEN_NO}, {@link #KEYBOARDHIDDEN_YES}.
    227      */
    228     public int keyboardHidden;
    229 
    230     /** Constant for {@link #hardKeyboardHidden}: a value indicating that no value has been set. */
    231     public static final int HARDKEYBOARDHIDDEN_UNDEFINED = 0;
    232     /** Constant for {@link #hardKeyboardHidden}, value corresponding to the
    233      * physical keyboard being exposed. */
    234     public static final int HARDKEYBOARDHIDDEN_NO = 1;
    235     /** Constant for {@link #hardKeyboardHidden}, value corresponding to the
    236      * physical keyboard being hidden. */
    237     public static final int HARDKEYBOARDHIDDEN_YES = 2;
    238 
    239     /**
    240      * A flag indicating whether the hard keyboard has been hidden.  This will
    241      * be set on a device with a mechanism to hide the keyboard from the
    242      * user, when that mechanism is closed.  One of:
    243      * {@link #HARDKEYBOARDHIDDEN_NO}, {@link #HARDKEYBOARDHIDDEN_YES}.
    244      */
    245     public int hardKeyboardHidden;
    246 
    247     /** Constant for {@link #navigation}: a value indicating that no value has been set. */
    248     public static final int NAVIGATION_UNDEFINED = 0;
    249     /** Constant for {@link #navigation}, value corresponding to the
    250      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">nonav</a>
    251      * resource qualifier. */
    252     public static final int NAVIGATION_NONAV = 1;
    253     /** Constant for {@link #navigation}, value corresponding to the
    254      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">dpad</a>
    255      * resource qualifier. */
    256     public static final int NAVIGATION_DPAD = 2;
    257     /** Constant for {@link #navigation}, value corresponding to the
    258      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">trackball</a>
    259      * resource qualifier. */
    260     public static final int NAVIGATION_TRACKBALL = 3;
    261     /** Constant for {@link #navigation}, value corresponding to the
    262      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">wheel</a>
    263      * resource qualifier. */
    264     public static final int NAVIGATION_WHEEL = 4;
    265 
    266     /**
    267      * The kind of navigation method available on the device.
    268      * One of: {@link #NAVIGATION_NONAV}, {@link #NAVIGATION_DPAD},
    269      * {@link #NAVIGATION_TRACKBALL}, {@link #NAVIGATION_WHEEL}.
    270      */
    271     public int navigation;
    272 
    273     /** Constant for {@link #navigationHidden}: a value indicating that no value has been set. */
    274     public static final int NAVIGATIONHIDDEN_UNDEFINED = 0;
    275     /** Constant for {@link #navigationHidden}, value corresponding to the
    276      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavAvailQualifier">navexposed</a>
    277      * resource qualifier. */
    278     public static final int NAVIGATIONHIDDEN_NO = 1;
    279     /** Constant for {@link #navigationHidden}, value corresponding to the
    280      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavAvailQualifier">navhidden</a>
    281      * resource qualifier. */
    282     public static final int NAVIGATIONHIDDEN_YES = 2;
    283 
    284     /**
    285      * A flag indicating whether any 5-way or DPAD navigation available.
    286      * This will be set on a device with a mechanism to hide the navigation
    287      * controls from the user, when that mechanism is closed.  One of:
    288      * {@link #NAVIGATIONHIDDEN_NO}, {@link #NAVIGATIONHIDDEN_YES}.
    289      */
    290     public int navigationHidden;
    291 
    292     /** Constant for {@link #orientation}: a value indicating that no value has been set. */
    293     public static final int ORIENTATION_UNDEFINED = 0;
    294     /** Constant for {@link #orientation}, value corresponding to the
    295      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#OrientationQualifier">port</a>
    296      * resource qualifier. */
    297     public static final int ORIENTATION_PORTRAIT = 1;
    298     /** Constant for {@link #orientation}, value corresponding to the
    299      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#OrientationQualifier">land</a>
    300      * resource qualifier. */
    301     public static final int ORIENTATION_LANDSCAPE = 2;
    302     /** @deprecated Not currently supported or used. */
    303     @Deprecated public static final int ORIENTATION_SQUARE = 3;
    304 
    305     /**
    306      * Overall orientation of the screen.  May be one of
    307      * {@link #ORIENTATION_LANDSCAPE}, {@link #ORIENTATION_PORTRAIT}.
    308      */
    309     public int orientation;
    310 
    311     /** Constant for {@link #uiMode}: bits that encode the mode type. */
    312     public static final int UI_MODE_TYPE_MASK = 0x0f;
    313     /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
    314      * value indicating that no mode type has been set. */
    315     public static final int UI_MODE_TYPE_UNDEFINED = 0x00;
    316     /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
    317      * value that corresponds to
    318      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">no
    319      * UI mode</a> resource qualifier specified. */
    320     public static final int UI_MODE_TYPE_NORMAL = 0x01;
    321     /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
    322      * value that corresponds to the
    323      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">desk</a>
    324      * resource qualifier. */
    325     public static final int UI_MODE_TYPE_DESK = 0x02;
    326     /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
    327      * value that corresponds to the
    328      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">car</a>
    329      * resource qualifier. */
    330     public static final int UI_MODE_TYPE_CAR = 0x03;
    331     /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
    332      * value that corresponds to the
    333      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">television</a>
    334      * resource qualifier. */
    335     public static final int UI_MODE_TYPE_TELEVISION = 0x04;
    336     /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
    337      * value that corresponds to the
    338      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">appliance</a>
    339      * resource qualifier. */
    340     public static final int UI_MODE_TYPE_APPLIANCE = 0x05;
    341 
    342     /** Constant for {@link #uiMode}: bits that encode the night mode. */
    343     public static final int UI_MODE_NIGHT_MASK = 0x30;
    344     /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
    345      * value indicating that no mode type has been set. */
    346     public static final int UI_MODE_NIGHT_UNDEFINED = 0x00;
    347     /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
    348      * value that corresponds to the
    349      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NightQualifier">notnight</a>
    350      * resource qualifier. */
    351     public static final int UI_MODE_NIGHT_NO = 0x10;
    352     /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
    353      * value that corresponds to the
    354      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NightQualifier">night</a>
    355      * resource qualifier. */
    356     public static final int UI_MODE_NIGHT_YES = 0x20;
    357 
    358     /**
    359      * Bit mask of the ui mode.  Currently there are two fields:
    360      * <p>The {@link #UI_MODE_TYPE_MASK} bits define the overall ui mode of the
    361      * device. They may be one of {@link #UI_MODE_TYPE_UNDEFINED},
    362      * {@link #UI_MODE_TYPE_NORMAL}, {@link #UI_MODE_TYPE_DESK},
    363      * {@link #UI_MODE_TYPE_CAR}, {@link #UI_MODE_TYPE_TELEVISION}, or
    364      * {@link #UI_MODE_TYPE_APPLIANCE}.
    365      *
    366      * <p>The {@link #UI_MODE_NIGHT_MASK} defines whether the screen
    367      * is in a special mode. They may be one of {@link #UI_MODE_NIGHT_UNDEFINED},
    368      * {@link #UI_MODE_NIGHT_NO} or {@link #UI_MODE_NIGHT_YES}.
    369      */
    370     public int uiMode;
    371 
    372     public static final int SCREEN_WIDTH_DP_UNDEFINED = 0;
    373 
    374     /**
    375      * The current width of the available screen space, in dp units,
    376      * corresponding to
    377      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenWidthQualifier">screen
    378      * width</a> resource qualifier.
    379      */
    380     public int screenWidthDp;
    381 
    382     public static final int SCREEN_HEIGHT_DP_UNDEFINED = 0;
    383 
    384     /**
    385      * The current height of the available screen space, in dp units,
    386      * corresponding to
    387      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenHeightQualifier">screen
    388      * height</a> resource qualifier.
    389      */
    390     public int screenHeightDp;
    391 
    392     public static final int SMALLEST_SCREEN_WIDTH_DP_UNDEFINED = 0;
    393 
    394     /**
    395      * The smallest screen size an application will see in normal operation,
    396      * corresponding to
    397      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#SmallestScreenWidthQualifier">smallest
    398      * screen width</a> resource qualifier.
    399      * This is the smallest value of both screenWidthDp and screenHeightDp
    400      * in both portrait and landscape.
    401      */
    402     public int smallestScreenWidthDp;
    403 
    404     /** @hide Hack to get this information from WM to app running in compat mode. */
    405     public int compatScreenWidthDp;
    406     /** @hide Hack to get this information from WM to app running in compat mode. */
    407     public int compatScreenHeightDp;
    408     /** @hide Hack to get this information from WM to app running in compat mode. */
    409     public int compatSmallestScreenWidthDp;
    410 
    411     /**
    412      * @hide The layout direction associated to the current Locale
    413      */
    414     public int layoutDirection;
    415 
    416     /**
    417      * @hide Internal book-keeping.
    418      */
    419     public int seq;
    420 
    421     /**
    422      * Construct an invalid Configuration.  You must call {@link #setToDefaults}
    423      * for this object to be valid.  {@more}
    424      */
    425     public Configuration() {
    426         setToDefaults();
    427     }
    428 
    429     /**
    430      * Makes a deep copy suitable for modification.
    431      */
    432     public Configuration(Configuration o) {
    433         setTo(o);
    434     }
    435 
    436     public void setTo(Configuration o) {
    437         fontScale = o.fontScale;
    438         mcc = o.mcc;
    439         mnc = o.mnc;
    440         if (o.locale != null) {
    441             locale = (Locale) o.locale.clone();
    442             layoutDirection = o.layoutDirection;
    443         }
    444         userSetLocale = o.userSetLocale;
    445         touchscreen = o.touchscreen;
    446         keyboard = o.keyboard;
    447         keyboardHidden = o.keyboardHidden;
    448         hardKeyboardHidden = o.hardKeyboardHidden;
    449         navigation = o.navigation;
    450         navigationHidden = o.navigationHidden;
    451         orientation = o.orientation;
    452         screenLayout = o.screenLayout;
    453         uiMode = o.uiMode;
    454         screenWidthDp = o.screenWidthDp;
    455         screenHeightDp = o.screenHeightDp;
    456         smallestScreenWidthDp = o.smallestScreenWidthDp;
    457         compatScreenWidthDp = o.compatScreenWidthDp;
    458         compatScreenHeightDp = o.compatScreenHeightDp;
    459         compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp;
    460         seq = o.seq;
    461     }
    462 
    463     public String toString() {
    464         StringBuilder sb = new StringBuilder(128);
    465         sb.append("{");
    466         sb.append(fontScale);
    467         sb.append(" ");
    468         sb.append(mcc);
    469         sb.append("mcc");
    470         sb.append(mnc);
    471         sb.append("mnc");
    472         if (locale != null) {
    473             sb.append(" ");
    474             sb.append(locale);
    475         } else {
    476             sb.append(" (no locale)");
    477         }
    478         switch (layoutDirection) {
    479             case View.LAYOUT_DIRECTION_LTR: /* ltr not interesting */ break;
    480             case View.LAYOUT_DIRECTION_RTL: sb.append(" rtl"); break;
    481             default: sb.append(" layoutDir="); sb.append(layoutDirection); break;
    482         }
    483         if (smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
    484             sb.append(" sw"); sb.append(smallestScreenWidthDp); sb.append("dp");
    485         } else {
    486             sb.append(" ?swdp");
    487         }
    488         if (screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
    489             sb.append(" w"); sb.append(screenWidthDp); sb.append("dp");
    490         } else {
    491             sb.append(" ?wdp");
    492         }
    493         if (screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
    494             sb.append(" h"); sb.append(screenHeightDp); sb.append("dp");
    495         } else {
    496             sb.append(" ?hdp");
    497         }
    498         switch ((screenLayout&SCREENLAYOUT_SIZE_MASK)) {
    499             case SCREENLAYOUT_SIZE_UNDEFINED: sb.append(" ?lsize"); break;
    500             case SCREENLAYOUT_SIZE_SMALL: sb.append(" smll"); break;
    501             case SCREENLAYOUT_SIZE_NORMAL: sb.append(" nrml"); break;
    502             case SCREENLAYOUT_SIZE_LARGE: sb.append(" lrg"); break;
    503             case SCREENLAYOUT_SIZE_XLARGE: sb.append(" xlrg"); break;
    504             default: sb.append(" layoutSize=");
    505                     sb.append(screenLayout&SCREENLAYOUT_SIZE_MASK); break;
    506         }
    507         switch ((screenLayout&SCREENLAYOUT_LONG_MASK)) {
    508             case SCREENLAYOUT_LONG_UNDEFINED: sb.append(" ?long"); break;
    509             case SCREENLAYOUT_LONG_NO: /* not-long is not interesting to print */ break;
    510             case SCREENLAYOUT_LONG_YES: sb.append(" long"); break;
    511             default: sb.append(" layoutLong=");
    512                     sb.append(screenLayout&SCREENLAYOUT_LONG_MASK); break;
    513         }
    514         switch (orientation) {
    515             case ORIENTATION_UNDEFINED: sb.append(" ?orien"); break;
    516             case ORIENTATION_LANDSCAPE: sb.append(" land"); break;
    517             case ORIENTATION_PORTRAIT: sb.append(" port"); break;
    518             default: sb.append(" orien="); sb.append(orientation); break;
    519         }
    520         switch ((uiMode&UI_MODE_TYPE_MASK)) {
    521             case UI_MODE_TYPE_UNDEFINED: sb.append(" ?uimode"); break;
    522             case UI_MODE_TYPE_NORMAL: /* normal is not interesting to print */ break;
    523             case UI_MODE_TYPE_DESK: sb.append(" desk"); break;
    524             case UI_MODE_TYPE_CAR: sb.append(" car"); break;
    525             case UI_MODE_TYPE_TELEVISION: sb.append(" television"); break;
    526             case UI_MODE_TYPE_APPLIANCE: sb.append(" appliance"); break;
    527             default: sb.append(" uimode="); sb.append(uiMode&UI_MODE_TYPE_MASK); break;
    528         }
    529         switch ((uiMode&UI_MODE_NIGHT_MASK)) {
    530             case UI_MODE_NIGHT_UNDEFINED: sb.append(" ?night"); break;
    531             case UI_MODE_NIGHT_NO: /* not-night is not interesting to print */ break;
    532             case UI_MODE_NIGHT_YES: sb.append(" night"); break;
    533             default: sb.append(" night="); sb.append(uiMode&UI_MODE_NIGHT_MASK); break;
    534         }
    535         switch (touchscreen) {
    536             case TOUCHSCREEN_UNDEFINED: sb.append(" ?touch"); break;
    537             case TOUCHSCREEN_NOTOUCH: sb.append(" -touch"); break;
    538             case TOUCHSCREEN_STYLUS: sb.append(" stylus"); break;
    539             case TOUCHSCREEN_FINGER: sb.append(" finger"); break;
    540             default: sb.append(" touch="); sb.append(touchscreen); break;
    541         }
    542         switch (keyboard) {
    543             case KEYBOARD_UNDEFINED: sb.append(" ?keyb"); break;
    544             case KEYBOARD_NOKEYS: sb.append(" -keyb"); break;
    545             case KEYBOARD_QWERTY: sb.append(" qwerty"); break;
    546             case KEYBOARD_12KEY: sb.append(" 12key"); break;
    547             default: sb.append(" keys="); sb.append(keyboard); break;
    548         }
    549         switch (keyboardHidden) {
    550             case KEYBOARDHIDDEN_UNDEFINED: sb.append("/?"); break;
    551             case KEYBOARDHIDDEN_NO: sb.append("/v"); break;
    552             case KEYBOARDHIDDEN_YES: sb.append("/h"); break;
    553             case KEYBOARDHIDDEN_SOFT: sb.append("/s"); break;
    554             default: sb.append("/"); sb.append(keyboardHidden); break;
    555         }
    556         switch (hardKeyboardHidden) {
    557             case HARDKEYBOARDHIDDEN_UNDEFINED: sb.append("/?"); break;
    558             case HARDKEYBOARDHIDDEN_NO: sb.append("/v"); break;
    559             case HARDKEYBOARDHIDDEN_YES: sb.append("/h"); break;
    560             default: sb.append("/"); sb.append(hardKeyboardHidden); break;
    561         }
    562         switch (navigation) {
    563             case NAVIGATION_UNDEFINED: sb.append(" ?nav"); break;
    564             case NAVIGATION_NONAV: sb.append(" -nav"); break;
    565             case NAVIGATION_DPAD: sb.append(" dpad"); break;
    566             case NAVIGATION_TRACKBALL: sb.append(" tball"); break;
    567             case NAVIGATION_WHEEL: sb.append(" wheel"); break;
    568             default: sb.append(" nav="); sb.append(navigation); break;
    569         }
    570         switch (navigationHidden) {
    571             case NAVIGATIONHIDDEN_UNDEFINED: sb.append("/?"); break;
    572             case NAVIGATIONHIDDEN_NO: sb.append("/v"); break;
    573             case NAVIGATIONHIDDEN_YES: sb.append("/h"); break;
    574             default: sb.append("/"); sb.append(navigationHidden); break;
    575         }
    576         if (seq != 0) {
    577             sb.append(" s.");
    578             sb.append(seq);
    579         }
    580         sb.append('}');
    581         return sb.toString();
    582     }
    583 
    584     /**
    585      * Set this object to the system defaults.
    586      */
    587     public void setToDefaults() {
    588         fontScale = 1;
    589         mcc = mnc = 0;
    590         locale = null;
    591         userSetLocale = false;
    592         touchscreen = TOUCHSCREEN_UNDEFINED;
    593         keyboard = KEYBOARD_UNDEFINED;
    594         keyboardHidden = KEYBOARDHIDDEN_UNDEFINED;
    595         hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED;
    596         navigation = NAVIGATION_UNDEFINED;
    597         navigationHidden = NAVIGATIONHIDDEN_UNDEFINED;
    598         orientation = ORIENTATION_UNDEFINED;
    599         screenLayout = SCREENLAYOUT_SIZE_UNDEFINED;
    600         uiMode = UI_MODE_TYPE_UNDEFINED;
    601         screenWidthDp = compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED;
    602         screenHeightDp = compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED;
    603         smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
    604         layoutDirection = View.LAYOUT_DIRECTION_LTR;
    605         seq = 0;
    606     }
    607 
    608     /** {@hide} */
    609     @Deprecated public void makeDefault() {
    610         setToDefaults();
    611     }
    612 
    613     /**
    614      * Copy the fields from delta into this Configuration object, keeping
    615      * track of which ones have changed.  Any undefined fields in
    616      * <var>delta</var> are ignored and not copied in to the current
    617      * Configuration.
    618      * @return Returns a bit mask of the changed fields, as per
    619      * {@link #diff}.
    620      */
    621     public int updateFrom(Configuration delta) {
    622         int changed = 0;
    623         if (delta.fontScale > 0 && fontScale != delta.fontScale) {
    624             changed |= ActivityInfo.CONFIG_FONT_SCALE;
    625             fontScale = delta.fontScale;
    626         }
    627         if (delta.mcc != 0 && mcc != delta.mcc) {
    628             changed |= ActivityInfo.CONFIG_MCC;
    629             mcc = delta.mcc;
    630         }
    631         if (delta.mnc != 0 && mnc != delta.mnc) {
    632             changed |= ActivityInfo.CONFIG_MNC;
    633             mnc = delta.mnc;
    634         }
    635         if (delta.locale != null
    636                 && (locale == null || !locale.equals(delta.locale))) {
    637             changed |= ActivityInfo.CONFIG_LOCALE;
    638             locale = delta.locale != null
    639                     ? (Locale) delta.locale.clone() : null;
    640             layoutDirection = LocaleUtil.getLayoutDirectionFromLocale(locale);
    641         }
    642         if (delta.userSetLocale && (!userSetLocale || ((changed & ActivityInfo.CONFIG_LOCALE) != 0)))
    643         {
    644             userSetLocale = true;
    645             changed |= ActivityInfo.CONFIG_LOCALE;
    646         }
    647         if (delta.touchscreen != TOUCHSCREEN_UNDEFINED
    648                 && touchscreen != delta.touchscreen) {
    649             changed |= ActivityInfo.CONFIG_TOUCHSCREEN;
    650             touchscreen = delta.touchscreen;
    651         }
    652         if (delta.keyboard != KEYBOARD_UNDEFINED
    653                 && keyboard != delta.keyboard) {
    654             changed |= ActivityInfo.CONFIG_KEYBOARD;
    655             keyboard = delta.keyboard;
    656         }
    657         if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED
    658                 && keyboardHidden != delta.keyboardHidden) {
    659             changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
    660             keyboardHidden = delta.keyboardHidden;
    661         }
    662         if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED
    663                 && hardKeyboardHidden != delta.hardKeyboardHidden) {
    664             changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
    665             hardKeyboardHidden = delta.hardKeyboardHidden;
    666         }
    667         if (delta.navigation != NAVIGATION_UNDEFINED
    668                 && navigation != delta.navigation) {
    669             changed |= ActivityInfo.CONFIG_NAVIGATION;
    670             navigation = delta.navigation;
    671         }
    672         if (delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED
    673                 && navigationHidden != delta.navigationHidden) {
    674             changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
    675             navigationHidden = delta.navigationHidden;
    676         }
    677         if (delta.orientation != ORIENTATION_UNDEFINED
    678                 && orientation != delta.orientation) {
    679             changed |= ActivityInfo.CONFIG_ORIENTATION;
    680             orientation = delta.orientation;
    681         }
    682         if (delta.screenLayout != SCREENLAYOUT_SIZE_UNDEFINED
    683                 && screenLayout != delta.screenLayout) {
    684             changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
    685             screenLayout = delta.screenLayout;
    686         }
    687         if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)
    688                 && uiMode != delta.uiMode) {
    689             changed |= ActivityInfo.CONFIG_UI_MODE;
    690             if ((delta.uiMode&UI_MODE_TYPE_MASK) != UI_MODE_TYPE_UNDEFINED) {
    691                 uiMode = (uiMode&~UI_MODE_TYPE_MASK)
    692                         | (delta.uiMode&UI_MODE_TYPE_MASK);
    693             }
    694             if ((delta.uiMode&UI_MODE_NIGHT_MASK) != UI_MODE_NIGHT_UNDEFINED) {
    695                 uiMode = (uiMode&~UI_MODE_NIGHT_MASK)
    696                         | (delta.uiMode&UI_MODE_NIGHT_MASK);
    697             }
    698         }
    699         if (delta.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED
    700                 && screenWidthDp != delta.screenWidthDp) {
    701             changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
    702             screenWidthDp = delta.screenWidthDp;
    703         }
    704         if (delta.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED
    705                 && screenHeightDp != delta.screenHeightDp) {
    706             changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
    707             screenHeightDp = delta.screenHeightDp;
    708         }
    709         if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
    710             smallestScreenWidthDp = delta.smallestScreenWidthDp;
    711         }
    712         if (delta.compatScreenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
    713             compatScreenWidthDp = delta.compatScreenWidthDp;
    714         }
    715         if (delta.compatScreenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
    716             compatScreenHeightDp = delta.compatScreenHeightDp;
    717         }
    718         if (delta.compatSmallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
    719             compatSmallestScreenWidthDp = delta.compatSmallestScreenWidthDp;
    720         }
    721 
    722         if (delta.seq != 0) {
    723             seq = delta.seq;
    724         }
    725 
    726         return changed;
    727     }
    728 
    729     /**
    730      * Return a bit mask of the differences between this Configuration
    731      * object and the given one.  Does not change the values of either.  Any
    732      * undefined fields in <var>delta</var> are ignored.
    733      * @return Returns a bit mask indicating which configuration
    734      * values has changed, containing any combination of
    735      * {@link android.content.pm.ActivityInfo#CONFIG_FONT_SCALE
    736      * PackageManager.ActivityInfo.CONFIG_FONT_SCALE},
    737      * {@link android.content.pm.ActivityInfo#CONFIG_MCC
    738      * PackageManager.ActivityInfo.CONFIG_MCC},
    739      * {@link android.content.pm.ActivityInfo#CONFIG_MNC
    740      * PackageManager.ActivityInfo.CONFIG_MNC},
    741      * {@link android.content.pm.ActivityInfo#CONFIG_LOCALE
    742      * PackageManager.ActivityInfo.CONFIG_LOCALE},
    743      * {@link android.content.pm.ActivityInfo#CONFIG_TOUCHSCREEN
    744      * PackageManager.ActivityInfo.CONFIG_TOUCHSCREEN},
    745      * {@link android.content.pm.ActivityInfo#CONFIG_KEYBOARD
    746      * PackageManager.ActivityInfo.CONFIG_KEYBOARD},
    747      * {@link android.content.pm.ActivityInfo#CONFIG_NAVIGATION
    748      * PackageManager.ActivityInfo.CONFIG_NAVIGATION},
    749      * {@link android.content.pm.ActivityInfo#CONFIG_ORIENTATION
    750      * PackageManager.ActivityInfo.CONFIG_ORIENTATION},
    751      * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_LAYOUT
    752      * PackageManager.ActivityInfo.CONFIG_SCREEN_LAYOUT}, or
    753      * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_SIZE
    754      * PackageManager.ActivityInfo.CONFIG_SCREEN_SIZE}, or
    755      * {@link android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE
    756      * PackageManager.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE}.
    757      */
    758     public int diff(Configuration delta) {
    759         int changed = 0;
    760         if (delta.fontScale > 0 && fontScale != delta.fontScale) {
    761             changed |= ActivityInfo.CONFIG_FONT_SCALE;
    762         }
    763         if (delta.mcc != 0 && mcc != delta.mcc) {
    764             changed |= ActivityInfo.CONFIG_MCC;
    765         }
    766         if (delta.mnc != 0 && mnc != delta.mnc) {
    767             changed |= ActivityInfo.CONFIG_MNC;
    768         }
    769         if (delta.locale != null
    770                 && (locale == null || !locale.equals(delta.locale))) {
    771             changed |= ActivityInfo.CONFIG_LOCALE;
    772         }
    773         if (delta.touchscreen != TOUCHSCREEN_UNDEFINED
    774                 && touchscreen != delta.touchscreen) {
    775             changed |= ActivityInfo.CONFIG_TOUCHSCREEN;
    776         }
    777         if (delta.keyboard != KEYBOARD_UNDEFINED
    778                 && keyboard != delta.keyboard) {
    779             changed |= ActivityInfo.CONFIG_KEYBOARD;
    780         }
    781         if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED
    782                 && keyboardHidden != delta.keyboardHidden) {
    783             changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
    784         }
    785         if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED
    786                 && hardKeyboardHidden != delta.hardKeyboardHidden) {
    787             changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
    788         }
    789         if (delta.navigation != NAVIGATION_UNDEFINED
    790                 && navigation != delta.navigation) {
    791             changed |= ActivityInfo.CONFIG_NAVIGATION;
    792         }
    793         if (delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED
    794                 && navigationHidden != delta.navigationHidden) {
    795             changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
    796         }
    797         if (delta.orientation != ORIENTATION_UNDEFINED
    798                 && orientation != delta.orientation) {
    799             changed |= ActivityInfo.CONFIG_ORIENTATION;
    800         }
    801         if (delta.screenLayout != SCREENLAYOUT_SIZE_UNDEFINED
    802                 && screenLayout != delta.screenLayout) {
    803             changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
    804         }
    805         if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)
    806                 && uiMode != delta.uiMode) {
    807             changed |= ActivityInfo.CONFIG_UI_MODE;
    808         }
    809         if (delta.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED
    810                 && screenWidthDp != delta.screenWidthDp) {
    811             changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
    812         }
    813         if (delta.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED
    814                 && screenHeightDp != delta.screenHeightDp) {
    815             changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
    816         }
    817         if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
    818                 && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
    819             changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
    820         }
    821 
    822         return changed;
    823     }
    824 
    825     /**
    826      * Determine if a new resource needs to be loaded from the bit set of
    827      * configuration changes returned by {@link #updateFrom(Configuration)}.
    828      *
    829      * @param configChanges The mask of changes configurations as returned by
    830      * {@link #updateFrom(Configuration)}.
    831      * @param interestingChanges The configuration changes that the resource
    832      * can handled, as given in {@link android.util.TypedValue#changingConfigurations}.
    833      *
    834      * @return Return true if the resource needs to be loaded, else false.
    835      */
    836     public static boolean needNewResources(int configChanges, int interestingChanges) {
    837         return (configChanges & (interestingChanges|ActivityInfo.CONFIG_FONT_SCALE)) != 0;
    838     }
    839 
    840     /**
    841      * @hide Return true if the sequence of 'other' is better than this.  Assumes
    842      * that 'this' is your current sequence and 'other' is a new one you have
    843      * received some how and want to compare with what you have.
    844      */
    845     public boolean isOtherSeqNewer(Configuration other) {
    846         if (other == null) {
    847             // Sanity check.
    848             return false;
    849         }
    850         if (other.seq == 0) {
    851             // If the other sequence is not specified, then we must assume
    852             // it is newer since we don't know any better.
    853             return true;
    854         }
    855         if (seq == 0) {
    856             // If this sequence is not specified, then we also consider the
    857             // other is better.  Yes we have a preference for other.  Sue us.
    858             return true;
    859         }
    860         int diff = other.seq - seq;
    861         if (diff > 0x10000) {
    862             // If there has been a sufficiently large jump, assume the
    863             // sequence has wrapped around.
    864             return false;
    865         }
    866         return diff > 0;
    867     }
    868 
    869     /**
    870      * Parcelable methods
    871      */
    872     public int describeContents() {
    873         return 0;
    874     }
    875 
    876     public void writeToParcel(Parcel dest, int flags) {
    877         dest.writeFloat(fontScale);
    878         dest.writeInt(mcc);
    879         dest.writeInt(mnc);
    880         if (locale == null) {
    881             dest.writeInt(0);
    882         } else {
    883             dest.writeInt(1);
    884             dest.writeString(locale.getLanguage());
    885             dest.writeString(locale.getCountry());
    886             dest.writeString(locale.getVariant());
    887         }
    888         if(userSetLocale) {
    889             dest.writeInt(1);
    890         } else {
    891             dest.writeInt(0);
    892         }
    893         dest.writeInt(touchscreen);
    894         dest.writeInt(keyboard);
    895         dest.writeInt(keyboardHidden);
    896         dest.writeInt(hardKeyboardHidden);
    897         dest.writeInt(navigation);
    898         dest.writeInt(navigationHidden);
    899         dest.writeInt(orientation);
    900         dest.writeInt(screenLayout);
    901         dest.writeInt(uiMode);
    902         dest.writeInt(screenWidthDp);
    903         dest.writeInt(screenHeightDp);
    904         dest.writeInt(smallestScreenWidthDp);
    905         dest.writeInt(compatScreenWidthDp);
    906         dest.writeInt(compatScreenHeightDp);
    907         dest.writeInt(compatSmallestScreenWidthDp);
    908         dest.writeInt(layoutDirection);
    909         dest.writeInt(seq);
    910     }
    911 
    912     public void readFromParcel(Parcel source) {
    913         fontScale = source.readFloat();
    914         mcc = source.readInt();
    915         mnc = source.readInt();
    916         if (source.readInt() != 0) {
    917             locale = new Locale(source.readString(), source.readString(),
    918                     source.readString());
    919         }
    920         userSetLocale = (source.readInt()==1);
    921         touchscreen = source.readInt();
    922         keyboard = source.readInt();
    923         keyboardHidden = source.readInt();
    924         hardKeyboardHidden = source.readInt();
    925         navigation = source.readInt();
    926         navigationHidden = source.readInt();
    927         orientation = source.readInt();
    928         screenLayout = source.readInt();
    929         uiMode = source.readInt();
    930         screenWidthDp = source.readInt();
    931         screenHeightDp = source.readInt();
    932         smallestScreenWidthDp = source.readInt();
    933         compatScreenWidthDp = source.readInt();
    934         compatScreenHeightDp = source.readInt();
    935         compatSmallestScreenWidthDp = source.readInt();
    936         layoutDirection = source.readInt();
    937         seq = source.readInt();
    938     }
    939 
    940     public static final Parcelable.Creator<Configuration> CREATOR
    941             = new Parcelable.Creator<Configuration>() {
    942         public Configuration createFromParcel(Parcel source) {
    943             return new Configuration(source);
    944         }
    945 
    946         public Configuration[] newArray(int size) {
    947             return new Configuration[size];
    948         }
    949     };
    950 
    951     /**
    952      * Construct this Configuration object, reading from the Parcel.
    953      */
    954     private Configuration(Parcel source) {
    955         readFromParcel(source);
    956     }
    957 
    958     public int compareTo(Configuration that) {
    959         int n;
    960         float a = this.fontScale;
    961         float b = that.fontScale;
    962         if (a < b) return -1;
    963         if (a > b) return 1;
    964         n = this.mcc - that.mcc;
    965         if (n != 0) return n;
    966         n = this.mnc - that.mnc;
    967         if (n != 0) return n;
    968         if (this.locale == null) {
    969             if (that.locale != null) return 1;
    970         } else if (that.locale == null) {
    971             return -1;
    972         } else {
    973             n = this.locale.getLanguage().compareTo(that.locale.getLanguage());
    974             if (n != 0) return n;
    975             n = this.locale.getCountry().compareTo(that.locale.getCountry());
    976             if (n != 0) return n;
    977             n = this.locale.getVariant().compareTo(that.locale.getVariant());
    978             if (n != 0) return n;
    979         }
    980         n = this.touchscreen - that.touchscreen;
    981         if (n != 0) return n;
    982         n = this.keyboard - that.keyboard;
    983         if (n != 0) return n;
    984         n = this.keyboardHidden - that.keyboardHidden;
    985         if (n != 0) return n;
    986         n = this.hardKeyboardHidden - that.hardKeyboardHidden;
    987         if (n != 0) return n;
    988         n = this.navigation - that.navigation;
    989         if (n != 0) return n;
    990         n = this.navigationHidden - that.navigationHidden;
    991         if (n != 0) return n;
    992         n = this.orientation - that.orientation;
    993         if (n != 0) return n;
    994         n = this.screenLayout - that.screenLayout;
    995         if (n != 0) return n;
    996         n = this.uiMode - that.uiMode;
    997         if (n != 0) return n;
    998         n = this.screenWidthDp - that.screenWidthDp;
    999         if (n != 0) return n;
   1000         n = this.screenHeightDp - that.screenHeightDp;
   1001         if (n != 0) return n;
   1002         n = this.smallestScreenWidthDp - that.smallestScreenWidthDp;
   1003         //if (n != 0) return n;
   1004         return n;
   1005     }
   1006 
   1007     public boolean equals(Configuration that) {
   1008         if (that == null) return false;
   1009         if (that == this) return true;
   1010         return this.compareTo(that) == 0;
   1011     }
   1012 
   1013     public boolean equals(Object that) {
   1014         try {
   1015             return equals((Configuration)that);
   1016         } catch (ClassCastException e) {
   1017         }
   1018         return false;
   1019     }
   1020 
   1021     public int hashCode() {
   1022         int result = 17;
   1023         result = 31 * result + Float.floatToIntBits(fontScale);
   1024         result = 31 * result + mcc;
   1025         result = 31 * result + mnc;
   1026         result = 31 * result + (locale != null ? locale.hashCode() : 0);
   1027         result = 31 * result + touchscreen;
   1028         result = 31 * result + keyboard;
   1029         result = 31 * result + keyboardHidden;
   1030         result = 31 * result + hardKeyboardHidden;
   1031         result = 31 * result + navigation;
   1032         result = 31 * result + navigationHidden;
   1033         result = 31 * result + orientation;
   1034         result = 31 * result + screenLayout;
   1035         result = 31 * result + uiMode;
   1036         result = 31 * result + screenWidthDp;
   1037         result = 31 * result + screenHeightDp;
   1038         result = 31 * result + smallestScreenWidthDp;
   1039         return result;
   1040     }
   1041 }
   1042