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 static android.content.ConfigurationProto.COLOR_MODE; 20 import static android.content.ConfigurationProto.DENSITY_DPI; 21 import static android.content.ConfigurationProto.FONT_SCALE; 22 import static android.content.ConfigurationProto.FONT_WEIGHT_ADJUSTMENT; 23 import static android.content.ConfigurationProto.GRAMMATICAL_GENDER; 24 import static android.content.ConfigurationProto.HARD_KEYBOARD_HIDDEN; 25 import static android.content.ConfigurationProto.KEYBOARD; 26 import static android.content.ConfigurationProto.KEYBOARD_HIDDEN; 27 import static android.content.ConfigurationProto.LOCALES; 28 import static android.content.ConfigurationProto.LOCALE_LIST; 29 import static android.content.ConfigurationProto.MCC; 30 import static android.content.ConfigurationProto.MNC; 31 import static android.content.ConfigurationProto.NAVIGATION; 32 import static android.content.ConfigurationProto.NAVIGATION_HIDDEN; 33 import static android.content.ConfigurationProto.ORIENTATION; 34 import static android.content.ConfigurationProto.SCREEN_HEIGHT_DP; 35 import static android.content.ConfigurationProto.SCREEN_LAYOUT; 36 import static android.content.ConfigurationProto.SCREEN_WIDTH_DP; 37 import static android.content.ConfigurationProto.SMALLEST_SCREEN_WIDTH_DP; 38 import static android.content.ConfigurationProto.TOUCHSCREEN; 39 import static android.content.ConfigurationProto.UI_MODE; 40 import static android.content.ConfigurationProto.WINDOW_CONFIGURATION; 41 import static android.content.ResourcesConfigurationProto.CONFIGURATION; 42 import static android.content.ResourcesConfigurationProto.SCREEN_HEIGHT_PX; 43 import static android.content.ResourcesConfigurationProto.SCREEN_WIDTH_PX; 44 import static android.content.ResourcesConfigurationProto.SDK_VERSION; 45 46 import android.annotation.IntDef; 47 import android.annotation.NonNull; 48 import android.annotation.Nullable; 49 import android.annotation.TestApi; 50 import android.app.GrammaticalInflectionManager; 51 import android.app.WindowConfiguration; 52 import android.compat.annotation.UnsupportedAppUsage; 53 import android.content.LocaleProto; 54 import android.content.pm.ActivityInfo; 55 import android.content.pm.ActivityInfo.Config; 56 import android.graphics.Typeface; 57 import android.os.Build; 58 import android.os.LocaleList; 59 import android.os.Parcel; 60 import android.os.Parcelable; 61 import android.ravenwood.annotation.RavenwoodKeepWholeClass; 62 import android.text.TextUtils; 63 import android.util.DisplayMetrics; 64 import android.util.Slog; 65 import android.util.proto.ProtoInputStream; 66 import android.util.proto.ProtoOutputStream; 67 import android.util.proto.WireTypeMismatchException; 68 import android.view.View; 69 70 import com.android.internal.util.XmlUtils; 71 72 import org.xmlpull.v1.XmlPullParser; 73 import org.xmlpull.v1.XmlPullParserException; 74 75 import java.io.IOException; 76 import java.lang.annotation.Retention; 77 import java.lang.annotation.RetentionPolicy; 78 import java.util.ArrayList; 79 import java.util.IllformedLocaleException; 80 import java.util.List; 81 import java.util.Locale; 82 83 /** 84 * This class describes all device configuration information that can 85 * impact the resources the application retrieves. This includes both 86 * user-specified configuration options (locale list and scaling) as well 87 * as device configurations (such as input modes, screen size and screen orientation). 88 * <p>You can acquire this object from {@link Resources}, using {@link 89 * Resources#getConfiguration}. Thus, from an activity, you can get it by chaining the request 90 * with {@link android.app.Activity#getResources}:</p> 91 * <pre>Configuration config = getResources().getConfiguration();</pre> 92 */ 93 @RavenwoodKeepWholeClass 94 public final class Configuration implements Parcelable, Comparable<Configuration> { 95 /** @hide */ 96 public static final Configuration EMPTY = new Configuration(); 97 98 private static final String TAG = "Configuration"; 99 100 /** 101 * Current user preference for the scaling factor for fonts, relative 102 * to the base density scaling. 103 * 104 * <p>Note: Please do not use this to hardcode font size equations. The equation for font 105 * scaling is now non-linear; this coefficient is no longer used as a direct multiplier to 106 * determine font size. It exists for informational purposes only. 107 * 108 * <p>Please use {@link android.util.TypedValue#applyDimension(int, float, DisplayMetrics)} or 109 * {@link android.util.TypedValue#deriveDimension(int, float, DisplayMetrics)} to convert 110 * between scaled font size dimensions and pixels. 111 */ 112 public float fontScale; 113 114 /** 115 * IMSI MCC (Mobile Country Code), corresponding to 116 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#MccQualifier">mcc</a> 117 * resource qualifier. 0 if undefined. 118 */ 119 public int mcc; 120 121 /** 122 * IMSI MNC (Mobile Network Code), corresponding to 123 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#MccQualifier">mnc</a> 124 * resource qualifier. 0 if undefined. Note that the actual MNC may be 0; in order to check 125 * for this use the {@link #MNC_ZERO} symbol. 126 */ 127 public int mnc; 128 129 /** 130 * Constant used to to represent MNC (Mobile Network Code) zero. 131 * 0 cannot be used, since it is used to represent an undefined MNC. 132 */ 133 public static final int MNC_ZERO = 0xffff; 134 135 /** 136 * Current user preference for the locale, corresponding to 137 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#LocaleQualifier">locale</a> 138 * resource qualifier. 139 * 140 * @deprecated Do not set or read this directly. Use {@link #getLocales()} and 141 * {@link #setLocales(LocaleList)}. If only the primary locale is needed, 142 * <code>getLocales().get(0)</code> is now the preferred accessor. 143 */ 144 @Deprecated public Locale locale; 145 146 private LocaleList mLocaleList; 147 148 /** 149 * Locale should persist on setting. This is hidden because it is really 150 * questionable whether this is the right way to expose the functionality. 151 * @hide 152 */ 153 @UnsupportedAppUsage 154 public boolean userSetLocale; 155 156 /** 157 * Current user preference for the grammatical gender. 158 */ 159 private int mGrammaticalGender; 160 161 /** @hide */ 162 @IntDef(prefix = { "GRAMMATICAL_GENDER_" }, value = { 163 GRAMMATICAL_GENDER_NOT_SPECIFIED, 164 GRAMMATICAL_GENDER_NEUTRAL, 165 GRAMMATICAL_GENDER_FEMININE, 166 GRAMMATICAL_GENDER_MASCULINE, 167 }) 168 @Retention(RetentionPolicy.SOURCE) 169 public @interface GrammaticalGender {} 170 171 /** 172 * Constant for grammatical gender: to indicate that the grammatical gender is undefined. 173 * Only for internal usage. 174 * @hide 175 */ 176 public static final int GRAMMATICAL_GENDER_UNDEFINED = -1; 177 178 /** 179 * Constant for grammatical gender: to indicate the user has not specified the terms 180 * of address for the application. 181 */ 182 public static final int GRAMMATICAL_GENDER_NOT_SPECIFIED = 0; 183 184 /** 185 * Constant for grammatical gender: to indicate the terms of address the user 186 * preferred in an application is neuter. 187 */ 188 public static final int GRAMMATICAL_GENDER_NEUTRAL = 1; 189 190 /** 191 * Constant for grammatical gender: to indicate the terms of address the user 192 * preferred in an application is feminine. 193 */ 194 public static final int GRAMMATICAL_GENDER_FEMININE = 2; 195 196 /** 197 * Constant for grammatical gender: to indicate the terms of address the user 198 * preferred in an application is masculine. 199 */ 200 public static final int GRAMMATICAL_GENDER_MASCULINE = 3; 201 202 /** Constant for {@link #colorMode}: bits that encode whether the screen is wide gamut. */ 203 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_MASK = 0x3; 204 /** 205 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} value 206 * indicating that it is unknown whether or not the screen is wide gamut. 207 */ 208 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED = 0x0; 209 /** 210 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} value 211 * indicating that the screen is not wide gamut. 212 * <p>Corresponds to the <code>-nowidecg</code> resource qualifier.</p> 213 */ 214 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_NO = 0x1; 215 /** 216 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} value 217 * indicating that the screen is wide gamut. 218 * <p>Corresponds to the <code>-widecg</code> resource qualifier.</p> 219 */ 220 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_YES = 0x2; 221 222 /** Constant for {@link #colorMode}: bits that encode the dynamic range of the screen. */ 223 public static final int COLOR_MODE_HDR_MASK = 0xc; 224 /** Constant for {@link #colorMode}: bits shift to get the screen dynamic range. */ 225 public static final int COLOR_MODE_HDR_SHIFT = 2; 226 /** 227 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_HDR_MASK} value 228 * indicating that it is unknown whether or not the screen is HDR. 229 */ 230 public static final int COLOR_MODE_HDR_UNDEFINED = 0x0; 231 /** 232 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_HDR_MASK} value 233 * indicating that the screen is not HDR (low/standard dynamic range). 234 * <p>Corresponds to the <code>-lowdr</code> resource qualifier.</p> 235 */ 236 public static final int COLOR_MODE_HDR_NO = 0x1 << COLOR_MODE_HDR_SHIFT; 237 /** 238 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_HDR_MASK} value 239 * indicating that the screen is HDR (dynamic range). 240 * <p>Corresponds to the <code>-highdr</code> resource qualifier.</p> 241 */ 242 public static final int COLOR_MODE_HDR_YES = 0x2 << COLOR_MODE_HDR_SHIFT; 243 244 /** Constant for {@link #colorMode}: a value indicating that the color mode is undefined */ 245 @SuppressWarnings("PointlessBitwiseExpression") 246 public static final int COLOR_MODE_UNDEFINED = COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED | 247 COLOR_MODE_HDR_UNDEFINED; 248 249 /** 250 * Bit mask of color capabilities of the screen. Currently there are two fields: 251 * <p>The {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} bits define the color gamut of 252 * the screen. They may be one of 253 * {@link #COLOR_MODE_WIDE_COLOR_GAMUT_NO} or {@link #COLOR_MODE_WIDE_COLOR_GAMUT_YES}.</p> 254 * 255 * <p>The {@link #COLOR_MODE_HDR_MASK} defines the dynamic range of the screen. They may be 256 * one of {@link #COLOR_MODE_HDR_NO} or {@link #COLOR_MODE_HDR_YES}.</p> 257 * 258 * <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting 259 * Multiple Screens</a> for more information.</p> 260 */ 261 public int colorMode; 262 263 /** Constant for {@link #screenLayout}: bits that encode the size. */ 264 public static final int SCREENLAYOUT_SIZE_MASK = 0x0f; 265 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK} 266 * value indicating that no size has been set. */ 267 public static final int SCREENLAYOUT_SIZE_UNDEFINED = 0x00; 268 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK} 269 * value indicating the screen is at least approximately 320x426 dp units, 270 * corresponds to the 271 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">small</a> 272 * resource qualifier. 273 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting 274 * Multiple Screens</a> for more information. */ 275 public static final int SCREENLAYOUT_SIZE_SMALL = 0x01; 276 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK} 277 * value indicating the screen is at least approximately 320x470 dp units, 278 * corresponds to the 279 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">normal</a> 280 * resource qualifier. 281 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting 282 * Multiple Screens</a> for more information. */ 283 public static final int SCREENLAYOUT_SIZE_NORMAL = 0x02; 284 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK} 285 * value indicating the screen is at least approximately 480x640 dp units, 286 * corresponds to the 287 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">large</a> 288 * resource qualifier. 289 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting 290 * Multiple Screens</a> for more information. */ 291 public static final int SCREENLAYOUT_SIZE_LARGE = 0x03; 292 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK} 293 * value indicating the screen is at least approximately 720x960 dp units, 294 * corresponds to the 295 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">xlarge</a> 296 * resource qualifier. 297 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting 298 * Multiple Screens</a> for more information.*/ 299 public static final int SCREENLAYOUT_SIZE_XLARGE = 0x04; 300 301 /** Constant for {@link #screenLayout}: bits that encode the aspect ratio. */ 302 public static final int SCREENLAYOUT_LONG_MASK = 0x30; 303 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK} 304 * value indicating that no size has been set. */ 305 public static final int SCREENLAYOUT_LONG_UNDEFINED = 0x00; 306 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK} 307 * value that corresponds to the 308 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenAspectQualifier">notlong</a> 309 * resource qualifier. */ 310 public static final int SCREENLAYOUT_LONG_NO = 0x10; 311 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK} 312 * value that corresponds to the 313 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenAspectQualifier">long</a> 314 * resource qualifier. */ 315 public static final int SCREENLAYOUT_LONG_YES = 0x20; 316 317 /** Constant for {@link #screenLayout}: bits that encode the layout direction. */ 318 public static final int SCREENLAYOUT_LAYOUTDIR_MASK = 0xC0; 319 /** Constant for {@link #screenLayout}: bits shift to get the layout direction. */ 320 public static final int SCREENLAYOUT_LAYOUTDIR_SHIFT = 6; 321 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK} 322 * value indicating that no layout dir has been set. */ 323 public static final int SCREENLAYOUT_LAYOUTDIR_UNDEFINED = 0x00; 324 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK} 325 * value indicating that a layout dir has been set to LTR. */ 326 public static final int SCREENLAYOUT_LAYOUTDIR_LTR = 0x01 << SCREENLAYOUT_LAYOUTDIR_SHIFT; 327 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK} 328 * value indicating that a layout dir has been set to RTL. */ 329 public static final int SCREENLAYOUT_LAYOUTDIR_RTL = 0x02 << SCREENLAYOUT_LAYOUTDIR_SHIFT; 330 331 /** Constant for {@link #screenLayout}: bits that encode roundness of the screen. */ 332 public static final int SCREENLAYOUT_ROUND_MASK = 0x300; 333 /** @hide Constant for {@link #screenLayout}: bit shift to get to screen roundness bits */ 334 public static final int SCREENLAYOUT_ROUND_SHIFT = 8; 335 /** 336 * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating 337 * that it is unknown whether or not the screen has a round shape. 338 */ 339 public static final int SCREENLAYOUT_ROUND_UNDEFINED = 0x00; 340 /** 341 * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating 342 * that the screen does not have a rounded shape. 343 */ 344 public static final int SCREENLAYOUT_ROUND_NO = 0x1 << SCREENLAYOUT_ROUND_SHIFT; 345 /** 346 * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating 347 * that the screen has a rounded shape. Corners may not be visible to the user; 348 * developers should pay special attention to the {@link android.view.WindowInsets} delivered 349 * to views for more information about ensuring content is not obscured. 350 * 351 * <p>Corresponds to the <code>-round</code> resource qualifier.</p> 352 */ 353 public static final int SCREENLAYOUT_ROUND_YES = 0x2 << SCREENLAYOUT_ROUND_SHIFT; 354 355 /** Constant for {@link #screenLayout}: a value indicating that screenLayout is undefined */ 356 public static final int SCREENLAYOUT_UNDEFINED = SCREENLAYOUT_SIZE_UNDEFINED | 357 SCREENLAYOUT_LONG_UNDEFINED | SCREENLAYOUT_LAYOUTDIR_UNDEFINED | 358 SCREENLAYOUT_ROUND_UNDEFINED; 359 360 /** 361 * Special flag we generate to indicate that the screen layout requires 362 * us to use a compatibility mode for apps that are not modern layout 363 * aware. 364 * @hide 365 */ 366 public static final int SCREENLAYOUT_COMPAT_NEEDED = 0x10000000; 367 368 /** 369 * Bit mask of overall layout of the screen. Currently there are four 370 * fields: 371 * <p>The {@link #SCREENLAYOUT_SIZE_MASK} bits define the overall size 372 * of the screen. They may be one of 373 * {@link #SCREENLAYOUT_SIZE_SMALL}, {@link #SCREENLAYOUT_SIZE_NORMAL}, 374 * {@link #SCREENLAYOUT_SIZE_LARGE}, or {@link #SCREENLAYOUT_SIZE_XLARGE}.</p> 375 * 376 * <p>The {@link #SCREENLAYOUT_LONG_MASK} defines whether the screen 377 * is wider/taller than normal. They may be one of 378 * {@link #SCREENLAYOUT_LONG_NO} or {@link #SCREENLAYOUT_LONG_YES}.</p> 379 * 380 * <p>The {@link #SCREENLAYOUT_LAYOUTDIR_MASK} defines whether the screen layout 381 * is either LTR or RTL. They may be one of 382 * {@link #SCREENLAYOUT_LAYOUTDIR_LTR} or {@link #SCREENLAYOUT_LAYOUTDIR_RTL}.</p> 383 * 384 * <p>The {@link #SCREENLAYOUT_ROUND_MASK} defines whether the screen has a rounded 385 * shape. They may be one of {@link #SCREENLAYOUT_ROUND_NO} or {@link #SCREENLAYOUT_ROUND_YES}. 386 * </p> 387 * 388 * <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting 389 * Multiple Screens</a> for more information.</p> 390 */ 391 public int screenLayout; 392 393 /** 394 * An undefined fontWeightAdjustment. 395 */ 396 public static final int FONT_WEIGHT_ADJUSTMENT_UNDEFINED = Integer.MAX_VALUE; 397 398 /** 399 * Adjustment in text font weight. Used to reflect the current user preference for increasing 400 * font weight. 401 * 402 * <p> If the text font weight is less than the minimum of 1, 1 will be used. If the font weight 403 * exceeds the maximum of 1000, 1000 will be used. 404 * 405 * @see android.graphics.Typeface#create(Typeface, int, boolean) 406 * @see android.graphics.fonts.FontStyle#FONT_WEIGHT_MIN 407 * @see android.graphics.fonts.FontStyle#FONT_WEIGHT_MAX 408 */ 409 public int fontWeightAdjustment; 410 411 /** 412 * Configuration relating to the windowing state of the object associated with this 413 * Configuration. Contents of this field are not intended to affect resources, but need to be 414 * communicated and propagated at the same time as the rest of Configuration. 415 * @hide 416 */ 417 @TestApi 418 public final WindowConfiguration windowConfiguration = new WindowConfiguration(); 419 420 /** @hide */ resetScreenLayout(int curLayout)421 static public int resetScreenLayout(int curLayout) { 422 return (curLayout&~(SCREENLAYOUT_LONG_MASK | SCREENLAYOUT_SIZE_MASK 423 | SCREENLAYOUT_COMPAT_NEEDED)) 424 | (SCREENLAYOUT_LONG_YES | SCREENLAYOUT_SIZE_XLARGE); 425 } 426 427 /** @hide */ reduceScreenLayout(int curLayout, int longSizeDp, int shortSizeDp)428 static public int reduceScreenLayout(int curLayout, int longSizeDp, int shortSizeDp) { 429 int screenLayoutSize; 430 boolean screenLayoutLong; 431 boolean screenLayoutCompatNeeded; 432 433 // These semi-magic numbers define our compatibility modes for 434 // applications with different screens. These are guarantees to 435 // app developers about the space they can expect for a particular 436 // configuration. DO NOT CHANGE! 437 if (longSizeDp < 470) { 438 // This is shorter than an HVGA normal density screen (which 439 // is 480 pixels on its long side). 440 screenLayoutSize = SCREENLAYOUT_SIZE_SMALL; 441 screenLayoutLong = false; 442 screenLayoutCompatNeeded = false; 443 } else { 444 // What size is this screen screen? 445 if (longSizeDp >= 960 && shortSizeDp >= 720) { 446 // 1.5xVGA or larger screens at medium density are the point 447 // at which we consider it to be an extra large screen. 448 screenLayoutSize = SCREENLAYOUT_SIZE_XLARGE; 449 } else if (longSizeDp >= 640 && shortSizeDp >= 480) { 450 // VGA or larger screens at medium density are the point 451 // at which we consider it to be a large screen. 452 screenLayoutSize = SCREENLAYOUT_SIZE_LARGE; 453 } else { 454 screenLayoutSize = SCREENLAYOUT_SIZE_NORMAL; 455 } 456 457 // If this screen is wider than normal HVGA, or taller 458 // than FWVGA, then for old apps we want to run in size 459 // compatibility mode. 460 if (shortSizeDp > 321 || longSizeDp > 570) { 461 screenLayoutCompatNeeded = true; 462 } else { 463 screenLayoutCompatNeeded = false; 464 } 465 466 // Is this a long screen? 467 if (((longSizeDp*3)/5) >= (shortSizeDp-1)) { 468 // Anything wider than WVGA (5:3) is considering to be long. 469 screenLayoutLong = true; 470 } else { 471 screenLayoutLong = false; 472 } 473 } 474 475 // Now reduce the last screenLayout to not be better than what we 476 // have found. 477 if (!screenLayoutLong) { 478 curLayout = (curLayout&~SCREENLAYOUT_LONG_MASK) | SCREENLAYOUT_LONG_NO; 479 } 480 if (screenLayoutCompatNeeded) { 481 curLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED; 482 } 483 int curSize = curLayout&SCREENLAYOUT_SIZE_MASK; 484 if (screenLayoutSize < curSize) { 485 curLayout = (curLayout&~SCREENLAYOUT_SIZE_MASK) | screenLayoutSize; 486 } 487 return curLayout; 488 } 489 490 /** @hide */ configurationDiffToString(int diff)491 public static String configurationDiffToString(int diff) { 492 ArrayList<String> list = new ArrayList<>(); 493 if ((diff & ActivityInfo.CONFIG_MCC) != 0) { 494 list.add("CONFIG_MCC"); 495 } 496 if ((diff & ActivityInfo.CONFIG_MNC) != 0) { 497 list.add("CONFIG_MNC"); 498 } 499 if ((diff & ActivityInfo.CONFIG_LOCALE) != 0) { 500 list.add("CONFIG_LOCALE"); 501 } 502 if ((diff & ActivityInfo.CONFIG_TOUCHSCREEN) != 0) { 503 list.add("CONFIG_TOUCHSCREEN"); 504 } 505 if ((diff & ActivityInfo.CONFIG_KEYBOARD) != 0) { 506 list.add("CONFIG_KEYBOARD"); 507 } 508 if ((diff & ActivityInfo.CONFIG_KEYBOARD_HIDDEN) != 0) { 509 list.add("CONFIG_KEYBOARD_HIDDEN"); 510 } 511 if ((diff & ActivityInfo.CONFIG_NAVIGATION) != 0) { 512 list.add("CONFIG_NAVIGATION"); 513 } 514 if ((diff & ActivityInfo.CONFIG_ORIENTATION) != 0) { 515 list.add("CONFIG_ORIENTATION"); 516 } 517 if ((diff & ActivityInfo.CONFIG_SCREEN_LAYOUT) != 0) { 518 list.add("CONFIG_SCREEN_LAYOUT"); 519 } 520 if ((diff & ActivityInfo.CONFIG_COLOR_MODE) != 0) { 521 list.add("CONFIG_COLOR_MODE"); 522 } 523 if ((diff & ActivityInfo.CONFIG_UI_MODE) != 0) { 524 list.add("CONFIG_UI_MODE"); 525 } 526 if ((diff & ActivityInfo.CONFIG_SCREEN_SIZE) != 0) { 527 list.add("CONFIG_SCREEN_SIZE"); 528 } 529 if ((diff & ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE) != 0) { 530 list.add("CONFIG_SMALLEST_SCREEN_SIZE"); 531 } 532 if ((diff & ActivityInfo.CONFIG_DENSITY) != 0) { 533 list.add("CONFIG_DENSITY"); 534 } 535 if ((diff & ActivityInfo.CONFIG_LAYOUT_DIRECTION) != 0) { 536 list.add("CONFIG_LAYOUT_DIRECTION"); 537 } 538 if ((diff & ActivityInfo.CONFIG_FONT_SCALE) != 0) { 539 list.add("CONFIG_FONT_SCALE"); 540 } 541 if ((diff & ActivityInfo.CONFIG_ASSETS_PATHS) != 0) { 542 list.add("CONFIG_ASSETS_PATHS"); 543 } 544 if ((diff & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0) { 545 list.add("CONFIG_WINDOW_CONFIGURATION"); 546 } 547 if ((diff & ActivityInfo.CONFIG_FONT_WEIGHT_ADJUSTMENT) != 0) { 548 list.add("CONFIG_AUTO_BOLD_TEXT"); 549 } 550 if ((diff & ActivityInfo.CONFIG_GRAMMATICAL_GENDER) != 0) { 551 list.add("CONFIG_GRAMMATICAL_GENDER"); 552 } 553 return "{" + TextUtils.join(", ", list) + "}"; 554 } 555 556 /** 557 * Check if the Configuration's current {@link #screenLayout} is at 558 * least the given size. 559 * 560 * @param size The desired size, either {@link #SCREENLAYOUT_SIZE_SMALL}, 561 * {@link #SCREENLAYOUT_SIZE_NORMAL}, {@link #SCREENLAYOUT_SIZE_LARGE}, or 562 * {@link #SCREENLAYOUT_SIZE_XLARGE}. 563 * @return Returns true if the current screen layout size is at least 564 * the given size. 565 */ isLayoutSizeAtLeast(int size)566 public boolean isLayoutSizeAtLeast(int size) { 567 int cur = screenLayout&SCREENLAYOUT_SIZE_MASK; 568 if (cur == SCREENLAYOUT_SIZE_UNDEFINED) return false; 569 return cur >= size; 570 } 571 572 /** Constant for {@link #touchscreen}: a value indicating that no value has been set. */ 573 public static final int TOUCHSCREEN_UNDEFINED = 0; 574 /** Constant for {@link #touchscreen}, value corresponding to the 575 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#TouchscreenQualifier">notouch</a> 576 * resource qualifier. */ 577 public static final int TOUCHSCREEN_NOTOUCH = 1; 578 /** @deprecated Not currently supported or used. */ 579 @Deprecated public static final int TOUCHSCREEN_STYLUS = 2; 580 /** Constant for {@link #touchscreen}, value corresponding to the 581 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#TouchscreenQualifier">finger</a> 582 * resource qualifier. */ 583 public static final int TOUCHSCREEN_FINGER = 3; 584 585 /** 586 * The kind of touch screen attached to the device. 587 * One of: {@link #TOUCHSCREEN_NOTOUCH}, {@link #TOUCHSCREEN_FINGER}. 588 */ 589 public int touchscreen; 590 591 /** Constant for {@link #keyboard}: a value indicating that no value has been set. */ 592 public static final int KEYBOARD_UNDEFINED = 0; 593 /** Constant for {@link #keyboard}, value corresponding to the 594 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">nokeys</a> 595 * resource qualifier. */ 596 public static final int KEYBOARD_NOKEYS = 1; 597 /** Constant for {@link #keyboard}, value corresponding to the 598 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">qwerty</a> 599 * resource qualifier. */ 600 public static final int KEYBOARD_QWERTY = 2; 601 /** Constant for {@link #keyboard}, value corresponding to the 602 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">12key</a> 603 * resource qualifier. */ 604 public static final int KEYBOARD_12KEY = 3; 605 606 /** 607 * The kind of keyboard attached to the device. 608 * One of: {@link #KEYBOARD_NOKEYS}, {@link #KEYBOARD_QWERTY}, 609 * {@link #KEYBOARD_12KEY}. 610 */ 611 public int keyboard; 612 613 /** Constant for {@link #keyboardHidden}: a value indicating that no value has been set. */ 614 public static final int KEYBOARDHIDDEN_UNDEFINED = 0; 615 /** Constant for {@link #keyboardHidden}, value corresponding to the 616 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keysexposed</a> 617 * resource qualifier. */ 618 public static final int KEYBOARDHIDDEN_NO = 1; 619 /** Constant for {@link #keyboardHidden}, value corresponding to the 620 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keyshidden</a> 621 * resource qualifier. */ 622 public static final int KEYBOARDHIDDEN_YES = 2; 623 /** Constant matching actual resource implementation. {@hide} */ 624 public static final int KEYBOARDHIDDEN_SOFT = 3; 625 626 /** 627 * A flag indicating whether any keyboard is available. Unlike 628 * {@link #hardKeyboardHidden}, this also takes into account a soft 629 * keyboard, so if the hard keyboard is hidden but there is soft 630 * keyboard available, it will be set to NO. Value is one of: 631 * {@link #KEYBOARDHIDDEN_NO}, {@link #KEYBOARDHIDDEN_YES}. 632 */ 633 public int keyboardHidden; 634 635 /** Constant for {@link #hardKeyboardHidden}: a value indicating that no value has been set. */ 636 public static final int HARDKEYBOARDHIDDEN_UNDEFINED = 0; 637 /** Constant for {@link #hardKeyboardHidden}, value corresponding to the 638 * physical keyboard being exposed. */ 639 public static final int HARDKEYBOARDHIDDEN_NO = 1; 640 /** Constant for {@link #hardKeyboardHidden}, value corresponding to the 641 * physical keyboard being hidden. */ 642 public static final int HARDKEYBOARDHIDDEN_YES = 2; 643 644 /** 645 * A flag indicating whether the hard keyboard has been hidden. This will 646 * be set on a device with a mechanism to hide the keyboard from the 647 * user, when that mechanism is closed. One of: 648 * {@link #HARDKEYBOARDHIDDEN_NO}, {@link #HARDKEYBOARDHIDDEN_YES}. 649 */ 650 public int hardKeyboardHidden; 651 652 /** Constant for {@link #navigation}: a value indicating that no value has been set. */ 653 public static final int NAVIGATION_UNDEFINED = 0; 654 /** Constant for {@link #navigation}, value corresponding to the 655 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">nonav</a> 656 * resource qualifier. */ 657 public static final int NAVIGATION_NONAV = 1; 658 /** Constant for {@link #navigation}, value corresponding to the 659 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">dpad</a> 660 * resource qualifier. */ 661 public static final int NAVIGATION_DPAD = 2; 662 /** Constant for {@link #navigation}, value corresponding to the 663 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">trackball</a> 664 * resource qualifier. */ 665 public static final int NAVIGATION_TRACKBALL = 3; 666 /** Constant for {@link #navigation}, value corresponding to the 667 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">wheel</a> 668 * resource qualifier. */ 669 public static final int NAVIGATION_WHEEL = 4; 670 671 /** 672 * The kind of navigation method available on the device. 673 * One of: {@link #NAVIGATION_NONAV}, {@link #NAVIGATION_DPAD}, 674 * {@link #NAVIGATION_TRACKBALL}, {@link #NAVIGATION_WHEEL}. 675 */ 676 public int navigation; 677 678 /** Constant for {@link #navigationHidden}: a value indicating that no value has been set. */ 679 public static final int NAVIGATIONHIDDEN_UNDEFINED = 0; 680 /** Constant for {@link #navigationHidden}, value corresponding to the 681 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavAvailQualifier">navexposed</a> 682 * resource qualifier. */ 683 public static final int NAVIGATIONHIDDEN_NO = 1; 684 /** Constant for {@link #navigationHidden}, value corresponding to the 685 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavAvailQualifier">navhidden</a> 686 * resource qualifier. */ 687 public static final int NAVIGATIONHIDDEN_YES = 2; 688 689 /** 690 * A flag indicating whether any 5-way or DPAD navigation available. 691 * This will be set on a device with a mechanism to hide the navigation 692 * controls from the user, when that mechanism is closed. One of: 693 * {@link #NAVIGATIONHIDDEN_NO}, {@link #NAVIGATIONHIDDEN_YES}. 694 */ 695 public int navigationHidden; 696 697 /** @hide **/ 698 @IntDef(prefix = {"ORIENTATION_"}, value = { 699 ORIENTATION_UNDEFINED, 700 ORIENTATION_PORTRAIT, 701 ORIENTATION_LANDSCAPE, 702 ORIENTATION_SQUARE 703 }) 704 @Retention(RetentionPolicy.SOURCE) 705 public @interface Orientation { 706 } 707 708 /** Constant for {@link #orientation}: a value indicating that no value has been set. */ 709 public static final int ORIENTATION_UNDEFINED = 0; 710 /** Constant for {@link #orientation}, value corresponding to the 711 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#OrientationQualifier">port</a> 712 * resource qualifier. */ 713 public static final int ORIENTATION_PORTRAIT = 1; 714 /** Constant for {@link #orientation}, value corresponding to the 715 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#OrientationQualifier">land</a> 716 * resource qualifier. */ 717 public static final int ORIENTATION_LANDSCAPE = 2; 718 /** @deprecated Not currently supported or used. */ 719 @Deprecated public static final int ORIENTATION_SQUARE = 3; 720 721 /** 722 * Overall orientation of the screen. May be one of 723 * {@link #ORIENTATION_LANDSCAPE}, {@link #ORIENTATION_PORTRAIT}. 724 */ 725 @Orientation 726 public int orientation; 727 728 /** Constant for {@link #uiMode}: bits that encode the mode type. */ 729 public static final int UI_MODE_TYPE_MASK = 0x0f; 730 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK} 731 * value indicating that no mode type has been set. */ 732 public static final int UI_MODE_TYPE_UNDEFINED = 0x00; 733 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK} 734 * value that corresponds to 735 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">no 736 * UI mode</a> resource qualifier specified. */ 737 public static final int UI_MODE_TYPE_NORMAL = 0x01; 738 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK} 739 * value that corresponds to the 740 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">desk</a> 741 * resource qualifier. */ 742 public static final int UI_MODE_TYPE_DESK = 0x02; 743 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK} 744 * value that corresponds to the 745 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">car</a> 746 * resource qualifier. */ 747 public static final int UI_MODE_TYPE_CAR = 0x03; 748 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK} 749 * value that corresponds to the 750 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">television</a> 751 * resource qualifier. */ 752 public static final int UI_MODE_TYPE_TELEVISION = 0x04; 753 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK} 754 * value that corresponds to the 755 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">appliance</a> 756 * resource qualifier. */ 757 public static final int UI_MODE_TYPE_APPLIANCE = 0x05; 758 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK} 759 * value that corresponds to the 760 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">watch</a> 761 * resource qualifier. */ 762 public static final int UI_MODE_TYPE_WATCH = 0x06; 763 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK} 764 * value that corresponds to the 765 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">vrheadset</a> 766 * resource qualifier. */ 767 public static final int UI_MODE_TYPE_VR_HEADSET = 0x07; 768 769 /** Constant for {@link #uiMode}: bits that encode the night mode. */ 770 public static final int UI_MODE_NIGHT_MASK = 0x30; 771 /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK} 772 * value indicating that no mode type has been set. */ 773 public static final int UI_MODE_NIGHT_UNDEFINED = 0x00; 774 /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK} 775 * value that corresponds to the 776 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NightQualifier">notnight</a> 777 * resource qualifier. */ 778 public static final int UI_MODE_NIGHT_NO = 0x10; 779 /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK} 780 * value that corresponds to the 781 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NightQualifier">night</a> 782 * resource qualifier. */ 783 public static final int UI_MODE_NIGHT_YES = 0x20; 784 785 /** 786 * Bit mask of the ui mode. Currently there are two fields: 787 * <p>The {@link #UI_MODE_TYPE_MASK} bits define the overall ui mode of the 788 * device. They may be one of {@link #UI_MODE_TYPE_UNDEFINED}, 789 * {@link #UI_MODE_TYPE_NORMAL}, {@link #UI_MODE_TYPE_DESK}, 790 * {@link #UI_MODE_TYPE_CAR}, {@link #UI_MODE_TYPE_TELEVISION}, 791 * {@link #UI_MODE_TYPE_APPLIANCE}, {@link #UI_MODE_TYPE_WATCH}, 792 * or {@link #UI_MODE_TYPE_VR_HEADSET}. 793 * 794 * <p>The {@link #UI_MODE_NIGHT_MASK} defines whether the screen 795 * is in a special mode. They may be one of {@link #UI_MODE_NIGHT_UNDEFINED}, 796 * {@link #UI_MODE_NIGHT_NO} or {@link #UI_MODE_NIGHT_YES}. 797 */ 798 public int uiMode; 799 800 /** 801 * Default value for {@link #screenWidthDp} indicating that no width 802 * has been specified. 803 */ 804 public static final int SCREEN_WIDTH_DP_UNDEFINED = 0; 805 806 /** 807 * The width of the available screen space in dp units. 808 * 809 * <aside class="note"><b>Note:</b> If the app targets 810 * {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM} 811 * or after, the width measurement reflects the window size without excluding insets. 812 * Otherwise, the measurement excludes window insets even when the app is displayed edge to edge 813 * using {@link android.view.Window#setDecorFitsSystemWindows(boolean) 814 * Window#setDecorFitsSystemWindows(boolean)}.</aside> 815 * 816 * Use {@link android.view.WindowMetrics#getBounds()} to always obtain the horizontal 817 * display area available to an app or embedded activity including the area 818 * occupied by window insets. A version of the API is also available for use on older platforms 819 * through {@link androidx.window.layout.WindowMetrics}. 820 * 821 * <p>Corresponds to the 822 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#AvailableWidthHeightQualifier"> 823 * available width</a> resource qualifier. Defaults to 824 * {@link #SCREEN_WIDTH_DP_UNDEFINED} if no width is specified. 825 * 826 * <p>In multi-window mode, equals the width of the available display area 827 * of the app window, not the available display area of the device screen 828 * (for example, when apps are displayed side by side in split-screen mode 829 * in landscape orientation). 830 * 831 * <p>For embedded activities, equals the width of the individual 832 * activities, not the width of the app window or the device screen. 833 * 834 * <p>In multiple-screen scenarios, the width measurement can span screens. 835 * For example, if the app is spanning both screens of a dual-screen device 836 * (with the screens side by side), {@code screenWidthDp} represents the 837 * width of both screens excluding the area occupied by window insets. When 838 * the app is restricted to a single screen in a multiple-screen 839 * environment, {@code screenWidthDp} is the width of the screen on which 840 * the app is displayed excluding window insets. 841 * 842 * <p>If the app targets {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM} or after, 843 * it is the same as {@link android.view.WindowMetrics}, but is expressed rounded to the nearest 844 * dp rather than px. 845 * 846 * <p>Otherwise, differs from {@link android.view.WindowMetrics} by not including 847 * window insets in the width measurement and by expressing the measurement 848 * in dp rather than px. Use {@code screenWidthDp} to obtain the width of 849 * the display area available to an app or embedded activity excluding the 850 * area occupied by window insets. 851 */ 852 public int screenWidthDp; 853 854 /** 855 * Default value for {@link #screenHeightDp} indicating that no width 856 * has been specified. 857 */ 858 public static final int SCREEN_HEIGHT_DP_UNDEFINED = 0; 859 860 /** 861 * The height of the available screen space in dp units. 862 * 863 * <aside class="note"><b>Note:</b> If the app targets 864 * {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM} 865 * or after, the height measurement reflects the window size without excluding insets. 866 * Otherwise, the measurement excludes window insets even when the app is displayed edge to edge 867 * using {@link android.view.Window#setDecorFitsSystemWindows(boolean) 868 * Window#setDecorFitsSystemWindows(boolean)}.</aside> 869 * 870 * Use {@link android.view.WindowMetrics#getBounds()} to always obtain the vertical 871 * display area available to an app or embedded activity including the area 872 * occupied by window insets. A version of the API is also available for use on older platforms 873 * through {@link androidx.window.layout.WindowMetrics}. 874 * 875 * <p>Corresponds to the 876 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#AvailableWidthHeightQualifier"> 877 * available height</a> resource qualifier. Defaults to 878 * {@link #SCREEN_HEIGHT_DP_UNDEFINED} if no height is specified. 879 * 880 * <p>In multi-window mode, equals the height of the available display area 881 * of the app window, not the available display area of the device screen 882 * (for example, when apps are displayed one above another in split-screen 883 * mode in portrait orientation). 884 * 885 * <p>For embedded activities, equals the height of the individual 886 * activities, not the height of the app window or the device screen. 887 * 888 * <p>In multiple-screen scenarios, the height measurement can span screens. 889 * For example, if the app is spanning both screens of a dual-screen device 890 * rotated 90 degrees (one screen above the other), {@code screenHeightDp} 891 * represents the height of both screens excluding the area occupied by 892 * window insets. When the app is restricted to a single screen in a 893 * multiple-screen environment, {@code screenHeightDp} is the height of the 894 * screen on which the app is displayed excluding window insets. 895 * 896 * <p>If the app targets {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM} or after, 897 * it is the same as {@link android.view.WindowMetrics}, but is expressed rounded to the nearest 898 * dp rather than px. 899 * 900 * <p>Otherwise, differs from {@link android.view.WindowMetrics} by not including 901 * window insets in the height measurement and by expressing the measurement 902 * in dp rather than px. Use {@code screenHeightDp} to obtain the height of 903 * the display area available to an app or embedded activity excluding the 904 * area occupied by window insets. 905 */ 906 public int screenHeightDp; 907 908 /** 909 * Default value for {@link #smallestScreenWidthDp} indicating that no width 910 * has been specified. 911 */ 912 public static final int SMALLEST_SCREEN_WIDTH_DP_UNDEFINED = 0; 913 914 /** 915 * The smallest screen size an application will see in normal operation. 916 * Corresponds to the 917 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#SmallestScreenWidthQualifier"> 918 * smallest width</a> resource qualifier. This is the smallest value of 919 * {@link #screenWidthDp} and {@link #screenHeightDp} in both portrait and 920 * landscape orientations. Defaults to 921 * {@link #SMALLEST_SCREEN_WIDTH_DP_UNDEFINED} if no width is specified. 922 */ 923 public int smallestScreenWidthDp; 924 925 /** 926 * Default value for {@link #densityDpi} indicating that no width 927 * has been specified. 928 */ 929 public static final int DENSITY_DPI_UNDEFINED = 0; 930 931 /** 932 * Value for {@link #densityDpi} for resources that scale to any density (vector drawables). 933 * {@hide} 934 */ 935 public static final int DENSITY_DPI_ANY = 0xfffe; 936 937 /** 938 * Value for {@link #densityDpi} for resources that are not meant to be scaled. 939 * {@hide} 940 */ 941 public static final int DENSITY_DPI_NONE = 0xffff; 942 943 /** 944 * The target screen density being rendered to, 945 * corresponding to 946 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#DensityQualifier">density</a> 947 * resource qualifier. Set to 948 * {@link #DENSITY_DPI_UNDEFINED} if no density is specified. 949 */ 950 public int densityDpi; 951 952 /** @hide Hack to get this information from WM to app running in compat mode. */ 953 public int compatScreenWidthDp; 954 /** @hide Hack to get this information from WM to app running in compat mode. */ 955 public int compatScreenHeightDp; 956 /** @hide Hack to get this information from WM to app running in compat mode. */ 957 public int compatSmallestScreenWidthDp; 958 959 /** 960 * An undefined assetsSeq. This will not override an existing assetsSeq. 961 * @hide 962 */ 963 public static final int ASSETS_SEQ_UNDEFINED = 0; 964 965 /** 966 * Internal counter that allows us to piggyback off the configuration change mechanism to 967 * signal to apps that the the assets for an Application have changed. A difference in these 968 * between two Configurations will yield a diff flag of 969 * {@link ActivityInfo#CONFIG_ASSETS_PATHS}. 970 * @hide 971 */ 972 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 973 @TestApi 974 public int assetsSeq; 975 976 /** 977 * @hide Internal book-keeping. 978 */ 979 @UnsupportedAppUsage 980 public int seq; 981 982 /** @hide */ 983 @IntDef(flag = true, prefix = { "NATIVE_CONFIG_" }, value = { 984 NATIVE_CONFIG_MCC, 985 NATIVE_CONFIG_MNC, 986 NATIVE_CONFIG_LOCALE, 987 NATIVE_CONFIG_TOUCHSCREEN, 988 NATIVE_CONFIG_KEYBOARD, 989 NATIVE_CONFIG_KEYBOARD_HIDDEN, 990 NATIVE_CONFIG_NAVIGATION, 991 NATIVE_CONFIG_ORIENTATION, 992 NATIVE_CONFIG_DENSITY, 993 NATIVE_CONFIG_SCREEN_SIZE, 994 NATIVE_CONFIG_VERSION, 995 NATIVE_CONFIG_SCREEN_LAYOUT, 996 NATIVE_CONFIG_UI_MODE, 997 NATIVE_CONFIG_SMALLEST_SCREEN_SIZE, 998 NATIVE_CONFIG_LAYOUTDIR, 999 NATIVE_CONFIG_COLOR_MODE, 1000 NATIVE_CONFIG_GRAMMATICAL_GENDER, 1001 }) 1002 @Retention(RetentionPolicy.SOURCE) 1003 public @interface NativeConfig {} 1004 1005 /** @hide Native-specific bit mask for MCC config; DO NOT USE UNLESS YOU ARE SURE. */ 1006 public static final int NATIVE_CONFIG_MCC = 0x0001; 1007 /** @hide Native-specific bit mask for MNC config; DO NOT USE UNLESS YOU ARE SURE. */ 1008 public static final int NATIVE_CONFIG_MNC = 0x0002; 1009 /** @hide Native-specific bit mask for LOCALE config; DO NOT USE UNLESS YOU ARE SURE. */ 1010 public static final int NATIVE_CONFIG_LOCALE = 0x0004; 1011 /** @hide Native-specific bit mask for TOUCHSCREEN config; DO NOT USE UNLESS YOU ARE SURE. */ 1012 public static final int NATIVE_CONFIG_TOUCHSCREEN = 0x0008; 1013 /** @hide Native-specific bit mask for KEYBOARD config; DO NOT USE UNLESS YOU ARE SURE. */ 1014 public static final int NATIVE_CONFIG_KEYBOARD = 0x0010; 1015 /** @hide Native-specific bit mask for KEYBOARD_HIDDEN config; DO NOT USE UNLESS YOU 1016 * ARE SURE. */ 1017 public static final int NATIVE_CONFIG_KEYBOARD_HIDDEN = 0x0020; 1018 /** @hide Native-specific bit mask for NAVIGATION config; DO NOT USE UNLESS YOU ARE SURE. */ 1019 public static final int NATIVE_CONFIG_NAVIGATION = 0x0040; 1020 /** @hide Native-specific bit mask for ORIENTATION config; DO NOT USE UNLESS YOU ARE SURE. */ 1021 public static final int NATIVE_CONFIG_ORIENTATION = 0x0080; 1022 /** @hide Native-specific bit mask for DENSITY config; DO NOT USE UNLESS YOU ARE SURE. */ 1023 public static final int NATIVE_CONFIG_DENSITY = 0x0100; 1024 /** @hide Native-specific bit mask for SCREEN_SIZE config; DO NOT USE UNLESS YOU ARE SURE. */ 1025 public static final int NATIVE_CONFIG_SCREEN_SIZE = 0x0200; 1026 /** @hide Native-specific bit mask for VERSION config; DO NOT USE UNLESS YOU ARE SURE. */ 1027 public static final int NATIVE_CONFIG_VERSION = 0x0400; 1028 /** @hide Native-specific bit mask for SCREEN_LAYOUT config; DO NOT USE UNLESS YOU ARE SURE. */ 1029 public static final int NATIVE_CONFIG_SCREEN_LAYOUT = 0x0800; 1030 /** @hide Native-specific bit mask for UI_MODE config; DO NOT USE UNLESS YOU ARE SURE. */ 1031 public static final int NATIVE_CONFIG_UI_MODE = 0x1000; 1032 /** @hide Native-specific bit mask for SMALLEST_SCREEN_SIZE config; DO NOT USE UNLESS YOU 1033 * ARE SURE. */ 1034 public static final int NATIVE_CONFIG_SMALLEST_SCREEN_SIZE = 0x2000; 1035 /** @hide Native-specific bit mask for LAYOUTDIR config ; DO NOT USE UNLESS YOU ARE SURE.*/ 1036 public static final int NATIVE_CONFIG_LAYOUTDIR = 0x4000; 1037 /** @hide Native-specific bit mask for COLOR_MODE config ; DO NOT USE UNLESS YOU ARE SURE.*/ 1038 public static final int NATIVE_CONFIG_COLOR_MODE = 0x10000; 1039 /** @hide Native-specific bit mask for GRAMMATICAL_GENDER config; DO NOT USE UNLESS YOU 1040 * ARE SURE.*/ 1041 public static final int NATIVE_CONFIG_GRAMMATICAL_GENDER = 0x20000; 1042 1043 /** 1044 * <p>Construct an invalid Configuration. This state is only suitable for constructing a 1045 * Configuration delta that will be applied to some valid Configuration object. In order to 1046 * create a valid standalone Configuration, you must call {@link #setToDefaults}. </p> 1047 * 1048 * <p>Example:</p> 1049 * <pre class="prettyprint"> 1050 * Configuration validConfig = new Configuration(); 1051 * validConfig.setToDefaults(); 1052 * 1053 * Configuration deltaOnlyConfig = new Configuration(); 1054 * deltaOnlyConfig.orientation = Configuration.ORIENTATION_LANDSCAPE; 1055 * 1056 * validConfig.updateFrom(deltaOnlyConfig); 1057 * </pre> 1058 */ Configuration()1059 public Configuration() { 1060 unset(); 1061 } 1062 1063 /** 1064 * Makes a deep copy suitable for modification. 1065 */ Configuration(Configuration o)1066 public Configuration(Configuration o) { 1067 setTo(o); 1068 } 1069 1070 /* This brings mLocaleList in sync with locale in case a user of the older API who doesn't know 1071 * about setLocales() has changed locale directly. */ fixUpLocaleList()1072 private void fixUpLocaleList() { 1073 if ((locale == null && !mLocaleList.isEmpty()) || 1074 (locale != null && !locale.equals(mLocaleList.get(0)))) { 1075 mLocaleList = locale == null ? LocaleList.getEmptyLocaleList() : new LocaleList(locale); 1076 } 1077 } 1078 1079 /** 1080 * Sets the fields in this object to those in the given Configuration. 1081 * 1082 * @param o The Configuration object used to set the values of this Configuration's fields. 1083 */ setTo(Configuration o)1084 public void setTo(Configuration o) { 1085 fontScale = o.fontScale; 1086 mcc = o.mcc; 1087 mnc = o.mnc; 1088 if (o.locale == null) { 1089 locale = null; 1090 } else if (!o.locale.equals(locale)) { 1091 // Only clone a new Locale instance if we need to: the clone() is 1092 // both CPU and GC intensive. 1093 locale = (Locale) o.locale.clone(); 1094 } 1095 o.fixUpLocaleList(); 1096 mLocaleList = o.mLocaleList; 1097 mGrammaticalGender = o.mGrammaticalGender; 1098 userSetLocale = o.userSetLocale; 1099 touchscreen = o.touchscreen; 1100 keyboard = o.keyboard; 1101 keyboardHidden = o.keyboardHidden; 1102 hardKeyboardHidden = o.hardKeyboardHidden; 1103 navigation = o.navigation; 1104 navigationHidden = o.navigationHidden; 1105 orientation = o.orientation; 1106 screenLayout = o.screenLayout; 1107 colorMode = o.colorMode; 1108 uiMode = o.uiMode; 1109 screenWidthDp = o.screenWidthDp; 1110 screenHeightDp = o.screenHeightDp; 1111 smallestScreenWidthDp = o.smallestScreenWidthDp; 1112 densityDpi = o.densityDpi; 1113 compatScreenWidthDp = o.compatScreenWidthDp; 1114 compatScreenHeightDp = o.compatScreenHeightDp; 1115 compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp; 1116 assetsSeq = o.assetsSeq; 1117 seq = o.seq; 1118 windowConfiguration.setTo(o.windowConfiguration); 1119 fontWeightAdjustment = o.fontWeightAdjustment; 1120 } 1121 toString()1122 public String toString() { 1123 StringBuilder sb = new StringBuilder(128); 1124 sb.append("{"); 1125 sb.append(fontScale); 1126 sb.append(" "); 1127 if (mcc != 0) { 1128 sb.append(mcc); 1129 sb.append("mcc"); 1130 } else { 1131 sb.append("?mcc"); 1132 } 1133 if (mnc != MNC_ZERO) { 1134 sb.append(mnc); 1135 sb.append("mnc"); 1136 } else { 1137 sb.append("?mnc"); 1138 } 1139 fixUpLocaleList(); 1140 if (!mLocaleList.isEmpty()) { 1141 sb.append(" "); 1142 sb.append(mLocaleList); 1143 } else { 1144 sb.append(" ?localeList"); 1145 } 1146 if (mGrammaticalGender > 0) { 1147 switch (mGrammaticalGender) { 1148 case GRAMMATICAL_GENDER_NEUTRAL: sb.append(" neuter"); break; 1149 case GRAMMATICAL_GENDER_FEMININE: sb.append(" feminine"); break; 1150 case GRAMMATICAL_GENDER_MASCULINE: sb.append(" masculine"); break; 1151 default: sb.append(" ?grgend"); break; 1152 } 1153 } 1154 int layoutDir = (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK); 1155 switch (layoutDir) { 1156 case SCREENLAYOUT_LAYOUTDIR_UNDEFINED: sb.append(" ?layoutDir"); break; 1157 case SCREENLAYOUT_LAYOUTDIR_LTR: sb.append(" ldltr"); break; 1158 case SCREENLAYOUT_LAYOUTDIR_RTL: sb.append(" ldrtl"); break; 1159 default: sb.append(" layoutDir="); 1160 sb.append(layoutDir >> SCREENLAYOUT_LAYOUTDIR_SHIFT); break; 1161 } 1162 if (smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) { 1163 sb.append(" sw"); sb.append(smallestScreenWidthDp); sb.append("dp"); 1164 } else { 1165 sb.append(" ?swdp"); 1166 } 1167 if (screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) { 1168 sb.append(" w"); sb.append(screenWidthDp); sb.append("dp"); 1169 } else { 1170 sb.append(" ?wdp"); 1171 } 1172 if (screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) { 1173 sb.append(" h"); sb.append(screenHeightDp); sb.append("dp"); 1174 } else { 1175 sb.append(" ?hdp"); 1176 } 1177 if (densityDpi != DENSITY_DPI_UNDEFINED) { 1178 sb.append(" "); sb.append(densityDpi); sb.append("dpi"); 1179 } else { 1180 sb.append(" ?density"); 1181 } 1182 switch ((screenLayout&SCREENLAYOUT_SIZE_MASK)) { 1183 case SCREENLAYOUT_SIZE_UNDEFINED: sb.append(" ?lsize"); break; 1184 case SCREENLAYOUT_SIZE_SMALL: sb.append(" smll"); break; 1185 case SCREENLAYOUT_SIZE_NORMAL: sb.append(" nrml"); break; 1186 case SCREENLAYOUT_SIZE_LARGE: sb.append(" lrg"); break; 1187 case SCREENLAYOUT_SIZE_XLARGE: sb.append(" xlrg"); break; 1188 default: sb.append(" layoutSize="); 1189 sb.append(screenLayout&SCREENLAYOUT_SIZE_MASK); break; 1190 } 1191 switch ((screenLayout&SCREENLAYOUT_LONG_MASK)) { 1192 case SCREENLAYOUT_LONG_UNDEFINED: sb.append(" ?long"); break; 1193 case SCREENLAYOUT_LONG_NO: /* not-long is not interesting to print */ break; 1194 case SCREENLAYOUT_LONG_YES: sb.append(" long"); break; 1195 default: sb.append(" layoutLong="); 1196 sb.append(screenLayout&SCREENLAYOUT_LONG_MASK); break; 1197 } 1198 switch ((colorMode &COLOR_MODE_HDR_MASK)) { 1199 case COLOR_MODE_HDR_UNDEFINED: sb.append(" ?ldr"); break; // most likely not HDR 1200 case COLOR_MODE_HDR_NO: /* ldr is not interesting to print */ break; 1201 case COLOR_MODE_HDR_YES: sb.append(" hdr"); break; 1202 default: sb.append(" dynamicRange="); 1203 sb.append(colorMode &COLOR_MODE_HDR_MASK); break; 1204 } 1205 switch ((colorMode &COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) { 1206 case COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED: sb.append(" ?wideColorGamut"); break; 1207 case COLOR_MODE_WIDE_COLOR_GAMUT_NO: /* not wide is not interesting to print */ break; 1208 case COLOR_MODE_WIDE_COLOR_GAMUT_YES: sb.append(" widecg"); break; 1209 default: sb.append(" wideColorGamut="); 1210 sb.append(colorMode &COLOR_MODE_WIDE_COLOR_GAMUT_MASK); break; 1211 } 1212 switch (orientation) { 1213 case ORIENTATION_UNDEFINED: sb.append(" ?orien"); break; 1214 case ORIENTATION_LANDSCAPE: sb.append(" land"); break; 1215 case ORIENTATION_PORTRAIT: sb.append(" port"); break; 1216 default: sb.append(" orien="); sb.append(orientation); break; 1217 } 1218 switch ((uiMode&UI_MODE_TYPE_MASK)) { 1219 case UI_MODE_TYPE_UNDEFINED: sb.append(" ?uimode"); break; 1220 case UI_MODE_TYPE_NORMAL: /* normal is not interesting to print */ break; 1221 case UI_MODE_TYPE_DESK: sb.append(" desk"); break; 1222 case UI_MODE_TYPE_CAR: sb.append(" car"); break; 1223 case UI_MODE_TYPE_TELEVISION: sb.append(" television"); break; 1224 case UI_MODE_TYPE_APPLIANCE: sb.append(" appliance"); break; 1225 case UI_MODE_TYPE_WATCH: sb.append(" watch"); break; 1226 case UI_MODE_TYPE_VR_HEADSET: sb.append(" vrheadset"); break; 1227 default: sb.append(" uimode="); sb.append(uiMode&UI_MODE_TYPE_MASK); break; 1228 } 1229 switch ((uiMode&UI_MODE_NIGHT_MASK)) { 1230 case UI_MODE_NIGHT_UNDEFINED: sb.append(" ?night"); break; 1231 case UI_MODE_NIGHT_NO: /* not-night is not interesting to print */ break; 1232 case UI_MODE_NIGHT_YES: sb.append(" night"); break; 1233 default: sb.append(" night="); sb.append(uiMode&UI_MODE_NIGHT_MASK); break; 1234 } 1235 switch (touchscreen) { 1236 case TOUCHSCREEN_UNDEFINED: sb.append(" ?touch"); break; 1237 case TOUCHSCREEN_NOTOUCH: sb.append(" -touch"); break; 1238 case TOUCHSCREEN_STYLUS: sb.append(" stylus"); break; 1239 case TOUCHSCREEN_FINGER: sb.append(" finger"); break; 1240 default: sb.append(" touch="); sb.append(touchscreen); break; 1241 } 1242 switch (keyboard) { 1243 case KEYBOARD_UNDEFINED: sb.append(" ?keyb"); break; 1244 case KEYBOARD_NOKEYS: sb.append(" -keyb"); break; 1245 case KEYBOARD_QWERTY: sb.append(" qwerty"); break; 1246 case KEYBOARD_12KEY: sb.append(" 12key"); break; 1247 default: sb.append(" keys="); sb.append(keyboard); break; 1248 } 1249 switch (keyboardHidden) { 1250 case KEYBOARDHIDDEN_UNDEFINED: sb.append("/?"); break; 1251 case KEYBOARDHIDDEN_NO: sb.append("/v"); break; 1252 case KEYBOARDHIDDEN_YES: sb.append("/h"); break; 1253 case KEYBOARDHIDDEN_SOFT: sb.append("/s"); break; 1254 default: sb.append("/"); sb.append(keyboardHidden); break; 1255 } 1256 switch (hardKeyboardHidden) { 1257 case HARDKEYBOARDHIDDEN_UNDEFINED: sb.append("/?"); break; 1258 case HARDKEYBOARDHIDDEN_NO: sb.append("/v"); break; 1259 case HARDKEYBOARDHIDDEN_YES: sb.append("/h"); break; 1260 default: sb.append("/"); sb.append(hardKeyboardHidden); break; 1261 } 1262 switch (navigation) { 1263 case NAVIGATION_UNDEFINED: sb.append(" ?nav"); break; 1264 case NAVIGATION_NONAV: sb.append(" -nav"); break; 1265 case NAVIGATION_DPAD: sb.append(" dpad"); break; 1266 case NAVIGATION_TRACKBALL: sb.append(" tball"); break; 1267 case NAVIGATION_WHEEL: sb.append(" wheel"); break; 1268 default: sb.append(" nav="); sb.append(navigation); break; 1269 } 1270 switch (navigationHidden) { 1271 case NAVIGATIONHIDDEN_UNDEFINED: sb.append("/?"); break; 1272 case NAVIGATIONHIDDEN_NO: sb.append("/v"); break; 1273 case NAVIGATIONHIDDEN_YES: sb.append("/h"); break; 1274 default: sb.append("/"); sb.append(navigationHidden); break; 1275 } 1276 sb.append(" winConfig="); sb.append(windowConfiguration); 1277 if (assetsSeq != 0) { 1278 sb.append(" as.").append(assetsSeq); 1279 } 1280 if (seq != 0) { 1281 sb.append(" s.").append(seq); 1282 } 1283 if (fontWeightAdjustment != FONT_WEIGHT_ADJUSTMENT_UNDEFINED) { 1284 sb.append(" fontWeightAdjustment="); 1285 sb.append(fontWeightAdjustment); 1286 } else { 1287 sb.append(" ?fontWeightAdjustment"); 1288 } 1289 sb.append('}'); 1290 return sb.toString(); 1291 } 1292 1293 /** 1294 * Write to a protocol buffer output stream. 1295 * Protocol buffer message definition at {@link android.content.ConfigurationProto} 1296 * Has the option to ignore fields that don't need to be persisted to disk. 1297 * 1298 * @param protoOutputStream Stream to write the Configuration object to. 1299 * @param fieldId Field Id of the Configuration as defined in the parent message 1300 * @param persisted Note if this proto will be persisted to disk 1301 * @param critical If true, reduce amount of data written. 1302 * @hide 1303 */ dumpDebug(ProtoOutputStream protoOutputStream, long fieldId, boolean persisted, boolean critical)1304 public void dumpDebug(ProtoOutputStream protoOutputStream, long fieldId, boolean persisted, 1305 boolean critical) { 1306 final long token = protoOutputStream.start(fieldId); 1307 if (!critical) { 1308 protoOutputStream.write(FONT_SCALE, fontScale); 1309 protoOutputStream.write(MCC, mcc); 1310 protoOutputStream.write(MNC, mnc); 1311 if (mLocaleList != null) { 1312 protoOutputStream.write(LOCALE_LIST, mLocaleList.toLanguageTags()); 1313 } 1314 protoOutputStream.write(SCREEN_LAYOUT, screenLayout); 1315 protoOutputStream.write(COLOR_MODE, colorMode); 1316 protoOutputStream.write(TOUCHSCREEN, touchscreen); 1317 protoOutputStream.write(KEYBOARD, keyboard); 1318 protoOutputStream.write(KEYBOARD_HIDDEN, keyboardHidden); 1319 protoOutputStream.write(HARD_KEYBOARD_HIDDEN, hardKeyboardHidden); 1320 protoOutputStream.write(NAVIGATION, navigation); 1321 protoOutputStream.write(NAVIGATION_HIDDEN, navigationHidden); 1322 protoOutputStream.write(UI_MODE, uiMode); 1323 protoOutputStream.write(SMALLEST_SCREEN_WIDTH_DP, smallestScreenWidthDp); 1324 protoOutputStream.write(DENSITY_DPI, densityDpi); 1325 // For persistence, we do not care about window configuration 1326 if (!persisted && windowConfiguration != null) { 1327 windowConfiguration.dumpDebug(protoOutputStream, WINDOW_CONFIGURATION); 1328 } 1329 protoOutputStream.write(FONT_WEIGHT_ADJUSTMENT, fontWeightAdjustment); 1330 } 1331 protoOutputStream.write(ORIENTATION, orientation); 1332 protoOutputStream.write(SCREEN_WIDTH_DP, screenWidthDp); 1333 protoOutputStream.write(SCREEN_HEIGHT_DP, screenHeightDp); 1334 protoOutputStream.write(GRAMMATICAL_GENDER, mGrammaticalGender); 1335 protoOutputStream.end(token); 1336 } 1337 1338 /** 1339 * Write to a protocol buffer output stream. 1340 * Protocol buffer message definition at {@link android.content.ConfigurationProto} 1341 * 1342 * @param protoOutputStream Stream to write the Configuration object to. 1343 * @param fieldId Field Id of the Configuration as defined in the parent message 1344 * @hide 1345 */ dumpDebug(ProtoOutputStream protoOutputStream, long fieldId)1346 public void dumpDebug(ProtoOutputStream protoOutputStream, long fieldId) { 1347 dumpDebug(protoOutputStream, fieldId, false /* persisted */, false /* critical */); 1348 } 1349 1350 /** 1351 * Write to a protocol buffer output stream. 1352 * Protocol buffer message definition at {@link android.content.ConfigurationProto} 1353 * 1354 * @param protoOutputStream Stream to write the Configuration object to. 1355 * @param fieldId Field Id of the Configuration as defined in the parent message 1356 * @param critical If true, reduce amount of data written. 1357 * @hide 1358 */ dumpDebug(ProtoOutputStream protoOutputStream, long fieldId, boolean critical)1359 public void dumpDebug(ProtoOutputStream protoOutputStream, long fieldId, boolean critical) { 1360 dumpDebug(protoOutputStream, fieldId, false /* persisted */, critical); 1361 } 1362 1363 /** 1364 * Read from a protocol buffer output stream. 1365 * Protocol buffer message definition at {@link android.content.ConfigurationProto} 1366 * 1367 * @param protoInputStream Stream to read the Configuration object from. 1368 * @param fieldId Field Id of the Configuration as defined in the parent message 1369 * @hide 1370 */ readFromProto(ProtoInputStream protoInputStream, long fieldId)1371 public void readFromProto(ProtoInputStream protoInputStream, long fieldId) throws IOException { 1372 final long token = protoInputStream.start(fieldId); 1373 final List<Locale> list = new ArrayList(); 1374 try { 1375 while (protoInputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 1376 switch (protoInputStream.getFieldNumber()) { 1377 case (int) FONT_SCALE: 1378 fontScale = protoInputStream.readFloat(FONT_SCALE); 1379 break; 1380 case (int) MCC: 1381 mcc = protoInputStream.readInt(MCC); 1382 break; 1383 case (int) MNC: 1384 mnc = protoInputStream.readInt(MNC); 1385 break; 1386 case (int) LOCALES: 1387 // Parse the Locale here to handle all the repeated Locales 1388 // The LocaleList will be created when the message is completed 1389 final long localeToken = protoInputStream.start(LOCALES); 1390 String language = ""; 1391 String country = ""; 1392 String variant = ""; 1393 String script = ""; 1394 try { 1395 while (protoInputStream.nextField() 1396 != ProtoInputStream.NO_MORE_FIELDS) { 1397 switch (protoInputStream.getFieldNumber()) { 1398 case (int) LocaleProto.LANGUAGE: 1399 language = protoInputStream.readString( 1400 LocaleProto.LANGUAGE); 1401 break; 1402 case (int) LocaleProto.COUNTRY: 1403 country = protoInputStream.readString(LocaleProto.COUNTRY); 1404 break; 1405 case (int) LocaleProto.VARIANT: 1406 variant = protoInputStream.readString(LocaleProto.VARIANT); 1407 break; 1408 case (int) LocaleProto.SCRIPT: 1409 script = protoInputStream.readString(LocaleProto.SCRIPT); 1410 break; 1411 } 1412 } 1413 } catch (WireTypeMismatchException wtme) { 1414 // rethrow for caller deal with 1415 throw wtme; 1416 } finally { 1417 protoInputStream.end(localeToken); 1418 try { 1419 final Locale locale = new Locale.Builder() 1420 .setLanguage(language) 1421 .setRegion(country) 1422 .setVariant(variant) 1423 .setScript(script) 1424 .build(); 1425 // Log a WTF here if a repeated locale is found to avoid throwing an 1426 // exception in system server when LocaleList is created below 1427 final int inListIndex = list.indexOf(locale); 1428 if (inListIndex != -1) { 1429 Slog.wtf(TAG, "Repeated locale (" + list.get(inListIndex) + ")" 1430 + " found when trying to add: " + locale.toString()); 1431 } else { 1432 list.add(locale); 1433 } 1434 } catch (IllformedLocaleException e) { 1435 Slog.e(TAG, "readFromProto error building locale with: " 1436 + "language-" + language + ";country-" + country 1437 + ";variant-" + variant + ";script-" + script); 1438 } 1439 } 1440 break; 1441 case (int) SCREEN_LAYOUT: 1442 screenLayout = protoInputStream.readInt(SCREEN_LAYOUT); 1443 break; 1444 case (int) COLOR_MODE: 1445 colorMode = protoInputStream.readInt(COLOR_MODE); 1446 break; 1447 case (int) TOUCHSCREEN: 1448 touchscreen = protoInputStream.readInt(TOUCHSCREEN); 1449 break; 1450 case (int) KEYBOARD: 1451 keyboard = protoInputStream.readInt(KEYBOARD); 1452 break; 1453 case (int) KEYBOARD_HIDDEN: 1454 keyboardHidden = protoInputStream.readInt(KEYBOARD_HIDDEN); 1455 break; 1456 case (int) HARD_KEYBOARD_HIDDEN: 1457 hardKeyboardHidden = protoInputStream.readInt(HARD_KEYBOARD_HIDDEN); 1458 break; 1459 case (int) NAVIGATION: 1460 navigation = protoInputStream.readInt(NAVIGATION); 1461 break; 1462 case (int) NAVIGATION_HIDDEN: 1463 navigationHidden = protoInputStream.readInt(NAVIGATION_HIDDEN); 1464 break; 1465 case (int) ORIENTATION: 1466 orientation = protoInputStream.readInt(ORIENTATION); 1467 break; 1468 case (int) UI_MODE: 1469 uiMode = protoInputStream.readInt(UI_MODE); 1470 break; 1471 case (int) SCREEN_WIDTH_DP: 1472 screenWidthDp = protoInputStream.readInt(SCREEN_WIDTH_DP); 1473 break; 1474 case (int) SCREEN_HEIGHT_DP: 1475 screenHeightDp = protoInputStream.readInt(SCREEN_HEIGHT_DP); 1476 break; 1477 case (int) SMALLEST_SCREEN_WIDTH_DP: 1478 smallestScreenWidthDp = protoInputStream.readInt(SMALLEST_SCREEN_WIDTH_DP); 1479 break; 1480 case (int) DENSITY_DPI: 1481 densityDpi = protoInputStream.readInt(DENSITY_DPI); 1482 break; 1483 case (int) WINDOW_CONFIGURATION: 1484 windowConfiguration.readFromProto(protoInputStream, WINDOW_CONFIGURATION); 1485 break; 1486 case (int) LOCALE_LIST: 1487 try { 1488 setLocales(LocaleList.forLanguageTags(protoInputStream.readString( 1489 LOCALE_LIST))); 1490 } catch (Exception e) { 1491 Slog.e(TAG, "error parsing locale list in configuration.", e); 1492 } 1493 break; 1494 case (int) FONT_WEIGHT_ADJUSTMENT: 1495 fontWeightAdjustment = protoInputStream.readInt(FONT_WEIGHT_ADJUSTMENT); 1496 break; 1497 case (int) GRAMMATICAL_GENDER: 1498 mGrammaticalGender = protoInputStream.readInt(GRAMMATICAL_GENDER); 1499 break; 1500 } 1501 } 1502 } finally { 1503 // Let caller handle any exceptions 1504 if (list.size() > 0) { 1505 //Create the LocaleList from the collected Locales 1506 setLocales(new LocaleList(list.toArray(new Locale[list.size()]))); 1507 } 1508 protoInputStream.end(token); 1509 } 1510 } 1511 1512 /** 1513 * Write full {@link android.content.ResourcesConfigurationProto} to protocol buffer output 1514 * stream. 1515 * 1516 * @param protoOutputStream Stream to write the Configuration object to. 1517 * @param fieldId Field Id of the Configuration as defined in the parent message 1518 * @param metrics Current display information 1519 * @hide 1520 */ writeResConfigToProto(ProtoOutputStream protoOutputStream, long fieldId, DisplayMetrics metrics)1521 public void writeResConfigToProto(ProtoOutputStream protoOutputStream, long fieldId, 1522 DisplayMetrics metrics) { 1523 final int width, height; 1524 if (metrics.widthPixels >= metrics.heightPixels) { 1525 width = metrics.widthPixels; 1526 height = metrics.heightPixels; 1527 } else { 1528 //noinspection SuspiciousNameCombination 1529 width = metrics.heightPixels; 1530 //noinspection SuspiciousNameCombination 1531 height = metrics.widthPixels; 1532 } 1533 1534 final long token = protoOutputStream.start(fieldId); 1535 dumpDebug(protoOutputStream, CONFIGURATION); 1536 protoOutputStream.write(SDK_VERSION, Build.VERSION.RESOURCES_SDK_INT); 1537 protoOutputStream.write(SCREEN_WIDTH_PX, width); 1538 protoOutputStream.write(SCREEN_HEIGHT_PX, height); 1539 protoOutputStream.end(token); 1540 } 1541 1542 /** 1543 * Convert the UI mode to a human readable format. 1544 * @hide 1545 */ uiModeToString(int uiMode)1546 public static String uiModeToString(int uiMode) { 1547 switch (uiMode) { 1548 case UI_MODE_TYPE_UNDEFINED: 1549 return "UI_MODE_TYPE_UNDEFINED"; 1550 case UI_MODE_TYPE_NORMAL: 1551 return "UI_MODE_TYPE_NORMAL"; 1552 case UI_MODE_TYPE_DESK: 1553 return "UI_MODE_TYPE_DESK"; 1554 case UI_MODE_TYPE_CAR: 1555 return "UI_MODE_TYPE_CAR"; 1556 case UI_MODE_TYPE_TELEVISION: 1557 return "UI_MODE_TYPE_TELEVISION"; 1558 case UI_MODE_TYPE_APPLIANCE: 1559 return "UI_MODE_TYPE_APPLIANCE"; 1560 case UI_MODE_TYPE_WATCH: 1561 return "UI_MODE_TYPE_WATCH"; 1562 case UI_MODE_TYPE_VR_HEADSET: 1563 return "UI_MODE_TYPE_VR_HEADSET"; 1564 default: 1565 return Integer.toString(uiMode); 1566 } 1567 } 1568 1569 /** 1570 * Set this object to the system defaults. 1571 */ setToDefaults()1572 public void setToDefaults() { 1573 fontScale = 1; 1574 mcc = mnc = 0; 1575 mLocaleList = LocaleList.getEmptyLocaleList(); 1576 locale = null; 1577 userSetLocale = false; 1578 touchscreen = TOUCHSCREEN_UNDEFINED; 1579 keyboard = KEYBOARD_UNDEFINED; 1580 keyboardHidden = KEYBOARDHIDDEN_UNDEFINED; 1581 hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED; 1582 navigation = NAVIGATION_UNDEFINED; 1583 navigationHidden = NAVIGATIONHIDDEN_UNDEFINED; 1584 orientation = ORIENTATION_UNDEFINED; 1585 screenLayout = SCREENLAYOUT_UNDEFINED; 1586 colorMode = COLOR_MODE_UNDEFINED; 1587 uiMode = UI_MODE_TYPE_UNDEFINED; 1588 screenWidthDp = compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED; 1589 screenHeightDp = compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED; 1590 smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED; 1591 densityDpi = DENSITY_DPI_UNDEFINED; 1592 assetsSeq = ASSETS_SEQ_UNDEFINED; 1593 seq = 0; 1594 windowConfiguration.setToDefaults(); 1595 fontWeightAdjustment = FONT_WEIGHT_ADJUSTMENT_UNDEFINED; 1596 mGrammaticalGender = GRAMMATICAL_GENDER_UNDEFINED; 1597 } 1598 1599 /** 1600 * Set this object to completely undefined. 1601 * @hide 1602 */ unset()1603 public void unset() { 1604 setToDefaults(); 1605 fontScale = 0; 1606 } 1607 1608 /** {@hide} */ 1609 @UnsupportedAppUsage makeDefault()1610 @Deprecated public void makeDefault() { 1611 setToDefaults(); 1612 } 1613 1614 /** 1615 * Copies the fields from delta into this Configuration object, keeping 1616 * track of which ones have changed. Any undefined fields in {@code delta} 1617 * are ignored and not copied in to the current Configuration. 1618 * 1619 * @return a bit mask of the changed fields, as per {@link #diff} 1620 */ updateFrom(@onNull Configuration delta)1621 public @Config int updateFrom(@NonNull Configuration delta) { 1622 int changed = 0; 1623 if (delta.fontScale > 0 && fontScale != delta.fontScale) { 1624 changed |= ActivityInfo.CONFIG_FONT_SCALE; 1625 fontScale = delta.fontScale; 1626 } 1627 if (delta.mcc != 0 && mcc != delta.mcc) { 1628 changed |= ActivityInfo.CONFIG_MCC; 1629 mcc = delta.mcc; 1630 } 1631 if (delta.mnc != 0 && mnc != delta.mnc) { 1632 changed |= ActivityInfo.CONFIG_MNC; 1633 mnc = delta.mnc; 1634 } 1635 fixUpLocaleList(); 1636 delta.fixUpLocaleList(); 1637 if (!delta.mLocaleList.isEmpty() && !mLocaleList.equals(delta.mLocaleList)) { 1638 changed |= ActivityInfo.CONFIG_LOCALE; 1639 mLocaleList = delta.mLocaleList; 1640 // delta.locale can't be null, since delta.mLocaleList is not empty. 1641 if (!delta.locale.equals(locale)) { 1642 locale = (Locale) delta.locale.clone(); 1643 // If locale has changed, then layout direction is also changed ... 1644 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION; 1645 // ... and we need to update the layout direction (represented by the first 1646 // 2 most significant bits in screenLayout). 1647 setLayoutDirection(locale); 1648 } 1649 } 1650 final int deltaScreenLayoutDir = delta.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK; 1651 if (deltaScreenLayoutDir != SCREENLAYOUT_LAYOUTDIR_UNDEFINED && 1652 deltaScreenLayoutDir != (screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) { 1653 screenLayout = (screenLayout & ~SCREENLAYOUT_LAYOUTDIR_MASK) | deltaScreenLayoutDir; 1654 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION; 1655 } 1656 if (delta.userSetLocale && (!userSetLocale || ((changed & ActivityInfo.CONFIG_LOCALE) != 0))) 1657 { 1658 changed |= ActivityInfo.CONFIG_LOCALE; 1659 userSetLocale = true; 1660 } 1661 if (delta.touchscreen != TOUCHSCREEN_UNDEFINED 1662 && touchscreen != delta.touchscreen) { 1663 changed |= ActivityInfo.CONFIG_TOUCHSCREEN; 1664 touchscreen = delta.touchscreen; 1665 } 1666 if (delta.keyboard != KEYBOARD_UNDEFINED 1667 && keyboard != delta.keyboard) { 1668 changed |= ActivityInfo.CONFIG_KEYBOARD; 1669 keyboard = delta.keyboard; 1670 } 1671 if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED 1672 && keyboardHidden != delta.keyboardHidden) { 1673 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN; 1674 keyboardHidden = delta.keyboardHidden; 1675 } 1676 if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED 1677 && hardKeyboardHidden != delta.hardKeyboardHidden) { 1678 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN; 1679 hardKeyboardHidden = delta.hardKeyboardHidden; 1680 } 1681 if (delta.navigation != NAVIGATION_UNDEFINED 1682 && navigation != delta.navigation) { 1683 changed |= ActivityInfo.CONFIG_NAVIGATION; 1684 navigation = delta.navigation; 1685 } 1686 if (delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED 1687 && navigationHidden != delta.navigationHidden) { 1688 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN; 1689 navigationHidden = delta.navigationHidden; 1690 } 1691 if (delta.orientation != ORIENTATION_UNDEFINED 1692 && orientation != delta.orientation) { 1693 changed |= ActivityInfo.CONFIG_ORIENTATION; 1694 orientation = delta.orientation; 1695 } 1696 if (((delta.screenLayout & SCREENLAYOUT_SIZE_MASK) != SCREENLAYOUT_SIZE_UNDEFINED) 1697 && (delta.screenLayout & SCREENLAYOUT_SIZE_MASK) 1698 != (screenLayout & SCREENLAYOUT_SIZE_MASK)) { 1699 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT; 1700 screenLayout = (screenLayout & ~SCREENLAYOUT_SIZE_MASK) 1701 | (delta.screenLayout & SCREENLAYOUT_SIZE_MASK); 1702 } 1703 if (((delta.screenLayout & SCREENLAYOUT_LONG_MASK) != SCREENLAYOUT_LONG_UNDEFINED) 1704 && (delta.screenLayout & SCREENLAYOUT_LONG_MASK) 1705 != (screenLayout & SCREENLAYOUT_LONG_MASK)) { 1706 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT; 1707 screenLayout = (screenLayout & ~SCREENLAYOUT_LONG_MASK) 1708 | (delta.screenLayout & SCREENLAYOUT_LONG_MASK); 1709 } 1710 if (((delta.screenLayout & SCREENLAYOUT_ROUND_MASK) != SCREENLAYOUT_ROUND_UNDEFINED) 1711 && (delta.screenLayout & SCREENLAYOUT_ROUND_MASK) 1712 != (screenLayout & SCREENLAYOUT_ROUND_MASK)) { 1713 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT; 1714 screenLayout = (screenLayout & ~SCREENLAYOUT_ROUND_MASK) 1715 | (delta.screenLayout & SCREENLAYOUT_ROUND_MASK); 1716 } 1717 if ((delta.screenLayout & SCREENLAYOUT_COMPAT_NEEDED) 1718 != (screenLayout & SCREENLAYOUT_COMPAT_NEEDED) 1719 && delta.screenLayout != 0) { 1720 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT; 1721 screenLayout = (screenLayout & ~SCREENLAYOUT_COMPAT_NEEDED) 1722 | (delta.screenLayout & SCREENLAYOUT_COMPAT_NEEDED); 1723 } 1724 1725 if (((delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) != 1726 COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED) 1727 && (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) 1728 != (colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) { 1729 changed |= ActivityInfo.CONFIG_COLOR_MODE; 1730 colorMode = (colorMode & ~COLOR_MODE_WIDE_COLOR_GAMUT_MASK) 1731 | (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK); 1732 } 1733 1734 if (((delta.colorMode & COLOR_MODE_HDR_MASK) != COLOR_MODE_HDR_UNDEFINED) 1735 && (delta.colorMode & COLOR_MODE_HDR_MASK) 1736 != (colorMode & COLOR_MODE_HDR_MASK)) { 1737 changed |= ActivityInfo.CONFIG_COLOR_MODE; 1738 colorMode = (colorMode & ~COLOR_MODE_HDR_MASK) 1739 | (delta.colorMode & COLOR_MODE_HDR_MASK); 1740 } 1741 1742 if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED) 1743 && uiMode != delta.uiMode) { 1744 changed |= ActivityInfo.CONFIG_UI_MODE; 1745 if ((delta.uiMode&UI_MODE_TYPE_MASK) != UI_MODE_TYPE_UNDEFINED) { 1746 uiMode = (uiMode&~UI_MODE_TYPE_MASK) 1747 | (delta.uiMode&UI_MODE_TYPE_MASK); 1748 } 1749 if ((delta.uiMode&UI_MODE_NIGHT_MASK) != UI_MODE_NIGHT_UNDEFINED) { 1750 uiMode = (uiMode&~UI_MODE_NIGHT_MASK) 1751 | (delta.uiMode&UI_MODE_NIGHT_MASK); 1752 } 1753 } 1754 if (delta.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED 1755 && screenWidthDp != delta.screenWidthDp) { 1756 changed |= ActivityInfo.CONFIG_SCREEN_SIZE; 1757 screenWidthDp = delta.screenWidthDp; 1758 } 1759 if (delta.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED 1760 && screenHeightDp != delta.screenHeightDp) { 1761 changed |= ActivityInfo.CONFIG_SCREEN_SIZE; 1762 screenHeightDp = delta.screenHeightDp; 1763 } 1764 if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED 1765 && smallestScreenWidthDp != delta.smallestScreenWidthDp) { 1766 changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE; 1767 smallestScreenWidthDp = delta.smallestScreenWidthDp; 1768 } 1769 if (delta.densityDpi != DENSITY_DPI_UNDEFINED && 1770 densityDpi != delta.densityDpi) { 1771 changed |= ActivityInfo.CONFIG_DENSITY; 1772 densityDpi = delta.densityDpi; 1773 } 1774 if (delta.compatScreenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) { 1775 compatScreenWidthDp = delta.compatScreenWidthDp; 1776 } 1777 if (delta.compatScreenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) { 1778 compatScreenHeightDp = delta.compatScreenHeightDp; 1779 } 1780 if (delta.compatSmallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) { 1781 compatSmallestScreenWidthDp = delta.compatSmallestScreenWidthDp; 1782 } 1783 if (delta.assetsSeq != ASSETS_SEQ_UNDEFINED && delta.assetsSeq != assetsSeq) { 1784 changed |= ActivityInfo.CONFIG_ASSETS_PATHS; 1785 assetsSeq = delta.assetsSeq; 1786 } 1787 if (delta.seq != 0) { 1788 seq = delta.seq; 1789 } 1790 if (windowConfiguration.updateFrom(delta.windowConfiguration) != 0) { 1791 changed |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION; 1792 } 1793 1794 if (delta.fontWeightAdjustment != FONT_WEIGHT_ADJUSTMENT_UNDEFINED 1795 && delta.fontWeightAdjustment != fontWeightAdjustment) { 1796 changed |= ActivityInfo.CONFIG_FONT_WEIGHT_ADJUSTMENT; 1797 fontWeightAdjustment = delta.fontWeightAdjustment; 1798 } 1799 if (delta.mGrammaticalGender != GRAMMATICAL_GENDER_UNDEFINED 1800 && delta.mGrammaticalGender != mGrammaticalGender) { 1801 changed |= ActivityInfo.CONFIG_GRAMMATICAL_GENDER; 1802 mGrammaticalGender = delta.mGrammaticalGender; 1803 } 1804 1805 return changed; 1806 } 1807 1808 /** 1809 * Copies the fields specified by mask from delta into this Configuration object. This will 1810 * copy anything allowed by the mask (including undefined values). 1811 * @hide 1812 */ setTo(@onNull Configuration delta, @Config int mask, @WindowConfiguration.WindowConfig int windowMask)1813 public void setTo(@NonNull Configuration delta, @Config int mask, 1814 @WindowConfiguration.WindowConfig int windowMask) { 1815 if ((mask & ActivityInfo.CONFIG_FONT_SCALE) != 0) { 1816 fontScale = delta.fontScale; 1817 } 1818 if ((mask & ActivityInfo.CONFIG_MCC) != 0) { 1819 mcc = delta.mcc; 1820 } 1821 if ((mask & ActivityInfo.CONFIG_MNC) != 0) { 1822 mnc = delta.mnc; 1823 } 1824 if ((mask & ActivityInfo.CONFIG_LOCALE) != 0) { 1825 mLocaleList = delta.mLocaleList; 1826 if (!mLocaleList.isEmpty()) { 1827 if (!delta.locale.equals(locale)) { 1828 // Don't churn a new Locale clone unless we're actually changing it 1829 locale = (Locale) delta.locale.clone(); 1830 } 1831 } 1832 } 1833 if ((mask & ActivityInfo.CONFIG_LAYOUT_DIRECTION) != 0) { 1834 final int deltaScreenLayoutDir = delta.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK; 1835 screenLayout = (screenLayout & ~SCREENLAYOUT_LAYOUTDIR_MASK) | deltaScreenLayoutDir; 1836 } 1837 if ((mask & ActivityInfo.CONFIG_LOCALE) != 0) { 1838 userSetLocale = delta.userSetLocale; 1839 } 1840 if ((mask & ActivityInfo.CONFIG_TOUCHSCREEN) != 0) { 1841 touchscreen = delta.touchscreen; 1842 } 1843 if ((mask & ActivityInfo.CONFIG_KEYBOARD) != 0) { 1844 keyboard = delta.keyboard; 1845 } 1846 if ((mask & ActivityInfo.CONFIG_KEYBOARD_HIDDEN) != 0) { 1847 keyboardHidden = delta.keyboardHidden; 1848 hardKeyboardHidden = delta.hardKeyboardHidden; 1849 navigationHidden = delta.navigationHidden; 1850 } 1851 if ((mask & ActivityInfo.CONFIG_NAVIGATION) != 0) { 1852 navigation = delta.navigation; 1853 } 1854 if ((mask & ActivityInfo.CONFIG_ORIENTATION) != 0) { 1855 orientation = delta.orientation; 1856 } 1857 if ((mask & ActivityInfo.CONFIG_SCREEN_LAYOUT) != 0) { 1858 // Not enough granularity for each component unfortunately. 1859 screenLayout = screenLayout | (delta.screenLayout & ~SCREENLAYOUT_LAYOUTDIR_MASK); 1860 } 1861 if ((mask & ActivityInfo.CONFIG_COLOR_MODE) != 0) { 1862 colorMode = delta.colorMode; 1863 } 1864 if ((mask & ActivityInfo.CONFIG_UI_MODE) != 0) { 1865 uiMode = delta.uiMode; 1866 } 1867 if ((mask & ActivityInfo.CONFIG_SCREEN_SIZE) != 0) { 1868 screenWidthDp = delta.screenWidthDp; 1869 screenHeightDp = delta.screenHeightDp; 1870 } 1871 if ((mask & ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE) != 0) { 1872 smallestScreenWidthDp = delta.smallestScreenWidthDp; 1873 } 1874 if ((mask & ActivityInfo.CONFIG_DENSITY) != 0) { 1875 densityDpi = delta.densityDpi; 1876 } 1877 if ((mask & ActivityInfo.CONFIG_ASSETS_PATHS) != 0) { 1878 assetsSeq = delta.assetsSeq; 1879 } 1880 if ((mask & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0) { 1881 windowConfiguration.setTo(delta.windowConfiguration, windowMask); 1882 } 1883 if ((mask & ActivityInfo.CONFIG_FONT_WEIGHT_ADJUSTMENT) != 0) { 1884 fontWeightAdjustment = delta.fontWeightAdjustment; 1885 } 1886 if ((mask & ActivityInfo.CONFIG_GRAMMATICAL_GENDER) != 0) { 1887 mGrammaticalGender = delta.mGrammaticalGender; 1888 } 1889 } 1890 1891 /** 1892 * Return a bit mask of the differences between this Configuration 1893 * object and the given one. Does not change the values of either. Any 1894 * undefined fields in <var>delta</var> are ignored. 1895 * @return Returns a bit mask indicating which configuration 1896 * values have changed. 1897 */ diff(Configuration delta)1898 public @Config int diff(Configuration delta) { 1899 return diff(delta, false /* compareUndefined */, false /* publicOnly */); 1900 } 1901 1902 /** 1903 * Returns the diff against the provided {@link Configuration} excluding values that would 1904 * publicly be equivalent, such as appBounds. 1905 * @param delta {@link Configuration} to compare to. 1906 * 1907 * TODO(b/36812336): Remove once appBounds has been moved out of Configuration. 1908 * {@hide} 1909 */ diffPublicOnly(Configuration delta)1910 public int diffPublicOnly(Configuration delta) { 1911 return diff(delta, false /* compareUndefined */, true /* publicOnly */); 1912 } 1913 1914 /** 1915 * Variation of {@link #diff(Configuration)} with an option to skip checks for undefined values. 1916 * 1917 * @hide 1918 */ diff(Configuration delta, boolean compareUndefined, boolean publicOnly)1919 public int diff(Configuration delta, boolean compareUndefined, boolean publicOnly) { 1920 int changed = 0; 1921 if ((compareUndefined || delta.fontScale > 0) && fontScale != delta.fontScale) { 1922 changed |= ActivityInfo.CONFIG_FONT_SCALE; 1923 } 1924 if ((compareUndefined || delta.mcc != 0) && mcc != delta.mcc) { 1925 changed |= ActivityInfo.CONFIG_MCC; 1926 } 1927 if ((compareUndefined || delta.mnc != 0) && mnc != delta.mnc) { 1928 changed |= ActivityInfo.CONFIG_MNC; 1929 } 1930 fixUpLocaleList(); 1931 delta.fixUpLocaleList(); 1932 if ((compareUndefined || !delta.mLocaleList.isEmpty()) 1933 && !mLocaleList.equals(delta.mLocaleList)) { 1934 changed |= ActivityInfo.CONFIG_LOCALE; 1935 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION; 1936 } 1937 final int deltaScreenLayoutDir = delta.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK; 1938 if ((compareUndefined || deltaScreenLayoutDir != SCREENLAYOUT_LAYOUTDIR_UNDEFINED) 1939 && deltaScreenLayoutDir != (screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) { 1940 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION; 1941 } 1942 if ((compareUndefined || delta.touchscreen != TOUCHSCREEN_UNDEFINED) 1943 && touchscreen != delta.touchscreen) { 1944 changed |= ActivityInfo.CONFIG_TOUCHSCREEN; 1945 } 1946 if ((compareUndefined || delta.keyboard != KEYBOARD_UNDEFINED) 1947 && keyboard != delta.keyboard) { 1948 changed |= ActivityInfo.CONFIG_KEYBOARD; 1949 } 1950 if ((compareUndefined || delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED) 1951 && keyboardHidden != delta.keyboardHidden) { 1952 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN; 1953 } 1954 if ((compareUndefined || delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED) 1955 && hardKeyboardHidden != delta.hardKeyboardHidden) { 1956 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN; 1957 } 1958 if ((compareUndefined || delta.navigation != NAVIGATION_UNDEFINED) 1959 && navigation != delta.navigation) { 1960 changed |= ActivityInfo.CONFIG_NAVIGATION; 1961 } 1962 if ((compareUndefined || delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED) 1963 && navigationHidden != delta.navigationHidden) { 1964 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN; 1965 } 1966 if ((compareUndefined || delta.orientation != ORIENTATION_UNDEFINED) 1967 && orientation != delta.orientation) { 1968 changed |= ActivityInfo.CONFIG_ORIENTATION; 1969 } 1970 if ((compareUndefined || getScreenLayoutNoDirection(delta.screenLayout) != 1971 (SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED)) 1972 && getScreenLayoutNoDirection(screenLayout) != 1973 getScreenLayoutNoDirection(delta.screenLayout)) { 1974 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT; 1975 } 1976 if ((compareUndefined || 1977 (delta.colorMode & COLOR_MODE_HDR_MASK) != COLOR_MODE_HDR_UNDEFINED) 1978 && (colorMode & COLOR_MODE_HDR_MASK) != 1979 (delta.colorMode & COLOR_MODE_HDR_MASK)) { 1980 changed |= ActivityInfo.CONFIG_COLOR_MODE; 1981 } 1982 if ((compareUndefined || 1983 (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) != 1984 COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED) 1985 && (colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) != 1986 (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) { 1987 changed |= ActivityInfo.CONFIG_COLOR_MODE; 1988 } 1989 if ((compareUndefined || delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)) 1990 && uiMode != delta.uiMode) { 1991 changed |= ActivityInfo.CONFIG_UI_MODE; 1992 } 1993 if ((compareUndefined || delta.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) 1994 && screenWidthDp != delta.screenWidthDp) { 1995 changed |= ActivityInfo.CONFIG_SCREEN_SIZE; 1996 } 1997 if ((compareUndefined || delta.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) 1998 && screenHeightDp != delta.screenHeightDp) { 1999 changed |= ActivityInfo.CONFIG_SCREEN_SIZE; 2000 } 2001 if ((compareUndefined || delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) 2002 && smallestScreenWidthDp != delta.smallestScreenWidthDp) { 2003 changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE; 2004 } 2005 if ((compareUndefined || delta.densityDpi != DENSITY_DPI_UNDEFINED) 2006 && densityDpi != delta.densityDpi) { 2007 changed |= ActivityInfo.CONFIG_DENSITY; 2008 } 2009 if ((compareUndefined || delta.assetsSeq != ASSETS_SEQ_UNDEFINED) 2010 && assetsSeq != delta.assetsSeq) { 2011 changed |= ActivityInfo.CONFIG_ASSETS_PATHS; 2012 } 2013 2014 // WindowConfiguration differences aren't considered public... 2015 if (!publicOnly 2016 && windowConfiguration.diff(delta.windowConfiguration, compareUndefined) != 0) { 2017 changed |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION; 2018 } 2019 2020 if ((compareUndefined || delta.fontWeightAdjustment != FONT_WEIGHT_ADJUSTMENT_UNDEFINED) 2021 && fontWeightAdjustment != delta.fontWeightAdjustment) { 2022 changed |= ActivityInfo.CONFIG_FONT_WEIGHT_ADJUSTMENT; 2023 } 2024 2025 if ((compareUndefined || delta.mGrammaticalGender != GRAMMATICAL_GENDER_UNDEFINED) 2026 && mGrammaticalGender != delta.mGrammaticalGender) { 2027 changed |= ActivityInfo.CONFIG_GRAMMATICAL_GENDER; 2028 } 2029 return changed; 2030 } 2031 2032 /** 2033 * Determines if a new resource needs to be loaded from the bit set of 2034 * configuration changes returned by {@link #updateFrom(Configuration)}. 2035 * 2036 * @param configChanges the mask of changes configurations as returned by 2037 * {@link #updateFrom(Configuration)} 2038 * @param interestingChanges the configuration changes that the resource 2039 * can handle as given in 2040 * {@link android.util.TypedValue#changingConfigurations} 2041 * @return {@code true} if the resource needs to be loaded, {@code false} 2042 * otherwise 2043 */ needNewResources(@onfig int configChanges, @Config int interestingChanges)2044 public static boolean needNewResources(@Config int configChanges, 2045 @Config int interestingChanges) { 2046 // CONFIG_ASSETS_PATHS and CONFIG_FONT_SCALE are higher level configuration changes that 2047 // all resources are subject to change with. 2048 interestingChanges = interestingChanges | ActivityInfo.CONFIG_ASSETS_PATHS 2049 | ActivityInfo.CONFIG_FONT_SCALE; 2050 return (configChanges & interestingChanges) != 0; 2051 } 2052 2053 /** 2054 * @hide Return true if the sequence of 'other' is better than this. Assumes 2055 * that 'this' is your current sequence and 'other' is a new one you have 2056 * received some how and want to compare with what you have. 2057 */ isOtherSeqNewer(Configuration other)2058 public boolean isOtherSeqNewer(Configuration other) { 2059 if (other == null) { 2060 // Validation check. 2061 return false; 2062 } 2063 if (other.seq == 0) { 2064 // If the other sequence is not specified, then we must assume 2065 // it is newer since we don't know any better. 2066 return true; 2067 } 2068 if (seq == 0) { 2069 // If this sequence is not specified, then we also consider the 2070 // other is better. Yes we have a preference for other. Sue us. 2071 return true; 2072 } 2073 int diff = other.seq - seq; 2074 if (Math.abs(diff) > 0x10000000) { 2075 // If there has been a sufficiently large jump, assume the 2076 // sequence has wrapped around. 2077 return diff < 0; 2078 } 2079 return diff > 0; 2080 } 2081 2082 /** 2083 * Parcelable methods 2084 */ describeContents()2085 public int describeContents() { 2086 return 0; 2087 } 2088 writeToParcel(Parcel dest, int flags)2089 public void writeToParcel(Parcel dest, int flags) { 2090 dest.writeFloat(fontScale); 2091 dest.writeInt(mcc); 2092 dest.writeInt(mnc); 2093 2094 fixUpLocaleList(); 2095 dest.writeTypedObject(mLocaleList, flags); 2096 2097 if(userSetLocale) { 2098 dest.writeInt(1); 2099 } else { 2100 dest.writeInt(0); 2101 } 2102 dest.writeInt(touchscreen); 2103 dest.writeInt(keyboard); 2104 dest.writeInt(keyboardHidden); 2105 dest.writeInt(hardKeyboardHidden); 2106 dest.writeInt(navigation); 2107 dest.writeInt(navigationHidden); 2108 dest.writeInt(orientation); 2109 dest.writeInt(screenLayout); 2110 dest.writeInt(colorMode); 2111 dest.writeInt(uiMode); 2112 dest.writeInt(screenWidthDp); 2113 dest.writeInt(screenHeightDp); 2114 dest.writeInt(smallestScreenWidthDp); 2115 dest.writeInt(densityDpi); 2116 dest.writeInt(compatScreenWidthDp); 2117 dest.writeInt(compatScreenHeightDp); 2118 dest.writeInt(compatSmallestScreenWidthDp); 2119 windowConfiguration.writeToParcel(dest, flags); 2120 dest.writeInt(assetsSeq); 2121 dest.writeInt(seq); 2122 dest.writeInt(fontWeightAdjustment); 2123 dest.writeInt(mGrammaticalGender); 2124 } 2125 readFromParcel(Parcel source)2126 public void readFromParcel(Parcel source) { 2127 fontScale = source.readFloat(); 2128 mcc = source.readInt(); 2129 mnc = source.readInt(); 2130 2131 mLocaleList = source.readTypedObject(LocaleList.CREATOR); 2132 locale = mLocaleList.get(0); 2133 2134 userSetLocale = (source.readInt()==1); 2135 touchscreen = source.readInt(); 2136 keyboard = source.readInt(); 2137 keyboardHidden = source.readInt(); 2138 hardKeyboardHidden = source.readInt(); 2139 navigation = source.readInt(); 2140 navigationHidden = source.readInt(); 2141 orientation = source.readInt(); 2142 screenLayout = source.readInt(); 2143 colorMode = source.readInt(); 2144 uiMode = source.readInt(); 2145 screenWidthDp = source.readInt(); 2146 screenHeightDp = source.readInt(); 2147 smallestScreenWidthDp = source.readInt(); 2148 densityDpi = source.readInt(); 2149 compatScreenWidthDp = source.readInt(); 2150 compatScreenHeightDp = source.readInt(); 2151 compatSmallestScreenWidthDp = source.readInt(); 2152 windowConfiguration.readFromParcel(source); 2153 assetsSeq = source.readInt(); 2154 seq = source.readInt(); 2155 fontWeightAdjustment = source.readInt(); 2156 mGrammaticalGender = source.readInt(); 2157 } 2158 2159 public static final @android.annotation.NonNull Parcelable.Creator<Configuration> CREATOR 2160 = new Parcelable.Creator<Configuration>() { 2161 public Configuration createFromParcel(Parcel source) { 2162 return new Configuration(source); 2163 } 2164 2165 public Configuration[] newArray(int size) { 2166 return new Configuration[size]; 2167 } 2168 }; 2169 2170 /** 2171 * Construct this Configuration object, reading from the Parcel. 2172 */ Configuration(Parcel source)2173 private Configuration(Parcel source) { 2174 readFromParcel(source); 2175 } 2176 2177 2178 /** 2179 * Retuns whether the configuration is in night mode 2180 * @return true if night mode is active and false otherwise 2181 */ isNightModeActive()2182 public boolean isNightModeActive() { 2183 return (uiMode & UI_MODE_NIGHT_MASK) == UI_MODE_NIGHT_YES; 2184 } 2185 compareTo(Configuration that)2186 public int compareTo(Configuration that) { 2187 int n; 2188 float a = this.fontScale; 2189 float b = that.fontScale; 2190 if (a < b) return -1; 2191 if (a > b) return 1; 2192 n = this.mcc - that.mcc; 2193 if (n != 0) return n; 2194 n = this.mnc - that.mnc; 2195 if (n != 0) return n; 2196 2197 fixUpLocaleList(); 2198 that.fixUpLocaleList(); 2199 // for backward compatibility, we consider an empty locale list to be greater 2200 // than any non-empty locale list. 2201 if (this.mLocaleList.isEmpty()) { 2202 if (!that.mLocaleList.isEmpty()) return 1; 2203 } else if (that.mLocaleList.isEmpty()) { 2204 return -1; 2205 } else { 2206 final int minSize = Math.min(this.mLocaleList.size(), that.mLocaleList.size()); 2207 for (int i = 0; i < minSize; ++i) { 2208 final Locale thisLocale = this.mLocaleList.get(i); 2209 final Locale thatLocale = that.mLocaleList.get(i); 2210 n = thisLocale.getLanguage().compareTo(thatLocale.getLanguage()); 2211 if (n != 0) return n; 2212 n = thisLocale.getCountry().compareTo(thatLocale.getCountry()); 2213 if (n != 0) return n; 2214 n = thisLocale.getVariant().compareTo(thatLocale.getVariant()); 2215 if (n != 0) return n; 2216 n = thisLocale.toLanguageTag().compareTo(thatLocale.toLanguageTag()); 2217 if (n != 0) return n; 2218 } 2219 n = this.mLocaleList.size() - that.mLocaleList.size(); 2220 if (n != 0) return n; 2221 } 2222 2223 n = this.mGrammaticalGender - that.mGrammaticalGender; 2224 if (n != 0) return n; 2225 n = this.touchscreen - that.touchscreen; 2226 if (n != 0) return n; 2227 n = this.keyboard - that.keyboard; 2228 if (n != 0) return n; 2229 n = this.keyboardHidden - that.keyboardHidden; 2230 if (n != 0) return n; 2231 n = this.hardKeyboardHidden - that.hardKeyboardHidden; 2232 if (n != 0) return n; 2233 n = this.navigation - that.navigation; 2234 if (n != 0) return n; 2235 n = this.navigationHidden - that.navigationHidden; 2236 if (n != 0) return n; 2237 n = this.orientation - that.orientation; 2238 if (n != 0) return n; 2239 n = this.colorMode - that.colorMode; 2240 if (n != 0) return n; 2241 n = this.screenLayout - that.screenLayout; 2242 if (n != 0) return n; 2243 n = this.uiMode - that.uiMode; 2244 if (n != 0) return n; 2245 n = this.screenWidthDp - that.screenWidthDp; 2246 if (n != 0) return n; 2247 n = this.screenHeightDp - that.screenHeightDp; 2248 if (n != 0) return n; 2249 n = this.smallestScreenWidthDp - that.smallestScreenWidthDp; 2250 if (n != 0) return n; 2251 n = this.densityDpi - that.densityDpi; 2252 if (n != 0) return n; 2253 n = this.assetsSeq - that.assetsSeq; 2254 if (n != 0) return n; 2255 n = windowConfiguration.compareTo(that.windowConfiguration); 2256 if (n != 0) return n; 2257 n = this.fontWeightAdjustment - that.fontWeightAdjustment; 2258 return n; 2259 } 2260 equals(Configuration that)2261 public boolean equals(Configuration that) { 2262 if (that == null) return false; 2263 if (that == this) return true; 2264 return this.compareTo(that) == 0; 2265 } 2266 equals(@ullable Object that)2267 public boolean equals(@Nullable Object that) { 2268 try { 2269 return equals((Configuration)that); 2270 } catch (ClassCastException e) { 2271 } 2272 return false; 2273 } 2274 hashCode()2275 public int hashCode() { 2276 int result = 17; 2277 result = 31 * result + Float.floatToIntBits(fontScale); 2278 result = 31 * result + mcc; 2279 result = 31 * result + mnc; 2280 result = 31 * result + mLocaleList.hashCode(); 2281 result = 31 * result + touchscreen; 2282 result = 31 * result + keyboard; 2283 result = 31 * result + keyboardHidden; 2284 result = 31 * result + hardKeyboardHidden; 2285 result = 31 * result + navigation; 2286 result = 31 * result + navigationHidden; 2287 result = 31 * result + orientation; 2288 result = 31 * result + screenLayout; 2289 result = 31 * result + colorMode; 2290 result = 31 * result + uiMode; 2291 result = 31 * result + screenWidthDp; 2292 result = 31 * result + screenHeightDp; 2293 result = 31 * result + smallestScreenWidthDp; 2294 result = 31 * result + densityDpi; 2295 result = 31 * result + assetsSeq; 2296 result = 31 * result + fontWeightAdjustment; 2297 result = 31 * result + mGrammaticalGender; 2298 return result; 2299 } 2300 2301 /** 2302 * Returns the user preference for the grammatical gender. Will be 2303 * {@link #GRAMMATICAL_GENDER_NOT_SPECIFIED} or 2304 * {@link #GRAMMATICAL_GENDER_NEUTRAL} or 2305 * {@link #GRAMMATICAL_GENDER_FEMININE} or 2306 * {@link #GRAMMATICAL_GENDER_MASCULINE}. 2307 * 2308 * @return The preferred grammatical gender. 2309 */ 2310 @GrammaticalGender getGrammaticalGender()2311 public int getGrammaticalGender() { 2312 return mGrammaticalGender == GRAMMATICAL_GENDER_UNDEFINED 2313 ? GRAMMATICAL_GENDER_NOT_SPECIFIED : mGrammaticalGender; 2314 } 2315 2316 /** 2317 * Internal getter of grammatical gender, to get the raw value of grammatical gender, 2318 * which include {@link #GRAMMATICAL_GENDER_UNDEFINED}. 2319 * @hide 2320 */ 2321 getGrammaticalGenderRaw()2322 public int getGrammaticalGenderRaw() { 2323 return mGrammaticalGender; 2324 } 2325 2326 /** 2327 * Sets the user preference for the grammatical gender. This is only for frameworks to easily 2328 * override the gender in the configuration. To update the grammatical gender for an application 2329 * use {@link GrammaticalInflectionManager#setRequestedApplicationGrammaticalGender(int)}. 2330 * 2331 * @param grammaticalGender The preferred grammatical gender. 2332 * @hide 2333 */ setGrammaticalGender(@rammaticalGender int grammaticalGender)2334 public void setGrammaticalGender(@GrammaticalGender int grammaticalGender) { 2335 mGrammaticalGender = grammaticalGender; 2336 } 2337 2338 /** 2339 * Get the locale list. This is the preferred way for getting the locales (instead of using 2340 * the direct accessor to {@link #locale}, which would only provide the primary locale). 2341 * 2342 * @return The locale list. 2343 */ getLocales()2344 public @NonNull LocaleList getLocales() { 2345 fixUpLocaleList(); 2346 return mLocaleList; 2347 } 2348 2349 /** 2350 * Set the locale list. This is the preferred way for setting up the locales (instead of using 2351 * the direct accessor or {@link #setLocale(Locale)}). This will also set the layout direction 2352 * according to the first locale in the list. 2353 * 2354 * Note that the layout direction will always come from the first locale in the locale list, 2355 * even if the locale is not supported by the resources (the resources may only support 2356 * another locale further down the list which has a different direction). 2357 * 2358 * @param locales The locale list. If null, an empty LocaleList will be assigned. 2359 */ setLocales(@ullable LocaleList locales)2360 public void setLocales(@Nullable LocaleList locales) { 2361 LocaleList oldList = mLocaleList; 2362 mLocaleList = locales == null ? LocaleList.getEmptyLocaleList() : locales; 2363 locale = mLocaleList.get(0); 2364 if (!mLocaleList.equals(oldList)) { 2365 Slog.v(TAG, "Updating configuration, locales updated from " + oldList 2366 + " to " + mLocaleList); 2367 } 2368 setLayoutDirection(locale); 2369 } 2370 2371 /** 2372 * Set the locale list to a list of just one locale. This will also set the layout direction 2373 * according to the locale. 2374 * 2375 * Note that after this is run, calling <code>.equals()</code> on the input locale and the 2376 * {@link #locale} attribute would return <code>true</code> if they are not null, but there is 2377 * no guarantee that they would be the same object. 2378 * 2379 * See also the note about layout direction in {@link #setLocales(LocaleList)}. 2380 * 2381 * @param loc The locale. Can be null. 2382 */ setLocale(@ullable Locale loc)2383 public void setLocale(@Nullable Locale loc) { 2384 setLocales(loc == null ? LocaleList.getEmptyLocaleList() : new LocaleList(loc)); 2385 } 2386 2387 /** 2388 * @hide 2389 * 2390 * Clears the locale without changing layout direction. 2391 */ clearLocales()2392 public void clearLocales() { 2393 mLocaleList = LocaleList.getEmptyLocaleList(); 2394 locale = null; 2395 } 2396 2397 /** 2398 * Return the layout direction. Will be either {@link View#LAYOUT_DIRECTION_LTR} or 2399 * {@link View#LAYOUT_DIRECTION_RTL}. 2400 * 2401 * @return Returns {@link View#LAYOUT_DIRECTION_RTL} if the configuration 2402 * is {@link #SCREENLAYOUT_LAYOUTDIR_RTL}, otherwise {@link View#LAYOUT_DIRECTION_LTR}. 2403 */ getLayoutDirection()2404 public int getLayoutDirection() { 2405 return (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK) == SCREENLAYOUT_LAYOUTDIR_RTL 2406 ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR; 2407 } 2408 2409 /** 2410 * Set the layout direction from a Locale. 2411 * 2412 * @param loc The Locale. If null will set the layout direction to 2413 * {@link View#LAYOUT_DIRECTION_LTR}. If not null will set it to the layout direction 2414 * corresponding to the Locale. 2415 * 2416 * @see View#LAYOUT_DIRECTION_LTR 2417 * @see View#LAYOUT_DIRECTION_RTL 2418 */ setLayoutDirection(Locale loc)2419 public void setLayoutDirection(Locale loc) { 2420 // There is a "1" difference between the configuration values for 2421 // layout direction and View constants for layout direction, just add "1". 2422 final int layoutDirection = 1 + TextUtils.getLayoutDirectionFromLocale(loc); 2423 screenLayout = (screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK)| 2424 (layoutDirection << SCREENLAYOUT_LAYOUTDIR_SHIFT); 2425 } 2426 getScreenLayoutNoDirection(int screenLayout)2427 private static int getScreenLayoutNoDirection(int screenLayout) { 2428 return screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK; 2429 } 2430 2431 /** 2432 * Return whether the screen has a round shape. Apps may choose to change styling based 2433 * on this property, such as the alignment or layout of text or informational icons. 2434 * 2435 * @return true if the screen is rounded, false otherwise 2436 */ isScreenRound()2437 public boolean isScreenRound() { 2438 return (screenLayout & SCREENLAYOUT_ROUND_MASK) == SCREENLAYOUT_ROUND_YES; 2439 } 2440 2441 /** 2442 * Return whether the screen has a wide color gamut and wide color gamut rendering 2443 * is supported by this device. 2444 * 2445 * When true, it implies the screen is colorspace aware but not 2446 * necessarily color-managed. The final colors may still be changed by the 2447 * screen depending on user settings. 2448 * 2449 * @return true if the screen has a wide color gamut and wide color gamut rendering 2450 * is supported, false otherwise 2451 */ isScreenWideColorGamut()2452 public boolean isScreenWideColorGamut() { 2453 return (colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) == COLOR_MODE_WIDE_COLOR_GAMUT_YES; 2454 } 2455 2456 /** 2457 * Return whether the screen has a high dynamic range. 2458 * 2459 * @return true if the screen has a high dynamic range, false otherwise 2460 */ isScreenHdr()2461 public boolean isScreenHdr() { 2462 return (colorMode & COLOR_MODE_HDR_MASK) == COLOR_MODE_HDR_YES; 2463 } 2464 2465 /** 2466 * 2467 * @hide 2468 */ localesToResourceQualifier(LocaleList locs)2469 public static String localesToResourceQualifier(LocaleList locs) { 2470 final StringBuilder sb = new StringBuilder(); 2471 for (int i = 0; i < locs.size(); i++) { 2472 final Locale loc = locs.get(i); 2473 final int l = loc.getLanguage().length(); 2474 if (l == 0) { 2475 continue; 2476 } 2477 final int s = loc.getScript().length(); 2478 final int c = loc.getCountry().length(); 2479 final int v = loc.getVariant().length(); 2480 // We ignore locale extensions, since they are not supported by AAPT 2481 2482 if (sb.length() != 0) { 2483 sb.append(","); 2484 } 2485 if (l == 2 && s == 0 && (c == 0 || c == 2) && v == 0) { 2486 // Traditional locale format: xx or xx-rYY 2487 sb.append(loc.getLanguage()); 2488 if (c == 2) { 2489 sb.append("-r").append(loc.getCountry()); 2490 } 2491 } else { 2492 sb.append("b+"); 2493 sb.append(loc.getLanguage()); 2494 if (s != 0) { 2495 sb.append("+"); 2496 sb.append(loc.getScript()); 2497 } 2498 if (c != 0) { 2499 sb.append("+"); 2500 sb.append(loc.getCountry()); 2501 } 2502 if (v != 0) { 2503 sb.append("+"); 2504 sb.append(loc.getVariant()); 2505 } 2506 } 2507 } 2508 return sb.toString(); 2509 } 2510 2511 2512 /** 2513 * Returns a string representation of the configuration that can be parsed 2514 * by build tools (like AAPT), without display metrics included 2515 * 2516 * @hide 2517 */ 2518 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) resourceQualifierString(Configuration config)2519 public static String resourceQualifierString(Configuration config) { 2520 return resourceQualifierString(config, null); 2521 } 2522 2523 /** 2524 * Returns a string representation of the configuration that can be parsed 2525 * by build tools (like AAPT). 2526 * 2527 * @hide 2528 */ resourceQualifierString(Configuration config, DisplayMetrics metrics)2529 public static String resourceQualifierString(Configuration config, DisplayMetrics metrics) { 2530 ArrayList<String> parts = new ArrayList<String>(); 2531 2532 if (config.mcc != 0) { 2533 parts.add("mcc" + config.mcc); 2534 if (config.mnc != 0) { 2535 parts.add("mnc" + config.mnc); 2536 } 2537 } 2538 2539 if (!config.mLocaleList.isEmpty()) { 2540 final String resourceQualifier = localesToResourceQualifier(config.mLocaleList); 2541 if (!resourceQualifier.isEmpty()) { 2542 parts.add(resourceQualifier); 2543 } 2544 } 2545 2546 switch (config.mGrammaticalGender) { 2547 case Configuration.GRAMMATICAL_GENDER_NEUTRAL: 2548 parts.add("neuter"); 2549 break; 2550 case Configuration.GRAMMATICAL_GENDER_FEMININE: 2551 parts.add("feminine"); 2552 break; 2553 case Configuration.GRAMMATICAL_GENDER_MASCULINE: 2554 parts.add("masculine"); 2555 break; 2556 default: 2557 break; 2558 } 2559 2560 switch (config.screenLayout & Configuration.SCREENLAYOUT_LAYOUTDIR_MASK) { 2561 case Configuration.SCREENLAYOUT_LAYOUTDIR_LTR: 2562 parts.add("ldltr"); 2563 break; 2564 case Configuration.SCREENLAYOUT_LAYOUTDIR_RTL: 2565 parts.add("ldrtl"); 2566 break; 2567 default: 2568 break; 2569 } 2570 2571 if (config.smallestScreenWidthDp != 0) { 2572 parts.add("sw" + config.smallestScreenWidthDp + "dp"); 2573 } 2574 2575 if (config.screenWidthDp != 0) { 2576 parts.add("w" + config.screenWidthDp + "dp"); 2577 } 2578 2579 if (config.screenHeightDp != 0) { 2580 parts.add("h" + config.screenHeightDp + "dp"); 2581 } 2582 2583 switch (config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) { 2584 case Configuration.SCREENLAYOUT_SIZE_SMALL: 2585 parts.add("small"); 2586 break; 2587 case Configuration.SCREENLAYOUT_SIZE_NORMAL: 2588 parts.add("normal"); 2589 break; 2590 case Configuration.SCREENLAYOUT_SIZE_LARGE: 2591 parts.add("large"); 2592 break; 2593 case Configuration.SCREENLAYOUT_SIZE_XLARGE: 2594 parts.add("xlarge"); 2595 break; 2596 default: 2597 break; 2598 } 2599 2600 switch (config.screenLayout & Configuration.SCREENLAYOUT_LONG_MASK) { 2601 case Configuration.SCREENLAYOUT_LONG_YES: 2602 parts.add("long"); 2603 break; 2604 case Configuration.SCREENLAYOUT_LONG_NO: 2605 parts.add("notlong"); 2606 break; 2607 default: 2608 break; 2609 } 2610 2611 switch (config.screenLayout & Configuration.SCREENLAYOUT_ROUND_MASK) { 2612 case Configuration.SCREENLAYOUT_ROUND_YES: 2613 parts.add("round"); 2614 break; 2615 case Configuration.SCREENLAYOUT_ROUND_NO: 2616 parts.add("notround"); 2617 break; 2618 default: 2619 break; 2620 } 2621 2622 switch (config.colorMode & Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_MASK) { 2623 case Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_YES: 2624 parts.add("widecg"); 2625 break; 2626 case Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_NO: 2627 parts.add("nowidecg"); 2628 break; 2629 default: 2630 break; 2631 } 2632 2633 switch (config.colorMode & Configuration.COLOR_MODE_HDR_MASK) { 2634 case Configuration.COLOR_MODE_HDR_YES: 2635 parts.add("highdr"); 2636 break; 2637 case Configuration.COLOR_MODE_HDR_NO: 2638 parts.add("lowdr"); 2639 break; 2640 default: 2641 break; 2642 } 2643 2644 switch (config.orientation) { 2645 case Configuration.ORIENTATION_LANDSCAPE: 2646 parts.add("land"); 2647 break; 2648 case Configuration.ORIENTATION_PORTRAIT: 2649 parts.add("port"); 2650 break; 2651 default: 2652 break; 2653 } 2654 2655 final String uiModeTypeString = 2656 getUiModeTypeString(config.uiMode & Configuration.UI_MODE_TYPE_MASK); 2657 if (uiModeTypeString != null) { 2658 parts.add(uiModeTypeString); 2659 } 2660 2661 switch (config.uiMode & Configuration.UI_MODE_NIGHT_MASK) { 2662 case Configuration.UI_MODE_NIGHT_YES: 2663 parts.add("night"); 2664 break; 2665 case Configuration.UI_MODE_NIGHT_NO: 2666 parts.add("notnight"); 2667 break; 2668 default: 2669 break; 2670 } 2671 2672 switch (config.densityDpi) { 2673 case DENSITY_DPI_UNDEFINED: 2674 break; 2675 case 120: 2676 parts.add("ldpi"); 2677 break; 2678 case 160: 2679 parts.add("mdpi"); 2680 break; 2681 case 213: 2682 parts.add("tvdpi"); 2683 break; 2684 case 240: 2685 parts.add("hdpi"); 2686 break; 2687 case 320: 2688 parts.add("xhdpi"); 2689 break; 2690 case 480: 2691 parts.add("xxhdpi"); 2692 break; 2693 case 640: 2694 parts.add("xxxhdpi"); 2695 break; 2696 case DENSITY_DPI_ANY: 2697 parts.add("anydpi"); 2698 break; 2699 case DENSITY_DPI_NONE: 2700 parts.add("nodpi"); 2701 break; 2702 default: 2703 parts.add(config.densityDpi + "dpi"); 2704 break; 2705 } 2706 2707 switch (config.touchscreen) { 2708 case Configuration.TOUCHSCREEN_NOTOUCH: 2709 parts.add("notouch"); 2710 break; 2711 case Configuration.TOUCHSCREEN_FINGER: 2712 parts.add("finger"); 2713 break; 2714 default: 2715 break; 2716 } 2717 2718 switch (config.keyboardHidden) { 2719 case Configuration.KEYBOARDHIDDEN_NO: 2720 parts.add("keysexposed"); 2721 break; 2722 case Configuration.KEYBOARDHIDDEN_YES: 2723 parts.add("keyshidden"); 2724 break; 2725 case Configuration.KEYBOARDHIDDEN_SOFT: 2726 parts.add("keyssoft"); 2727 break; 2728 default: 2729 break; 2730 } 2731 2732 switch (config.keyboard) { 2733 case Configuration.KEYBOARD_NOKEYS: 2734 parts.add("nokeys"); 2735 break; 2736 case Configuration.KEYBOARD_QWERTY: 2737 parts.add("qwerty"); 2738 break; 2739 case Configuration.KEYBOARD_12KEY: 2740 parts.add("12key"); 2741 break; 2742 default: 2743 break; 2744 } 2745 2746 switch (config.navigationHidden) { 2747 case Configuration.NAVIGATIONHIDDEN_NO: 2748 parts.add("navexposed"); 2749 break; 2750 case Configuration.NAVIGATIONHIDDEN_YES: 2751 parts.add("navhidden"); 2752 break; 2753 default: 2754 break; 2755 } 2756 2757 switch (config.navigation) { 2758 case Configuration.NAVIGATION_NONAV: 2759 parts.add("nonav"); 2760 break; 2761 case Configuration.NAVIGATION_DPAD: 2762 parts.add("dpad"); 2763 break; 2764 case Configuration.NAVIGATION_TRACKBALL: 2765 parts.add("trackball"); 2766 break; 2767 case Configuration.NAVIGATION_WHEEL: 2768 parts.add("wheel"); 2769 break; 2770 default: 2771 break; 2772 } 2773 2774 if (metrics != null) { 2775 final int width, height; 2776 if (metrics.widthPixels >= metrics.heightPixels) { 2777 width = metrics.widthPixels; 2778 height = metrics.heightPixels; 2779 } else { 2780 //noinspection SuspiciousNameCombination 2781 width = metrics.heightPixels; 2782 //noinspection SuspiciousNameCombination 2783 height = metrics.widthPixels; 2784 } 2785 parts.add(width + "x" + height); 2786 } 2787 2788 parts.add("v" + Build.VERSION.RESOURCES_SDK_INT); 2789 return TextUtils.join("-", parts); 2790 } 2791 2792 /** 2793 * @hide 2794 */ getUiModeTypeString(int uiModeType)2795 public static String getUiModeTypeString(int uiModeType) { 2796 switch (uiModeType) { 2797 case Configuration.UI_MODE_TYPE_APPLIANCE: 2798 return "appliance"; 2799 case Configuration.UI_MODE_TYPE_DESK: 2800 return "desk"; 2801 case Configuration.UI_MODE_TYPE_TELEVISION: 2802 return "television"; 2803 case Configuration.UI_MODE_TYPE_CAR: 2804 return "car"; 2805 case Configuration.UI_MODE_TYPE_WATCH: 2806 return "watch"; 2807 case Configuration.UI_MODE_TYPE_VR_HEADSET: 2808 return "vrheadset"; 2809 default: 2810 return null; 2811 } 2812 } 2813 2814 /** 2815 * Generate a delta Configuration between <code>base</code> and <code>change</code>. The 2816 * resulting delta can be used with {@link #updateFrom(Configuration)}. 2817 * <p /> 2818 * Caveat: If the any of the Configuration's members becomes undefined, then 2819 * {@link #updateFrom(Configuration)} will treat it as a no-op and not update that member. 2820 * 2821 * This is fine for device configurations as no member is ever undefined. 2822 */ 2823 @NonNull generateDelta( @onNull Configuration base, @NonNull Configuration change)2824 public static Configuration generateDelta( 2825 @NonNull Configuration base, @NonNull Configuration change) { 2826 final Configuration delta = new Configuration(); 2827 if (base.fontScale != change.fontScale) { 2828 delta.fontScale = change.fontScale; 2829 } 2830 2831 if (base.mcc != change.mcc) { 2832 delta.mcc = change.mcc; 2833 } 2834 2835 if (base.mnc != change.mnc) { 2836 delta.mnc = change.mnc; 2837 } 2838 2839 base.fixUpLocaleList(); 2840 change.fixUpLocaleList(); 2841 if (!base.mLocaleList.equals(change.mLocaleList)) { 2842 delta.mLocaleList = change.mLocaleList; 2843 delta.locale = change.locale; 2844 } 2845 2846 if (base.mGrammaticalGender != change.mGrammaticalGender) { 2847 delta.mGrammaticalGender = change.mGrammaticalGender; 2848 } 2849 2850 if (base.touchscreen != change.touchscreen) { 2851 delta.touchscreen = change.touchscreen; 2852 } 2853 2854 if (base.keyboard != change.keyboard) { 2855 delta.keyboard = change.keyboard; 2856 } 2857 2858 if (base.keyboardHidden != change.keyboardHidden) { 2859 delta.keyboardHidden = change.keyboardHidden; 2860 } 2861 2862 if (base.navigation != change.navigation) { 2863 delta.navigation = change.navigation; 2864 } 2865 2866 if (base.navigationHidden != change.navigationHidden) { 2867 delta.navigationHidden = change.navigationHidden; 2868 } 2869 2870 if (base.orientation != change.orientation) { 2871 delta.orientation = change.orientation; 2872 } 2873 2874 if ((base.screenLayout & SCREENLAYOUT_SIZE_MASK) != 2875 (change.screenLayout & SCREENLAYOUT_SIZE_MASK)) { 2876 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_SIZE_MASK; 2877 } 2878 2879 if ((base.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK) != 2880 (change.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) { 2881 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK; 2882 } 2883 2884 if ((base.screenLayout & SCREENLAYOUT_LONG_MASK) != 2885 (change.screenLayout & SCREENLAYOUT_LONG_MASK)) { 2886 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_LONG_MASK; 2887 } 2888 2889 if ((base.screenLayout & SCREENLAYOUT_ROUND_MASK) != 2890 (change.screenLayout & SCREENLAYOUT_ROUND_MASK)) { 2891 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_ROUND_MASK; 2892 } 2893 2894 if ((base.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) != 2895 (change.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) { 2896 delta.colorMode |= change.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK; 2897 } 2898 2899 if ((base.colorMode & COLOR_MODE_HDR_MASK) != 2900 (change.colorMode & COLOR_MODE_HDR_MASK)) { 2901 delta.colorMode |= change.colorMode & COLOR_MODE_HDR_MASK; 2902 } 2903 2904 if ((base.uiMode & UI_MODE_TYPE_MASK) != (change.uiMode & UI_MODE_TYPE_MASK)) { 2905 delta.uiMode |= change.uiMode & UI_MODE_TYPE_MASK; 2906 } 2907 2908 if ((base.uiMode & UI_MODE_NIGHT_MASK) != (change.uiMode & UI_MODE_NIGHT_MASK)) { 2909 delta.uiMode |= change.uiMode & UI_MODE_NIGHT_MASK; 2910 } 2911 2912 if (base.screenWidthDp != change.screenWidthDp) { 2913 delta.screenWidthDp = change.screenWidthDp; 2914 } 2915 2916 if (base.screenHeightDp != change.screenHeightDp) { 2917 delta.screenHeightDp = change.screenHeightDp; 2918 } 2919 2920 if (base.smallestScreenWidthDp != change.smallestScreenWidthDp) { 2921 delta.smallestScreenWidthDp = change.smallestScreenWidthDp; 2922 } 2923 2924 if (base.densityDpi != change.densityDpi) { 2925 delta.densityDpi = change.densityDpi; 2926 } 2927 2928 if (base.assetsSeq != change.assetsSeq) { 2929 delta.assetsSeq = change.assetsSeq; 2930 } 2931 2932 if (!base.windowConfiguration.equals(change.windowConfiguration)) { 2933 delta.windowConfiguration.setTo(change.windowConfiguration); 2934 } 2935 2936 if (base.fontWeightAdjustment != change.fontWeightAdjustment) { 2937 delta.fontWeightAdjustment = change.fontWeightAdjustment; 2938 } 2939 return delta; 2940 } 2941 2942 private static final String XML_ATTR_FONT_SCALE = "fs"; 2943 private static final String XML_ATTR_MCC = "mcc"; 2944 private static final String XML_ATTR_MNC = "mnc"; 2945 private static final String XML_ATTR_LOCALES = "locales"; 2946 private static final String XML_ATTR_TOUCHSCREEN = "touch"; 2947 private static final String XML_ATTR_KEYBOARD = "key"; 2948 private static final String XML_ATTR_KEYBOARD_HIDDEN = "keyHid"; 2949 private static final String XML_ATTR_HARD_KEYBOARD_HIDDEN = "hardKeyHid"; 2950 private static final String XML_ATTR_NAVIGATION = "nav"; 2951 private static final String XML_ATTR_NAVIGATION_HIDDEN = "navHid"; 2952 private static final String XML_ATTR_ORIENTATION = "ori"; 2953 private static final String XML_ATTR_ROTATION = "rot"; 2954 private static final String XML_ATTR_SCREEN_LAYOUT = "scrLay"; 2955 private static final String XML_ATTR_COLOR_MODE = "clrMod"; 2956 private static final String XML_ATTR_UI_MODE = "ui"; 2957 private static final String XML_ATTR_SCREEN_WIDTH = "width"; 2958 private static final String XML_ATTR_SCREEN_HEIGHT = "height"; 2959 private static final String XML_ATTR_SMALLEST_WIDTH = "sw"; 2960 private static final String XML_ATTR_DENSITY = "density"; 2961 private static final String XML_ATTR_APP_BOUNDS = "app_bounds"; 2962 private static final String XML_ATTR_FONT_WEIGHT_ADJUSTMENT = "fontWeightAdjustment"; 2963 private static final String XML_ATTR_GRAMMATICAL_GENDER = "grammaticalGender"; 2964 2965 /** 2966 * Reads the attributes corresponding to Configuration member fields from the Xml parser. 2967 * The parser is expected to be on a tag which has Configuration attributes. 2968 * 2969 * @param parser The Xml parser from which to read attributes. 2970 * @param configOut The Configuration to populate from the Xml attributes. 2971 * {@hide} 2972 */ readXmlAttrs(XmlPullParser parser, Configuration configOut)2973 public static void readXmlAttrs(XmlPullParser parser, Configuration configOut) 2974 throws XmlPullParserException, IOException { 2975 configOut.fontScale = Float.intBitsToFloat( 2976 XmlUtils.readIntAttribute(parser, XML_ATTR_FONT_SCALE, 0)); 2977 configOut.mcc = XmlUtils.readIntAttribute(parser, XML_ATTR_MCC, 0); 2978 configOut.mnc = XmlUtils.readIntAttribute(parser, XML_ATTR_MNC, 0); 2979 2980 final String localesStr = XmlUtils.readStringAttribute(parser, XML_ATTR_LOCALES); 2981 configOut.mLocaleList = LocaleList.forLanguageTags(localesStr); 2982 configOut.locale = configOut.mLocaleList.get(0); 2983 2984 configOut.touchscreen = XmlUtils.readIntAttribute(parser, XML_ATTR_TOUCHSCREEN, 2985 TOUCHSCREEN_UNDEFINED); 2986 configOut.keyboard = XmlUtils.readIntAttribute(parser, XML_ATTR_KEYBOARD, 2987 KEYBOARD_UNDEFINED); 2988 configOut.keyboardHidden = XmlUtils.readIntAttribute(parser, XML_ATTR_KEYBOARD_HIDDEN, 2989 KEYBOARDHIDDEN_UNDEFINED); 2990 configOut.hardKeyboardHidden = 2991 XmlUtils.readIntAttribute(parser, XML_ATTR_HARD_KEYBOARD_HIDDEN, 2992 HARDKEYBOARDHIDDEN_UNDEFINED); 2993 configOut.navigation = XmlUtils.readIntAttribute(parser, XML_ATTR_NAVIGATION, 2994 NAVIGATION_UNDEFINED); 2995 configOut.navigationHidden = XmlUtils.readIntAttribute(parser, XML_ATTR_NAVIGATION_HIDDEN, 2996 NAVIGATIONHIDDEN_UNDEFINED); 2997 configOut.orientation = XmlUtils.readIntAttribute(parser, XML_ATTR_ORIENTATION, 2998 ORIENTATION_UNDEFINED); 2999 configOut.screenLayout = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_LAYOUT, 3000 SCREENLAYOUT_UNDEFINED); 3001 configOut.colorMode = XmlUtils.readIntAttribute(parser, XML_ATTR_COLOR_MODE, 3002 COLOR_MODE_UNDEFINED); 3003 configOut.uiMode = XmlUtils.readIntAttribute(parser, XML_ATTR_UI_MODE, 0); 3004 configOut.screenWidthDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_WIDTH, 3005 SCREEN_WIDTH_DP_UNDEFINED); 3006 configOut.screenHeightDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_HEIGHT, 3007 SCREEN_HEIGHT_DP_UNDEFINED); 3008 configOut.smallestScreenWidthDp = 3009 XmlUtils.readIntAttribute(parser, XML_ATTR_SMALLEST_WIDTH, 3010 SMALLEST_SCREEN_WIDTH_DP_UNDEFINED); 3011 configOut.densityDpi = XmlUtils.readIntAttribute(parser, XML_ATTR_DENSITY, 3012 DENSITY_DPI_UNDEFINED); 3013 configOut.fontWeightAdjustment = XmlUtils.readIntAttribute(parser, 3014 XML_ATTR_FONT_WEIGHT_ADJUSTMENT, FONT_WEIGHT_ADJUSTMENT_UNDEFINED); 3015 configOut.mGrammaticalGender = XmlUtils.readIntAttribute(parser, 3016 XML_ATTR_GRAMMATICAL_GENDER, GRAMMATICAL_GENDER_UNDEFINED); 3017 3018 // For persistence, we don't care about assetsSeq and WindowConfiguration, so do not read it 3019 // out. 3020 } 3021 } 3022