Configuration.java revision a8339dfec9d1b2c6d6fd2f8268f8075d184f64c0
1package android.content.res; 2 3import android.content.pm.ActivityInfo; 4import android.os.Parcel; 5import android.os.Parcelable; 6 7import java.util.Locale; 8 9/** 10 * This class describes all device configuration information that can 11 * impact the resources the application retrieves. This includes both 12 * user-specified configuration options (locale and scaling) as well 13 * as dynamic device configuration (various types of input devices). 14 */ 15public final class Configuration implements Parcelable, Comparable<Configuration> { 16 /** 17 * Current user preference for the scaling factor for fonts, relative 18 * to the base density scaling. 19 */ 20 public float fontScale; 21 22 /** 23 * IMSI MCC (Mobile Country Code). 0 if undefined. 24 */ 25 public int mcc; 26 27 /** 28 * IMSI MNC (Mobile Network Code). 0 if undefined. 29 */ 30 public int mnc; 31 32 /** 33 * Current user preference for the locale. 34 */ 35 public Locale locale; 36 37 /** 38 * Locale should persist on setting. This is hidden because it is really 39 * questionable whether this is the right way to expose the functionality. 40 * @hide 41 */ 42 public boolean userSetLocale; 43 44 public static final int SCREENLAYOUT_SIZE_MASK = 0x0f; 45 public static final int SCREENLAYOUT_SIZE_UNDEFINED = 0x00; 46 public static final int SCREENLAYOUT_SIZE_SMALL = 0x01; 47 public static final int SCREENLAYOUT_SIZE_NORMAL = 0x02; 48 public static final int SCREENLAYOUT_SIZE_LARGE = 0x03; 49 50 public static final int SCREENLAYOUT_LONG_MASK = 0x30; 51 public static final int SCREENLAYOUT_LONG_UNDEFINED = 0x00; 52 public static final int SCREENLAYOUT_LONG_NO = 0x10; 53 public static final int SCREENLAYOUT_LONG_YES = 0x20; 54 55 /** 56 * Special flag we generate to indicate that the screen layout requires 57 * us to use a compatibility mode for apps that are not modern layout 58 * aware. 59 * @hide 60 */ 61 public static final int SCREENLAYOUT_COMPAT_NEEDED = 0x10000000; 62 63 /** 64 * Bit mask of overall layout of the screen. Currently there are two 65 * fields: 66 * <p>The {@link #SCREENLAYOUT_SIZE_MASK} bits define the overall size 67 * of the screen. They may be one of 68 * {@link #SCREENLAYOUT_SIZE_SMALL}, {@link #SCREENLAYOUT_SIZE_NORMAL}, 69 * or {@link #SCREENLAYOUT_SIZE_LARGE}. 70 * 71 * <p>The {@link #SCREENLAYOUT_LONG_MASK} defines whether the screen 72 * is wider/taller than normal. They may be one of 73 * {@link #SCREENLAYOUT_LONG_NO} or {@link #SCREENLAYOUT_LONG_YES}. 74 */ 75 public int screenLayout; 76 77 public static final int TOUCHSCREEN_UNDEFINED = 0; 78 public static final int TOUCHSCREEN_NOTOUCH = 1; 79 public static final int TOUCHSCREEN_STYLUS = 2; 80 public static final int TOUCHSCREEN_FINGER = 3; 81 82 /** 83 * The kind of touch screen attached to the device. 84 * One of: {@link #TOUCHSCREEN_NOTOUCH}, {@link #TOUCHSCREEN_STYLUS}, 85 * {@link #TOUCHSCREEN_FINGER}. 86 */ 87 public int touchscreen; 88 89 public static final int KEYBOARD_UNDEFINED = 0; 90 public static final int KEYBOARD_NOKEYS = 1; 91 public static final int KEYBOARD_QWERTY = 2; 92 public static final int KEYBOARD_12KEY = 3; 93 94 /** 95 * The kind of keyboard attached to the device. 96 * One of: {@link #KEYBOARD_NOKEYS}, {@link #KEYBOARD_QWERTY}, 97 * {@link #KEYBOARD_12KEY}. 98 */ 99 public int keyboard; 100 101 public static final int KEYBOARDHIDDEN_UNDEFINED = 0; 102 public static final int KEYBOARDHIDDEN_NO = 1; 103 public static final int KEYBOARDHIDDEN_YES = 2; 104 /** Constant matching actual resource implementation. {@hide} */ 105 public static final int KEYBOARDHIDDEN_SOFT = 3; 106 107 /** 108 * A flag indicating whether any keyboard is available. Unlike 109 * {@link #hardKeyboardHidden}, this also takes into account a soft 110 * keyboard, so if the hard keyboard is hidden but there is soft 111 * keyboard available, it will be set to NO. Value is one of: 112 * {@link #KEYBOARDHIDDEN_NO}, {@link #KEYBOARDHIDDEN_YES}. 113 */ 114 public int keyboardHidden; 115 116 public static final int HARDKEYBOARDHIDDEN_UNDEFINED = 0; 117 public static final int HARDKEYBOARDHIDDEN_NO = 1; 118 public static final int HARDKEYBOARDHIDDEN_YES = 2; 119 120 /** 121 * A flag indicating whether the hard keyboard has been hidden. This will 122 * be set on a device with a mechanism to hide the keyboard from the 123 * user, when that mechanism is closed. One of: 124 * {@link #HARDKEYBOARDHIDDEN_NO}, {@link #HARDKEYBOARDHIDDEN_YES}. 125 */ 126 public int hardKeyboardHidden; 127 128 public static final int NAVIGATION_UNDEFINED = 0; 129 public static final int NAVIGATION_NONAV = 1; 130 public static final int NAVIGATION_DPAD = 2; 131 public static final int NAVIGATION_TRACKBALL = 3; 132 public static final int NAVIGATION_WHEEL = 4; 133 134 /** 135 * The kind of navigation method available on the device. 136 * One of: {@link #NAVIGATION_NONAV}, {@link #NAVIGATION_DPAD}, 137 * {@link #NAVIGATION_TRACKBALL}, {@link #NAVIGATION_WHEEL}. 138 */ 139 public int navigation; 140 141 public static final int ORIENTATION_UNDEFINED = 0; 142 public static final int ORIENTATION_PORTRAIT = 1; 143 public static final int ORIENTATION_LANDSCAPE = 2; 144 public static final int ORIENTATION_SQUARE = 3; 145 146 /** 147 * Overall orientation of the screen. May be one of 148 * {@link #ORIENTATION_LANDSCAPE}, {@link #ORIENTATION_PORTRAIT}, 149 * or {@link #ORIENTATION_SQUARE}. 150 */ 151 public int orientation; 152 153 /** 154 * Construct an invalid Configuration. You must call {@link #setToDefaults} 155 * for this object to be valid. {@more} 156 */ 157 public Configuration() { 158 setToDefaults(); 159 } 160 161 /** 162 * Makes a deep copy suitable for modification. 163 */ 164 public Configuration(Configuration o) { 165 fontScale = o.fontScale; 166 mcc = o.mcc; 167 mnc = o.mnc; 168 if (o.locale != null) { 169 locale = (Locale) o.locale.clone(); 170 } 171 userSetLocale = o.userSetLocale; 172 touchscreen = o.touchscreen; 173 keyboard = o.keyboard; 174 keyboardHidden = o.keyboardHidden; 175 hardKeyboardHidden = o.hardKeyboardHidden; 176 navigation = o.navigation; 177 orientation = o.orientation; 178 screenLayout = o.screenLayout; 179 } 180 181 public String toString() { 182 StringBuilder sb = new StringBuilder(128); 183 sb.append("{ scale="); 184 sb.append(fontScale); 185 sb.append(" imsi="); 186 sb.append(mcc); 187 sb.append("/"); 188 sb.append(mnc); 189 sb.append(" loc="); 190 sb.append(locale); 191 sb.append(" touch="); 192 sb.append(touchscreen); 193 sb.append(" keys="); 194 sb.append(keyboard); 195 sb.append("/"); 196 sb.append(keyboardHidden); 197 sb.append("/"); 198 sb.append(hardKeyboardHidden); 199 sb.append(" nav="); 200 sb.append(navigation); 201 sb.append(" orien="); 202 sb.append(orientation); 203 sb.append(" layout="); 204 sb.append(screenLayout); 205 sb.append('}'); 206 return sb.toString(); 207 } 208 209 /** 210 * Set this object to the system defaults. 211 */ 212 public void setToDefaults() { 213 fontScale = 1; 214 mcc = mnc = 0; 215 locale = Locale.getDefault(); 216 userSetLocale = false; 217 touchscreen = TOUCHSCREEN_UNDEFINED; 218 keyboard = KEYBOARD_UNDEFINED; 219 keyboardHidden = KEYBOARDHIDDEN_UNDEFINED; 220 hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED; 221 navigation = NAVIGATION_UNDEFINED; 222 orientation = ORIENTATION_UNDEFINED; 223 screenLayout = SCREENLAYOUT_SIZE_UNDEFINED; 224 } 225 226 /** {@hide} */ 227 @Deprecated public void makeDefault() { 228 setToDefaults(); 229 } 230 231 /** 232 * Copy the fields from delta into this Configuration object, keeping 233 * track of which ones have changed. Any undefined fields in 234 * <var>delta</var> are ignored and not copied in to the current 235 * Configuration. 236 * @return Returns a bit mask of the changed fields, as per 237 * {@link #diff}. 238 */ 239 public int updateFrom(Configuration delta) { 240 int changed = 0; 241 if (delta.fontScale > 0 && fontScale != delta.fontScale) { 242 changed |= ActivityInfo.CONFIG_FONT_SCALE; 243 fontScale = delta.fontScale; 244 } 245 if (delta.mcc != 0 && mcc != delta.mcc) { 246 changed |= ActivityInfo.CONFIG_MCC; 247 mcc = delta.mcc; 248 } 249 if (delta.mnc != 0 && mnc != delta.mnc) { 250 changed |= ActivityInfo.CONFIG_MNC; 251 mnc = delta.mnc; 252 } 253 if (delta.locale != null 254 && (locale == null || !locale.equals(delta.locale))) { 255 changed |= ActivityInfo.CONFIG_LOCALE; 256 locale = delta.locale != null 257 ? (Locale) delta.locale.clone() : null; 258 } 259 if (delta.userSetLocale && (!userSetLocale || ((changed & ActivityInfo.CONFIG_LOCALE) != 0))) 260 { 261 userSetLocale = true; 262 changed |= ActivityInfo.CONFIG_LOCALE; 263 } 264 if (delta.touchscreen != TOUCHSCREEN_UNDEFINED 265 && touchscreen != delta.touchscreen) { 266 changed |= ActivityInfo.CONFIG_TOUCHSCREEN; 267 touchscreen = delta.touchscreen; 268 } 269 if (delta.keyboard != KEYBOARD_UNDEFINED 270 && keyboard != delta.keyboard) { 271 changed |= ActivityInfo.CONFIG_KEYBOARD; 272 keyboard = delta.keyboard; 273 } 274 if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED 275 && keyboardHidden != delta.keyboardHidden) { 276 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN; 277 keyboardHidden = delta.keyboardHidden; 278 } 279 if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED 280 && hardKeyboardHidden != delta.hardKeyboardHidden) { 281 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN; 282 hardKeyboardHidden = delta.hardKeyboardHidden; 283 } 284 if (delta.navigation != NAVIGATION_UNDEFINED 285 && navigation != delta.navigation) { 286 changed |= ActivityInfo.CONFIG_NAVIGATION; 287 navigation = delta.navigation; 288 } 289 if (delta.orientation != ORIENTATION_UNDEFINED 290 && orientation != delta.orientation) { 291 changed |= ActivityInfo.CONFIG_ORIENTATION; 292 orientation = delta.orientation; 293 } 294 if (delta.screenLayout != SCREENLAYOUT_SIZE_UNDEFINED 295 && screenLayout != delta.screenLayout) { 296 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT; 297 screenLayout = delta.screenLayout; 298 } 299 300 return changed; 301 } 302 303 /** 304 * Return a bit mask of the differences between this Configuration 305 * object and the given one. Does not change the values of either. Any 306 * undefined fields in <var>delta</var> are ignored. 307 * @return Returns a bit mask indicating which configuration 308 * values has changed, containing any combination of 309 * {@link android.content.pm.ActivityInfo#CONFIG_FONT_SCALE 310 * PackageManager.ActivityInfo.CONFIG_FONT_SCALE}, 311 * {@link android.content.pm.ActivityInfo#CONFIG_MCC 312 * PackageManager.ActivityInfo.CONFIG_MCC}, 313 * {@link android.content.pm.ActivityInfo#CONFIG_MNC 314 * PackageManager.ActivityInfo.CONFIG_MNC}, 315 * {@link android.content.pm.ActivityInfo#CONFIG_LOCALE 316 * PackageManager.ActivityInfo.CONFIG_LOCALE}, 317 * {@link android.content.pm.ActivityInfo#CONFIG_TOUCHSCREEN 318 * PackageManager.ActivityInfo.CONFIG_TOUCHSCREEN}, 319 * {@link android.content.pm.ActivityInfo#CONFIG_KEYBOARD 320 * PackageManager.ActivityInfo.CONFIG_KEYBOARD}, 321 * {@link android.content.pm.ActivityInfo#CONFIG_NAVIGATION 322 * PackageManager.ActivityInfo.CONFIG_NAVIGATION}, 323 * {@link android.content.pm.ActivityInfo#CONFIG_ORIENTATION 324 * PackageManager.ActivityInfo.CONFIG_ORIENTATION}, or 325 * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_LAYOUT 326 * PackageManager.ActivityInfo.CONFIG_SCREEN_LAYOUT}. 327 */ 328 public int diff(Configuration delta) { 329 int changed = 0; 330 if (delta.fontScale > 0 && fontScale != delta.fontScale) { 331 changed |= ActivityInfo.CONFIG_FONT_SCALE; 332 } 333 if (delta.mcc != 0 && mcc != delta.mcc) { 334 changed |= ActivityInfo.CONFIG_MCC; 335 } 336 if (delta.mnc != 0 && mnc != delta.mnc) { 337 changed |= ActivityInfo.CONFIG_MNC; 338 } 339 if (delta.locale != null 340 && (locale == null || !locale.equals(delta.locale))) { 341 changed |= ActivityInfo.CONFIG_LOCALE; 342 } 343 if (delta.touchscreen != TOUCHSCREEN_UNDEFINED 344 && touchscreen != delta.touchscreen) { 345 changed |= ActivityInfo.CONFIG_TOUCHSCREEN; 346 } 347 if (delta.keyboard != KEYBOARD_UNDEFINED 348 && keyboard != delta.keyboard) { 349 changed |= ActivityInfo.CONFIG_KEYBOARD; 350 } 351 if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED 352 && keyboardHidden != delta.keyboardHidden) { 353 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN; 354 } 355 if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED 356 && hardKeyboardHidden != delta.hardKeyboardHidden) { 357 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN; 358 } 359 if (delta.navigation != NAVIGATION_UNDEFINED 360 && navigation != delta.navigation) { 361 changed |= ActivityInfo.CONFIG_NAVIGATION; 362 } 363 if (delta.orientation != ORIENTATION_UNDEFINED 364 && orientation != delta.orientation) { 365 changed |= ActivityInfo.CONFIG_ORIENTATION; 366 } 367 if (delta.screenLayout != SCREENLAYOUT_SIZE_UNDEFINED 368 && screenLayout != delta.screenLayout) { 369 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT; 370 } 371 372 return changed; 373 } 374 375 /** 376 * Determine if a new resource needs to be loaded from the bit set of 377 * configuration changes returned by {@link #updateFrom(Configuration)}. 378 * 379 * @param configChanges The mask of changes configurations as returned by 380 * {@link #updateFrom(Configuration)}. 381 * @param interestingChanges The configuration changes that the resource 382 * can handled, as given in {@link android.util.TypedValue#changingConfigurations}. 383 * 384 * @return Return true if the resource needs to be loaded, else false. 385 */ 386 public static boolean needNewResources(int configChanges, int interestingChanges) { 387 return (configChanges & (interestingChanges|ActivityInfo.CONFIG_FONT_SCALE)) != 0; 388 } 389 390 /** 391 * Parcelable methods 392 */ 393 public int describeContents() { 394 return 0; 395 } 396 397 public void writeToParcel(Parcel dest, int flags) { 398 dest.writeFloat(fontScale); 399 dest.writeInt(mcc); 400 dest.writeInt(mnc); 401 if (locale == null) { 402 dest.writeInt(0); 403 } else { 404 dest.writeInt(1); 405 dest.writeString(locale.getLanguage()); 406 dest.writeString(locale.getCountry()); 407 dest.writeString(locale.getVariant()); 408 } 409 if(userSetLocale) { 410 dest.writeInt(1); 411 } else { 412 dest.writeInt(0); 413 } 414 dest.writeInt(touchscreen); 415 dest.writeInt(keyboard); 416 dest.writeInt(keyboardHidden); 417 dest.writeInt(hardKeyboardHidden); 418 dest.writeInt(navigation); 419 dest.writeInt(orientation); 420 dest.writeInt(screenLayout); 421 } 422 423 public static final Parcelable.Creator<Configuration> CREATOR 424 = new Parcelable.Creator<Configuration>() { 425 public Configuration createFromParcel(Parcel source) { 426 return new Configuration(source); 427 } 428 429 public Configuration[] newArray(int size) { 430 return new Configuration[size]; 431 } 432 }; 433 434 /** 435 * Construct this Configuration object, reading from the Parcel. 436 */ 437 private Configuration(Parcel source) { 438 fontScale = source.readFloat(); 439 mcc = source.readInt(); 440 mnc = source.readInt(); 441 if (source.readInt() != 0) { 442 locale = new Locale(source.readString(), source.readString(), 443 source.readString()); 444 } 445 userSetLocale = (source.readInt()==1); 446 touchscreen = source.readInt(); 447 keyboard = source.readInt(); 448 keyboardHidden = source.readInt(); 449 hardKeyboardHidden = source.readInt(); 450 navigation = source.readInt(); 451 orientation = source.readInt(); 452 screenLayout = source.readInt(); 453 } 454 455 public int compareTo(Configuration that) { 456 int n; 457 float a = this.fontScale; 458 float b = that.fontScale; 459 if (a < b) return -1; 460 if (a > b) return 1; 461 n = this.mcc - that.mcc; 462 if (n != 0) return n; 463 n = this.mnc - that.mnc; 464 if (n != 0) return n; 465 n = this.locale.getLanguage().compareTo(that.locale.getLanguage()); 466 if (n != 0) return n; 467 n = this.locale.getCountry().compareTo(that.locale.getCountry()); 468 if (n != 0) return n; 469 n = this.locale.getVariant().compareTo(that.locale.getVariant()); 470 if (n != 0) return n; 471 n = this.touchscreen - that.touchscreen; 472 if (n != 0) return n; 473 n = this.keyboard - that.keyboard; 474 if (n != 0) return n; 475 n = this.keyboardHidden - that.keyboardHidden; 476 if (n != 0) return n; 477 n = this.hardKeyboardHidden - that.hardKeyboardHidden; 478 if (n != 0) return n; 479 n = this.navigation - that.navigation; 480 if (n != 0) return n; 481 n = this.orientation - that.orientation; 482 if (n != 0) return n; 483 n = this.screenLayout - that.screenLayout; 484 //if (n != 0) return n; 485 return n; 486 } 487 488 public boolean equals(Configuration that) { 489 if (that == null) return false; 490 if (that == this) return true; 491 return this.compareTo(that) == 0; 492 } 493 494 public boolean equals(Object that) { 495 try { 496 return equals((Configuration)that); 497 } catch (ClassCastException e) { 498 } 499 return false; 500 } 501 502 public int hashCode() { 503 return ((int)this.fontScale) + this.mcc + this.mnc 504 + this.locale.hashCode() + this.touchscreen 505 + this.keyboard + this.keyboardHidden + this.hardKeyboardHidden 506 + this.navigation + this.orientation + this.screenLayout; 507 } 508} 509