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