blob: bb3486c205545776e0c3bbbfe568384aa58c9f12 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001package 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 /**
Andy Stadlerf8a7cea2009-04-10 16:24:47 -070038 * 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041 */
42 public boolean userSetLocale;
43
44 public static final int TOUCHSCREEN_UNDEFINED = 0;
45 public static final int TOUCHSCREEN_NOTOUCH = 1;
46 public static final int TOUCHSCREEN_STYLUS = 2;
47 public static final int TOUCHSCREEN_FINGER = 3;
48
49 /**
50 * The kind of touch screen attached to the device.
51 * One of: {@link #TOUCHSCREEN_NOTOUCH}, {@link #TOUCHSCREEN_STYLUS},
52 * {@link #TOUCHSCREEN_FINGER}.
53 */
54 public int touchscreen;
55
56 public static final int KEYBOARD_UNDEFINED = 0;
57 public static final int KEYBOARD_NOKEYS = 1;
58 public static final int KEYBOARD_QWERTY = 2;
59 public static final int KEYBOARD_12KEY = 3;
60
61 /**
62 * The kind of keyboard attached to the device.
63 * One of: {@link #KEYBOARD_QWERTY}, {@link #KEYBOARD_12KEY}.
64 */
65 public int keyboard;
66
67 public static final int KEYBOARDHIDDEN_UNDEFINED = 0;
68 public static final int KEYBOARDHIDDEN_NO = 1;
69 public static final int KEYBOARDHIDDEN_YES = 2;
70 /** Constant matching actual resource implementation. {@hide} */
71 public static final int KEYBOARDHIDDEN_SOFT = 3;
72
73 /**
74 * A flag indicating whether any keyboard is available. Unlike
75 * {@link #hardKeyboardHidden}, this also takes into account a soft
76 * keyboard, so if the hard keyboard is hidden but there is soft
77 * keyboard available, it will be set to NO. Value is one of:
78 * {@link #KEYBOARDHIDDEN_NO}, {@link #KEYBOARDHIDDEN_YES}.
79 */
80 public int keyboardHidden;
81
82 public static final int HARDKEYBOARDHIDDEN_UNDEFINED = 0;
83 public static final int HARDKEYBOARDHIDDEN_NO = 1;
84 public static final int HARDKEYBOARDHIDDEN_YES = 2;
85
86 /**
87 * A flag indicating whether the hard keyboard has been hidden. This will
88 * be set on a device with a mechanism to hide the keyboard from the
89 * user, when that mechanism is closed. One of:
90 * {@link #HARDKEYBOARDHIDDEN_NO}, {@link #HARDKEYBOARDHIDDEN_YES}.
91 */
92 public int hardKeyboardHidden;
93
94 public static final int NAVIGATION_UNDEFINED = 0;
95 public static final int NAVIGATION_NONAV = 1;
96 public static final int NAVIGATION_DPAD = 2;
97 public static final int NAVIGATION_TRACKBALL = 3;
98 public static final int NAVIGATION_WHEEL = 4;
99
100 /**
101 * The kind of navigation method available on the device.
102 * One of: {@link #NAVIGATION_DPAD}, {@link #NAVIGATION_TRACKBALL},
103 * {@link #NAVIGATION_WHEEL}.
104 */
105 public int navigation;
106
107 public static final int ORIENTATION_UNDEFINED = 0;
108 public static final int ORIENTATION_PORTRAIT = 1;
109 public static final int ORIENTATION_LANDSCAPE = 2;
110 public static final int ORIENTATION_SQUARE = 3;
111
112 /**
113 * Overall orientation of the screen. May be one of
114 * {@link #ORIENTATION_LANDSCAPE}, {@link #ORIENTATION_PORTRAIT},
115 * or {@link #ORIENTATION_SQUARE}.
116 */
117 public int orientation;
118
119 /**
120 * Construct an invalid Configuration. You must call {@link #setToDefaults}
121 * for this object to be valid. {@more}
122 */
123 public Configuration() {
124 setToDefaults();
125 }
126
127 /**
128 * Makes a deep copy suitable for modification.
129 */
130 public Configuration(Configuration o) {
131 fontScale = o.fontScale;
132 mcc = o.mcc;
133 mnc = o.mnc;
134 if (o.locale != null) {
135 locale = (Locale) o.locale.clone();
136 }
137 userSetLocale = o.userSetLocale;
138 touchscreen = o.touchscreen;
139 keyboard = o.keyboard;
140 keyboardHidden = o.keyboardHidden;
141 hardKeyboardHidden = o.hardKeyboardHidden;
142 navigation = o.navigation;
143 orientation = o.orientation;
144 }
145
146 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700147 StringBuilder sb = new StringBuilder(128);
148 sb.append("{ scale=");
149 sb.append(fontScale);
150 sb.append(" imsi=");
151 sb.append(mcc);
152 sb.append("/");
153 sb.append(mnc);
154 sb.append(" loc=");
155 sb.append(locale);
156 sb.append(" touch=");
157 sb.append(touchscreen);
158 sb.append(" keys=");
159 sb.append(keyboard);
160 sb.append("/");
161 sb.append(keyboardHidden);
162 sb.append("/");
163 sb.append(hardKeyboardHidden);
164 sb.append(" nav=");
165 sb.append(navigation);
166 sb.append(" orien=");
167 sb.append(orientation);
168 sb.append('}');
169 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170 }
171
172 /**
173 * Set this object to the system defaults.
174 */
175 public void setToDefaults() {
176 fontScale = 1;
177 mcc = mnc = 0;
178 locale = Locale.getDefault();
179 userSetLocale = false;
180 touchscreen = TOUCHSCREEN_UNDEFINED;
181 keyboard = KEYBOARD_UNDEFINED;
182 keyboardHidden = KEYBOARDHIDDEN_UNDEFINED;
183 hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED;
184 navigation = NAVIGATION_UNDEFINED;
185 orientation = ORIENTATION_UNDEFINED;
186 }
187
188 /** {@hide} */
189 @Deprecated public void makeDefault() {
190 setToDefaults();
191 }
192
193 /**
194 * Copy the fields from delta into this Configuration object, keeping
195 * track of which ones have changed. Any undefined fields in
196 * <var>delta</var> are ignored and not copied in to the current
197 * Configuration.
198 * @return Returns a bit mask of the changed fields, as per
199 * {@link #diff}.
200 */
201 public int updateFrom(Configuration delta) {
202 int changed = 0;
203 if (delta.fontScale > 0 && fontScale != delta.fontScale) {
204 changed |= ActivityInfo.CONFIG_FONT_SCALE;
205 fontScale = delta.fontScale;
206 }
207 if (delta.mcc != 0 && mcc != delta.mcc) {
208 changed |= ActivityInfo.CONFIG_MCC;
209 mcc = delta.mcc;
210 }
211 if (delta.mnc != 0 && mnc != delta.mnc) {
212 changed |= ActivityInfo.CONFIG_MNC;
213 mnc = delta.mnc;
214 }
215 if (delta.locale != null
216 && (locale == null || !locale.equals(delta.locale))) {
217 changed |= ActivityInfo.CONFIG_LOCALE;
218 locale = delta.locale != null
219 ? (Locale) delta.locale.clone() : null;
220 }
221 if (delta.userSetLocale && (!userSetLocale || ((changed & ActivityInfo.CONFIG_LOCALE) != 0)))
222 {
223 userSetLocale = true;
224 changed |= ActivityInfo.CONFIG_LOCALE;
225 }
226 if (delta.touchscreen != TOUCHSCREEN_UNDEFINED
227 && touchscreen != delta.touchscreen) {
228 changed |= ActivityInfo.CONFIG_TOUCHSCREEN;
229 touchscreen = delta.touchscreen;
230 }
231 if (delta.keyboard != KEYBOARD_UNDEFINED
232 && keyboard != delta.keyboard) {
233 changed |= ActivityInfo.CONFIG_KEYBOARD;
234 keyboard = delta.keyboard;
235 }
236 if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED
237 && keyboardHidden != delta.keyboardHidden) {
238 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
239 keyboardHidden = delta.keyboardHidden;
240 }
241 if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED
242 && hardKeyboardHidden != delta.hardKeyboardHidden) {
243 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
244 hardKeyboardHidden = delta.hardKeyboardHidden;
245 }
246 if (delta.navigation != NAVIGATION_UNDEFINED
247 && navigation != delta.navigation) {
248 changed |= ActivityInfo.CONFIG_NAVIGATION;
249 navigation = delta.navigation;
250 }
251 if (delta.orientation != ORIENTATION_UNDEFINED
252 && orientation != delta.orientation) {
253 changed |= ActivityInfo.CONFIG_ORIENTATION;
254 orientation = delta.orientation;
255 }
256
257 return changed;
258 }
259
260 /**
261 * Return a bit mask of the differences between this Configuration
262 * object and the given one. Does not change the values of either. Any
263 * undefined fields in <var>delta</var> are ignored.
264 * @return Returns a bit mask indicating which configuration
265 * values has changed, containing any combination of
266 * {@link android.content.pm.ActivityInfo#CONFIG_FONT_SCALE
267 * PackageManager.ActivityInfo.CONFIG_FONT_SCALE},
268 * {@link android.content.pm.ActivityInfo#CONFIG_MCC
269 * PackageManager.ActivityInfo.CONFIG_MCC},
270 * {@link android.content.pm.ActivityInfo#CONFIG_MNC
271 * PackageManager.ActivityInfo.CONFIG_MNC},
272 * {@link android.content.pm.ActivityInfo#CONFIG_LOCALE
273 * PackageManager.ActivityInfo.CONFIG_LOCALE},
274 * {@link android.content.pm.ActivityInfo#CONFIG_TOUCHSCREEN
275 * PackageManager.ActivityInfo.CONFIG_TOUCHSCREEN},
276 * {@link android.content.pm.ActivityInfo#CONFIG_KEYBOARD
277 * PackageManager.ActivityInfo.CONFIG_KEYBOARD},
278 * {@link android.content.pm.ActivityInfo#CONFIG_NAVIGATION
279 * PackageManager.ActivityInfo.CONFIG_NAVIGATION}, or
280 * {@link android.content.pm.ActivityInfo#CONFIG_ORIENTATION
281 * PackageManager.ActivityInfo.CONFIG_ORIENTATION}.
282 */
283 public int diff(Configuration delta) {
284 int changed = 0;
285 if (delta.fontScale > 0 && fontScale != delta.fontScale) {
286 changed |= ActivityInfo.CONFIG_FONT_SCALE;
287 }
288 if (delta.mcc != 0 && mcc != delta.mcc) {
289 changed |= ActivityInfo.CONFIG_MCC;
290 }
291 if (delta.mnc != 0 && mnc != delta.mnc) {
292 changed |= ActivityInfo.CONFIG_MNC;
293 }
294 if (delta.locale != null
295 && (locale == null || !locale.equals(delta.locale))) {
296 changed |= ActivityInfo.CONFIG_LOCALE;
297 }
298 if (delta.touchscreen != TOUCHSCREEN_UNDEFINED
299 && touchscreen != delta.touchscreen) {
300 changed |= ActivityInfo.CONFIG_TOUCHSCREEN;
301 }
302 if (delta.keyboard != KEYBOARD_UNDEFINED
303 && keyboard != delta.keyboard) {
304 changed |= ActivityInfo.CONFIG_KEYBOARD;
305 }
306 if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED
307 && keyboardHidden != delta.keyboardHidden) {
308 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
309 }
310 if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED
311 && hardKeyboardHidden != delta.hardKeyboardHidden) {
312 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
313 }
314 if (delta.navigation != NAVIGATION_UNDEFINED
315 && navigation != delta.navigation) {
316 changed |= ActivityInfo.CONFIG_NAVIGATION;
317 }
318 if (delta.orientation != ORIENTATION_UNDEFINED
319 && orientation != delta.orientation) {
320 changed |= ActivityInfo.CONFIG_ORIENTATION;
321 }
322
323 return changed;
324 }
325
326 /**
327 * Determine if a new resource needs to be loaded from the bit set of
328 * configuration changes returned by {@link #updateFrom(Configuration)}.
329 *
330 * @param configChanges The mask of changes configurations as returned by
331 * {@link #updateFrom(Configuration)}.
332 * @param interestingChanges The configuration changes that the resource
333 * can handled, as given in {@link android.util.TypedValue#changingConfigurations}.
334 *
335 * @return Return true if the resource needs to be loaded, else false.
336 */
337 public static boolean needNewResources(int configChanges, int interestingChanges) {
338 return (configChanges & (interestingChanges|ActivityInfo.CONFIG_FONT_SCALE)) != 0;
339 }
340
341 /**
342 * Parcelable methods
343 */
344 public int describeContents() {
345 return 0;
346 }
347
348 public void writeToParcel(Parcel dest, int flags) {
349 dest.writeFloat(fontScale);
350 dest.writeInt(mcc);
351 dest.writeInt(mnc);
352 if (locale == null) {
353 dest.writeInt(0);
354 } else {
355 dest.writeInt(1);
356 dest.writeString(locale.getLanguage());
357 dest.writeString(locale.getCountry());
358 dest.writeString(locale.getVariant());
359 }
360 if(userSetLocale) {
361 dest.writeInt(1);
362 } else {
363 dest.writeInt(0);
364 }
365 dest.writeInt(touchscreen);
366 dest.writeInt(keyboard);
367 dest.writeInt(keyboardHidden);
368 dest.writeInt(hardKeyboardHidden);
369 dest.writeInt(navigation);
370 dest.writeInt(orientation);
371 }
372
373 public static final Parcelable.Creator<Configuration> CREATOR
374 = new Parcelable.Creator<Configuration>() {
375 public Configuration createFromParcel(Parcel source) {
376 return new Configuration(source);
377 }
378
379 public Configuration[] newArray(int size) {
380 return new Configuration[size];
381 }
382 };
383
384 /**
385 * Construct this Configuration object, reading from the Parcel.
386 */
387 private Configuration(Parcel source) {
388 fontScale = source.readFloat();
389 mcc = source.readInt();
390 mnc = source.readInt();
391 if (source.readInt() != 0) {
392 locale = new Locale(source.readString(), source.readString(),
393 source.readString());
394 }
395 userSetLocale = (source.readInt()==1);
396 touchscreen = source.readInt();
397 keyboard = source.readInt();
398 keyboardHidden = source.readInt();
399 hardKeyboardHidden = source.readInt();
400 navigation = source.readInt();
401 orientation = source.readInt();
402 }
403
404 public int compareTo(Configuration that) {
405 int n;
406 float a = this.fontScale;
407 float b = that.fontScale;
408 if (a < b) return -1;
409 if (a > b) return 1;
410 n = this.mcc - that.mcc;
411 if (n != 0) return n;
412 n = this.mnc - that.mnc;
413 if (n != 0) return n;
414 n = this.locale.getLanguage().compareTo(that.locale.getLanguage());
415 if (n != 0) return n;
416 n = this.locale.getCountry().compareTo(that.locale.getCountry());
417 if (n != 0) return n;
418 n = this.locale.getVariant().compareTo(that.locale.getVariant());
419 if (n != 0) return n;
420 n = this.touchscreen - that.touchscreen;
421 if (n != 0) return n;
422 n = this.keyboard - that.keyboard;
423 if (n != 0) return n;
424 n = this.keyboardHidden - that.keyboardHidden;
425 if (n != 0) return n;
426 n = this.hardKeyboardHidden - that.hardKeyboardHidden;
427 if (n != 0) return n;
428 n = this.navigation - that.navigation;
429 if (n != 0) return n;
430 n = this.orientation - that.orientation;
431 //if (n != 0) return n;
432 return n;
433 }
434
435 public boolean equals(Configuration that) {
436 if (that == null) return false;
437 if (that == this) return true;
438 return this.compareTo(that) == 0;
439 }
440
441 public boolean equals(Object that) {
442 try {
443 return equals((Configuration)that);
444 } catch (ClassCastException e) {
445 }
446 return false;
447 }
448
449 public int hashCode() {
450 return ((int)this.fontScale) + this.mcc + this.mnc
451 + this.locale.hashCode() + this.touchscreen
452 + this.keyboard + this.keyboardHidden + this.hardKeyboardHidden
453 + this.navigation + this.orientation;
454 }
455}