Configuration.java revision e89d0bba66d76fe4c0d316f065a3d0f96f375c75
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 17package android.content.res; 18 19import android.annotation.IntDef; 20import android.annotation.NonNull; 21import android.annotation.Nullable; 22import android.content.pm.ActivityInfo; 23import android.content.pm.ActivityInfo.Config; 24import android.graphics.Rect; 25import android.os.Build; 26import android.os.LocaleList; 27import android.os.Parcel; 28import android.os.Parcelable; 29import android.text.TextUtils; 30import android.view.DisplayInfo; 31import android.view.View; 32 33import com.android.internal.util.XmlUtils; 34 35import org.xmlpull.v1.XmlPullParser; 36import org.xmlpull.v1.XmlPullParserException; 37import org.xmlpull.v1.XmlSerializer; 38 39import java.io.IOException; 40import java.lang.annotation.Retention; 41import java.lang.annotation.RetentionPolicy; 42import java.util.ArrayList; 43import java.util.Locale; 44 45/** 46 * This class describes all device configuration information that can 47 * impact the resources the application retrieves. This includes both 48 * user-specified configuration options (locale list and scaling) as well 49 * as device configurations (such as input modes, screen size and screen orientation). 50 * <p>You can acquire this object from {@link Resources}, using {@link 51 * Resources#getConfiguration}. Thus, from an activity, you can get it by chaining the request 52 * with {@link android.app.Activity#getResources}:</p> 53 * <pre>Configuration config = getResources().getConfiguration();</pre> 54 */ 55public final class Configuration implements Parcelable, Comparable<Configuration> { 56 /** @hide */ 57 public static final Configuration EMPTY = new Configuration(); 58 59 /** 60 * Current user preference for the scaling factor for fonts, relative 61 * to the base density scaling. 62 */ 63 public float fontScale; 64 65 /** 66 * IMSI MCC (Mobile Country Code), corresponding to 67 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#MccQualifier">mcc</a> 68 * resource qualifier. 0 if undefined. 69 */ 70 public int mcc; 71 72 /** 73 * IMSI MNC (Mobile Network Code), corresponding to 74 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#MccQualifier">mnc</a> 75 * resource qualifier. 0 if undefined. Note that the actual MNC may be 0; in order to check 76 * for this use the {@link #MNC_ZERO} symbol. 77 */ 78 public int mnc; 79 80 /** 81 * Constant used to to represent MNC (Mobile Network Code) zero. 82 * 0 cannot be used, since it is used to represent an undefined MNC. 83 */ 84 public static final int MNC_ZERO = 0xffff; 85 86 /** 87 * Current user preference for the locale, corresponding to 88 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#LocaleQualifier">locale</a> 89 * resource qualifier. 90 * 91 * @deprecated Do not set or read this directly. Use {@link #getLocales()} and 92 * {@link #setLocales(LocaleList)}. If only the primary locale is needed, 93 * <code>getLocales().get(0)</code> is now the preferred accessor. 94 */ 95 @Deprecated public Locale locale; 96 97 private LocaleList mLocaleList; 98 99 /** 100 * Locale should persist on setting. This is hidden because it is really 101 * questionable whether this is the right way to expose the functionality. 102 * @hide 103 */ 104 public boolean userSetLocale; 105 106 107 /** Constant for {@link #colorMode}: bits that encode whether the screen is wide gamut. */ 108 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_MASK = 0x3; 109 /** 110 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} value 111 * indicating that it is unknown whether or not the screen is wide gamut. 112 */ 113 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED = 0x0; 114 /** 115 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} value 116 * indicating that the screen is not wide gamut. 117 * <p>Corresponds to the <code>-nowidecg</code> resource qualifier.</p> 118 */ 119 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_NO = 0x1; 120 /** 121 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} value 122 * indicating that the screen is wide gamut. 123 * <p>Corresponds to the <code>-widecg</code> resource qualifier.</p> 124 */ 125 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_YES = 0x2; 126 127 /** Constant for {@link #colorMode}: bits that encode the dynamic range of the screen. */ 128 public static final int COLOR_MODE_HDR_MASK = 0xc; 129 /** Constant for {@link #colorMode}: bits shift to get the screen dynamic range. */ 130 public static final int COLOR_MODE_HDR_SHIFT = 2; 131 /** 132 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_HDR_MASK} value 133 * indicating that it is unknown whether or not the screen is HDR. 134 */ 135 public static final int COLOR_MODE_HDR_UNDEFINED = 0x0; 136 /** 137 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_HDR_MASK} value 138 * indicating that the screen is not HDR (low/standard dynamic range). 139 * <p>Corresponds to the <code>-lowdr</code> resource qualifier.</p> 140 */ 141 public static final int COLOR_MODE_HDR_NO = 0x1 << COLOR_MODE_HDR_SHIFT; 142 /** 143 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_HDR_MASK} value 144 * indicating that the screen is HDR (dynamic range). 145 * <p>Corresponds to the <code>-highdr</code> resource qualifier.</p> 146 */ 147 public static final int COLOR_MODE_HDR_YES = 0x2 << COLOR_MODE_HDR_SHIFT; 148 149 /** Constant for {@link #colorMode}: a value indicating that the color mode is undefined */ 150 @SuppressWarnings("PointlessBitwiseExpression") 151 public static final int COLOR_MODE_UNDEFINED = COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED | 152 COLOR_MODE_HDR_UNDEFINED; 153 154 /** 155 * Bit mask of color capabilities of the screen. Currently there are two fields: 156 * <p>The {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} bits define the color gamut of 157 * the screen. They may be one of 158 * {@link #COLOR_MODE_WIDE_COLOR_GAMUT_NO} or {@link #COLOR_MODE_WIDE_COLOR_GAMUT_YES}.</p> 159 * 160 * <p>The {@link #COLOR_MODE_HDR_MASK} defines the dynamic range of the screen. They may be 161 * one of {@link #COLOR_MODE_HDR_NO} or {@link #COLOR_MODE_HDR_YES}.</p> 162 * 163 * <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting 164 * Multiple Screens</a> for more information.</p> 165 */ 166 public int colorMode; 167 168 /** Constant for {@link #screenLayout}: bits that encode the size. */ 169 public static final int SCREENLAYOUT_SIZE_MASK = 0x0f; 170 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK} 171 * value indicating that no size has been set. */ 172 public static final int SCREENLAYOUT_SIZE_UNDEFINED = 0x00; 173 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK} 174 * value indicating the screen is at least approximately 320x426 dp units, 175 * corresponds to the 176 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">small</a> 177 * resource qualifier. 178 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting 179 * Multiple Screens</a> for more information. */ 180 public static final int SCREENLAYOUT_SIZE_SMALL = 0x01; 181 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK} 182 * value indicating the screen is at least approximately 320x470 dp units, 183 * corresponds to the 184 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">normal</a> 185 * resource qualifier. 186 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting 187 * Multiple Screens</a> for more information. */ 188 public static final int SCREENLAYOUT_SIZE_NORMAL = 0x02; 189 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK} 190 * value indicating the screen is at least approximately 480x640 dp units, 191 * corresponds to the 192 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">large</a> 193 * resource qualifier. 194 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting 195 * Multiple Screens</a> for more information. */ 196 public static final int SCREENLAYOUT_SIZE_LARGE = 0x03; 197 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK} 198 * value indicating the screen is at least approximately 720x960 dp units, 199 * corresponds to the 200 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">xlarge</a> 201 * resource qualifier. 202 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting 203 * Multiple Screens</a> for more information.*/ 204 public static final int SCREENLAYOUT_SIZE_XLARGE = 0x04; 205 206 /** Constant for {@link #screenLayout}: bits that encode the aspect ratio. */ 207 public static final int SCREENLAYOUT_LONG_MASK = 0x30; 208 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK} 209 * value indicating that no size has been set. */ 210 public static final int SCREENLAYOUT_LONG_UNDEFINED = 0x00; 211 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK} 212 * value that corresponds to the 213 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenAspectQualifier">notlong</a> 214 * resource qualifier. */ 215 public static final int SCREENLAYOUT_LONG_NO = 0x10; 216 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK} 217 * value that corresponds to the 218 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenAspectQualifier">long</a> 219 * resource qualifier. */ 220 public static final int SCREENLAYOUT_LONG_YES = 0x20; 221 222 /** Constant for {@link #screenLayout}: bits that encode the layout direction. */ 223 public static final int SCREENLAYOUT_LAYOUTDIR_MASK = 0xC0; 224 /** Constant for {@link #screenLayout}: bits shift to get the layout direction. */ 225 public static final int SCREENLAYOUT_LAYOUTDIR_SHIFT = 6; 226 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK} 227 * value indicating that no layout dir has been set. */ 228 public static final int SCREENLAYOUT_LAYOUTDIR_UNDEFINED = 0x00; 229 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK} 230 * value indicating that a layout dir has been set to LTR. */ 231 public static final int SCREENLAYOUT_LAYOUTDIR_LTR = 0x01 << SCREENLAYOUT_LAYOUTDIR_SHIFT; 232 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK} 233 * value indicating that a layout dir has been set to RTL. */ 234 public static final int SCREENLAYOUT_LAYOUTDIR_RTL = 0x02 << SCREENLAYOUT_LAYOUTDIR_SHIFT; 235 236 /** Constant for {@link #screenLayout}: bits that encode roundness of the screen. */ 237 public static final int SCREENLAYOUT_ROUND_MASK = 0x300; 238 /** @hide Constant for {@link #screenLayout}: bit shift to get to screen roundness bits */ 239 public static final int SCREENLAYOUT_ROUND_SHIFT = 8; 240 /** 241 * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating 242 * that it is unknown whether or not the screen has a round shape. 243 */ 244 public static final int SCREENLAYOUT_ROUND_UNDEFINED = 0x00; 245 /** 246 * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating 247 * that the screen does not have a rounded shape. 248 */ 249 public static final int SCREENLAYOUT_ROUND_NO = 0x1 << SCREENLAYOUT_ROUND_SHIFT; 250 /** 251 * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating 252 * that the screen has a rounded shape. Corners may not be visible to the user; 253 * developers should pay special attention to the {@link android.view.WindowInsets} delivered 254 * to views for more information about ensuring content is not obscured. 255 * 256 * <p>Corresponds to the <code>-round</code> resource qualifier.</p> 257 */ 258 public static final int SCREENLAYOUT_ROUND_YES = 0x2 << SCREENLAYOUT_ROUND_SHIFT; 259 260 /** Constant for {@link #screenLayout}: a value indicating that screenLayout is undefined */ 261 public static final int SCREENLAYOUT_UNDEFINED = SCREENLAYOUT_SIZE_UNDEFINED | 262 SCREENLAYOUT_LONG_UNDEFINED | SCREENLAYOUT_LAYOUTDIR_UNDEFINED | 263 SCREENLAYOUT_ROUND_UNDEFINED; 264 265 /** 266 * Special flag we generate to indicate that the screen layout requires 267 * us to use a compatibility mode for apps that are not modern layout 268 * aware. 269 * @hide 270 */ 271 public static final int SCREENLAYOUT_COMPAT_NEEDED = 0x10000000; 272 273 /** 274 * Bit mask of overall layout of the screen. Currently there are four 275 * fields: 276 * <p>The {@link #SCREENLAYOUT_SIZE_MASK} bits define the overall size 277 * of the screen. They may be one of 278 * {@link #SCREENLAYOUT_SIZE_SMALL}, {@link #SCREENLAYOUT_SIZE_NORMAL}, 279 * {@link #SCREENLAYOUT_SIZE_LARGE}, or {@link #SCREENLAYOUT_SIZE_XLARGE}.</p> 280 * 281 * <p>The {@link #SCREENLAYOUT_LONG_MASK} defines whether the screen 282 * is wider/taller than normal. They may be one of 283 * {@link #SCREENLAYOUT_LONG_NO} or {@link #SCREENLAYOUT_LONG_YES}.</p> 284 * 285 * <p>The {@link #SCREENLAYOUT_LAYOUTDIR_MASK} defines whether the screen layout 286 * is either LTR or RTL. They may be one of 287 * {@link #SCREENLAYOUT_LAYOUTDIR_LTR} or {@link #SCREENLAYOUT_LAYOUTDIR_RTL}.</p> 288 * 289 * <p>The {@link #SCREENLAYOUT_ROUND_MASK} defines whether the screen has a rounded 290 * shape. They may be one of {@link #SCREENLAYOUT_ROUND_NO} or {@link #SCREENLAYOUT_ROUND_YES}. 291 * </p> 292 * 293 * <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting 294 * Multiple Screens</a> for more information.</p> 295 */ 296 public int screenLayout; 297 298 /** 299 * @hide 300 * {@link android.graphics.Rect} defining app bounds. The dimensions override usages of 301 * {@link DisplayInfo#appHeight} and {@link DisplayInfo#appWidth} and mirrors these values at 302 * the display level. Lower levels can override these values to provide custom bounds to enforce 303 * features such as a max aspect ratio. 304 * TODO(b/36812336): Move appBounds out of {@link Configuration}. 305 */ 306 public Rect appBounds; 307 308 /** @hide */ 309 static public int resetScreenLayout(int curLayout) { 310 return (curLayout&~(SCREENLAYOUT_LONG_MASK | SCREENLAYOUT_SIZE_MASK 311 | SCREENLAYOUT_COMPAT_NEEDED)) 312 | (SCREENLAYOUT_LONG_YES | SCREENLAYOUT_SIZE_XLARGE); 313 } 314 315 /** @hide */ 316 static public int reduceScreenLayout(int curLayout, int longSizeDp, int shortSizeDp) { 317 int screenLayoutSize; 318 boolean screenLayoutLong; 319 boolean screenLayoutCompatNeeded; 320 321 // These semi-magic numbers define our compatibility modes for 322 // applications with different screens. These are guarantees to 323 // app developers about the space they can expect for a particular 324 // configuration. DO NOT CHANGE! 325 if (longSizeDp < 470) { 326 // This is shorter than an HVGA normal density screen (which 327 // is 480 pixels on its long side). 328 screenLayoutSize = SCREENLAYOUT_SIZE_SMALL; 329 screenLayoutLong = false; 330 screenLayoutCompatNeeded = false; 331 } else { 332 // What size is this screen screen? 333 if (longSizeDp >= 960 && shortSizeDp >= 720) { 334 // 1.5xVGA or larger screens at medium density are the point 335 // at which we consider it to be an extra large screen. 336 screenLayoutSize = SCREENLAYOUT_SIZE_XLARGE; 337 } else if (longSizeDp >= 640 && shortSizeDp >= 480) { 338 // VGA or larger screens at medium density are the point 339 // at which we consider it to be a large screen. 340 screenLayoutSize = SCREENLAYOUT_SIZE_LARGE; 341 } else { 342 screenLayoutSize = SCREENLAYOUT_SIZE_NORMAL; 343 } 344 345 // If this screen is wider than normal HVGA, or taller 346 // than FWVGA, then for old apps we want to run in size 347 // compatibility mode. 348 if (shortSizeDp > 321 || longSizeDp > 570) { 349 screenLayoutCompatNeeded = true; 350 } else { 351 screenLayoutCompatNeeded = false; 352 } 353 354 // Is this a long screen? 355 if (((longSizeDp*3)/5) >= (shortSizeDp-1)) { 356 // Anything wider than WVGA (5:3) is considering to be long. 357 screenLayoutLong = true; 358 } else { 359 screenLayoutLong = false; 360 } 361 } 362 363 // Now reduce the last screenLayout to not be better than what we 364 // have found. 365 if (!screenLayoutLong) { 366 curLayout = (curLayout&~SCREENLAYOUT_LONG_MASK) | SCREENLAYOUT_LONG_NO; 367 } 368 if (screenLayoutCompatNeeded) { 369 curLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED; 370 } 371 int curSize = curLayout&SCREENLAYOUT_SIZE_MASK; 372 if (screenLayoutSize < curSize) { 373 curLayout = (curLayout&~SCREENLAYOUT_SIZE_MASK) | screenLayoutSize; 374 } 375 return curLayout; 376 } 377 378 /** @hide */ 379 public static String configurationDiffToString(int diff) { 380 ArrayList<String> list = new ArrayList<>(); 381 if ((diff & ActivityInfo.CONFIG_MCC) != 0) { 382 list.add("CONFIG_MCC"); 383 } 384 if ((diff & ActivityInfo.CONFIG_MNC) != 0) { 385 list.add("CONFIG_MNC"); 386 } 387 if ((diff & ActivityInfo.CONFIG_LOCALE) != 0) { 388 list.add("CONFIG_LOCALE"); 389 } 390 if ((diff & ActivityInfo.CONFIG_TOUCHSCREEN) != 0) { 391 list.add("CONFIG_TOUCHSCREEN"); 392 } 393 if ((diff & ActivityInfo.CONFIG_KEYBOARD) != 0) { 394 list.add("CONFIG_KEYBOARD"); 395 } 396 if ((diff & ActivityInfo.CONFIG_KEYBOARD_HIDDEN) != 0) { 397 list.add("CONFIG_KEYBOARD_HIDDEN"); 398 } 399 if ((diff & ActivityInfo.CONFIG_NAVIGATION) != 0) { 400 list.add("CONFIG_NAVIGATION"); 401 } 402 if ((diff & ActivityInfo.CONFIG_ORIENTATION) != 0) { 403 list.add("CONFIG_ORIENTATION"); 404 } 405 if ((diff & ActivityInfo.CONFIG_SCREEN_LAYOUT) != 0) { 406 list.add("CONFIG_SCREEN_LAYOUT"); 407 } 408 if ((diff & ActivityInfo.CONFIG_COLOR_MODE) != 0) { 409 list.add("CONFIG_COLOR_MODE"); 410 } 411 if ((diff & ActivityInfo.CONFIG_UI_MODE) != 0) { 412 list.add("CONFIG_UI_MODE"); 413 } 414 if ((diff & ActivityInfo.CONFIG_SCREEN_SIZE) != 0) { 415 list.add("CONFIG_SCREEN_SIZE"); 416 } 417 if ((diff & ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE) != 0) { 418 list.add("CONFIG_SMALLEST_SCREEN_SIZE"); 419 } 420 if ((diff & ActivityInfo.CONFIG_LAYOUT_DIRECTION) != 0) { 421 list.add("CONFIG_LAYOUT_DIRECTION"); 422 } 423 if ((diff & ActivityInfo.CONFIG_FONT_SCALE) != 0) { 424 list.add("CONFIG_FONT_SCALE"); 425 } 426 if ((diff & ActivityInfo.CONFIG_ASSETS_PATHS) != 0) { 427 list.add("CONFIG_ASSETS_PATHS"); 428 } 429 StringBuilder builder = new StringBuilder("{"); 430 for (int i = 0, n = list.size(); i < n; i++) { 431 builder.append(list.get(i)); 432 if (i != n - 1) { 433 builder.append(", "); 434 } 435 } 436 builder.append("}"); 437 return builder.toString(); 438 } 439 440 /** 441 * Check if the Configuration's current {@link #screenLayout} is at 442 * least the given size. 443 * 444 * @param size The desired size, either {@link #SCREENLAYOUT_SIZE_SMALL}, 445 * {@link #SCREENLAYOUT_SIZE_NORMAL}, {@link #SCREENLAYOUT_SIZE_LARGE}, or 446 * {@link #SCREENLAYOUT_SIZE_XLARGE}. 447 * @return Returns true if the current screen layout size is at least 448 * the given size. 449 */ 450 public boolean isLayoutSizeAtLeast(int size) { 451 int cur = screenLayout&SCREENLAYOUT_SIZE_MASK; 452 if (cur == SCREENLAYOUT_SIZE_UNDEFINED) return false; 453 return cur >= size; 454 } 455 456 /** Constant for {@link #touchscreen}: a value indicating that no value has been set. */ 457 public static final int TOUCHSCREEN_UNDEFINED = 0; 458 /** Constant for {@link #touchscreen}, value corresponding to the 459 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#TouchscreenQualifier">notouch</a> 460 * resource qualifier. */ 461 public static final int TOUCHSCREEN_NOTOUCH = 1; 462 /** @deprecated Not currently supported or used. */ 463 @Deprecated public static final int TOUCHSCREEN_STYLUS = 2; 464 /** Constant for {@link #touchscreen}, value corresponding to the 465 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#TouchscreenQualifier">finger</a> 466 * resource qualifier. */ 467 public static final int TOUCHSCREEN_FINGER = 3; 468 469 /** 470 * The kind of touch screen attached to the device. 471 * One of: {@link #TOUCHSCREEN_NOTOUCH}, {@link #TOUCHSCREEN_FINGER}. 472 */ 473 public int touchscreen; 474 475 /** Constant for {@link #keyboard}: a value indicating that no value has been set. */ 476 public static final int KEYBOARD_UNDEFINED = 0; 477 /** Constant for {@link #keyboard}, value corresponding to the 478 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">nokeys</a> 479 * resource qualifier. */ 480 public static final int KEYBOARD_NOKEYS = 1; 481 /** Constant for {@link #keyboard}, value corresponding to the 482 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">qwerty</a> 483 * resource qualifier. */ 484 public static final int KEYBOARD_QWERTY = 2; 485 /** Constant for {@link #keyboard}, value corresponding to the 486 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">12key</a> 487 * resource qualifier. */ 488 public static final int KEYBOARD_12KEY = 3; 489 490 /** 491 * The kind of keyboard attached to the device. 492 * One of: {@link #KEYBOARD_NOKEYS}, {@link #KEYBOARD_QWERTY}, 493 * {@link #KEYBOARD_12KEY}. 494 */ 495 public int keyboard; 496 497 /** Constant for {@link #keyboardHidden}: a value indicating that no value has been set. */ 498 public static final int KEYBOARDHIDDEN_UNDEFINED = 0; 499 /** Constant for {@link #keyboardHidden}, value corresponding to the 500 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keysexposed</a> 501 * resource qualifier. */ 502 public static final int KEYBOARDHIDDEN_NO = 1; 503 /** Constant for {@link #keyboardHidden}, value corresponding to the 504 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keyshidden</a> 505 * resource qualifier. */ 506 public static final int KEYBOARDHIDDEN_YES = 2; 507 /** Constant matching actual resource implementation. {@hide} */ 508 public static final int KEYBOARDHIDDEN_SOFT = 3; 509 510 /** 511 * A flag indicating whether any keyboard is available. Unlike 512 * {@link #hardKeyboardHidden}, this also takes into account a soft 513 * keyboard, so if the hard keyboard is hidden but there is soft 514 * keyboard available, it will be set to NO. Value is one of: 515 * {@link #KEYBOARDHIDDEN_NO}, {@link #KEYBOARDHIDDEN_YES}. 516 */ 517 public int keyboardHidden; 518 519 /** Constant for {@link #hardKeyboardHidden}: a value indicating that no value has been set. */ 520 public static final int HARDKEYBOARDHIDDEN_UNDEFINED = 0; 521 /** Constant for {@link #hardKeyboardHidden}, value corresponding to the 522 * physical keyboard being exposed. */ 523 public static final int HARDKEYBOARDHIDDEN_NO = 1; 524 /** Constant for {@link #hardKeyboardHidden}, value corresponding to the 525 * physical keyboard being hidden. */ 526 public static final int HARDKEYBOARDHIDDEN_YES = 2; 527 528 /** 529 * A flag indicating whether the hard keyboard has been hidden. This will 530 * be set on a device with a mechanism to hide the keyboard from the 531 * user, when that mechanism is closed. One of: 532 * {@link #HARDKEYBOARDHIDDEN_NO}, {@link #HARDKEYBOARDHIDDEN_YES}. 533 */ 534 public int hardKeyboardHidden; 535 536 /** Constant for {@link #navigation}: a value indicating that no value has been set. */ 537 public static final int NAVIGATION_UNDEFINED = 0; 538 /** Constant for {@link #navigation}, value corresponding to the 539 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">nonav</a> 540 * resource qualifier. */ 541 public static final int NAVIGATION_NONAV = 1; 542 /** Constant for {@link #navigation}, value corresponding to the 543 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">dpad</a> 544 * resource qualifier. */ 545 public static final int NAVIGATION_DPAD = 2; 546 /** Constant for {@link #navigation}, value corresponding to the 547 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">trackball</a> 548 * resource qualifier. */ 549 public static final int NAVIGATION_TRACKBALL = 3; 550 /** Constant for {@link #navigation}, value corresponding to the 551 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">wheel</a> 552 * resource qualifier. */ 553 public static final int NAVIGATION_WHEEL = 4; 554 555 /** 556 * The kind of navigation method available on the device. 557 * One of: {@link #NAVIGATION_NONAV}, {@link #NAVIGATION_DPAD}, 558 * {@link #NAVIGATION_TRACKBALL}, {@link #NAVIGATION_WHEEL}. 559 */ 560 public int navigation; 561 562 /** Constant for {@link #navigationHidden}: a value indicating that no value has been set. */ 563 public static final int NAVIGATIONHIDDEN_UNDEFINED = 0; 564 /** Constant for {@link #navigationHidden}, value corresponding to the 565 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavAvailQualifier">navexposed</a> 566 * resource qualifier. */ 567 public static final int NAVIGATIONHIDDEN_NO = 1; 568 /** Constant for {@link #navigationHidden}, value corresponding to the 569 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavAvailQualifier">navhidden</a> 570 * resource qualifier. */ 571 public static final int NAVIGATIONHIDDEN_YES = 2; 572 573 /** 574 * A flag indicating whether any 5-way or DPAD navigation available. 575 * This will be set on a device with a mechanism to hide the navigation 576 * controls from the user, when that mechanism is closed. One of: 577 * {@link #NAVIGATIONHIDDEN_NO}, {@link #NAVIGATIONHIDDEN_YES}. 578 */ 579 public int navigationHidden; 580 581 /** Constant for {@link #orientation}: a value indicating that no value has been set. */ 582 public static final int ORIENTATION_UNDEFINED = 0; 583 /** Constant for {@link #orientation}, value corresponding to the 584 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#OrientationQualifier">port</a> 585 * resource qualifier. */ 586 public static final int ORIENTATION_PORTRAIT = 1; 587 /** Constant for {@link #orientation}, value corresponding to the 588 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#OrientationQualifier">land</a> 589 * resource qualifier. */ 590 public static final int ORIENTATION_LANDSCAPE = 2; 591 /** @deprecated Not currently supported or used. */ 592 @Deprecated public static final int ORIENTATION_SQUARE = 3; 593 594 /** 595 * Overall orientation of the screen. May be one of 596 * {@link #ORIENTATION_LANDSCAPE}, {@link #ORIENTATION_PORTRAIT}. 597 */ 598 public int orientation; 599 600 /** Constant for {@link #uiMode}: bits that encode the mode type. */ 601 public static final int UI_MODE_TYPE_MASK = 0x0f; 602 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK} 603 * value indicating that no mode type has been set. */ 604 public static final int UI_MODE_TYPE_UNDEFINED = 0x00; 605 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK} 606 * value that corresponds to 607 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">no 608 * UI mode</a> resource qualifier specified. */ 609 public static final int UI_MODE_TYPE_NORMAL = 0x01; 610 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK} 611 * value that corresponds to the 612 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">desk</a> 613 * resource qualifier. */ 614 public static final int UI_MODE_TYPE_DESK = 0x02; 615 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK} 616 * value that corresponds to the 617 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">car</a> 618 * resource qualifier. */ 619 public static final int UI_MODE_TYPE_CAR = 0x03; 620 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK} 621 * value that corresponds to the 622 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">television</a> 623 * resource qualifier. */ 624 public static final int UI_MODE_TYPE_TELEVISION = 0x04; 625 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK} 626 * value that corresponds to the 627 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">appliance</a> 628 * resource qualifier. */ 629 public static final int UI_MODE_TYPE_APPLIANCE = 0x05; 630 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK} 631 * value that corresponds to the 632 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">watch</a> 633 * resource qualifier. */ 634 public static final int UI_MODE_TYPE_WATCH = 0x06; 635 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK} 636 * value that corresponds to the 637 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">vrheadset</a> 638 * resource qualifier. */ 639 public static final int UI_MODE_TYPE_VR_HEADSET = 0x07; 640 641 /** Constant for {@link #uiMode}: bits that encode the night mode. */ 642 public static final int UI_MODE_NIGHT_MASK = 0x30; 643 /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK} 644 * value indicating that no mode type has been set. */ 645 public static final int UI_MODE_NIGHT_UNDEFINED = 0x00; 646 /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK} 647 * value that corresponds to the 648 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NightQualifier">notnight</a> 649 * resource qualifier. */ 650 public static final int UI_MODE_NIGHT_NO = 0x10; 651 /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK} 652 * value that corresponds to the 653 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NightQualifier">night</a> 654 * resource qualifier. */ 655 public static final int UI_MODE_NIGHT_YES = 0x20; 656 657 /** 658 * Bit mask of the ui mode. Currently there are two fields: 659 * <p>The {@link #UI_MODE_TYPE_MASK} bits define the overall ui mode of the 660 * device. They may be one of {@link #UI_MODE_TYPE_UNDEFINED}, 661 * {@link #UI_MODE_TYPE_NORMAL}, {@link #UI_MODE_TYPE_DESK}, 662 * {@link #UI_MODE_TYPE_CAR}, {@link #UI_MODE_TYPE_TELEVISION}, 663 * {@link #UI_MODE_TYPE_APPLIANCE}, {@link #UI_MODE_TYPE_WATCH}, 664 * or {@link #UI_MODE_TYPE_VR_HEADSET}. 665 * 666 * <p>The {@link #UI_MODE_NIGHT_MASK} defines whether the screen 667 * is in a special mode. They may be one of {@link #UI_MODE_NIGHT_UNDEFINED}, 668 * {@link #UI_MODE_NIGHT_NO} or {@link #UI_MODE_NIGHT_YES}. 669 */ 670 public int uiMode; 671 672 /** 673 * Default value for {@link #screenWidthDp} indicating that no width 674 * has been specified. 675 */ 676 public static final int SCREEN_WIDTH_DP_UNDEFINED = 0; 677 678 /** 679 * The current width of the available screen space, in dp units, 680 * corresponding to 681 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenWidthQualifier">screen 682 * width</a> resource qualifier. Set to 683 * {@link #SCREEN_WIDTH_DP_UNDEFINED} if no width is specified. 684 */ 685 public int screenWidthDp; 686 687 /** 688 * Default value for {@link #screenHeightDp} indicating that no width 689 * has been specified. 690 */ 691 public static final int SCREEN_HEIGHT_DP_UNDEFINED = 0; 692 693 /** 694 * The current height of the available screen space, in dp units, 695 * corresponding to 696 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenHeightQualifier">screen 697 * height</a> resource qualifier. Set to 698 * {@link #SCREEN_HEIGHT_DP_UNDEFINED} if no height is specified. 699 */ 700 public int screenHeightDp; 701 702 /** 703 * Default value for {@link #smallestScreenWidthDp} indicating that no width 704 * has been specified. 705 */ 706 public static final int SMALLEST_SCREEN_WIDTH_DP_UNDEFINED = 0; 707 708 /** 709 * The smallest screen size an application will see in normal operation, 710 * corresponding to 711 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#SmallestScreenWidthQualifier">smallest 712 * screen width</a> resource qualifier. 713 * This is the smallest value of both screenWidthDp and screenHeightDp 714 * in both portrait and landscape. Set to 715 * {@link #SMALLEST_SCREEN_WIDTH_DP_UNDEFINED} if no width is specified. 716 */ 717 public int smallestScreenWidthDp; 718 719 /** 720 * Default value for {@link #densityDpi} indicating that no width 721 * has been specified. 722 */ 723 public static final int DENSITY_DPI_UNDEFINED = 0; 724 725 /** 726 * Value for {@link #densityDpi} for resources that scale to any density (vector drawables). 727 * {@hide} 728 */ 729 public static final int DENSITY_DPI_ANY = 0xfffe; 730 731 /** 732 * Value for {@link #densityDpi} for resources that are not meant to be scaled. 733 * {@hide} 734 */ 735 public static final int DENSITY_DPI_NONE = 0xffff; 736 737 /** 738 * The target screen density being rendered to, 739 * corresponding to 740 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#DensityQualifier">density</a> 741 * resource qualifier. Set to 742 * {@link #DENSITY_DPI_UNDEFINED} if no density is specified. 743 */ 744 public int densityDpi; 745 746 /** @hide Hack to get this information from WM to app running in compat mode. */ 747 public int compatScreenWidthDp; 748 /** @hide Hack to get this information from WM to app running in compat mode. */ 749 public int compatScreenHeightDp; 750 /** @hide Hack to get this information from WM to app running in compat mode. */ 751 public int compatSmallestScreenWidthDp; 752 753 /** 754 * An undefined assetsSeq. This will not override an existing assetsSeq. 755 * @hide 756 */ 757 public static final int ASSETS_SEQ_UNDEFINED = 0; 758 759 /** 760 * Internal counter that allows us to piggyback off the configuration change mechanism to 761 * signal to apps that the the assets for an Application have changed. A difference in these 762 * between two Configurations will yield a diff flag of 763 * {@link ActivityInfo#CONFIG_ASSETS_PATHS}. 764 * @hide 765 */ 766 public int assetsSeq; 767 768 /** 769 * @hide Internal book-keeping. 770 */ 771 public int seq; 772 773 /** @hide */ 774 @IntDef(flag = true, 775 value = { 776 NATIVE_CONFIG_MCC, 777 NATIVE_CONFIG_MNC, 778 NATIVE_CONFIG_LOCALE, 779 NATIVE_CONFIG_TOUCHSCREEN, 780 NATIVE_CONFIG_KEYBOARD, 781 NATIVE_CONFIG_KEYBOARD_HIDDEN, 782 NATIVE_CONFIG_NAVIGATION, 783 NATIVE_CONFIG_ORIENTATION, 784 NATIVE_CONFIG_DENSITY, 785 NATIVE_CONFIG_SCREEN_SIZE, 786 NATIVE_CONFIG_VERSION, 787 NATIVE_CONFIG_SCREEN_LAYOUT, 788 NATIVE_CONFIG_UI_MODE, 789 NATIVE_CONFIG_SMALLEST_SCREEN_SIZE, 790 NATIVE_CONFIG_LAYOUTDIR, 791 NATIVE_CONFIG_COLOR_MODE, 792 }) 793 @Retention(RetentionPolicy.SOURCE) 794 public @interface NativeConfig {} 795 796 /** @hide Native-specific bit mask for MCC config; DO NOT USE UNLESS YOU ARE SURE. */ 797 public static final int NATIVE_CONFIG_MCC = 0x0001; 798 /** @hide Native-specific bit mask for MNC config; DO NOT USE UNLESS YOU ARE SURE. */ 799 public static final int NATIVE_CONFIG_MNC = 0x0002; 800 /** @hide Native-specific bit mask for LOCALE config; DO NOT USE UNLESS YOU ARE SURE. */ 801 public static final int NATIVE_CONFIG_LOCALE = 0x0004; 802 /** @hide Native-specific bit mask for TOUCHSCREEN config; DO NOT USE UNLESS YOU ARE SURE. */ 803 public static final int NATIVE_CONFIG_TOUCHSCREEN = 0x0008; 804 /** @hide Native-specific bit mask for KEYBOARD config; DO NOT USE UNLESS YOU ARE SURE. */ 805 public static final int NATIVE_CONFIG_KEYBOARD = 0x0010; 806 /** @hide Native-specific bit mask for KEYBOARD_HIDDEN config; DO NOT USE UNLESS YOU 807 * ARE SURE. */ 808 public static final int NATIVE_CONFIG_KEYBOARD_HIDDEN = 0x0020; 809 /** @hide Native-specific bit mask for NAVIGATION config; DO NOT USE UNLESS YOU ARE SURE. */ 810 public static final int NATIVE_CONFIG_NAVIGATION = 0x0040; 811 /** @hide Native-specific bit mask for ORIENTATION config; DO NOT USE UNLESS YOU ARE SURE. */ 812 public static final int NATIVE_CONFIG_ORIENTATION = 0x0080; 813 /** @hide Native-specific bit mask for DENSITY config; DO NOT USE UNLESS YOU ARE SURE. */ 814 public static final int NATIVE_CONFIG_DENSITY = 0x0100; 815 /** @hide Native-specific bit mask for SCREEN_SIZE config; DO NOT USE UNLESS YOU ARE SURE. */ 816 public static final int NATIVE_CONFIG_SCREEN_SIZE = 0x0200; 817 /** @hide Native-specific bit mask for VERSION config; DO NOT USE UNLESS YOU ARE SURE. */ 818 public static final int NATIVE_CONFIG_VERSION = 0x0400; 819 /** @hide Native-specific bit mask for SCREEN_LAYOUT config; DO NOT USE UNLESS YOU ARE SURE. */ 820 public static final int NATIVE_CONFIG_SCREEN_LAYOUT = 0x0800; 821 /** @hide Native-specific bit mask for UI_MODE config; DO NOT USE UNLESS YOU ARE SURE. */ 822 public static final int NATIVE_CONFIG_UI_MODE = 0x1000; 823 /** @hide Native-specific bit mask for SMALLEST_SCREEN_SIZE config; DO NOT USE UNLESS YOU 824 * ARE SURE. */ 825 public static final int NATIVE_CONFIG_SMALLEST_SCREEN_SIZE = 0x2000; 826 /** @hide Native-specific bit mask for LAYOUTDIR config ; DO NOT USE UNLESS YOU ARE SURE.*/ 827 public static final int NATIVE_CONFIG_LAYOUTDIR = 0x4000; 828 /** @hide Native-specific bit mask for COLOR_MODE config ; DO NOT USE UNLESS YOU ARE SURE.*/ 829 public static final int NATIVE_CONFIG_COLOR_MODE = 0x10000; 830 831 /** 832 * <p>Construct an invalid Configuration. This state is only suitable for constructing a 833 * Configuration delta that will be applied to some valid Configuration object. In order to 834 * create a valid standalone Configuration, you must call {@link #setToDefaults}. </p> 835 * 836 * <p>Example:</p> 837 * <pre class="prettyprint"> 838 * Configuration validConfig = new Configuration(); 839 * validConfig.setToDefaults(); 840 * 841 * Configuration deltaOnlyConfig = new Configuration(); 842 * deltaOnlyConfig.orientation = Configuration.ORIENTATION_LANDSCAPE; 843 * 844 * validConfig.updateFrom(deltaOnlyConfig); 845 * </pre> 846 */ 847 public Configuration() { 848 unset(); 849 } 850 851 /** 852 * Makes a deep copy suitable for modification. 853 */ 854 public Configuration(Configuration o) { 855 setTo(o); 856 } 857 858 /* This brings mLocaleList in sync with locale in case a user of the older API who doesn't know 859 * about setLocales() has changed locale directly. */ 860 private void fixUpLocaleList() { 861 if ((locale == null && !mLocaleList.isEmpty()) || 862 (locale != null && !locale.equals(mLocaleList.get(0)))) { 863 mLocaleList = locale == null ? LocaleList.getEmptyLocaleList() : new LocaleList(locale); 864 } 865 } 866 867 /** 868 * Sets the fields in this object to those in the given Configuration. 869 * 870 * @param o The Configuration object used to set the values of this Configuration's fields. 871 */ 872 public void setTo(Configuration o) { 873 fontScale = o.fontScale; 874 mcc = o.mcc; 875 mnc = o.mnc; 876 locale = o.locale == null ? null : (Locale) o.locale.clone(); 877 o.fixUpLocaleList(); 878 mLocaleList = o.mLocaleList; 879 userSetLocale = o.userSetLocale; 880 touchscreen = o.touchscreen; 881 keyboard = o.keyboard; 882 keyboardHidden = o.keyboardHidden; 883 hardKeyboardHidden = o.hardKeyboardHidden; 884 navigation = o.navigation; 885 navigationHidden = o.navigationHidden; 886 orientation = o.orientation; 887 screenLayout = o.screenLayout; 888 colorMode = o.colorMode; 889 uiMode = o.uiMode; 890 screenWidthDp = o.screenWidthDp; 891 screenHeightDp = o.screenHeightDp; 892 smallestScreenWidthDp = o.smallestScreenWidthDp; 893 densityDpi = o.densityDpi; 894 compatScreenWidthDp = o.compatScreenWidthDp; 895 compatScreenHeightDp = o.compatScreenHeightDp; 896 compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp; 897 setAppBounds(o.appBounds); 898 assetsSeq = o.assetsSeq; 899 seq = o.seq; 900 } 901 902 public String toString() { 903 StringBuilder sb = new StringBuilder(128); 904 sb.append("{"); 905 sb.append(fontScale); 906 sb.append(" "); 907 if (mcc != 0) { 908 sb.append(mcc); 909 sb.append("mcc"); 910 } else { 911 sb.append("?mcc"); 912 } 913 if (mnc != 0) { 914 sb.append(mnc); 915 sb.append("mnc"); 916 } else { 917 sb.append("?mnc"); 918 } 919 fixUpLocaleList(); 920 if (!mLocaleList.isEmpty()) { 921 sb.append(" "); 922 sb.append(mLocaleList); 923 } else { 924 sb.append(" ?localeList"); 925 } 926 int layoutDir = (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK); 927 switch (layoutDir) { 928 case SCREENLAYOUT_LAYOUTDIR_UNDEFINED: sb.append(" ?layoutDir"); break; 929 case SCREENLAYOUT_LAYOUTDIR_LTR: sb.append(" ldltr"); break; 930 case SCREENLAYOUT_LAYOUTDIR_RTL: sb.append(" ldrtl"); break; 931 default: sb.append(" layoutDir="); 932 sb.append(layoutDir >> SCREENLAYOUT_LAYOUTDIR_SHIFT); break; 933 } 934 if (smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) { 935 sb.append(" sw"); sb.append(smallestScreenWidthDp); sb.append("dp"); 936 } else { 937 sb.append(" ?swdp"); 938 } 939 if (screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) { 940 sb.append(" w"); sb.append(screenWidthDp); sb.append("dp"); 941 } else { 942 sb.append(" ?wdp"); 943 } 944 if (screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) { 945 sb.append(" h"); sb.append(screenHeightDp); sb.append("dp"); 946 } else { 947 sb.append(" ?hdp"); 948 } 949 if (densityDpi != DENSITY_DPI_UNDEFINED) { 950 sb.append(" "); sb.append(densityDpi); sb.append("dpi"); 951 } else { 952 sb.append(" ?density"); 953 } 954 switch ((screenLayout&SCREENLAYOUT_SIZE_MASK)) { 955 case SCREENLAYOUT_SIZE_UNDEFINED: sb.append(" ?lsize"); break; 956 case SCREENLAYOUT_SIZE_SMALL: sb.append(" smll"); break; 957 case SCREENLAYOUT_SIZE_NORMAL: sb.append(" nrml"); break; 958 case SCREENLAYOUT_SIZE_LARGE: sb.append(" lrg"); break; 959 case SCREENLAYOUT_SIZE_XLARGE: sb.append(" xlrg"); break; 960 default: sb.append(" layoutSize="); 961 sb.append(screenLayout&SCREENLAYOUT_SIZE_MASK); break; 962 } 963 switch ((screenLayout&SCREENLAYOUT_LONG_MASK)) { 964 case SCREENLAYOUT_LONG_UNDEFINED: sb.append(" ?long"); break; 965 case SCREENLAYOUT_LONG_NO: /* not-long is not interesting to print */ break; 966 case SCREENLAYOUT_LONG_YES: sb.append(" long"); break; 967 default: sb.append(" layoutLong="); 968 sb.append(screenLayout&SCREENLAYOUT_LONG_MASK); break; 969 } 970 switch ((colorMode &COLOR_MODE_HDR_MASK)) { 971 case COLOR_MODE_HDR_UNDEFINED: sb.append(" ?ldr"); break; // most likely not HDR 972 case COLOR_MODE_HDR_NO: /* ldr is not interesting to print */ break; 973 case COLOR_MODE_HDR_YES: sb.append(" hdr"); break; 974 default: sb.append(" dynamicRange="); 975 sb.append(colorMode &COLOR_MODE_HDR_MASK); break; 976 } 977 switch ((colorMode &COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) { 978 case COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED: sb.append(" ?wideColorGamut"); break; 979 case COLOR_MODE_WIDE_COLOR_GAMUT_NO: /* not wide is not interesting to print */ break; 980 case COLOR_MODE_WIDE_COLOR_GAMUT_YES: sb.append(" widecg"); break; 981 default: sb.append(" wideColorGamut="); 982 sb.append(colorMode &COLOR_MODE_WIDE_COLOR_GAMUT_MASK); break; 983 } 984 switch (orientation) { 985 case ORIENTATION_UNDEFINED: sb.append(" ?orien"); break; 986 case ORIENTATION_LANDSCAPE: sb.append(" land"); break; 987 case ORIENTATION_PORTRAIT: sb.append(" port"); break; 988 default: sb.append(" orien="); sb.append(orientation); break; 989 } 990 switch ((uiMode&UI_MODE_TYPE_MASK)) { 991 case UI_MODE_TYPE_UNDEFINED: sb.append(" ?uimode"); break; 992 case UI_MODE_TYPE_NORMAL: /* normal is not interesting to print */ break; 993 case UI_MODE_TYPE_DESK: sb.append(" desk"); break; 994 case UI_MODE_TYPE_CAR: sb.append(" car"); break; 995 case UI_MODE_TYPE_TELEVISION: sb.append(" television"); break; 996 case UI_MODE_TYPE_APPLIANCE: sb.append(" appliance"); break; 997 case UI_MODE_TYPE_WATCH: sb.append(" watch"); break; 998 case UI_MODE_TYPE_VR_HEADSET: sb.append(" vrheadset"); break; 999 default: sb.append(" uimode="); sb.append(uiMode&UI_MODE_TYPE_MASK); break; 1000 } 1001 switch ((uiMode&UI_MODE_NIGHT_MASK)) { 1002 case UI_MODE_NIGHT_UNDEFINED: sb.append(" ?night"); break; 1003 case UI_MODE_NIGHT_NO: /* not-night is not interesting to print */ break; 1004 case UI_MODE_NIGHT_YES: sb.append(" night"); break; 1005 default: sb.append(" night="); sb.append(uiMode&UI_MODE_NIGHT_MASK); break; 1006 } 1007 switch (touchscreen) { 1008 case TOUCHSCREEN_UNDEFINED: sb.append(" ?touch"); break; 1009 case TOUCHSCREEN_NOTOUCH: sb.append(" -touch"); break; 1010 case TOUCHSCREEN_STYLUS: sb.append(" stylus"); break; 1011 case TOUCHSCREEN_FINGER: sb.append(" finger"); break; 1012 default: sb.append(" touch="); sb.append(touchscreen); break; 1013 } 1014 switch (keyboard) { 1015 case KEYBOARD_UNDEFINED: sb.append(" ?keyb"); break; 1016 case KEYBOARD_NOKEYS: sb.append(" -keyb"); break; 1017 case KEYBOARD_QWERTY: sb.append(" qwerty"); break; 1018 case KEYBOARD_12KEY: sb.append(" 12key"); break; 1019 default: sb.append(" keys="); sb.append(keyboard); break; 1020 } 1021 switch (keyboardHidden) { 1022 case KEYBOARDHIDDEN_UNDEFINED: sb.append("/?"); break; 1023 case KEYBOARDHIDDEN_NO: sb.append("/v"); break; 1024 case KEYBOARDHIDDEN_YES: sb.append("/h"); break; 1025 case KEYBOARDHIDDEN_SOFT: sb.append("/s"); break; 1026 default: sb.append("/"); sb.append(keyboardHidden); break; 1027 } 1028 switch (hardKeyboardHidden) { 1029 case HARDKEYBOARDHIDDEN_UNDEFINED: sb.append("/?"); break; 1030 case HARDKEYBOARDHIDDEN_NO: sb.append("/v"); break; 1031 case HARDKEYBOARDHIDDEN_YES: sb.append("/h"); break; 1032 default: sb.append("/"); sb.append(hardKeyboardHidden); break; 1033 } 1034 switch (navigation) { 1035 case NAVIGATION_UNDEFINED: sb.append(" ?nav"); break; 1036 case NAVIGATION_NONAV: sb.append(" -nav"); break; 1037 case NAVIGATION_DPAD: sb.append(" dpad"); break; 1038 case NAVIGATION_TRACKBALL: sb.append(" tball"); break; 1039 case NAVIGATION_WHEEL: sb.append(" wheel"); break; 1040 default: sb.append(" nav="); sb.append(navigation); break; 1041 } 1042 switch (navigationHidden) { 1043 case NAVIGATIONHIDDEN_UNDEFINED: sb.append("/?"); break; 1044 case NAVIGATIONHIDDEN_NO: sb.append("/v"); break; 1045 case NAVIGATIONHIDDEN_YES: sb.append("/h"); break; 1046 default: sb.append("/"); sb.append(navigationHidden); break; 1047 } 1048 if (appBounds != null) { 1049 sb.append(" appBounds="); sb.append(appBounds); 1050 } 1051 if (assetsSeq != 0) { 1052 sb.append(" as.").append(assetsSeq); 1053 } 1054 if (seq != 0) { 1055 sb.append(" s.").append(seq); 1056 } 1057 sb.append('}'); 1058 return sb.toString(); 1059 } 1060 1061 /** 1062 * Set this object to the system defaults. 1063 */ 1064 public void setToDefaults() { 1065 fontScale = 1; 1066 mcc = mnc = 0; 1067 mLocaleList = LocaleList.getEmptyLocaleList(); 1068 locale = null; 1069 userSetLocale = false; 1070 touchscreen = TOUCHSCREEN_UNDEFINED; 1071 keyboard = KEYBOARD_UNDEFINED; 1072 keyboardHidden = KEYBOARDHIDDEN_UNDEFINED; 1073 hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED; 1074 navigation = NAVIGATION_UNDEFINED; 1075 navigationHidden = NAVIGATIONHIDDEN_UNDEFINED; 1076 orientation = ORIENTATION_UNDEFINED; 1077 screenLayout = SCREENLAYOUT_UNDEFINED; 1078 colorMode = COLOR_MODE_UNDEFINED; 1079 uiMode = UI_MODE_TYPE_UNDEFINED; 1080 screenWidthDp = compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED; 1081 screenHeightDp = compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED; 1082 smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED; 1083 densityDpi = DENSITY_DPI_UNDEFINED; 1084 assetsSeq = ASSETS_SEQ_UNDEFINED; 1085 appBounds = null; 1086 seq = 0; 1087 } 1088 1089 /** 1090 * Set this object to completely undefined. 1091 * @hide 1092 */ 1093 public void unset() { 1094 setToDefaults(); 1095 fontScale = 0; 1096 } 1097 1098 /** {@hide} */ 1099 @Deprecated public void makeDefault() { 1100 setToDefaults(); 1101 } 1102 1103 /** 1104 * Copies the fields from delta into this Configuration object, keeping 1105 * track of which ones have changed. Any undefined fields in {@code delta} 1106 * are ignored and not copied in to the current Configuration. 1107 * 1108 * @return a bit mask of the changed fields, as per {@link #diff} 1109 */ 1110 public @Config int updateFrom(@NonNull Configuration delta) { 1111 int changed = 0; 1112 if (delta.fontScale > 0 && fontScale != delta.fontScale) { 1113 changed |= ActivityInfo.CONFIG_FONT_SCALE; 1114 fontScale = delta.fontScale; 1115 } 1116 if (delta.mcc != 0 && mcc != delta.mcc) { 1117 changed |= ActivityInfo.CONFIG_MCC; 1118 mcc = delta.mcc; 1119 } 1120 if (delta.mnc != 0 && mnc != delta.mnc) { 1121 changed |= ActivityInfo.CONFIG_MNC; 1122 mnc = delta.mnc; 1123 } 1124 fixUpLocaleList(); 1125 delta.fixUpLocaleList(); 1126 if (!delta.mLocaleList.isEmpty() && !mLocaleList.equals(delta.mLocaleList)) { 1127 changed |= ActivityInfo.CONFIG_LOCALE; 1128 mLocaleList = delta.mLocaleList; 1129 // delta.locale can't be null, since delta.mLocaleList is not empty. 1130 if (!delta.locale.equals(locale)) { 1131 locale = (Locale) delta.locale.clone(); 1132 // If locale has changed, then layout direction is also changed ... 1133 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION; 1134 // ... and we need to update the layout direction (represented by the first 1135 // 2 most significant bits in screenLayout). 1136 setLayoutDirection(locale); 1137 } 1138 } 1139 final int deltaScreenLayoutDir = delta.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK; 1140 if (deltaScreenLayoutDir != SCREENLAYOUT_LAYOUTDIR_UNDEFINED && 1141 deltaScreenLayoutDir != (screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) { 1142 screenLayout = (screenLayout & ~SCREENLAYOUT_LAYOUTDIR_MASK) | deltaScreenLayoutDir; 1143 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION; 1144 } 1145 if (delta.userSetLocale && (!userSetLocale || ((changed & ActivityInfo.CONFIG_LOCALE) != 0))) 1146 { 1147 changed |= ActivityInfo.CONFIG_LOCALE; 1148 userSetLocale = true; 1149 } 1150 if (delta.touchscreen != TOUCHSCREEN_UNDEFINED 1151 && touchscreen != delta.touchscreen) { 1152 changed |= ActivityInfo.CONFIG_TOUCHSCREEN; 1153 touchscreen = delta.touchscreen; 1154 } 1155 if (delta.keyboard != KEYBOARD_UNDEFINED 1156 && keyboard != delta.keyboard) { 1157 changed |= ActivityInfo.CONFIG_KEYBOARD; 1158 keyboard = delta.keyboard; 1159 } 1160 if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED 1161 && keyboardHidden != delta.keyboardHidden) { 1162 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN; 1163 keyboardHidden = delta.keyboardHidden; 1164 } 1165 if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED 1166 && hardKeyboardHidden != delta.hardKeyboardHidden) { 1167 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN; 1168 hardKeyboardHidden = delta.hardKeyboardHidden; 1169 } 1170 if (delta.navigation != NAVIGATION_UNDEFINED 1171 && navigation != delta.navigation) { 1172 changed |= ActivityInfo.CONFIG_NAVIGATION; 1173 navigation = delta.navigation; 1174 } 1175 if (delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED 1176 && navigationHidden != delta.navigationHidden) { 1177 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN; 1178 navigationHidden = delta.navigationHidden; 1179 } 1180 if (delta.orientation != ORIENTATION_UNDEFINED 1181 && orientation != delta.orientation) { 1182 changed |= ActivityInfo.CONFIG_ORIENTATION; 1183 orientation = delta.orientation; 1184 } 1185 1186 if (((delta.screenLayout & SCREENLAYOUT_SIZE_MASK) != SCREENLAYOUT_SIZE_UNDEFINED) 1187 && (delta.screenLayout & SCREENLAYOUT_SIZE_MASK) 1188 != (screenLayout & SCREENLAYOUT_SIZE_MASK)) { 1189 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT; 1190 screenLayout = (screenLayout & ~SCREENLAYOUT_SIZE_MASK) 1191 | (delta.screenLayout & SCREENLAYOUT_SIZE_MASK); 1192 } 1193 if (((delta.screenLayout & SCREENLAYOUT_LONG_MASK) != SCREENLAYOUT_LONG_UNDEFINED) 1194 && (delta.screenLayout & SCREENLAYOUT_LONG_MASK) 1195 != (screenLayout & SCREENLAYOUT_LONG_MASK)) { 1196 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT; 1197 screenLayout = (screenLayout & ~SCREENLAYOUT_LONG_MASK) 1198 | (delta.screenLayout & SCREENLAYOUT_LONG_MASK); 1199 } 1200 if (((delta.screenLayout & SCREENLAYOUT_ROUND_MASK) != SCREENLAYOUT_ROUND_UNDEFINED) 1201 && (delta.screenLayout & SCREENLAYOUT_ROUND_MASK) 1202 != (screenLayout & SCREENLAYOUT_ROUND_MASK)) { 1203 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT; 1204 screenLayout = (screenLayout & ~SCREENLAYOUT_ROUND_MASK) 1205 | (delta.screenLayout & SCREENLAYOUT_ROUND_MASK); 1206 } 1207 if ((delta.screenLayout & SCREENLAYOUT_COMPAT_NEEDED) 1208 != (screenLayout & SCREENLAYOUT_COMPAT_NEEDED) 1209 && delta.screenLayout != 0) { 1210 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT; 1211 screenLayout = (screenLayout & ~SCREENLAYOUT_COMPAT_NEEDED) 1212 | (delta.screenLayout & SCREENLAYOUT_COMPAT_NEEDED); 1213 } 1214 1215 if (((delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) != 1216 COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED) 1217 && (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) 1218 != (colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) { 1219 changed |= ActivityInfo.CONFIG_COLOR_MODE; 1220 colorMode = (colorMode & ~COLOR_MODE_WIDE_COLOR_GAMUT_MASK) 1221 | (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK); 1222 } 1223 1224 if (((delta.colorMode & COLOR_MODE_HDR_MASK) != COLOR_MODE_HDR_UNDEFINED) 1225 && (delta.colorMode & COLOR_MODE_HDR_MASK) 1226 != (colorMode & COLOR_MODE_HDR_MASK)) { 1227 changed |= ActivityInfo.CONFIG_COLOR_MODE; 1228 colorMode = (colorMode & ~COLOR_MODE_HDR_MASK) 1229 | (delta.colorMode & COLOR_MODE_HDR_MASK); 1230 } 1231 1232 if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED) 1233 && uiMode != delta.uiMode) { 1234 changed |= ActivityInfo.CONFIG_UI_MODE; 1235 if ((delta.uiMode&UI_MODE_TYPE_MASK) != UI_MODE_TYPE_UNDEFINED) { 1236 uiMode = (uiMode&~UI_MODE_TYPE_MASK) 1237 | (delta.uiMode&UI_MODE_TYPE_MASK); 1238 } 1239 if ((delta.uiMode&UI_MODE_NIGHT_MASK) != UI_MODE_NIGHT_UNDEFINED) { 1240 uiMode = (uiMode&~UI_MODE_NIGHT_MASK) 1241 | (delta.uiMode&UI_MODE_NIGHT_MASK); 1242 } 1243 } 1244 if (delta.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED 1245 && screenWidthDp != delta.screenWidthDp) { 1246 changed |= ActivityInfo.CONFIG_SCREEN_SIZE; 1247 screenWidthDp = delta.screenWidthDp; 1248 } 1249 if (delta.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED 1250 && screenHeightDp != delta.screenHeightDp) { 1251 changed |= ActivityInfo.CONFIG_SCREEN_SIZE; 1252 screenHeightDp = delta.screenHeightDp; 1253 } 1254 if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED 1255 && smallestScreenWidthDp != delta.smallestScreenWidthDp) { 1256 changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE; 1257 smallestScreenWidthDp = delta.smallestScreenWidthDp; 1258 } 1259 if (delta.densityDpi != DENSITY_DPI_UNDEFINED && 1260 densityDpi != delta.densityDpi) { 1261 changed |= ActivityInfo.CONFIG_DENSITY; 1262 densityDpi = delta.densityDpi; 1263 } 1264 if (delta.compatScreenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) { 1265 compatScreenWidthDp = delta.compatScreenWidthDp; 1266 } 1267 if (delta.compatScreenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) { 1268 compatScreenHeightDp = delta.compatScreenHeightDp; 1269 } 1270 if (delta.compatSmallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) { 1271 compatSmallestScreenWidthDp = delta.compatSmallestScreenWidthDp; 1272 } 1273 if (delta.appBounds != null && !delta.appBounds.equals(appBounds)) { 1274 changed |= ActivityInfo.CONFIG_SCREEN_SIZE; 1275 setAppBounds(delta.appBounds); 1276 } 1277 if (delta.assetsSeq != ASSETS_SEQ_UNDEFINED) { 1278 changed |= ActivityInfo.CONFIG_ASSETS_PATHS; 1279 assetsSeq = delta.assetsSeq; 1280 } 1281 if (delta.seq != 0) { 1282 seq = delta.seq; 1283 } 1284 1285 return changed; 1286 } 1287 1288 /** 1289 * Return a bit mask of the differences between this Configuration 1290 * object and the given one. Does not change the values of either. Any 1291 * undefined fields in <var>delta</var> are ignored. 1292 * @return Returns a bit mask indicating which configuration 1293 * values has changed, containing any combination of 1294 * {@link android.content.pm.ActivityInfo#CONFIG_FONT_SCALE 1295 * PackageManager.ActivityInfo.CONFIG_FONT_SCALE}, 1296 * {@link android.content.pm.ActivityInfo#CONFIG_MCC 1297 * PackageManager.ActivityInfo.CONFIG_MCC}, 1298 * {@link android.content.pm.ActivityInfo#CONFIG_MNC 1299 * PackageManager.ActivityInfo.CONFIG_MNC}, 1300 * {@link android.content.pm.ActivityInfo#CONFIG_LOCALE 1301 * PackageManager.ActivityInfo.CONFIG_LOCALE}, 1302 * {@link android.content.pm.ActivityInfo#CONFIG_TOUCHSCREEN 1303 * PackageManager.ActivityInfo.CONFIG_TOUCHSCREEN}, 1304 * {@link android.content.pm.ActivityInfo#CONFIG_KEYBOARD 1305 * PackageManager.ActivityInfo.CONFIG_KEYBOARD}, 1306 * {@link android.content.pm.ActivityInfo#CONFIG_NAVIGATION 1307 * PackageManager.ActivityInfo.CONFIG_NAVIGATION}, 1308 * {@link android.content.pm.ActivityInfo#CONFIG_ORIENTATION 1309 * PackageManager.ActivityInfo.CONFIG_ORIENTATION}, 1310 * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_LAYOUT 1311 * PackageManager.ActivityInfo.CONFIG_SCREEN_LAYOUT}, or 1312 * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_SIZE 1313 * PackageManager.ActivityInfo.CONFIG_SCREEN_SIZE}, or 1314 * {@link android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE 1315 * PackageManager.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE}. 1316 * {@link android.content.pm.ActivityInfo#CONFIG_LAYOUT_DIRECTION 1317 * PackageManager.ActivityInfo.CONFIG_LAYOUT_DIRECTION}. 1318 */ 1319 public int diff(Configuration delta) { 1320 return diff(delta, false /* compareUndefined */); 1321 } 1322 1323 /** 1324 * Variation of {@link #diff(Configuration)} with an option to skip checks for undefined values. 1325 * 1326 * @hide 1327 */ 1328 public int diff(Configuration delta, boolean compareUndefined) { 1329 int changed = 0; 1330 if ((compareUndefined || delta.fontScale > 0) && fontScale != delta.fontScale) { 1331 changed |= ActivityInfo.CONFIG_FONT_SCALE; 1332 } 1333 if ((compareUndefined || delta.mcc != 0) && mcc != delta.mcc) { 1334 changed |= ActivityInfo.CONFIG_MCC; 1335 } 1336 if ((compareUndefined || delta.mnc != 0) && mnc != delta.mnc) { 1337 changed |= ActivityInfo.CONFIG_MNC; 1338 } 1339 fixUpLocaleList(); 1340 delta.fixUpLocaleList(); 1341 if ((compareUndefined || !delta.mLocaleList.isEmpty()) 1342 && !mLocaleList.equals(delta.mLocaleList)) { 1343 changed |= ActivityInfo.CONFIG_LOCALE; 1344 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION; 1345 } 1346 final int deltaScreenLayoutDir = delta.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK; 1347 if ((compareUndefined || deltaScreenLayoutDir != SCREENLAYOUT_LAYOUTDIR_UNDEFINED) 1348 && deltaScreenLayoutDir != (screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) { 1349 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION; 1350 } 1351 if ((compareUndefined || delta.touchscreen != TOUCHSCREEN_UNDEFINED) 1352 && touchscreen != delta.touchscreen) { 1353 changed |= ActivityInfo.CONFIG_TOUCHSCREEN; 1354 } 1355 if ((compareUndefined || delta.keyboard != KEYBOARD_UNDEFINED) 1356 && keyboard != delta.keyboard) { 1357 changed |= ActivityInfo.CONFIG_KEYBOARD; 1358 } 1359 if ((compareUndefined || delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED) 1360 && keyboardHidden != delta.keyboardHidden) { 1361 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN; 1362 } 1363 if ((compareUndefined || delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED) 1364 && hardKeyboardHidden != delta.hardKeyboardHidden) { 1365 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN; 1366 } 1367 if ((compareUndefined || delta.navigation != NAVIGATION_UNDEFINED) 1368 && navigation != delta.navigation) { 1369 changed |= ActivityInfo.CONFIG_NAVIGATION; 1370 } 1371 if ((compareUndefined || delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED) 1372 && navigationHidden != delta.navigationHidden) { 1373 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN; 1374 } 1375 if ((compareUndefined || delta.orientation != ORIENTATION_UNDEFINED) 1376 && orientation != delta.orientation) { 1377 changed |= ActivityInfo.CONFIG_ORIENTATION; 1378 } 1379 if ((compareUndefined || getScreenLayoutNoDirection(delta.screenLayout) != 1380 (SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED)) 1381 && getScreenLayoutNoDirection(screenLayout) != 1382 getScreenLayoutNoDirection(delta.screenLayout)) { 1383 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT; 1384 } 1385 if ((compareUndefined || 1386 (delta.colorMode & COLOR_MODE_HDR_MASK) != COLOR_MODE_HDR_UNDEFINED) 1387 && (colorMode & COLOR_MODE_HDR_MASK) != 1388 (delta.colorMode & COLOR_MODE_HDR_MASK)) { 1389 changed |= ActivityInfo.CONFIG_COLOR_MODE; 1390 } 1391 if ((compareUndefined || 1392 (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) != 1393 COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED) 1394 && (colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) != 1395 (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) { 1396 changed |= ActivityInfo.CONFIG_COLOR_MODE; 1397 } 1398 if ((compareUndefined || delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)) 1399 && uiMode != delta.uiMode) { 1400 changed |= ActivityInfo.CONFIG_UI_MODE; 1401 } 1402 if ((compareUndefined || delta.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) 1403 && screenWidthDp != delta.screenWidthDp) { 1404 changed |= ActivityInfo.CONFIG_SCREEN_SIZE; 1405 } 1406 if ((compareUndefined || delta.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) 1407 && screenHeightDp != delta.screenHeightDp) { 1408 changed |= ActivityInfo.CONFIG_SCREEN_SIZE; 1409 } 1410 if ((compareUndefined || delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) 1411 && smallestScreenWidthDp != delta.smallestScreenWidthDp) { 1412 changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE; 1413 } 1414 if ((compareUndefined || delta.densityDpi != DENSITY_DPI_UNDEFINED) 1415 && densityDpi != delta.densityDpi) { 1416 changed |= ActivityInfo.CONFIG_DENSITY; 1417 } 1418 if ((compareUndefined || delta.assetsSeq != ASSETS_SEQ_UNDEFINED) 1419 && assetsSeq != delta.assetsSeq) { 1420 changed |= ActivityInfo.CONFIG_ASSETS_PATHS; 1421 } 1422 1423 // Make sure that one of the values is not null and that they are not equal. 1424 if ((compareUndefined || delta.appBounds != null) 1425 && appBounds != delta.appBounds 1426 && (appBounds == null || !appBounds.equals(delta.appBounds))) { 1427 changed |= ActivityInfo.CONFIG_SCREEN_SIZE; 1428 } 1429 1430 return changed; 1431 } 1432 1433 /** 1434 * Determines if a new resource needs to be loaded from the bit set of 1435 * configuration changes returned by {@link #updateFrom(Configuration)}. 1436 * 1437 * @param configChanges the mask of changes configurations as returned by 1438 * {@link #updateFrom(Configuration)} 1439 * @param interestingChanges the configuration changes that the resource 1440 * can handle as given in 1441 * {@link android.util.TypedValue#changingConfigurations} 1442 * @return {@code true} if the resource needs to be loaded, {@code false} 1443 * otherwise 1444 */ 1445 public static boolean needNewResources(@Config int configChanges, 1446 @Config int interestingChanges) { 1447 // CONFIG_ASSETS_PATHS and CONFIG_FONT_SCALE are higher level configuration changes that 1448 // all resources are subject to change with. 1449 interestingChanges = interestingChanges | ActivityInfo.CONFIG_ASSETS_PATHS 1450 | ActivityInfo.CONFIG_FONT_SCALE; 1451 return (configChanges & interestingChanges) != 0; 1452 } 1453 1454 /** 1455 * @hide Return true if the sequence of 'other' is better than this. Assumes 1456 * that 'this' is your current sequence and 'other' is a new one you have 1457 * received some how and want to compare with what you have. 1458 */ 1459 public boolean isOtherSeqNewer(Configuration other) { 1460 if (other == null) { 1461 // Sanity check. 1462 return false; 1463 } 1464 if (other.seq == 0) { 1465 // If the other sequence is not specified, then we must assume 1466 // it is newer since we don't know any better. 1467 return true; 1468 } 1469 if (seq == 0) { 1470 // If this sequence is not specified, then we also consider the 1471 // other is better. Yes we have a preference for other. Sue us. 1472 return true; 1473 } 1474 int diff = other.seq - seq; 1475 if (diff > 0x10000) { 1476 // If there has been a sufficiently large jump, assume the 1477 // sequence has wrapped around. 1478 return false; 1479 } 1480 return diff > 0; 1481 } 1482 1483 /** 1484 * Parcelable methods 1485 */ 1486 public int describeContents() { 1487 return 0; 1488 } 1489 1490 public void writeToParcel(Parcel dest, int flags) { 1491 dest.writeFloat(fontScale); 1492 dest.writeInt(mcc); 1493 dest.writeInt(mnc); 1494 1495 fixUpLocaleList(); 1496 final int localeListSize = mLocaleList.size(); 1497 dest.writeInt(localeListSize); 1498 for (int i = 0; i < localeListSize; ++i) { 1499 final Locale l = mLocaleList.get(i); 1500 dest.writeString(l.toLanguageTag()); 1501 } 1502 1503 if(userSetLocale) { 1504 dest.writeInt(1); 1505 } else { 1506 dest.writeInt(0); 1507 } 1508 dest.writeInt(touchscreen); 1509 dest.writeInt(keyboard); 1510 dest.writeInt(keyboardHidden); 1511 dest.writeInt(hardKeyboardHidden); 1512 dest.writeInt(navigation); 1513 dest.writeInt(navigationHidden); 1514 dest.writeInt(orientation); 1515 dest.writeInt(screenLayout); 1516 dest.writeInt(colorMode); 1517 dest.writeInt(uiMode); 1518 dest.writeInt(screenWidthDp); 1519 dest.writeInt(screenHeightDp); 1520 dest.writeInt(smallestScreenWidthDp); 1521 dest.writeInt(densityDpi); 1522 dest.writeInt(compatScreenWidthDp); 1523 dest.writeInt(compatScreenHeightDp); 1524 dest.writeInt(compatSmallestScreenWidthDp); 1525 dest.writeValue(appBounds); 1526 dest.writeInt(assetsSeq); 1527 dest.writeInt(seq); 1528 } 1529 1530 public void readFromParcel(Parcel source) { 1531 fontScale = source.readFloat(); 1532 mcc = source.readInt(); 1533 mnc = source.readInt(); 1534 1535 final int localeListSize = source.readInt(); 1536 final Locale[] localeArray = new Locale[localeListSize]; 1537 for (int i = 0; i < localeListSize; ++i) { 1538 localeArray[i] = Locale.forLanguageTag(source.readString()); 1539 } 1540 mLocaleList = new LocaleList(localeArray); 1541 locale = mLocaleList.get(0); 1542 1543 userSetLocale = (source.readInt()==1); 1544 touchscreen = source.readInt(); 1545 keyboard = source.readInt(); 1546 keyboardHidden = source.readInt(); 1547 hardKeyboardHidden = source.readInt(); 1548 navigation = source.readInt(); 1549 navigationHidden = source.readInt(); 1550 orientation = source.readInt(); 1551 screenLayout = source.readInt(); 1552 colorMode = source.readInt(); 1553 uiMode = source.readInt(); 1554 screenWidthDp = source.readInt(); 1555 screenHeightDp = source.readInt(); 1556 smallestScreenWidthDp = source.readInt(); 1557 densityDpi = source.readInt(); 1558 compatScreenWidthDp = source.readInt(); 1559 compatScreenHeightDp = source.readInt(); 1560 compatSmallestScreenWidthDp = source.readInt(); 1561 appBounds = (Rect) source.readValue(null); 1562 assetsSeq = source.readInt(); 1563 seq = source.readInt(); 1564 } 1565 1566 public static final Parcelable.Creator<Configuration> CREATOR 1567 = new Parcelable.Creator<Configuration>() { 1568 public Configuration createFromParcel(Parcel source) { 1569 return new Configuration(source); 1570 } 1571 1572 public Configuration[] newArray(int size) { 1573 return new Configuration[size]; 1574 } 1575 }; 1576 1577 /** 1578 * Construct this Configuration object, reading from the Parcel. 1579 */ 1580 private Configuration(Parcel source) { 1581 readFromParcel(source); 1582 } 1583 1584 public int compareTo(Configuration that) { 1585 int n; 1586 float a = this.fontScale; 1587 float b = that.fontScale; 1588 if (a < b) return -1; 1589 if (a > b) return 1; 1590 n = this.mcc - that.mcc; 1591 if (n != 0) return n; 1592 n = this.mnc - that.mnc; 1593 if (n != 0) return n; 1594 1595 fixUpLocaleList(); 1596 that.fixUpLocaleList(); 1597 // for backward compatibility, we consider an empty locale list to be greater 1598 // than any non-empty locale list. 1599 if (this.mLocaleList.isEmpty()) { 1600 if (!that.mLocaleList.isEmpty()) return 1; 1601 } else if (that.mLocaleList.isEmpty()) { 1602 return -1; 1603 } else { 1604 final int minSize = Math.min(this.mLocaleList.size(), that.mLocaleList.size()); 1605 for (int i = 0; i < minSize; ++i) { 1606 final Locale thisLocale = this.mLocaleList.get(i); 1607 final Locale thatLocale = that.mLocaleList.get(i); 1608 n = thisLocale.getLanguage().compareTo(thatLocale.getLanguage()); 1609 if (n != 0) return n; 1610 n = thisLocale.getCountry().compareTo(thatLocale.getCountry()); 1611 if (n != 0) return n; 1612 n = thisLocale.getVariant().compareTo(thatLocale.getVariant()); 1613 if (n != 0) return n; 1614 n = thisLocale.toLanguageTag().compareTo(thatLocale.toLanguageTag()); 1615 if (n != 0) return n; 1616 } 1617 n = this.mLocaleList.size() - that.mLocaleList.size(); 1618 if (n != 0) return n; 1619 } 1620 1621 n = this.touchscreen - that.touchscreen; 1622 if (n != 0) return n; 1623 n = this.keyboard - that.keyboard; 1624 if (n != 0) return n; 1625 n = this.keyboardHidden - that.keyboardHidden; 1626 if (n != 0) return n; 1627 n = this.hardKeyboardHidden - that.hardKeyboardHidden; 1628 if (n != 0) return n; 1629 n = this.navigation - that.navigation; 1630 if (n != 0) return n; 1631 n = this.navigationHidden - that.navigationHidden; 1632 if (n != 0) return n; 1633 n = this.orientation - that.orientation; 1634 if (n != 0) return n; 1635 n = this.colorMode - that.colorMode; 1636 if (n != 0) return n; 1637 n = this.screenLayout - that.screenLayout; 1638 if (n != 0) return n; 1639 n = this.uiMode - that.uiMode; 1640 if (n != 0) return n; 1641 n = this.screenWidthDp - that.screenWidthDp; 1642 if (n != 0) return n; 1643 n = this.screenHeightDp - that.screenHeightDp; 1644 if (n != 0) return n; 1645 n = this.smallestScreenWidthDp - that.smallestScreenWidthDp; 1646 if (n != 0) return n; 1647 n = this.densityDpi - that.densityDpi; 1648 if (n != 0) return n; 1649 n = this.assetsSeq - that.assetsSeq; 1650 //if (n != 0) return n; 1651 return n; 1652 } 1653 1654 public boolean equals(Configuration that) { 1655 if (that == null) return false; 1656 if (that == this) return true; 1657 return this.compareTo(that) == 0; 1658 } 1659 1660 public boolean equals(Object that) { 1661 try { 1662 return equals((Configuration)that); 1663 } catch (ClassCastException e) { 1664 } 1665 return false; 1666 } 1667 1668 public int hashCode() { 1669 int result = 17; 1670 result = 31 * result + Float.floatToIntBits(fontScale); 1671 result = 31 * result + mcc; 1672 result = 31 * result + mnc; 1673 result = 31 * result + mLocaleList.hashCode(); 1674 result = 31 * result + touchscreen; 1675 result = 31 * result + keyboard; 1676 result = 31 * result + keyboardHidden; 1677 result = 31 * result + hardKeyboardHidden; 1678 result = 31 * result + navigation; 1679 result = 31 * result + navigationHidden; 1680 result = 31 * result + orientation; 1681 result = 31 * result + screenLayout; 1682 result = 31 * result + colorMode; 1683 result = 31 * result + uiMode; 1684 result = 31 * result + screenWidthDp; 1685 result = 31 * result + screenHeightDp; 1686 result = 31 * result + smallestScreenWidthDp; 1687 result = 31 * result + densityDpi; 1688 result = 31 * result + assetsSeq; 1689 return result; 1690 } 1691 1692 /** 1693 * Get the locale list. This is the preferred way for getting the locales (instead of using 1694 * the direct accessor to {@link #locale}, which would only provide the primary locale). 1695 * 1696 * @return The locale list. 1697 */ 1698 public @NonNull LocaleList getLocales() { 1699 fixUpLocaleList(); 1700 return mLocaleList; 1701 } 1702 1703 /** 1704 * Set the locale list. This is the preferred way for setting up the locales (instead of using 1705 * the direct accessor or {@link #setLocale(Locale)}). This will also set the layout direction 1706 * according to the first locale in the list. 1707 * 1708 * Note that the layout direction will always come from the first locale in the locale list, 1709 * even if the locale is not supported by the resources (the resources may only support 1710 * another locale further down the list which has a different direction). 1711 * 1712 * @param locales The locale list. If null, an empty LocaleList will be assigned. 1713 */ 1714 public void setLocales(@Nullable LocaleList locales) { 1715 mLocaleList = locales == null ? LocaleList.getEmptyLocaleList() : locales; 1716 locale = mLocaleList.get(0); 1717 setLayoutDirection(locale); 1718 } 1719 1720 /** 1721 * Set the locale list to a list of just one locale. This will also set the layout direction 1722 * according to the locale. 1723 * 1724 * Note that after this is run, calling <code>.equals()</code> on the input locale and the 1725 * {@link #locale} attribute would return <code>true</code> if they are not null, but there is 1726 * no guarantee that they would be the same object. 1727 * 1728 * See also the note about layout direction in {@link #setLocales(LocaleList)}. 1729 * 1730 * @param loc The locale. Can be null. 1731 */ 1732 public void setLocale(@Nullable Locale loc) { 1733 setLocales(loc == null ? LocaleList.getEmptyLocaleList() : new LocaleList(loc)); 1734 } 1735 1736 /** 1737 * @hide 1738 * 1739 * Helper method for setting the app bounds. 1740 */ 1741 public void setAppBounds(Rect rect) { 1742 if (rect == null) { 1743 appBounds = null; 1744 return; 1745 } 1746 1747 setAppBounds(rect.left, rect.top, rect.right, rect.bottom); 1748 } 1749 1750 /** 1751 * @hide 1752 * 1753 * Helper method for setting the app bounds. 1754 */ 1755 public void setAppBounds(int left, int top, int right, int bottom) { 1756 if (appBounds == null) { 1757 appBounds = new Rect(); 1758 } 1759 1760 appBounds.set(left, top, right, bottom); 1761 } 1762 1763 /** 1764 * @hide 1765 * 1766 * Clears the locale without changing layout direction. 1767 */ 1768 public void clearLocales() { 1769 mLocaleList = LocaleList.getEmptyLocaleList(); 1770 locale = null; 1771 } 1772 1773 /** 1774 * Return the layout direction. Will be either {@link View#LAYOUT_DIRECTION_LTR} or 1775 * {@link View#LAYOUT_DIRECTION_RTL}. 1776 * 1777 * @return Returns {@link View#LAYOUT_DIRECTION_RTL} if the configuration 1778 * is {@link #SCREENLAYOUT_LAYOUTDIR_RTL}, otherwise {@link View#LAYOUT_DIRECTION_LTR}. 1779 */ 1780 public int getLayoutDirection() { 1781 return (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK) == SCREENLAYOUT_LAYOUTDIR_RTL 1782 ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR; 1783 } 1784 1785 /** 1786 * Set the layout direction from a Locale. 1787 * 1788 * @param loc The Locale. If null will set the layout direction to 1789 * {@link View#LAYOUT_DIRECTION_LTR}. If not null will set it to the layout direction 1790 * corresponding to the Locale. 1791 * 1792 * @see View#LAYOUT_DIRECTION_LTR 1793 * @see View#LAYOUT_DIRECTION_RTL 1794 */ 1795 public void setLayoutDirection(Locale loc) { 1796 // There is a "1" difference between the configuration values for 1797 // layout direction and View constants for layout direction, just add "1". 1798 final int layoutDirection = 1 + TextUtils.getLayoutDirectionFromLocale(loc); 1799 screenLayout = (screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK)| 1800 (layoutDirection << SCREENLAYOUT_LAYOUTDIR_SHIFT); 1801 } 1802 1803 private static int getScreenLayoutNoDirection(int screenLayout) { 1804 return screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK; 1805 } 1806 1807 /** 1808 * Return whether the screen has a round shape. Apps may choose to change styling based 1809 * on this property, such as the alignment or layout of text or informational icons. 1810 * 1811 * @return true if the screen is rounded, false otherwise 1812 */ 1813 public boolean isScreenRound() { 1814 return (screenLayout & SCREENLAYOUT_ROUND_MASK) == SCREENLAYOUT_ROUND_YES; 1815 } 1816 1817 /** 1818 * Return whether the screen has a wide color gamut and wide color gamut rendering 1819 * is supported by this device. 1820 * 1821 * @return true if the screen has a wide color gamut and wide color gamut rendering 1822 * is supported, false otherwise 1823 */ 1824 public boolean isScreenWideColorGamut() { 1825 return (colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) == COLOR_MODE_WIDE_COLOR_GAMUT_YES; 1826 } 1827 1828 /** 1829 * Return whether the screen has a high dynamic range. 1830 * 1831 * @return true if the screen has a high dynamic range, false otherwise 1832 */ 1833 public boolean isScreenHdr() { 1834 return (colorMode & COLOR_MODE_HDR_MASK) == COLOR_MODE_HDR_YES; 1835 } 1836 1837 /** 1838 * 1839 * @hide 1840 */ 1841 public static String localesToResourceQualifier(LocaleList locs) { 1842 final StringBuilder sb = new StringBuilder(); 1843 for (int i = 0; i < locs.size(); i++) { 1844 final Locale loc = locs.get(i); 1845 final int l = loc.getLanguage().length(); 1846 if (l == 0) { 1847 continue; 1848 } 1849 final int s = loc.getScript().length(); 1850 final int c = loc.getCountry().length(); 1851 final int v = loc.getVariant().length(); 1852 // We ignore locale extensions, since they are not supported by AAPT 1853 1854 if (sb.length() != 0) { 1855 sb.append(","); 1856 } 1857 if (l == 2 && s == 0 && (c == 0 || c == 2) && v == 0) { 1858 // Traditional locale format: xx or xx-rYY 1859 sb.append(loc.getLanguage()); 1860 if (c == 2) { 1861 sb.append("-r").append(loc.getCountry()); 1862 } 1863 } else { 1864 sb.append("b+"); 1865 sb.append(loc.getLanguage()); 1866 if (s != 0) { 1867 sb.append("+"); 1868 sb.append(loc.getScript()); 1869 } 1870 if (c != 0) { 1871 sb.append("+"); 1872 sb.append(loc.getCountry()); 1873 } 1874 if (v != 0) { 1875 sb.append("+"); 1876 sb.append(loc.getVariant()); 1877 } 1878 } 1879 } 1880 return sb.toString(); 1881 } 1882 1883 1884 /** 1885 * Returns a string representation of the configuration that can be parsed 1886 * by build tools (like AAPT). 1887 * 1888 * @hide 1889 */ 1890 public static String resourceQualifierString(Configuration config) { 1891 ArrayList<String> parts = new ArrayList<String>(); 1892 1893 if (config.mcc != 0) { 1894 parts.add("mcc" + config.mcc); 1895 if (config.mnc != 0) { 1896 parts.add("mnc" + config.mnc); 1897 } 1898 } 1899 1900 if (!config.mLocaleList.isEmpty()) { 1901 final String resourceQualifier = localesToResourceQualifier(config.mLocaleList); 1902 if (!resourceQualifier.isEmpty()) { 1903 parts.add(resourceQualifier); 1904 } 1905 } 1906 1907 switch (config.screenLayout & Configuration.SCREENLAYOUT_LAYOUTDIR_MASK) { 1908 case Configuration.SCREENLAYOUT_LAYOUTDIR_LTR: 1909 parts.add("ldltr"); 1910 break; 1911 case Configuration.SCREENLAYOUT_LAYOUTDIR_RTL: 1912 parts.add("ldrtl"); 1913 break; 1914 default: 1915 break; 1916 } 1917 1918 if (config.smallestScreenWidthDp != 0) { 1919 parts.add("sw" + config.smallestScreenWidthDp + "dp"); 1920 } 1921 1922 if (config.screenWidthDp != 0) { 1923 parts.add("w" + config.screenWidthDp + "dp"); 1924 } 1925 1926 if (config.screenHeightDp != 0) { 1927 parts.add("h" + config.screenHeightDp + "dp"); 1928 } 1929 1930 switch (config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) { 1931 case Configuration.SCREENLAYOUT_SIZE_SMALL: 1932 parts.add("small"); 1933 break; 1934 case Configuration.SCREENLAYOUT_SIZE_NORMAL: 1935 parts.add("normal"); 1936 break; 1937 case Configuration.SCREENLAYOUT_SIZE_LARGE: 1938 parts.add("large"); 1939 break; 1940 case Configuration.SCREENLAYOUT_SIZE_XLARGE: 1941 parts.add("xlarge"); 1942 break; 1943 default: 1944 break; 1945 } 1946 1947 switch (config.screenLayout & Configuration.SCREENLAYOUT_LONG_MASK) { 1948 case Configuration.SCREENLAYOUT_LONG_YES: 1949 parts.add("long"); 1950 break; 1951 case Configuration.SCREENLAYOUT_LONG_NO: 1952 parts.add("notlong"); 1953 break; 1954 default: 1955 break; 1956 } 1957 1958 switch (config.screenLayout & Configuration.SCREENLAYOUT_ROUND_MASK) { 1959 case Configuration.SCREENLAYOUT_ROUND_YES: 1960 parts.add("round"); 1961 break; 1962 case Configuration.SCREENLAYOUT_ROUND_NO: 1963 parts.add("notround"); 1964 break; 1965 default: 1966 break; 1967 } 1968 1969 switch (config.colorMode & Configuration.COLOR_MODE_HDR_MASK) { 1970 case Configuration.COLOR_MODE_HDR_YES: 1971 parts.add("highdr"); 1972 break; 1973 case Configuration.COLOR_MODE_HDR_NO: 1974 parts.add("lowdr"); 1975 break; 1976 default: 1977 break; 1978 } 1979 1980 switch (config.colorMode & Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_MASK) { 1981 case Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_YES: 1982 parts.add("widecg"); 1983 break; 1984 case Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_NO: 1985 parts.add("nowidecg"); 1986 break; 1987 default: 1988 break; 1989 } 1990 1991 switch (config.orientation) { 1992 case Configuration.ORIENTATION_LANDSCAPE: 1993 parts.add("land"); 1994 break; 1995 case Configuration.ORIENTATION_PORTRAIT: 1996 parts.add("port"); 1997 break; 1998 default: 1999 break; 2000 } 2001 2002 switch (config.uiMode & Configuration.UI_MODE_TYPE_MASK) { 2003 case Configuration.UI_MODE_TYPE_APPLIANCE: 2004 parts.add("appliance"); 2005 break; 2006 case Configuration.UI_MODE_TYPE_DESK: 2007 parts.add("desk"); 2008 break; 2009 case Configuration.UI_MODE_TYPE_TELEVISION: 2010 parts.add("television"); 2011 break; 2012 case Configuration.UI_MODE_TYPE_CAR: 2013 parts.add("car"); 2014 break; 2015 case Configuration.UI_MODE_TYPE_WATCH: 2016 parts.add("watch"); 2017 break; 2018 case Configuration.UI_MODE_TYPE_VR_HEADSET: 2019 parts.add("vrheadset"); 2020 break; 2021 default: 2022 break; 2023 } 2024 2025 switch (config.uiMode & Configuration.UI_MODE_NIGHT_MASK) { 2026 case Configuration.UI_MODE_NIGHT_YES: 2027 parts.add("night"); 2028 break; 2029 case Configuration.UI_MODE_NIGHT_NO: 2030 parts.add("notnight"); 2031 break; 2032 default: 2033 break; 2034 } 2035 2036 switch (config.densityDpi) { 2037 case DENSITY_DPI_UNDEFINED: 2038 break; 2039 case 120: 2040 parts.add("ldpi"); 2041 break; 2042 case 160: 2043 parts.add("mdpi"); 2044 break; 2045 case 213: 2046 parts.add("tvdpi"); 2047 break; 2048 case 240: 2049 parts.add("hdpi"); 2050 break; 2051 case 320: 2052 parts.add("xhdpi"); 2053 break; 2054 case 480: 2055 parts.add("xxhdpi"); 2056 break; 2057 case 640: 2058 parts.add("xxxhdpi"); 2059 break; 2060 case DENSITY_DPI_ANY: 2061 parts.add("anydpi"); 2062 break; 2063 case DENSITY_DPI_NONE: 2064 parts.add("nodpi"); 2065 default: 2066 parts.add(config.densityDpi + "dpi"); 2067 break; 2068 } 2069 2070 switch (config.touchscreen) { 2071 case Configuration.TOUCHSCREEN_NOTOUCH: 2072 parts.add("notouch"); 2073 break; 2074 case Configuration.TOUCHSCREEN_FINGER: 2075 parts.add("finger"); 2076 break; 2077 default: 2078 break; 2079 } 2080 2081 switch (config.keyboardHidden) { 2082 case Configuration.KEYBOARDHIDDEN_NO: 2083 parts.add("keysexposed"); 2084 break; 2085 case Configuration.KEYBOARDHIDDEN_YES: 2086 parts.add("keyshidden"); 2087 break; 2088 case Configuration.KEYBOARDHIDDEN_SOFT: 2089 parts.add("keyssoft"); 2090 break; 2091 default: 2092 break; 2093 } 2094 2095 switch (config.keyboard) { 2096 case Configuration.KEYBOARD_NOKEYS: 2097 parts.add("nokeys"); 2098 break; 2099 case Configuration.KEYBOARD_QWERTY: 2100 parts.add("qwerty"); 2101 break; 2102 case Configuration.KEYBOARD_12KEY: 2103 parts.add("12key"); 2104 break; 2105 default: 2106 break; 2107 } 2108 2109 switch (config.navigationHidden) { 2110 case Configuration.NAVIGATIONHIDDEN_NO: 2111 parts.add("navexposed"); 2112 break; 2113 case Configuration.NAVIGATIONHIDDEN_YES: 2114 parts.add("navhidden"); 2115 break; 2116 default: 2117 break; 2118 } 2119 2120 switch (config.navigation) { 2121 case Configuration.NAVIGATION_NONAV: 2122 parts.add("nonav"); 2123 break; 2124 case Configuration.NAVIGATION_DPAD: 2125 parts.add("dpad"); 2126 break; 2127 case Configuration.NAVIGATION_TRACKBALL: 2128 parts.add("trackball"); 2129 break; 2130 case Configuration.NAVIGATION_WHEEL: 2131 parts.add("wheel"); 2132 break; 2133 default: 2134 break; 2135 } 2136 2137 parts.add("v" + Build.VERSION.RESOURCES_SDK_INT); 2138 return TextUtils.join("-", parts); 2139 } 2140 2141 /** 2142 * Generate a delta Configuration between <code>base</code> and <code>change</code>. The 2143 * resulting delta can be used with {@link #updateFrom(Configuration)}. 2144 * <p /> 2145 * Caveat: If the any of the Configuration's members becomes undefined, then 2146 * {@link #updateFrom(Configuration)} will treat it as a no-op and not update that member. 2147 * 2148 * This is fine for device configurations as no member is ever undefined. 2149 * {@hide} 2150 */ 2151 public static Configuration generateDelta(Configuration base, Configuration change) { 2152 final Configuration delta = new Configuration(); 2153 if (base.fontScale != change.fontScale) { 2154 delta.fontScale = change.fontScale; 2155 } 2156 2157 if (base.mcc != change.mcc) { 2158 delta.mcc = change.mcc; 2159 } 2160 2161 if (base.mnc != change.mnc) { 2162 delta.mnc = change.mnc; 2163 } 2164 2165 base.fixUpLocaleList(); 2166 change.fixUpLocaleList(); 2167 if (!base.mLocaleList.equals(change.mLocaleList)) { 2168 delta.mLocaleList = change.mLocaleList; 2169 delta.locale = change.locale; 2170 } 2171 2172 if (base.touchscreen != change.touchscreen) { 2173 delta.touchscreen = change.touchscreen; 2174 } 2175 2176 if (base.keyboard != change.keyboard) { 2177 delta.keyboard = change.keyboard; 2178 } 2179 2180 if (base.keyboardHidden != change.keyboardHidden) { 2181 delta.keyboardHidden = change.keyboardHidden; 2182 } 2183 2184 if (base.navigation != change.navigation) { 2185 delta.navigation = change.navigation; 2186 } 2187 2188 if (base.navigationHidden != change.navigationHidden) { 2189 delta.navigationHidden = change.navigationHidden; 2190 } 2191 2192 if (base.orientation != change.orientation) { 2193 delta.orientation = change.orientation; 2194 } 2195 2196 if ((base.screenLayout & SCREENLAYOUT_SIZE_MASK) != 2197 (change.screenLayout & SCREENLAYOUT_SIZE_MASK)) { 2198 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_SIZE_MASK; 2199 } 2200 2201 if ((base.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK) != 2202 (change.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) { 2203 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK; 2204 } 2205 2206 if ((base.screenLayout & SCREENLAYOUT_LONG_MASK) != 2207 (change.screenLayout & SCREENLAYOUT_LONG_MASK)) { 2208 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_LONG_MASK; 2209 } 2210 2211 if ((base.screenLayout & SCREENLAYOUT_ROUND_MASK) != 2212 (change.screenLayout & SCREENLAYOUT_ROUND_MASK)) { 2213 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_ROUND_MASK; 2214 } 2215 2216 if ((base.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) != 2217 (change.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) { 2218 delta.colorMode |= change.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK; 2219 } 2220 2221 if ((base.colorMode & COLOR_MODE_HDR_MASK) != 2222 (change.colorMode & COLOR_MODE_HDR_MASK)) { 2223 delta.colorMode |= change.colorMode & COLOR_MODE_HDR_MASK; 2224 } 2225 2226 if ((base.uiMode & UI_MODE_TYPE_MASK) != (change.uiMode & UI_MODE_TYPE_MASK)) { 2227 delta.uiMode |= change.uiMode & UI_MODE_TYPE_MASK; 2228 } 2229 2230 if ((base.uiMode & UI_MODE_NIGHT_MASK) != (change.uiMode & UI_MODE_NIGHT_MASK)) { 2231 delta.uiMode |= change.uiMode & UI_MODE_NIGHT_MASK; 2232 } 2233 2234 if (base.screenWidthDp != change.screenWidthDp) { 2235 delta.screenWidthDp = change.screenWidthDp; 2236 } 2237 2238 if (base.screenHeightDp != change.screenHeightDp) { 2239 delta.screenHeightDp = change.screenHeightDp; 2240 } 2241 2242 if (base.smallestScreenWidthDp != change.smallestScreenWidthDp) { 2243 delta.smallestScreenWidthDp = change.smallestScreenWidthDp; 2244 } 2245 2246 if (base.densityDpi != change.densityDpi) { 2247 delta.densityDpi = change.densityDpi; 2248 } 2249 2250 if (base.assetsSeq != change.assetsSeq) { 2251 delta.assetsSeq = change.assetsSeq; 2252 } 2253 return delta; 2254 } 2255 2256 private static final String XML_ATTR_FONT_SCALE = "fs"; 2257 private static final String XML_ATTR_MCC = "mcc"; 2258 private static final String XML_ATTR_MNC = "mnc"; 2259 private static final String XML_ATTR_LOCALES = "locales"; 2260 private static final String XML_ATTR_TOUCHSCREEN = "touch"; 2261 private static final String XML_ATTR_KEYBOARD = "key"; 2262 private static final String XML_ATTR_KEYBOARD_HIDDEN = "keyHid"; 2263 private static final String XML_ATTR_HARD_KEYBOARD_HIDDEN = "hardKeyHid"; 2264 private static final String XML_ATTR_NAVIGATION = "nav"; 2265 private static final String XML_ATTR_NAVIGATION_HIDDEN = "navHid"; 2266 private static final String XML_ATTR_ORIENTATION = "ori"; 2267 private static final String XML_ATTR_SCREEN_LAYOUT = "scrLay"; 2268 private static final String XML_ATTR_COLOR_MODE = "clrMod"; 2269 private static final String XML_ATTR_UI_MODE = "ui"; 2270 private static final String XML_ATTR_SCREEN_WIDTH = "width"; 2271 private static final String XML_ATTR_SCREEN_HEIGHT = "height"; 2272 private static final String XML_ATTR_SMALLEST_WIDTH = "sw"; 2273 private static final String XML_ATTR_DENSITY = "density"; 2274 private static final String XML_ATTR_APP_BOUNDS = "app_bounds"; 2275 2276 /** 2277 * Reads the attributes corresponding to Configuration member fields from the Xml parser. 2278 * The parser is expected to be on a tag which has Configuration attributes. 2279 * 2280 * @param parser The Xml parser from which to read attributes. 2281 * @param configOut The Configuration to populate from the Xml attributes. 2282 * {@hide} 2283 */ 2284 public static void readXmlAttrs(XmlPullParser parser, Configuration configOut) 2285 throws XmlPullParserException, IOException { 2286 configOut.fontScale = Float.intBitsToFloat( 2287 XmlUtils.readIntAttribute(parser, XML_ATTR_FONT_SCALE, 0)); 2288 configOut.mcc = XmlUtils.readIntAttribute(parser, XML_ATTR_MCC, 0); 2289 configOut.mnc = XmlUtils.readIntAttribute(parser, XML_ATTR_MNC, 0); 2290 2291 final String localesStr = XmlUtils.readStringAttribute(parser, XML_ATTR_LOCALES); 2292 configOut.mLocaleList = LocaleList.forLanguageTags(localesStr); 2293 configOut.locale = configOut.mLocaleList.get(0); 2294 2295 configOut.touchscreen = XmlUtils.readIntAttribute(parser, XML_ATTR_TOUCHSCREEN, 2296 TOUCHSCREEN_UNDEFINED); 2297 configOut.keyboard = XmlUtils.readIntAttribute(parser, XML_ATTR_KEYBOARD, 2298 KEYBOARD_UNDEFINED); 2299 configOut.keyboardHidden = XmlUtils.readIntAttribute(parser, XML_ATTR_KEYBOARD_HIDDEN, 2300 KEYBOARDHIDDEN_UNDEFINED); 2301 configOut.hardKeyboardHidden = 2302 XmlUtils.readIntAttribute(parser, XML_ATTR_HARD_KEYBOARD_HIDDEN, 2303 HARDKEYBOARDHIDDEN_UNDEFINED); 2304 configOut.navigation = XmlUtils.readIntAttribute(parser, XML_ATTR_NAVIGATION, 2305 NAVIGATION_UNDEFINED); 2306 configOut.navigationHidden = XmlUtils.readIntAttribute(parser, XML_ATTR_NAVIGATION_HIDDEN, 2307 NAVIGATIONHIDDEN_UNDEFINED); 2308 configOut.orientation = XmlUtils.readIntAttribute(parser, XML_ATTR_ORIENTATION, 2309 ORIENTATION_UNDEFINED); 2310 configOut.screenLayout = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_LAYOUT, 2311 SCREENLAYOUT_UNDEFINED); 2312 configOut.colorMode = XmlUtils.readIntAttribute(parser, XML_ATTR_COLOR_MODE, 2313 COLOR_MODE_UNDEFINED); 2314 configOut.uiMode = XmlUtils.readIntAttribute(parser, XML_ATTR_UI_MODE, 0); 2315 configOut.screenWidthDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_WIDTH, 2316 SCREEN_WIDTH_DP_UNDEFINED); 2317 configOut.screenHeightDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_HEIGHT, 2318 SCREEN_HEIGHT_DP_UNDEFINED); 2319 configOut.smallestScreenWidthDp = 2320 XmlUtils.readIntAttribute(parser, XML_ATTR_SMALLEST_WIDTH, 2321 SMALLEST_SCREEN_WIDTH_DP_UNDEFINED); 2322 configOut.densityDpi = XmlUtils.readIntAttribute(parser, XML_ATTR_DENSITY, 2323 DENSITY_DPI_UNDEFINED); 2324 configOut.appBounds = 2325 Rect.unflattenFromString(XmlUtils.readStringAttribute(parser, XML_ATTR_APP_BOUNDS)); 2326 2327 // For persistence, we don't care about assetsSeq, so do not read it out. 2328 } 2329 2330 2331 /** 2332 * Writes the Configuration's member fields as attributes into the XmlSerializer. 2333 * The serializer is expected to have already started a tag so that attributes can be 2334 * immediately written. 2335 * 2336 * @param xml The serializer to which to write the attributes. 2337 * @param config The Configuration whose member fields to write. 2338 * {@hide} 2339 */ 2340 public static void writeXmlAttrs(XmlSerializer xml, Configuration config) throws IOException { 2341 XmlUtils.writeIntAttribute(xml, XML_ATTR_FONT_SCALE, 2342 Float.floatToIntBits(config.fontScale)); 2343 if (config.mcc != 0) { 2344 XmlUtils.writeIntAttribute(xml, XML_ATTR_MCC, config.mcc); 2345 } 2346 if (config.mnc != 0) { 2347 XmlUtils.writeIntAttribute(xml, XML_ATTR_MNC, config.mnc); 2348 } 2349 config.fixUpLocaleList(); 2350 if (!config.mLocaleList.isEmpty()) { 2351 XmlUtils.writeStringAttribute(xml, XML_ATTR_LOCALES, config.mLocaleList.toLanguageTags()); 2352 } 2353 if (config.touchscreen != TOUCHSCREEN_UNDEFINED) { 2354 XmlUtils.writeIntAttribute(xml, XML_ATTR_TOUCHSCREEN, config.touchscreen); 2355 } 2356 if (config.keyboard != KEYBOARD_UNDEFINED) { 2357 XmlUtils.writeIntAttribute(xml, XML_ATTR_KEYBOARD, config.keyboard); 2358 } 2359 if (config.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED) { 2360 XmlUtils.writeIntAttribute(xml, XML_ATTR_KEYBOARD_HIDDEN, config.keyboardHidden); 2361 } 2362 if (config.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED) { 2363 XmlUtils.writeIntAttribute(xml, XML_ATTR_HARD_KEYBOARD_HIDDEN, 2364 config.hardKeyboardHidden); 2365 } 2366 if (config.navigation != NAVIGATION_UNDEFINED) { 2367 XmlUtils.writeIntAttribute(xml, XML_ATTR_NAVIGATION, config.navigation); 2368 } 2369 if (config.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED) { 2370 XmlUtils.writeIntAttribute(xml, XML_ATTR_NAVIGATION_HIDDEN, config.navigationHidden); 2371 } 2372 if (config.orientation != ORIENTATION_UNDEFINED) { 2373 XmlUtils.writeIntAttribute(xml, XML_ATTR_ORIENTATION, config.orientation); 2374 } 2375 if (config.screenLayout != SCREENLAYOUT_UNDEFINED) { 2376 XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_LAYOUT, config.screenLayout); 2377 } 2378 if (config.colorMode != COLOR_MODE_UNDEFINED) { 2379 XmlUtils.writeIntAttribute(xml, XML_ATTR_COLOR_MODE, config.colorMode); 2380 } 2381 if (config.uiMode != 0) { 2382 XmlUtils.writeIntAttribute(xml, XML_ATTR_UI_MODE, config.uiMode); 2383 } 2384 if (config.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) { 2385 XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_WIDTH, config.screenWidthDp); 2386 } 2387 if (config.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) { 2388 XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_HEIGHT, config.screenHeightDp); 2389 } 2390 if (config.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) { 2391 XmlUtils.writeIntAttribute(xml, XML_ATTR_SMALLEST_WIDTH, config.smallestScreenWidthDp); 2392 } 2393 if (config.densityDpi != DENSITY_DPI_UNDEFINED) { 2394 XmlUtils.writeIntAttribute(xml, XML_ATTR_DENSITY, config.densityDpi); 2395 } 2396 2397 if (config.appBounds != null) { 2398 XmlUtils.writeStringAttribute(xml, XML_ATTR_APP_BOUNDS, 2399 config.appBounds.flattenToString()); 2400 } 2401 2402 // For persistence, we do not care about assetsSeq, so do not write it out. 2403 } 2404} 2405