blob: 780e6f76929081ef0ff217d8ffef61c958f7fc86 [file] [log] [blame]
Kenny Root15a4d2f2010-03-11 18:20:12 -08001/*
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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017package android.content.res;
18
Alan Viveretteac85f902016-03-11 15:15:51 -050019import android.annotation.IntDef;
20import android.annotation.NonNull;
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -070021import android.annotation.Nullable;
Wale Ogunwale822e5122017-07-26 06:02:24 -070022import android.app.WindowConfiguration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.content.pm.ActivityInfo;
Alan Viveretteac85f902016-03-11 15:15:51 -050024import android.content.pm.ActivityInfo.Config;
Adam Lesinski2c749d22014-06-04 13:00:29 -070025import android.os.Build;
Yohei Yukawa23cbe852016-05-17 16:42:58 -070026import android.os.LocaleList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.os.Parcel;
28import android.os.Parcelable;
Fabrice Di Megliod3d9f3f2012-09-18 12:55:32 -070029import android.text.TextUtils;
Fabrice Di Meglio3fb824b2012-02-28 17:58:31 -080030import android.view.View;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031
Romain Guye89d0bb2017-06-20 12:23:42 -070032import com.android.internal.util.XmlUtils;
33
34import org.xmlpull.v1.XmlPullParser;
35import org.xmlpull.v1.XmlPullParserException;
36import org.xmlpull.v1.XmlSerializer;
37
Adam Lesinski7f61e962014-09-02 16:43:52 -070038import java.io.IOException;
Alan Viveretteac85f902016-03-11 15:15:51 -050039import java.lang.annotation.Retention;
40import java.lang.annotation.RetentionPolicy;
Adam Lesinski2c749d22014-06-04 13:00:29 -070041import java.util.ArrayList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import java.util.Locale;
43
44/**
45 * This class describes all device configuration information that can
46 * impact the resources the application retrieves. This includes both
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -070047 * user-specified configuration options (locale list and scaling) as well
Scott Main63848e32011-04-20 22:20:46 -070048 * as device configurations (such as input modes, screen size and screen orientation).
49 * <p>You can acquire this object from {@link Resources}, using {@link
50 * Resources#getConfiguration}. Thus, from an activity, you can get it by chaining the request
51 * with {@link android.app.Activity#getResources}:</p>
52 * <pre>Configuration config = getResources().getConfiguration();</pre>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053 */
54public final class Configuration implements Parcelable, Comparable<Configuration> {
Dianne Hackborn756220b2012-08-14 16:45:30 -070055 /** @hide */
56 public static final Configuration EMPTY = new Configuration();
57
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058 /**
59 * Current user preference for the scaling factor for fonts, relative
60 * to the base density scaling.
61 */
62 public float fontScale;
63
64 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -070065 * IMSI MCC (Mobile Country Code), corresponding to
66 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#MccQualifier">mcc</a>
67 * resource qualifier. 0 if undefined.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068 */
69 public int mcc;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -070070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -070072 * IMSI MNC (Mobile Network Code), corresponding to
73 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#MccQualifier">mnc</a>
Mattias Petersson1d766b52011-10-07 09:33:52 +020074 * resource qualifier. 0 if undefined. Note that the actual MNC may be 0; in order to check
75 * for this use the {@link #MNC_ZERO} symbol.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076 */
77 public int mnc;
Mattias Petersson1d766b52011-10-07 09:33:52 +020078
79 /**
80 * Constant used to to represent MNC (Mobile Network Code) zero.
81 * 0 cannot be used, since it is used to represent an undefined MNC.
82 */
83 public static final int MNC_ZERO = 0xffff;
84
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -070086 * Current user preference for the locale, corresponding to
87 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#LocaleQualifier">locale</a>
88 * resource qualifier.
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -070089 *
90 * @deprecated Do not set or read this directly. Use {@link #getLocales()} and
Raph Levienb1638702016-04-27 11:02:12 -070091 * {@link #setLocales(LocaleList)}. If only the primary locale is needed,
92 * <code>getLocales().get(0)</code> is now the preferred accessor.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093 */
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -070094 @Deprecated public Locale locale;
95
96 private LocaleList mLocaleList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097
98 /**
Andy Stadlerf8a7cea2009-04-10 16:24:47 -070099 * Locale should persist on setting. This is hidden because it is really
100 * questionable whether this is the right way to expose the functionality.
101 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102 */
103 public boolean userSetLocale;
104
Romain Guyc9ba5592017-01-18 16:34:42 -0800105
Romain Guy48327452017-01-23 17:03:35 -0800106 /** Constant for {@link #colorMode}: bits that encode whether the screen is wide gamut. */
107 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_MASK = 0x3;
Romain Guyc9ba5592017-01-18 16:34:42 -0800108 /**
Romain Guy48327452017-01-23 17:03:35 -0800109 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800110 * indicating that it is unknown whether or not the screen is wide gamut.
111 */
Romain Guy48327452017-01-23 17:03:35 -0800112 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED = 0x0;
Romain Guyc9ba5592017-01-18 16:34:42 -0800113 /**
Romain Guy48327452017-01-23 17:03:35 -0800114 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800115 * indicating that the screen is not wide gamut.
116 * <p>Corresponds to the <code>-nowidecg</code> resource qualifier.</p>
117 */
Romain Guy48327452017-01-23 17:03:35 -0800118 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_NO = 0x1;
Romain Guyc9ba5592017-01-18 16:34:42 -0800119 /**
Romain Guy48327452017-01-23 17:03:35 -0800120 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800121 * indicating that the screen is wide gamut.
122 * <p>Corresponds to the <code>-widecg</code> resource qualifier.</p>
123 */
Romain Guy48327452017-01-23 17:03:35 -0800124 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_YES = 0x2;
Romain Guyc9ba5592017-01-18 16:34:42 -0800125
Romain Guyb3f69262017-04-13 20:06:41 -0700126 /** Constant for {@link #colorMode}: bits that encode the dynamic range of the screen. */
Romain Guy48327452017-01-23 17:03:35 -0800127 public static final int COLOR_MODE_HDR_MASK = 0xc;
128 /** Constant for {@link #colorMode}: bits shift to get the screen dynamic range. */
129 public static final int COLOR_MODE_HDR_SHIFT = 2;
Romain Guyc9ba5592017-01-18 16:34:42 -0800130 /**
Romain Guy48327452017-01-23 17:03:35 -0800131 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_HDR_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800132 * indicating that it is unknown whether or not the screen is HDR.
133 */
Romain Guy48327452017-01-23 17:03:35 -0800134 public static final int COLOR_MODE_HDR_UNDEFINED = 0x0;
Romain Guyc9ba5592017-01-18 16:34:42 -0800135 /**
Romain Guy48327452017-01-23 17:03:35 -0800136 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_HDR_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800137 * indicating that the screen is not HDR (low/standard dynamic range).
138 * <p>Corresponds to the <code>-lowdr</code> resource qualifier.</p>
139 */
Romain Guy48327452017-01-23 17:03:35 -0800140 public static final int COLOR_MODE_HDR_NO = 0x1 << COLOR_MODE_HDR_SHIFT;
Romain Guyc9ba5592017-01-18 16:34:42 -0800141 /**
Romain Guy48327452017-01-23 17:03:35 -0800142 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_HDR_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800143 * indicating that the screen is HDR (dynamic range).
144 * <p>Corresponds to the <code>-highdr</code> resource qualifier.</p>
145 */
Romain Guy48327452017-01-23 17:03:35 -0800146 public static final int COLOR_MODE_HDR_YES = 0x2 << COLOR_MODE_HDR_SHIFT;
Romain Guyc9ba5592017-01-18 16:34:42 -0800147
Romain Guy48327452017-01-23 17:03:35 -0800148 /** Constant for {@link #colorMode}: a value indicating that the color mode is undefined */
Romain Guyc9ba5592017-01-18 16:34:42 -0800149 @SuppressWarnings("PointlessBitwiseExpression")
Romain Guy48327452017-01-23 17:03:35 -0800150 public static final int COLOR_MODE_UNDEFINED = COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED |
151 COLOR_MODE_HDR_UNDEFINED;
Romain Guyc9ba5592017-01-18 16:34:42 -0800152
153 /**
Romain Guyb3f69262017-04-13 20:06:41 -0700154 * Bit mask of color capabilities of the screen. Currently there are two fields:
Romain Guy48327452017-01-23 17:03:35 -0800155 * <p>The {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} bits define the color gamut of
Romain Guyc9ba5592017-01-18 16:34:42 -0800156 * the screen. They may be one of
Romain Guy48327452017-01-23 17:03:35 -0800157 * {@link #COLOR_MODE_WIDE_COLOR_GAMUT_NO} or {@link #COLOR_MODE_WIDE_COLOR_GAMUT_YES}.</p>
Romain Guyc9ba5592017-01-18 16:34:42 -0800158 *
Romain Guy48327452017-01-23 17:03:35 -0800159 * <p>The {@link #COLOR_MODE_HDR_MASK} defines the dynamic range of the screen. They may be
160 * one of {@link #COLOR_MODE_HDR_NO} or {@link #COLOR_MODE_HDR_YES}.</p>
Romain Guyc9ba5592017-01-18 16:34:42 -0800161 *
162 * <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
163 * Multiple Screens</a> for more information.</p>
164 */
Romain Guy48327452017-01-23 17:03:35 -0800165 public int colorMode;
Romain Guyc9ba5592017-01-18 16:34:42 -0800166
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700167 /** Constant for {@link #screenLayout}: bits that encode the size. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700168 public static final int SCREENLAYOUT_SIZE_MASK = 0x0f;
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700169 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
170 * value indicating that no size has been set. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700171 public static final int SCREENLAYOUT_SIZE_UNDEFINED = 0x00;
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700172 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700173 * value indicating the screen is at least approximately 320x426 dp units,
174 * corresponds to the
175 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">small</a>
176 * resource qualifier.
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700177 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
178 * Multiple Screens</a> for more information. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700179 public static final int SCREENLAYOUT_SIZE_SMALL = 0x01;
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700180 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700181 * value indicating the screen is at least approximately 320x470 dp units,
182 * corresponds to the
183 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">normal</a>
184 * resource qualifier.
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700185 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
186 * Multiple Screens</a> for more information. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700187 public static final int SCREENLAYOUT_SIZE_NORMAL = 0x02;
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700188 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700189 * value indicating the screen is at least approximately 480x640 dp units,
190 * corresponds to the
191 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">large</a>
192 * resource qualifier.
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700193 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
194 * Multiple Screens</a> for more information. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700195 public static final int SCREENLAYOUT_SIZE_LARGE = 0x03;
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700196 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700197 * value indicating the screen is at least approximately 720x960 dp units,
198 * corresponds to the
199 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">xlarge</a>
200 * resource qualifier.
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700201 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
202 * Multiple Screens</a> for more information.*/
Dianne Hackborn14cee9f2010-04-23 17:51:26 -0700203 public static final int SCREENLAYOUT_SIZE_XLARGE = 0x04;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700204
205 /** Constant for {@link #screenLayout}: bits that encode the aspect ratio. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700206 public static final int SCREENLAYOUT_LONG_MASK = 0x30;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700207 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
208 * value indicating that no size has been set. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700209 public static final int SCREENLAYOUT_LONG_UNDEFINED = 0x00;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700210 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
211 * value that corresponds to the
212 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenAspectQualifier">notlong</a>
213 * resource qualifier. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700214 public static final int SCREENLAYOUT_LONG_NO = 0x10;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700215 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
216 * value that corresponds to the
217 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenAspectQualifier">long</a>
218 * resource qualifier. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700219 public static final int SCREENLAYOUT_LONG_YES = 0x20;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700220
221 /** Constant for {@link #screenLayout}: bits that encode the layout direction. */
222 public static final int SCREENLAYOUT_LAYOUTDIR_MASK = 0xC0;
223 /** Constant for {@link #screenLayout}: bits shift to get the layout direction. */
224 public static final int SCREENLAYOUT_LAYOUTDIR_SHIFT = 6;
225 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
226 * value indicating that no layout dir has been set. */
227 public static final int SCREENLAYOUT_LAYOUTDIR_UNDEFINED = 0x00;
228 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
229 * value indicating that a layout dir has been set to LTR. */
230 public static final int SCREENLAYOUT_LAYOUTDIR_LTR = 0x01 << SCREENLAYOUT_LAYOUTDIR_SHIFT;
231 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
232 * value indicating that a layout dir has been set to RTL. */
233 public static final int SCREENLAYOUT_LAYOUTDIR_RTL = 0x02 << SCREENLAYOUT_LAYOUTDIR_SHIFT;
234
Adam Powell49e7ff92015-05-14 16:18:53 -0700235 /** Constant for {@link #screenLayout}: bits that encode roundness of the screen. */
236 public static final int SCREENLAYOUT_ROUND_MASK = 0x300;
237 /** @hide Constant for {@link #screenLayout}: bit shift to get to screen roundness bits */
238 public static final int SCREENLAYOUT_ROUND_SHIFT = 8;
239 /**
240 * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating
241 * that it is unknown whether or not the screen has a round shape.
242 */
243 public static final int SCREENLAYOUT_ROUND_UNDEFINED = 0x00;
244 /**
245 * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating
246 * that the screen does not have a rounded shape.
247 */
248 public static final int SCREENLAYOUT_ROUND_NO = 0x1 << SCREENLAYOUT_ROUND_SHIFT;
249 /**
250 * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating
251 * that the screen has a rounded shape. Corners may not be visible to the user;
252 * developers should pay special attention to the {@link android.view.WindowInsets} delivered
253 * to views for more information about ensuring content is not obscured.
254 *
255 * <p>Corresponds to the <code>-round</code> resource qualifier.</p>
256 */
257 public static final int SCREENLAYOUT_ROUND_YES = 0x2 << SCREENLAYOUT_ROUND_SHIFT;
258
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700259 /** Constant for {@link #screenLayout}: a value indicating that screenLayout is undefined */
260 public static final int SCREENLAYOUT_UNDEFINED = SCREENLAYOUT_SIZE_UNDEFINED |
Adam Powell49e7ff92015-05-14 16:18:53 -0700261 SCREENLAYOUT_LONG_UNDEFINED | SCREENLAYOUT_LAYOUTDIR_UNDEFINED |
262 SCREENLAYOUT_ROUND_UNDEFINED;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700263
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700264 /**
265 * Special flag we generate to indicate that the screen layout requires
266 * us to use a compatibility mode for apps that are not modern layout
267 * aware.
268 * @hide
269 */
270 public static final int SCREENLAYOUT_COMPAT_NEEDED = 0x10000000;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700271
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700272 /**
Andrii Kulianf12fce12016-05-27 17:30:16 -0700273 * Bit mask of overall layout of the screen. Currently there are four
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700274 * fields:
275 * <p>The {@link #SCREENLAYOUT_SIZE_MASK} bits define the overall size
276 * of the screen. They may be one of
277 * {@link #SCREENLAYOUT_SIZE_SMALL}, {@link #SCREENLAYOUT_SIZE_NORMAL},
Adam Powell49e7ff92015-05-14 16:18:53 -0700278 * {@link #SCREENLAYOUT_SIZE_LARGE}, or {@link #SCREENLAYOUT_SIZE_XLARGE}.</p>
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700279 *
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700280 * <p>The {@link #SCREENLAYOUT_LONG_MASK} defines whether the screen
281 * is wider/taller than normal. They may be one of
Adam Powell49e7ff92015-05-14 16:18:53 -0700282 * {@link #SCREENLAYOUT_LONG_NO} or {@link #SCREENLAYOUT_LONG_YES}.</p>
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700283 *
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700284 * <p>The {@link #SCREENLAYOUT_LAYOUTDIR_MASK} defines whether the screen layout
285 * is either LTR or RTL. They may be one of
Adam Powell49e7ff92015-05-14 16:18:53 -0700286 * {@link #SCREENLAYOUT_LAYOUTDIR_LTR} or {@link #SCREENLAYOUT_LAYOUTDIR_RTL}.</p>
287 *
288 * <p>The {@link #SCREENLAYOUT_ROUND_MASK} defines whether the screen has a rounded
289 * shape. They may be one of {@link #SCREENLAYOUT_ROUND_NO} or {@link #SCREENLAYOUT_ROUND_YES}.
290 * </p>
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700291 *
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700292 * <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
Adam Powell49e7ff92015-05-14 16:18:53 -0700293 * Multiple Screens</a> for more information.</p>
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700294 */
295 public int screenLayout;
Dianne Hackbornfe37f8f2012-09-30 12:24:33 -0700296
Bryce Lee7566d762017-03-30 09:34:15 -0700297 /**
298 * @hide
Wale Ogunwale822e5122017-07-26 06:02:24 -0700299 * Configuration relating to the windowing state of the object associated with this
300 * Configuration. Contents of this field are not intended to affect resources, but need to be
301 * communicated and propagated at the same time as the rest of Configuration.
Bryce Lee7566d762017-03-30 09:34:15 -0700302 */
Wale Ogunwale822e5122017-07-26 06:02:24 -0700303 public final WindowConfiguration windowConfiguration = new WindowConfiguration();
Bryce Lee7566d762017-03-30 09:34:15 -0700304
Dianne Hackbornfe37f8f2012-09-30 12:24:33 -0700305 /** @hide */
306 static public int resetScreenLayout(int curLayout) {
307 return (curLayout&~(SCREENLAYOUT_LONG_MASK | SCREENLAYOUT_SIZE_MASK
308 | SCREENLAYOUT_COMPAT_NEEDED))
309 | (SCREENLAYOUT_LONG_YES | SCREENLAYOUT_SIZE_XLARGE);
310 }
311
312 /** @hide */
313 static public int reduceScreenLayout(int curLayout, int longSizeDp, int shortSizeDp) {
314 int screenLayoutSize;
315 boolean screenLayoutLong;
316 boolean screenLayoutCompatNeeded;
317
318 // These semi-magic numbers define our compatibility modes for
319 // applications with different screens. These are guarantees to
320 // app developers about the space they can expect for a particular
321 // configuration. DO NOT CHANGE!
322 if (longSizeDp < 470) {
323 // This is shorter than an HVGA normal density screen (which
324 // is 480 pixels on its long side).
325 screenLayoutSize = SCREENLAYOUT_SIZE_SMALL;
326 screenLayoutLong = false;
327 screenLayoutCompatNeeded = false;
328 } else {
329 // What size is this screen screen?
330 if (longSizeDp >= 960 && shortSizeDp >= 720) {
331 // 1.5xVGA or larger screens at medium density are the point
332 // at which we consider it to be an extra large screen.
333 screenLayoutSize = SCREENLAYOUT_SIZE_XLARGE;
334 } else if (longSizeDp >= 640 && shortSizeDp >= 480) {
335 // VGA or larger screens at medium density are the point
336 // at which we consider it to be a large screen.
337 screenLayoutSize = SCREENLAYOUT_SIZE_LARGE;
338 } else {
339 screenLayoutSize = SCREENLAYOUT_SIZE_NORMAL;
340 }
341
342 // If this screen is wider than normal HVGA, or taller
343 // than FWVGA, then for old apps we want to run in size
344 // compatibility mode.
345 if (shortSizeDp > 321 || longSizeDp > 570) {
346 screenLayoutCompatNeeded = true;
347 } else {
348 screenLayoutCompatNeeded = false;
349 }
350
351 // Is this a long screen?
352 if (((longSizeDp*3)/5) >= (shortSizeDp-1)) {
353 // Anything wider than WVGA (5:3) is considering to be long.
354 screenLayoutLong = true;
355 } else {
356 screenLayoutLong = false;
357 }
358 }
359
360 // Now reduce the last screenLayout to not be better than what we
361 // have found.
362 if (!screenLayoutLong) {
363 curLayout = (curLayout&~SCREENLAYOUT_LONG_MASK) | SCREENLAYOUT_LONG_NO;
364 }
365 if (screenLayoutCompatNeeded) {
366 curLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
367 }
368 int curSize = curLayout&SCREENLAYOUT_SIZE_MASK;
369 if (screenLayoutSize < curSize) {
370 curLayout = (curLayout&~SCREENLAYOUT_SIZE_MASK) | screenLayoutSize;
371 }
372 return curLayout;
373 }
374
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700375 /** @hide */
376 public static String configurationDiffToString(int diff) {
377 ArrayList<String> list = new ArrayList<>();
378 if ((diff & ActivityInfo.CONFIG_MCC) != 0) {
379 list.add("CONFIG_MCC");
380 }
381 if ((diff & ActivityInfo.CONFIG_MNC) != 0) {
382 list.add("CONFIG_MNC");
383 }
384 if ((diff & ActivityInfo.CONFIG_LOCALE) != 0) {
385 list.add("CONFIG_LOCALE");
386 }
387 if ((diff & ActivityInfo.CONFIG_TOUCHSCREEN) != 0) {
388 list.add("CONFIG_TOUCHSCREEN");
389 }
390 if ((diff & ActivityInfo.CONFIG_KEYBOARD) != 0) {
391 list.add("CONFIG_KEYBOARD");
392 }
393 if ((diff & ActivityInfo.CONFIG_KEYBOARD_HIDDEN) != 0) {
394 list.add("CONFIG_KEYBOARD_HIDDEN");
395 }
396 if ((diff & ActivityInfo.CONFIG_NAVIGATION) != 0) {
397 list.add("CONFIG_NAVIGATION");
398 }
399 if ((diff & ActivityInfo.CONFIG_ORIENTATION) != 0) {
400 list.add("CONFIG_ORIENTATION");
401 }
402 if ((diff & ActivityInfo.CONFIG_SCREEN_LAYOUT) != 0) {
403 list.add("CONFIG_SCREEN_LAYOUT");
404 }
Romain Guy48327452017-01-23 17:03:35 -0800405 if ((diff & ActivityInfo.CONFIG_COLOR_MODE) != 0) {
406 list.add("CONFIG_COLOR_MODE");
Romain Guyc9ba5592017-01-18 16:34:42 -0800407 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700408 if ((diff & ActivityInfo.CONFIG_UI_MODE) != 0) {
409 list.add("CONFIG_UI_MODE");
410 }
411 if ((diff & ActivityInfo.CONFIG_SCREEN_SIZE) != 0) {
412 list.add("CONFIG_SCREEN_SIZE");
413 }
414 if ((diff & ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE) != 0) {
415 list.add("CONFIG_SMALLEST_SCREEN_SIZE");
416 }
417 if ((diff & ActivityInfo.CONFIG_LAYOUT_DIRECTION) != 0) {
418 list.add("CONFIG_LAYOUT_DIRECTION");
419 }
420 if ((diff & ActivityInfo.CONFIG_FONT_SCALE) != 0) {
421 list.add("CONFIG_FONT_SCALE");
422 }
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +0100423 if ((diff & ActivityInfo.CONFIG_ASSETS_PATHS) != 0) {
424 list.add("CONFIG_ASSETS_PATHS");
425 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700426 StringBuilder builder = new StringBuilder("{");
427 for (int i = 0, n = list.size(); i < n; i++) {
428 builder.append(list.get(i));
429 if (i != n - 1) {
430 builder.append(", ");
431 }
432 }
433 builder.append("}");
434 return builder.toString();
435 }
436
Dianne Hackborn711e62a2010-11-29 16:38:22 -0800437 /**
438 * Check if the Configuration's current {@link #screenLayout} is at
439 * least the given size.
440 *
441 * @param size The desired size, either {@link #SCREENLAYOUT_SIZE_SMALL},
442 * {@link #SCREENLAYOUT_SIZE_NORMAL}, {@link #SCREENLAYOUT_SIZE_LARGE}, or
443 * {@link #SCREENLAYOUT_SIZE_XLARGE}.
444 * @return Returns true if the current screen layout size is at least
445 * the given size.
446 */
447 public boolean isLayoutSizeAtLeast(int size) {
448 int cur = screenLayout&SCREENLAYOUT_SIZE_MASK;
449 if (cur == SCREENLAYOUT_SIZE_UNDEFINED) return false;
Dianne Hackborn7d3a5bc2010-11-29 22:52:12 -0800450 return cur >= size;
Dianne Hackborn711e62a2010-11-29 16:38:22 -0800451 }
452
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700453 /** Constant for {@link #touchscreen}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454 public static final int TOUCHSCREEN_UNDEFINED = 0;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700455 /** Constant for {@link #touchscreen}, value corresponding to the
456 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#TouchscreenQualifier">notouch</a>
457 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 public static final int TOUCHSCREEN_NOTOUCH = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700459 /** @deprecated Not currently supported or used. */
460 @Deprecated public static final int TOUCHSCREEN_STYLUS = 2;
461 /** Constant for {@link #touchscreen}, value corresponding to the
462 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#TouchscreenQualifier">finger</a>
463 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800464 public static final int TOUCHSCREEN_FINGER = 3;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466 /**
467 * The kind of touch screen attached to the device.
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700468 * One of: {@link #TOUCHSCREEN_NOTOUCH}, {@link #TOUCHSCREEN_FINGER}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800469 */
470 public int touchscreen;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700471
472 /** Constant for {@link #keyboard}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800473 public static final int KEYBOARD_UNDEFINED = 0;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700474 /** Constant for {@link #keyboard}, value corresponding to the
475 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">nokeys</a>
476 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800477 public static final int KEYBOARD_NOKEYS = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700478 /** Constant for {@link #keyboard}, value corresponding to the
479 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">qwerty</a>
480 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 public static final int KEYBOARD_QWERTY = 2;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700482 /** Constant for {@link #keyboard}, value corresponding to the
483 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">12key</a>
484 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800485 public static final int KEYBOARD_12KEY = 3;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700486
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800487 /**
488 * The kind of keyboard attached to the device.
Kenny Root507f8ed2009-06-09 11:21:11 -0500489 * One of: {@link #KEYBOARD_NOKEYS}, {@link #KEYBOARD_QWERTY},
490 * {@link #KEYBOARD_12KEY}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800491 */
492 public int keyboard;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700493
494 /** Constant for {@link #keyboardHidden}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495 public static final int KEYBOARDHIDDEN_UNDEFINED = 0;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700496 /** Constant for {@link #keyboardHidden}, value corresponding to the
497 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keysexposed</a>
498 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800499 public static final int KEYBOARDHIDDEN_NO = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700500 /** Constant for {@link #keyboardHidden}, value corresponding to the
501 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keyshidden</a>
502 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 public static final int KEYBOARDHIDDEN_YES = 2;
504 /** Constant matching actual resource implementation. {@hide} */
505 public static final int KEYBOARDHIDDEN_SOFT = 3;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800507 /**
508 * A flag indicating whether any keyboard is available. Unlike
509 * {@link #hardKeyboardHidden}, this also takes into account a soft
510 * keyboard, so if the hard keyboard is hidden but there is soft
511 * keyboard available, it will be set to NO. Value is one of:
512 * {@link #KEYBOARDHIDDEN_NO}, {@link #KEYBOARDHIDDEN_YES}.
513 */
514 public int keyboardHidden;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700515
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700516 /** Constant for {@link #hardKeyboardHidden}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800517 public static final int HARDKEYBOARDHIDDEN_UNDEFINED = 0;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700518 /** Constant for {@link #hardKeyboardHidden}, value corresponding to the
519 * physical keyboard being exposed. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800520 public static final int HARDKEYBOARDHIDDEN_NO = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700521 /** Constant for {@link #hardKeyboardHidden}, value corresponding to the
522 * physical keyboard being hidden. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523 public static final int HARDKEYBOARDHIDDEN_YES = 2;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700524
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525 /**
526 * A flag indicating whether the hard keyboard has been hidden. This will
527 * be set on a device with a mechanism to hide the keyboard from the
528 * user, when that mechanism is closed. One of:
529 * {@link #HARDKEYBOARDHIDDEN_NO}, {@link #HARDKEYBOARDHIDDEN_YES}.
530 */
531 public int hardKeyboardHidden;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700532
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700533 /** Constant for {@link #navigation}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800534 public static final int NAVIGATION_UNDEFINED = 0;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700535 /** Constant for {@link #navigation}, value corresponding to the
536 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">nonav</a>
537 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800538 public static final int NAVIGATION_NONAV = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700539 /** Constant for {@link #navigation}, value corresponding to the
540 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">dpad</a>
541 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800542 public static final int NAVIGATION_DPAD = 2;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700543 /** Constant for {@link #navigation}, value corresponding to the
544 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">trackball</a>
545 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546 public static final int NAVIGATION_TRACKBALL = 3;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700547 /** Constant for {@link #navigation}, value corresponding to the
548 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">wheel</a>
549 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550 public static final int NAVIGATION_WHEEL = 4;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700551
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800552 /**
553 * The kind of navigation method available on the device.
Kenny Root507f8ed2009-06-09 11:21:11 -0500554 * One of: {@link #NAVIGATION_NONAV}, {@link #NAVIGATION_DPAD},
555 * {@link #NAVIGATION_TRACKBALL}, {@link #NAVIGATION_WHEEL}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 */
557 public int navigation;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700558
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700559 /** Constant for {@link #navigationHidden}: a value indicating that no value has been set. */
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700560 public static final int NAVIGATIONHIDDEN_UNDEFINED = 0;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700561 /** Constant for {@link #navigationHidden}, value corresponding to the
562 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavAvailQualifier">navexposed</a>
563 * resource qualifier. */
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700564 public static final int NAVIGATIONHIDDEN_NO = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700565 /** Constant for {@link #navigationHidden}, value corresponding to the
566 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavAvailQualifier">navhidden</a>
567 * resource qualifier. */
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700568 public static final int NAVIGATIONHIDDEN_YES = 2;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700569
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700570 /**
571 * A flag indicating whether any 5-way or DPAD navigation available.
572 * This will be set on a device with a mechanism to hide the navigation
573 * controls from the user, when that mechanism is closed. One of:
574 * {@link #NAVIGATIONHIDDEN_NO}, {@link #NAVIGATIONHIDDEN_YES}.
575 */
576 public int navigationHidden;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700577
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700578 /** Constant for {@link #orientation}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800579 public static final int ORIENTATION_UNDEFINED = 0;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700580 /** Constant for {@link #orientation}, value corresponding to the
581 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#OrientationQualifier">port</a>
582 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800583 public static final int ORIENTATION_PORTRAIT = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700584 /** Constant for {@link #orientation}, value corresponding to the
585 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#OrientationQualifier">land</a>
586 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800587 public static final int ORIENTATION_LANDSCAPE = 2;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700588 /** @deprecated Not currently supported or used. */
589 @Deprecated public static final int ORIENTATION_SQUARE = 3;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700590
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800591 /**
592 * Overall orientation of the screen. May be one of
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700593 * {@link #ORIENTATION_LANDSCAPE}, {@link #ORIENTATION_PORTRAIT}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800594 */
595 public int orientation;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100596
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700597 /** Constant for {@link #uiMode}: bits that encode the mode type. */
Tobias Haamel27b28b32010-02-09 23:09:17 +0100598 public static final int UI_MODE_TYPE_MASK = 0x0f;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700599 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
600 * value indicating that no mode type has been set. */
Dianne Hackbornef05e072010-03-01 17:43:39 -0800601 public static final int UI_MODE_TYPE_UNDEFINED = 0x00;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700602 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
603 * value that corresponds to
604 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">no
605 * UI mode</a> resource qualifier specified. */
Dianne Hackbornef05e072010-03-01 17:43:39 -0800606 public static final int UI_MODE_TYPE_NORMAL = 0x01;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700607 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
608 * value that corresponds to the
609 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">desk</a>
610 * resource qualifier. */
Dianne Hackborn7299c412010-03-04 18:41:49 -0800611 public static final int UI_MODE_TYPE_DESK = 0x02;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700612 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
613 * value that corresponds to the
614 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">car</a>
615 * resource qualifier. */
Dianne Hackborn7299c412010-03-04 18:41:49 -0800616 public static final int UI_MODE_TYPE_CAR = 0x03;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700617 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
618 * value that corresponds to the
619 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">television</a>
620 * resource qualifier. */
Dianne Hackborne360bb62011-05-20 16:11:04 -0700621 public static final int UI_MODE_TYPE_TELEVISION = 0x04;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700622 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
623 * value that corresponds to the
624 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">appliance</a>
625 * resource qualifier. */
Joe Onorato44fcb832011-12-14 20:59:30 -0800626 public static final int UI_MODE_TYPE_APPLIANCE = 0x05;
John Spurlock6c191292014-04-03 16:37:27 -0400627 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
628 * value that corresponds to the
629 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">watch</a>
630 * resource qualifier. */
631 public static final int UI_MODE_TYPE_WATCH = 0x06;
Zak Cohen1a6acdb2016-12-12 15:21:21 -0800632 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
633 * value that corresponds to the
634 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">vrheadset</a>
635 * resource qualifier. */
636 public static final int UI_MODE_TYPE_VR_HEADSET = 0x07;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100637
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700638 /** Constant for {@link #uiMode}: bits that encode the night mode. */
Tobias Haamel27b28b32010-02-09 23:09:17 +0100639 public static final int UI_MODE_NIGHT_MASK = 0x30;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700640 /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
641 * value indicating that no mode type has been set. */
Tobias Haamel27b28b32010-02-09 23:09:17 +0100642 public static final int UI_MODE_NIGHT_UNDEFINED = 0x00;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700643 /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
644 * value that corresponds to the
645 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NightQualifier">notnight</a>
646 * resource qualifier. */
Tobias Haamel27b28b32010-02-09 23:09:17 +0100647 public static final int UI_MODE_NIGHT_NO = 0x10;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700648 /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
649 * value that corresponds to the
650 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NightQualifier">night</a>
651 * resource qualifier. */
Tobias Haamel27b28b32010-02-09 23:09:17 +0100652 public static final int UI_MODE_NIGHT_YES = 0x20;
653
654 /**
655 * Bit mask of the ui mode. Currently there are two fields:
656 * <p>The {@link #UI_MODE_TYPE_MASK} bits define the overall ui mode of the
Dianne Hackborn7299c412010-03-04 18:41:49 -0800657 * device. They may be one of {@link #UI_MODE_TYPE_UNDEFINED},
658 * {@link #UI_MODE_TYPE_NORMAL}, {@link #UI_MODE_TYPE_DESK},
John Spurlock6c191292014-04-03 16:37:27 -0400659 * {@link #UI_MODE_TYPE_CAR}, {@link #UI_MODE_TYPE_TELEVISION},
Zak Cohen1a6acdb2016-12-12 15:21:21 -0800660 * {@link #UI_MODE_TYPE_APPLIANCE}, {@link #UI_MODE_TYPE_WATCH},
661 * or {@link #UI_MODE_TYPE_VR_HEADSET}.
Tobias Haamel27b28b32010-02-09 23:09:17 +0100662 *
663 * <p>The {@link #UI_MODE_NIGHT_MASK} defines whether the screen
Dianne Hackborn7299c412010-03-04 18:41:49 -0800664 * is in a special mode. They may be one of {@link #UI_MODE_NIGHT_UNDEFINED},
Tobias Haamel27b28b32010-02-09 23:09:17 +0100665 * {@link #UI_MODE_NIGHT_NO} or {@link #UI_MODE_NIGHT_YES}.
Tobias Haamel27b28b32010-02-09 23:09:17 +0100666 */
667 public int uiMode;
668
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700669 /**
670 * Default value for {@link #screenWidthDp} indicating that no width
671 * has been specified.
672 */
Dianne Hackbornebff8f92011-05-12 18:07:47 -0700673 public static final int SCREEN_WIDTH_DP_UNDEFINED = 0;
674
675 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700676 * The current width of the available screen space, in dp units,
677 * corresponding to
678 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenWidthQualifier">screen
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700679 * width</a> resource qualifier. Set to
680 * {@link #SCREEN_WIDTH_DP_UNDEFINED} if no width is specified.
Dianne Hackbornebff8f92011-05-12 18:07:47 -0700681 */
682 public int screenWidthDp;
683
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700684 /**
685 * Default value for {@link #screenHeightDp} indicating that no width
686 * has been specified.
687 */
Dianne Hackbornebff8f92011-05-12 18:07:47 -0700688 public static final int SCREEN_HEIGHT_DP_UNDEFINED = 0;
689
690 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700691 * The current height of the available screen space, in dp units,
692 * corresponding to
693 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenHeightQualifier">screen
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700694 * height</a> resource qualifier. Set to
695 * {@link #SCREEN_HEIGHT_DP_UNDEFINED} if no height is specified.
Dianne Hackbornebff8f92011-05-12 18:07:47 -0700696 */
697 public int screenHeightDp;
698
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700699 /**
700 * Default value for {@link #smallestScreenWidthDp} indicating that no width
701 * has been specified.
702 */
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700703 public static final int SMALLEST_SCREEN_WIDTH_DP_UNDEFINED = 0;
704
705 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700706 * The smallest screen size an application will see in normal operation,
707 * corresponding to
708 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#SmallestScreenWidthQualifier">smallest
709 * screen width</a> resource qualifier.
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700710 * This is the smallest value of both screenWidthDp and screenHeightDp
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700711 * in both portrait and landscape. Set to
712 * {@link #SMALLEST_SCREEN_WIDTH_DP_UNDEFINED} if no width is specified.
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700713 */
714 public int smallestScreenWidthDp;
715
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700716 /**
717 * Default value for {@link #densityDpi} indicating that no width
718 * has been specified.
719 */
720 public static final int DENSITY_DPI_UNDEFINED = 0;
721
722 /**
Adam Lesinski31245b42014-08-22 19:10:56 -0700723 * Value for {@link #densityDpi} for resources that scale to any density (vector drawables).
724 * {@hide}
725 */
726 public static final int DENSITY_DPI_ANY = 0xfffe;
727
728 /**
729 * Value for {@link #densityDpi} for resources that are not meant to be scaled.
730 * {@hide}
731 */
732 public static final int DENSITY_DPI_NONE = 0xffff;
733
734 /**
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700735 * The target screen density being rendered to,
736 * corresponding to
737 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#DensityQualifier">density</a>
738 * resource qualifier. Set to
739 * {@link #DENSITY_DPI_UNDEFINED} if no density is specified.
740 */
741 public int densityDpi;
742
Dianne Hackborn5fd21692011-06-07 14:09:47 -0700743 /** @hide Hack to get this information from WM to app running in compat mode. */
744 public int compatScreenWidthDp;
745 /** @hide Hack to get this information from WM to app running in compat mode. */
746 public int compatScreenHeightDp;
747 /** @hide Hack to get this information from WM to app running in compat mode. */
748 public int compatSmallestScreenWidthDp;
749
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750 /**
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +0100751 * An undefined assetsSeq. This will not override an existing assetsSeq.
752 * @hide
753 */
754 public static final int ASSETS_SEQ_UNDEFINED = 0;
755
756 /**
757 * Internal counter that allows us to piggyback off the configuration change mechanism to
758 * signal to apps that the the assets for an Application have changed. A difference in these
759 * between two Configurations will yield a diff flag of
760 * {@link ActivityInfo#CONFIG_ASSETS_PATHS}.
761 * @hide
762 */
763 public int assetsSeq;
764
765 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800766 * @hide Internal book-keeping.
767 */
768 public int seq;
Dianne Hackborn1d0b1772013-09-06 14:02:54 -0700769
Alan Viveretteac85f902016-03-11 15:15:51 -0500770 /** @hide */
771 @IntDef(flag = true,
772 value = {
773 NATIVE_CONFIG_MCC,
774 NATIVE_CONFIG_MNC,
775 NATIVE_CONFIG_LOCALE,
776 NATIVE_CONFIG_TOUCHSCREEN,
777 NATIVE_CONFIG_KEYBOARD,
778 NATIVE_CONFIG_KEYBOARD_HIDDEN,
779 NATIVE_CONFIG_NAVIGATION,
780 NATIVE_CONFIG_ORIENTATION,
781 NATIVE_CONFIG_DENSITY,
782 NATIVE_CONFIG_SCREEN_SIZE,
783 NATIVE_CONFIG_VERSION,
784 NATIVE_CONFIG_SCREEN_LAYOUT,
785 NATIVE_CONFIG_UI_MODE,
786 NATIVE_CONFIG_SMALLEST_SCREEN_SIZE,
787 NATIVE_CONFIG_LAYOUTDIR,
Romain Guy48327452017-01-23 17:03:35 -0800788 NATIVE_CONFIG_COLOR_MODE,
Alan Viveretteac85f902016-03-11 15:15:51 -0500789 })
790 @Retention(RetentionPolicy.SOURCE)
791 public @interface NativeConfig {}
792
Dianne Hackborn1d0b1772013-09-06 14:02:54 -0700793 /** @hide Native-specific bit mask for MCC config; DO NOT USE UNLESS YOU ARE SURE. */
794 public static final int NATIVE_CONFIG_MCC = 0x0001;
795 /** @hide Native-specific bit mask for MNC config; DO NOT USE UNLESS YOU ARE SURE. */
796 public static final int NATIVE_CONFIG_MNC = 0x0002;
797 /** @hide Native-specific bit mask for LOCALE config; DO NOT USE UNLESS YOU ARE SURE. */
798 public static final int NATIVE_CONFIG_LOCALE = 0x0004;
799 /** @hide Native-specific bit mask for TOUCHSCREEN config; DO NOT USE UNLESS YOU ARE SURE. */
800 public static final int NATIVE_CONFIG_TOUCHSCREEN = 0x0008;
801 /** @hide Native-specific bit mask for KEYBOARD config; DO NOT USE UNLESS YOU ARE SURE. */
802 public static final int NATIVE_CONFIG_KEYBOARD = 0x0010;
803 /** @hide Native-specific bit mask for KEYBOARD_HIDDEN config; DO NOT USE UNLESS YOU
804 * ARE SURE. */
805 public static final int NATIVE_CONFIG_KEYBOARD_HIDDEN = 0x0020;
806 /** @hide Native-specific bit mask for NAVIGATION config; DO NOT USE UNLESS YOU ARE SURE. */
807 public static final int NATIVE_CONFIG_NAVIGATION = 0x0040;
808 /** @hide Native-specific bit mask for ORIENTATION config; DO NOT USE UNLESS YOU ARE SURE. */
809 public static final int NATIVE_CONFIG_ORIENTATION = 0x0080;
810 /** @hide Native-specific bit mask for DENSITY config; DO NOT USE UNLESS YOU ARE SURE. */
811 public static final int NATIVE_CONFIG_DENSITY = 0x0100;
812 /** @hide Native-specific bit mask for SCREEN_SIZE config; DO NOT USE UNLESS YOU ARE SURE. */
813 public static final int NATIVE_CONFIG_SCREEN_SIZE = 0x0200;
814 /** @hide Native-specific bit mask for VERSION config; DO NOT USE UNLESS YOU ARE SURE. */
815 public static final int NATIVE_CONFIG_VERSION = 0x0400;
816 /** @hide Native-specific bit mask for SCREEN_LAYOUT config; DO NOT USE UNLESS YOU ARE SURE. */
817 public static final int NATIVE_CONFIG_SCREEN_LAYOUT = 0x0800;
818 /** @hide Native-specific bit mask for UI_MODE config; DO NOT USE UNLESS YOU ARE SURE. */
819 public static final int NATIVE_CONFIG_UI_MODE = 0x1000;
820 /** @hide Native-specific bit mask for SMALLEST_SCREEN_SIZE config; DO NOT USE UNLESS YOU
821 * ARE SURE. */
822 public static final int NATIVE_CONFIG_SMALLEST_SCREEN_SIZE = 0x2000;
823 /** @hide Native-specific bit mask for LAYOUTDIR config ; DO NOT USE UNLESS YOU ARE SURE.*/
824 public static final int NATIVE_CONFIG_LAYOUTDIR = 0x4000;
Romain Guy48327452017-01-23 17:03:35 -0800825 /** @hide Native-specific bit mask for COLOR_MODE config ; DO NOT USE UNLESS YOU ARE SURE.*/
826 public static final int NATIVE_CONFIG_COLOR_MODE = 0x10000;
Dianne Hackborn1d0b1772013-09-06 14:02:54 -0700827
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800828 /**
Adam Lesinskibad43fc2016-07-19 13:35:01 -0700829 * <p>Construct an invalid Configuration. This state is only suitable for constructing a
830 * Configuration delta that will be applied to some valid Configuration object. In order to
831 * create a valid standalone Configuration, you must call {@link #setToDefaults}. </p>
832 *
833 * <p>Example:</p>
834 * <pre class="prettyprint">
835 * Configuration validConfig = new Configuration();
836 * validConfig.setToDefaults();
837 *
838 * Configuration deltaOnlyConfig = new Configuration();
839 * deltaOnlyConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
840 *
841 * validConfig.updateFrom(deltaOnlyConfig);
842 * </pre>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800843 */
844 public Configuration() {
Adam Lesinskibad43fc2016-07-19 13:35:01 -0700845 unset();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800846 }
847
848 /**
849 * Makes a deep copy suitable for modification.
850 */
851 public Configuration(Configuration o) {
Dianne Hackborn694f79b2010-03-17 19:44:59 -0700852 setTo(o);
853 }
854
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700855 /* This brings mLocaleList in sync with locale in case a user of the older API who doesn't know
856 * about setLocales() has changed locale directly. */
857 private void fixUpLocaleList() {
858 if ((locale == null && !mLocaleList.isEmpty()) ||
Roozbeh Pournaderfee44842016-02-04 15:24:24 -0800859 (locale != null && !locale.equals(mLocaleList.get(0)))) {
Raph Levien10ea92a2016-05-02 12:56:01 -0700860 mLocaleList = locale == null ? LocaleList.getEmptyLocaleList() : new LocaleList(locale);
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700861 }
862 }
863
Chet Haased30149e2017-01-13 12:55:16 -0800864 /**
865 * Sets the fields in this object to those in the given Configuration.
866 *
867 * @param o The Configuration object used to set the values of this Configuration's fields.
868 */
Dianne Hackborn694f79b2010-03-17 19:44:59 -0700869 public void setTo(Configuration o) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800870 fontScale = o.fontScale;
871 mcc = o.mcc;
872 mnc = o.mnc;
Roozbeh Pournader8a412e02015-12-02 18:39:50 -0800873 locale = o.locale == null ? null : (Locale) o.locale.clone();
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700874 o.fixUpLocaleList();
875 mLocaleList = o.mLocaleList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800876 userSetLocale = o.userSetLocale;
877 touchscreen = o.touchscreen;
878 keyboard = o.keyboard;
879 keyboardHidden = o.keyboardHidden;
880 hardKeyboardHidden = o.hardKeyboardHidden;
881 navigation = o.navigation;
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700882 navigationHidden = o.navigationHidden;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 orientation = o.orientation;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700884 screenLayout = o.screenLayout;
Romain Guy48327452017-01-23 17:03:35 -0800885 colorMode = o.colorMode;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100886 uiMode = o.uiMode;
Dianne Hackbornebff8f92011-05-12 18:07:47 -0700887 screenWidthDp = o.screenWidthDp;
888 screenHeightDp = o.screenHeightDp;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700889 smallestScreenWidthDp = o.smallestScreenWidthDp;
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700890 densityDpi = o.densityDpi;
Dianne Hackborn5fd21692011-06-07 14:09:47 -0700891 compatScreenWidthDp = o.compatScreenWidthDp;
892 compatScreenHeightDp = o.compatScreenHeightDp;
893 compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp;
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +0100894 assetsSeq = o.assetsSeq;
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800895 seq = o.seq;
Wale Ogunwale822e5122017-07-26 06:02:24 -0700896 windowConfiguration.setTo(o.windowConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800897 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700898
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800899 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700900 StringBuilder sb = new StringBuilder(128);
Dianne Hackborn29735682011-04-21 17:26:39 -0700901 sb.append("{");
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700902 sb.append(fontScale);
Dianne Hackborn5be8de32011-05-24 18:11:57 -0700903 sb.append(" ");
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700904 if (mcc != 0) {
905 sb.append(mcc);
906 sb.append("mcc");
907 } else {
908 sb.append("?mcc");
909 }
910 if (mnc != 0) {
911 sb.append(mnc);
912 sb.append("mnc");
913 } else {
914 sb.append("?mnc");
915 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700916 fixUpLocaleList();
917 if (!mLocaleList.isEmpty()) {
Dianne Hackborn9a849832011-04-07 15:11:57 -0700918 sb.append(" ");
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700919 sb.append(mLocaleList);
Dianne Hackborn9a849832011-04-07 15:11:57 -0700920 } else {
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700921 sb.append(" ?localeList");
Daniel Sandler7d6bddc2010-07-22 16:11:55 -0400922 }
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700923 int layoutDir = (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK);
924 switch (layoutDir) {
925 case SCREENLAYOUT_LAYOUTDIR_UNDEFINED: sb.append(" ?layoutDir"); break;
Fabrice Di Meglio8a802db2012-09-05 13:12:02 -0700926 case SCREENLAYOUT_LAYOUTDIR_LTR: sb.append(" ldltr"); break;
927 case SCREENLAYOUT_LAYOUTDIR_RTL: sb.append(" ldrtl"); break;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700928 default: sb.append(" layoutDir=");
929 sb.append(layoutDir >> SCREENLAYOUT_LAYOUTDIR_SHIFT); break;
Fabrice Di Meglio7a736fb2011-06-09 20:20:36 -0700930 }
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700931 if (smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
932 sb.append(" sw"); sb.append(smallestScreenWidthDp); sb.append("dp");
933 } else {
Dianne Hackborn2f0b1752011-05-31 17:59:49 -0700934 sb.append(" ?swdp");
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700935 }
936 if (screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
937 sb.append(" w"); sb.append(screenWidthDp); sb.append("dp");
938 } else {
Dianne Hackborn2f0b1752011-05-31 17:59:49 -0700939 sb.append(" ?wdp");
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700940 }
941 if (screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
942 sb.append(" h"); sb.append(screenHeightDp); sb.append("dp");
943 } else {
Dianne Hackborn2f0b1752011-05-31 17:59:49 -0700944 sb.append(" ?hdp");
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700945 }
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700946 if (densityDpi != DENSITY_DPI_UNDEFINED) {
947 sb.append(" "); sb.append(densityDpi); sb.append("dpi");
948 } else {
949 sb.append(" ?density");
950 }
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700951 switch ((screenLayout&SCREENLAYOUT_SIZE_MASK)) {
952 case SCREENLAYOUT_SIZE_UNDEFINED: sb.append(" ?lsize"); break;
953 case SCREENLAYOUT_SIZE_SMALL: sb.append(" smll"); break;
954 case SCREENLAYOUT_SIZE_NORMAL: sb.append(" nrml"); break;
955 case SCREENLAYOUT_SIZE_LARGE: sb.append(" lrg"); break;
956 case SCREENLAYOUT_SIZE_XLARGE: sb.append(" xlrg"); break;
957 default: sb.append(" layoutSize=");
958 sb.append(screenLayout&SCREENLAYOUT_SIZE_MASK); break;
959 }
960 switch ((screenLayout&SCREENLAYOUT_LONG_MASK)) {
961 case SCREENLAYOUT_LONG_UNDEFINED: sb.append(" ?long"); break;
962 case SCREENLAYOUT_LONG_NO: /* not-long is not interesting to print */ break;
963 case SCREENLAYOUT_LONG_YES: sb.append(" long"); break;
964 default: sb.append(" layoutLong=");
965 sb.append(screenLayout&SCREENLAYOUT_LONG_MASK); break;
966 }
Romain Guy48327452017-01-23 17:03:35 -0800967 switch ((colorMode &COLOR_MODE_HDR_MASK)) {
968 case COLOR_MODE_HDR_UNDEFINED: sb.append(" ?ldr"); break; // most likely not HDR
969 case COLOR_MODE_HDR_NO: /* ldr is not interesting to print */ break;
970 case COLOR_MODE_HDR_YES: sb.append(" hdr"); break;
Romain Guyc9ba5592017-01-18 16:34:42 -0800971 default: sb.append(" dynamicRange=");
Romain Guy48327452017-01-23 17:03:35 -0800972 sb.append(colorMode &COLOR_MODE_HDR_MASK); break;
Romain Guyc9ba5592017-01-18 16:34:42 -0800973 }
Romain Guy48327452017-01-23 17:03:35 -0800974 switch ((colorMode &COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) {
975 case COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED: sb.append(" ?wideColorGamut"); break;
976 case COLOR_MODE_WIDE_COLOR_GAMUT_NO: /* not wide is not interesting to print */ break;
977 case COLOR_MODE_WIDE_COLOR_GAMUT_YES: sb.append(" widecg"); break;
Romain Guyc9ba5592017-01-18 16:34:42 -0800978 default: sb.append(" wideColorGamut=");
Romain Guy48327452017-01-23 17:03:35 -0800979 sb.append(colorMode &COLOR_MODE_WIDE_COLOR_GAMUT_MASK); break;
Romain Guyc9ba5592017-01-18 16:34:42 -0800980 }
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700981 switch (orientation) {
982 case ORIENTATION_UNDEFINED: sb.append(" ?orien"); break;
983 case ORIENTATION_LANDSCAPE: sb.append(" land"); break;
984 case ORIENTATION_PORTRAIT: sb.append(" port"); break;
985 default: sb.append(" orien="); sb.append(orientation); break;
986 }
987 switch ((uiMode&UI_MODE_TYPE_MASK)) {
988 case UI_MODE_TYPE_UNDEFINED: sb.append(" ?uimode"); break;
989 case UI_MODE_TYPE_NORMAL: /* normal is not interesting to print */ break;
990 case UI_MODE_TYPE_DESK: sb.append(" desk"); break;
991 case UI_MODE_TYPE_CAR: sb.append(" car"); break;
Dianne Hackborne360bb62011-05-20 16:11:04 -0700992 case UI_MODE_TYPE_TELEVISION: sb.append(" television"); break;
Joe Onorato44fcb832011-12-14 20:59:30 -0800993 case UI_MODE_TYPE_APPLIANCE: sb.append(" appliance"); break;
John Spurlock6c191292014-04-03 16:37:27 -0400994 case UI_MODE_TYPE_WATCH: sb.append(" watch"); break;
Zak Cohen1a6acdb2016-12-12 15:21:21 -0800995 case UI_MODE_TYPE_VR_HEADSET: sb.append(" vrheadset"); break;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700996 default: sb.append(" uimode="); sb.append(uiMode&UI_MODE_TYPE_MASK); break;
997 }
998 switch ((uiMode&UI_MODE_NIGHT_MASK)) {
999 case UI_MODE_NIGHT_UNDEFINED: sb.append(" ?night"); break;
1000 case UI_MODE_NIGHT_NO: /* not-night is not interesting to print */ break;
1001 case UI_MODE_NIGHT_YES: sb.append(" night"); break;
1002 default: sb.append(" night="); sb.append(uiMode&UI_MODE_NIGHT_MASK); break;
1003 }
Dianne Hackborn9a849832011-04-07 15:11:57 -07001004 switch (touchscreen) {
1005 case TOUCHSCREEN_UNDEFINED: sb.append(" ?touch"); break;
1006 case TOUCHSCREEN_NOTOUCH: sb.append(" -touch"); break;
1007 case TOUCHSCREEN_STYLUS: sb.append(" stylus"); break;
1008 case TOUCHSCREEN_FINGER: sb.append(" finger"); break;
1009 default: sb.append(" touch="); sb.append(touchscreen); break;
1010 }
1011 switch (keyboard) {
1012 case KEYBOARD_UNDEFINED: sb.append(" ?keyb"); break;
1013 case KEYBOARD_NOKEYS: sb.append(" -keyb"); break;
1014 case KEYBOARD_QWERTY: sb.append(" qwerty"); break;
1015 case KEYBOARD_12KEY: sb.append(" 12key"); break;
1016 default: sb.append(" keys="); sb.append(keyboard); break;
1017 }
1018 switch (keyboardHidden) {
1019 case KEYBOARDHIDDEN_UNDEFINED: sb.append("/?"); break;
1020 case KEYBOARDHIDDEN_NO: sb.append("/v"); break;
1021 case KEYBOARDHIDDEN_YES: sb.append("/h"); break;
1022 case KEYBOARDHIDDEN_SOFT: sb.append("/s"); break;
1023 default: sb.append("/"); sb.append(keyboardHidden); break;
1024 }
1025 switch (hardKeyboardHidden) {
1026 case HARDKEYBOARDHIDDEN_UNDEFINED: sb.append("/?"); break;
1027 case HARDKEYBOARDHIDDEN_NO: sb.append("/v"); break;
1028 case HARDKEYBOARDHIDDEN_YES: sb.append("/h"); break;
1029 default: sb.append("/"); sb.append(hardKeyboardHidden); break;
1030 }
1031 switch (navigation) {
1032 case NAVIGATION_UNDEFINED: sb.append(" ?nav"); break;
1033 case NAVIGATION_NONAV: sb.append(" -nav"); break;
1034 case NAVIGATION_DPAD: sb.append(" dpad"); break;
1035 case NAVIGATION_TRACKBALL: sb.append(" tball"); break;
1036 case NAVIGATION_WHEEL: sb.append(" wheel"); break;
1037 default: sb.append(" nav="); sb.append(navigation); break;
1038 }
1039 switch (navigationHidden) {
1040 case NAVIGATIONHIDDEN_UNDEFINED: sb.append("/?"); break;
1041 case NAVIGATIONHIDDEN_NO: sb.append("/v"); break;
1042 case NAVIGATIONHIDDEN_YES: sb.append("/h"); break;
1043 default: sb.append("/"); sb.append(navigationHidden); break;
1044 }
Wale Ogunwale822e5122017-07-26 06:02:24 -07001045 sb.append(" winConfig="); sb.append(windowConfiguration);
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001046 if (assetsSeq != 0) {
1047 sb.append(" as.").append(assetsSeq);
1048 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001049 if (seq != 0) {
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001050 sb.append(" s.").append(seq);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001051 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001052 sb.append('}');
1053 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001054 }
1055
1056 /**
1057 * Set this object to the system defaults.
1058 */
1059 public void setToDefaults() {
1060 fontScale = 1;
1061 mcc = mnc = 0;
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001062 mLocaleList = LocaleList.getEmptyLocaleList();
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001063 locale = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001064 userSetLocale = false;
1065 touchscreen = TOUCHSCREEN_UNDEFINED;
1066 keyboard = KEYBOARD_UNDEFINED;
1067 keyboardHidden = KEYBOARDHIDDEN_UNDEFINED;
1068 hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED;
1069 navigation = NAVIGATION_UNDEFINED;
Dianne Hackborn93e462b2009-09-15 22:50:40 -07001070 navigationHidden = NAVIGATIONHIDDEN_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001071 orientation = ORIENTATION_UNDEFINED;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001072 screenLayout = SCREENLAYOUT_UNDEFINED;
Romain Guy48327452017-01-23 17:03:35 -08001073 colorMode = COLOR_MODE_UNDEFINED;
Dianne Hackborn7299c412010-03-04 18:41:49 -08001074 uiMode = UI_MODE_TYPE_UNDEFINED;
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001075 screenWidthDp = compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED;
1076 screenHeightDp = compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED;
1077 smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001078 densityDpi = DENSITY_DPI_UNDEFINED;
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001079 assetsSeq = ASSETS_SEQ_UNDEFINED;
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001080 seq = 0;
Wale Ogunwale822e5122017-07-26 06:02:24 -07001081 windowConfiguration.setToDefaults();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001082 }
1083
Adam Lesinskibad43fc2016-07-19 13:35:01 -07001084 /**
1085 * Set this object to completely undefined.
1086 * @hide
1087 */
1088 public void unset() {
1089 setToDefaults();
1090 fontScale = 0;
1091 }
1092
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 /** {@hide} */
1094 @Deprecated public void makeDefault() {
1095 setToDefaults();
1096 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -07001097
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001098 /**
Alan Viveretteac85f902016-03-11 15:15:51 -05001099 * Copies the fields from delta into this Configuration object, keeping
1100 * track of which ones have changed. Any undefined fields in {@code delta}
1101 * are ignored and not copied in to the current Configuration.
1102 *
1103 * @return a bit mask of the changed fields, as per {@link #diff}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 */
Alan Viveretteac85f902016-03-11 15:15:51 -05001105 public @Config int updateFrom(@NonNull Configuration delta) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001106 int changed = 0;
1107 if (delta.fontScale > 0 && fontScale != delta.fontScale) {
1108 changed |= ActivityInfo.CONFIG_FONT_SCALE;
1109 fontScale = delta.fontScale;
1110 }
1111 if (delta.mcc != 0 && mcc != delta.mcc) {
1112 changed |= ActivityInfo.CONFIG_MCC;
1113 mcc = delta.mcc;
1114 }
1115 if (delta.mnc != 0 && mnc != delta.mnc) {
1116 changed |= ActivityInfo.CONFIG_MNC;
1117 mnc = delta.mnc;
1118 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001119 fixUpLocaleList();
1120 delta.fixUpLocaleList();
1121 if (!delta.mLocaleList.isEmpty() && !mLocaleList.equals(delta.mLocaleList)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001122 changed |= ActivityInfo.CONFIG_LOCALE;
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001123 mLocaleList = delta.mLocaleList;
1124 // delta.locale can't be null, since delta.mLocaleList is not empty.
1125 if (!delta.locale.equals(locale)) {
1126 locale = (Locale) delta.locale.clone();
1127 // If locale has changed, then layout direction is also changed ...
1128 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
1129 // ... and we need to update the layout direction (represented by the first
1130 // 2 most significant bits in screenLayout).
1131 setLayoutDirection(locale);
1132 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001133 }
Craig Mautner31678b52013-08-12 17:56:34 -07001134 final int deltaScreenLayoutDir = delta.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
1135 if (deltaScreenLayoutDir != SCREENLAYOUT_LAYOUTDIR_UNDEFINED &&
1136 deltaScreenLayoutDir != (screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) {
1137 screenLayout = (screenLayout & ~SCREENLAYOUT_LAYOUTDIR_MASK) | deltaScreenLayoutDir;
Amith Yamasanid8415f42013-08-07 20:15:10 -07001138 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
Amith Yamasanid8415f42013-08-07 20:15:10 -07001139 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001140 if (delta.userSetLocale && (!userSetLocale || ((changed & ActivityInfo.CONFIG_LOCALE) != 0)))
1141 {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001142 changed |= ActivityInfo.CONFIG_LOCALE;
Amith Yamasanid8415f42013-08-07 20:15:10 -07001143 userSetLocale = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001144 }
1145 if (delta.touchscreen != TOUCHSCREEN_UNDEFINED
1146 && touchscreen != delta.touchscreen) {
1147 changed |= ActivityInfo.CONFIG_TOUCHSCREEN;
1148 touchscreen = delta.touchscreen;
1149 }
1150 if (delta.keyboard != KEYBOARD_UNDEFINED
1151 && keyboard != delta.keyboard) {
1152 changed |= ActivityInfo.CONFIG_KEYBOARD;
1153 keyboard = delta.keyboard;
1154 }
1155 if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED
1156 && keyboardHidden != delta.keyboardHidden) {
1157 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1158 keyboardHidden = delta.keyboardHidden;
1159 }
1160 if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED
1161 && hardKeyboardHidden != delta.hardKeyboardHidden) {
1162 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1163 hardKeyboardHidden = delta.hardKeyboardHidden;
1164 }
1165 if (delta.navigation != NAVIGATION_UNDEFINED
1166 && navigation != delta.navigation) {
1167 changed |= ActivityInfo.CONFIG_NAVIGATION;
1168 navigation = delta.navigation;
1169 }
Dianne Hackborn93e462b2009-09-15 22:50:40 -07001170 if (delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED
1171 && navigationHidden != delta.navigationHidden) {
1172 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1173 navigationHidden = delta.navigationHidden;
1174 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 if (delta.orientation != ORIENTATION_UNDEFINED
1176 && orientation != delta.orientation) {
1177 changed |= ActivityInfo.CONFIG_ORIENTATION;
1178 orientation = delta.orientation;
1179 }
Robert Carrdf259d32016-12-05 20:33:10 -08001180 if (((delta.screenLayout & SCREENLAYOUT_SIZE_MASK) != SCREENLAYOUT_SIZE_UNDEFINED)
1181 && (delta.screenLayout & SCREENLAYOUT_SIZE_MASK)
1182 != (screenLayout & SCREENLAYOUT_SIZE_MASK)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07001183 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
Robert Carrdf259d32016-12-05 20:33:10 -08001184 screenLayout = (screenLayout & ~SCREENLAYOUT_SIZE_MASK)
1185 | (delta.screenLayout & SCREENLAYOUT_SIZE_MASK);
Dianne Hackborn723738c2009-06-25 19:48:04 -07001186 }
Robert Carrdf259d32016-12-05 20:33:10 -08001187 if (((delta.screenLayout & SCREENLAYOUT_LONG_MASK) != SCREENLAYOUT_LONG_UNDEFINED)
1188 && (delta.screenLayout & SCREENLAYOUT_LONG_MASK)
1189 != (screenLayout & SCREENLAYOUT_LONG_MASK)) {
1190 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
1191 screenLayout = (screenLayout & ~SCREENLAYOUT_LONG_MASK)
1192 | (delta.screenLayout & SCREENLAYOUT_LONG_MASK);
1193 }
1194 if (((delta.screenLayout & SCREENLAYOUT_ROUND_MASK) != SCREENLAYOUT_ROUND_UNDEFINED)
1195 && (delta.screenLayout & SCREENLAYOUT_ROUND_MASK)
1196 != (screenLayout & SCREENLAYOUT_ROUND_MASK)) {
1197 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
1198 screenLayout = (screenLayout & ~SCREENLAYOUT_ROUND_MASK)
1199 | (delta.screenLayout & SCREENLAYOUT_ROUND_MASK);
1200 }
1201 if ((delta.screenLayout & SCREENLAYOUT_COMPAT_NEEDED)
1202 != (screenLayout & SCREENLAYOUT_COMPAT_NEEDED)
1203 && delta.screenLayout != 0) {
1204 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
1205 screenLayout = (screenLayout & ~SCREENLAYOUT_COMPAT_NEEDED)
1206 | (delta.screenLayout & SCREENLAYOUT_COMPAT_NEEDED);
1207 }
1208
Romain Guy48327452017-01-23 17:03:35 -08001209 if (((delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) !=
1210 COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED)
1211 && (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK)
1212 != (colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) {
1213 changed |= ActivityInfo.CONFIG_COLOR_MODE;
1214 colorMode = (colorMode & ~COLOR_MODE_WIDE_COLOR_GAMUT_MASK)
1215 | (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK);
Romain Guyc9ba5592017-01-18 16:34:42 -08001216 }
1217
Romain Guy48327452017-01-23 17:03:35 -08001218 if (((delta.colorMode & COLOR_MODE_HDR_MASK) != COLOR_MODE_HDR_UNDEFINED)
1219 && (delta.colorMode & COLOR_MODE_HDR_MASK)
1220 != (colorMode & COLOR_MODE_HDR_MASK)) {
1221 changed |= ActivityInfo.CONFIG_COLOR_MODE;
1222 colorMode = (colorMode & ~COLOR_MODE_HDR_MASK)
1223 | (delta.colorMode & COLOR_MODE_HDR_MASK);
Romain Guyc9ba5592017-01-18 16:34:42 -08001224 }
1225
Dianne Hackborn7299c412010-03-04 18:41:49 -08001226 if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)
Tobias Haamel27b28b32010-02-09 23:09:17 +01001227 && uiMode != delta.uiMode) {
1228 changed |= ActivityInfo.CONFIG_UI_MODE;
Dianne Hackborn7299c412010-03-04 18:41:49 -08001229 if ((delta.uiMode&UI_MODE_TYPE_MASK) != UI_MODE_TYPE_UNDEFINED) {
1230 uiMode = (uiMode&~UI_MODE_TYPE_MASK)
1231 | (delta.uiMode&UI_MODE_TYPE_MASK);
1232 }
1233 if ((delta.uiMode&UI_MODE_NIGHT_MASK) != UI_MODE_NIGHT_UNDEFINED) {
1234 uiMode = (uiMode&~UI_MODE_NIGHT_MASK)
1235 | (delta.uiMode&UI_MODE_NIGHT_MASK);
1236 }
Tobias Haamel27b28b32010-02-09 23:09:17 +01001237 }
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001238 if (delta.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED
1239 && screenWidthDp != delta.screenWidthDp) {
1240 changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1241 screenWidthDp = delta.screenWidthDp;
1242 }
1243 if (delta.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED
1244 && screenHeightDp != delta.screenHeightDp) {
1245 changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1246 screenHeightDp = delta.screenHeightDp;
1247 }
Danny Baumanne7123a62013-05-15 10:21:40 +02001248 if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
1249 && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
1250 changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001251 smallestScreenWidthDp = delta.smallestScreenWidthDp;
1252 }
Danny Baumanne7123a62013-05-15 10:21:40 +02001253 if (delta.densityDpi != DENSITY_DPI_UNDEFINED &&
1254 densityDpi != delta.densityDpi) {
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001255 changed |= ActivityInfo.CONFIG_DENSITY;
1256 densityDpi = delta.densityDpi;
1257 }
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001258 if (delta.compatScreenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
1259 compatScreenWidthDp = delta.compatScreenWidthDp;
1260 }
1261 if (delta.compatScreenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
1262 compatScreenHeightDp = delta.compatScreenHeightDp;
1263 }
1264 if (delta.compatSmallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
1265 compatSmallestScreenWidthDp = delta.compatSmallestScreenWidthDp;
1266 }
Adam Lesinski4eb41292017-07-06 12:06:13 -07001267 if (delta.assetsSeq != ASSETS_SEQ_UNDEFINED && delta.assetsSeq != assetsSeq) {
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001268 changed |= ActivityInfo.CONFIG_ASSETS_PATHS;
1269 assetsSeq = delta.assetsSeq;
1270 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001271 if (delta.seq != 0) {
1272 seq = delta.seq;
1273 }
Wale Ogunwale822e5122017-07-26 06:02:24 -07001274 if (windowConfiguration.updateFrom(delta.windowConfiguration) != 0) {
1275 changed |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
1276 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -07001277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001278 return changed;
1279 }
1280
1281 /**
1282 * Return a bit mask of the differences between this Configuration
1283 * object and the given one. Does not change the values of either. Any
1284 * undefined fields in <var>delta</var> are ignored.
1285 * @return Returns a bit mask indicating which configuration
1286 * values has changed, containing any combination of
1287 * {@link android.content.pm.ActivityInfo#CONFIG_FONT_SCALE
1288 * PackageManager.ActivityInfo.CONFIG_FONT_SCALE},
1289 * {@link android.content.pm.ActivityInfo#CONFIG_MCC
1290 * PackageManager.ActivityInfo.CONFIG_MCC},
1291 * {@link android.content.pm.ActivityInfo#CONFIG_MNC
1292 * PackageManager.ActivityInfo.CONFIG_MNC},
1293 * {@link android.content.pm.ActivityInfo#CONFIG_LOCALE
1294 * PackageManager.ActivityInfo.CONFIG_LOCALE},
1295 * {@link android.content.pm.ActivityInfo#CONFIG_TOUCHSCREEN
1296 * PackageManager.ActivityInfo.CONFIG_TOUCHSCREEN},
1297 * {@link android.content.pm.ActivityInfo#CONFIG_KEYBOARD
1298 * PackageManager.ActivityInfo.CONFIG_KEYBOARD},
1299 * {@link android.content.pm.ActivityInfo#CONFIG_NAVIGATION
Dianne Hackborn723738c2009-06-25 19:48:04 -07001300 * PackageManager.ActivityInfo.CONFIG_NAVIGATION},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001301 * {@link android.content.pm.ActivityInfo#CONFIG_ORIENTATION
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001302 * PackageManager.ActivityInfo.CONFIG_ORIENTATION},
Dianne Hackborn723738c2009-06-25 19:48:04 -07001303 * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_LAYOUT
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001304 * PackageManager.ActivityInfo.CONFIG_SCREEN_LAYOUT}, or
1305 * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_SIZE
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001306 * PackageManager.ActivityInfo.CONFIG_SCREEN_SIZE}, or
1307 * {@link android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE
1308 * PackageManager.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE}.
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001309 * {@link android.content.pm.ActivityInfo#CONFIG_LAYOUT_DIRECTION
1310 * PackageManager.ActivityInfo.CONFIG_LAYOUT_DIRECTION}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001311 */
1312 public int diff(Configuration delta) {
Bryce Lee658d9842017-07-28 08:33:36 -07001313 return diff(delta, false /* compareUndefined */, false /* publicOnly */);
1314 }
1315
1316 /**
1317 * Returns the diff against the provided {@link Configuration} excluding values that would
1318 * publicly be equivalent, such as appBounds.
1319 * @param delta {@link Configuration} to compare to.
1320 *
1321 * TODO(b/36812336): Remove once appBounds has been moved out of Configuration.
1322 * {@hide}
1323 */
1324 public int diffPublicOnly(Configuration delta) {
1325 return diff(delta, false /* compareUndefined */, true /* publicOnly */);
Andrii Kulianb10330d2016-09-16 13:51:46 -07001326 }
1327
1328 /**
1329 * Variation of {@link #diff(Configuration)} with an option to skip checks for undefined values.
1330 *
1331 * @hide
1332 */
Bryce Lee658d9842017-07-28 08:33:36 -07001333 public int diff(Configuration delta, boolean compareUndefined, boolean publicOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001334 int changed = 0;
Andrii Kulianb10330d2016-09-16 13:51:46 -07001335 if ((compareUndefined || delta.fontScale > 0) && fontScale != delta.fontScale) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001336 changed |= ActivityInfo.CONFIG_FONT_SCALE;
1337 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001338 if ((compareUndefined || delta.mcc != 0) && mcc != delta.mcc) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001339 changed |= ActivityInfo.CONFIG_MCC;
1340 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001341 if ((compareUndefined || delta.mnc != 0) && mnc != delta.mnc) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001342 changed |= ActivityInfo.CONFIG_MNC;
1343 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001344 fixUpLocaleList();
1345 delta.fixUpLocaleList();
Andrii Kulianb10330d2016-09-16 13:51:46 -07001346 if ((compareUndefined || !delta.mLocaleList.isEmpty())
1347 && !mLocaleList.equals(delta.mLocaleList)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001348 changed |= ActivityInfo.CONFIG_LOCALE;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001349 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001350 }
Craig Mautner31678b52013-08-12 17:56:34 -07001351 final int deltaScreenLayoutDir = delta.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
Andrii Kulianb10330d2016-09-16 13:51:46 -07001352 if ((compareUndefined || deltaScreenLayoutDir != SCREENLAYOUT_LAYOUTDIR_UNDEFINED)
1353 && deltaScreenLayoutDir != (screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) {
Amith Yamasanid8415f42013-08-07 20:15:10 -07001354 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
1355 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001356 if ((compareUndefined || delta.touchscreen != TOUCHSCREEN_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001357 && touchscreen != delta.touchscreen) {
1358 changed |= ActivityInfo.CONFIG_TOUCHSCREEN;
1359 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001360 if ((compareUndefined || delta.keyboard != KEYBOARD_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001361 && keyboard != delta.keyboard) {
1362 changed |= ActivityInfo.CONFIG_KEYBOARD;
1363 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001364 if ((compareUndefined || delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001365 && keyboardHidden != delta.keyboardHidden) {
1366 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1367 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001368 if ((compareUndefined || delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369 && hardKeyboardHidden != delta.hardKeyboardHidden) {
1370 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1371 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001372 if ((compareUndefined || delta.navigation != NAVIGATION_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001373 && navigation != delta.navigation) {
1374 changed |= ActivityInfo.CONFIG_NAVIGATION;
1375 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001376 if ((compareUndefined || delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED)
Dianne Hackborn93e462b2009-09-15 22:50:40 -07001377 && navigationHidden != delta.navigationHidden) {
1378 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1379 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001380 if ((compareUndefined || delta.orientation != ORIENTATION_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 && orientation != delta.orientation) {
1382 changed |= ActivityInfo.CONFIG_ORIENTATION;
1383 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001384 if ((compareUndefined || getScreenLayoutNoDirection(delta.screenLayout) !=
1385 (SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED))
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001386 && getScreenLayoutNoDirection(screenLayout) !=
Andrii Kulianb10330d2016-09-16 13:51:46 -07001387 getScreenLayoutNoDirection(delta.screenLayout)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07001388 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
1389 }
Romain Guyc9ba5592017-01-18 16:34:42 -08001390 if ((compareUndefined ||
Romain Guy48327452017-01-23 17:03:35 -08001391 (delta.colorMode & COLOR_MODE_HDR_MASK) != COLOR_MODE_HDR_UNDEFINED)
1392 && (colorMode & COLOR_MODE_HDR_MASK) !=
1393 (delta.colorMode & COLOR_MODE_HDR_MASK)) {
1394 changed |= ActivityInfo.CONFIG_COLOR_MODE;
Romain Guyc9ba5592017-01-18 16:34:42 -08001395 }
1396 if ((compareUndefined ||
Romain Guy48327452017-01-23 17:03:35 -08001397 (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) !=
1398 COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED)
1399 && (colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) !=
1400 (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) {
1401 changed |= ActivityInfo.CONFIG_COLOR_MODE;
Romain Guyc9ba5592017-01-18 16:34:42 -08001402 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001403 if ((compareUndefined || delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED))
Tobias Haamel27b28b32010-02-09 23:09:17 +01001404 && uiMode != delta.uiMode) {
1405 changed |= ActivityInfo.CONFIG_UI_MODE;
1406 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001407 if ((compareUndefined || delta.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED)
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001408 && screenWidthDp != delta.screenWidthDp) {
1409 changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1410 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001411 if ((compareUndefined || delta.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED)
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001412 && screenHeightDp != delta.screenHeightDp) {
1413 changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1414 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001415 if ((compareUndefined || delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED)
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001416 && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
1417 changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
1418 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001419 if ((compareUndefined || delta.densityDpi != DENSITY_DPI_UNDEFINED)
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001420 && densityDpi != delta.densityDpi) {
1421 changed |= ActivityInfo.CONFIG_DENSITY;
1422 }
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001423 if ((compareUndefined || delta.assetsSeq != ASSETS_SEQ_UNDEFINED)
1424 && assetsSeq != delta.assetsSeq) {
1425 changed |= ActivityInfo.CONFIG_ASSETS_PATHS;
1426 }
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001427
Wale Ogunwale822e5122017-07-26 06:02:24 -07001428 // WindowConfiguration differences aren't considered public...
1429 if (!publicOnly
1430 && windowConfiguration.diff(delta.windowConfiguration, compareUndefined) != 0) {
1431 changed |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
Bryce Lee7566d762017-03-30 09:34:15 -07001432 }
1433
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001434 return changed;
1435 }
1436
1437 /**
Alan Viveretteac85f902016-03-11 15:15:51 -05001438 * Determines if a new resource needs to be loaded from the bit set of
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001439 * configuration changes returned by {@link #updateFrom(Configuration)}.
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -07001440 *
Alan Viveretteac85f902016-03-11 15:15:51 -05001441 * @param configChanges the mask of changes configurations as returned by
1442 * {@link #updateFrom(Configuration)}
1443 * @param interestingChanges the configuration changes that the resource
1444 * can handle as given in
1445 * {@link android.util.TypedValue#changingConfigurations}
1446 * @return {@code true} if the resource needs to be loaded, {@code false}
1447 * otherwise
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001448 */
Alan Viveretteac85f902016-03-11 15:15:51 -05001449 public static boolean needNewResources(@Config int configChanges,
1450 @Config int interestingChanges) {
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001451 // CONFIG_ASSETS_PATHS and CONFIG_FONT_SCALE are higher level configuration changes that
1452 // all resources are subject to change with.
1453 interestingChanges = interestingChanges | ActivityInfo.CONFIG_ASSETS_PATHS
1454 | ActivityInfo.CONFIG_FONT_SCALE;
1455 return (configChanges & interestingChanges) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 }
Amith Yamasanid8415f42013-08-07 20:15:10 -07001457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001458 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001459 * @hide Return true if the sequence of 'other' is better than this. Assumes
1460 * that 'this' is your current sequence and 'other' is a new one you have
1461 * received some how and want to compare with what you have.
1462 */
1463 public boolean isOtherSeqNewer(Configuration other) {
1464 if (other == null) {
1465 // Sanity check.
1466 return false;
1467 }
1468 if (other.seq == 0) {
1469 // If the other sequence is not specified, then we must assume
1470 // it is newer since we don't know any better.
1471 return true;
1472 }
1473 if (seq == 0) {
1474 // If this sequence is not specified, then we also consider the
1475 // other is better. Yes we have a preference for other. Sue us.
1476 return true;
1477 }
1478 int diff = other.seq - seq;
1479 if (diff > 0x10000) {
1480 // If there has been a sufficiently large jump, assume the
1481 // sequence has wrapped around.
1482 return false;
1483 }
1484 return diff > 0;
1485 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -07001486
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001487 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 * Parcelable methods
1489 */
1490 public int describeContents() {
1491 return 0;
1492 }
1493
1494 public void writeToParcel(Parcel dest, int flags) {
1495 dest.writeFloat(fontScale);
1496 dest.writeInt(mcc);
1497 dest.writeInt(mnc);
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001498
1499 fixUpLocaleList();
1500 final int localeListSize = mLocaleList.size();
1501 dest.writeInt(localeListSize);
1502 for (int i = 0; i < localeListSize; ++i) {
1503 final Locale l = mLocaleList.get(i);
1504 dest.writeString(l.toLanguageTag());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001505 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 if(userSetLocale) {
1508 dest.writeInt(1);
1509 } else {
1510 dest.writeInt(0);
1511 }
1512 dest.writeInt(touchscreen);
1513 dest.writeInt(keyboard);
1514 dest.writeInt(keyboardHidden);
1515 dest.writeInt(hardKeyboardHidden);
1516 dest.writeInt(navigation);
Dianne Hackborn93e462b2009-09-15 22:50:40 -07001517 dest.writeInt(navigationHidden);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001518 dest.writeInt(orientation);
Dianne Hackborn723738c2009-06-25 19:48:04 -07001519 dest.writeInt(screenLayout);
Romain Guy48327452017-01-23 17:03:35 -08001520 dest.writeInt(colorMode);
Tobias Haamel27b28b32010-02-09 23:09:17 +01001521 dest.writeInt(uiMode);
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001522 dest.writeInt(screenWidthDp);
1523 dest.writeInt(screenHeightDp);
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001524 dest.writeInt(smallestScreenWidthDp);
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001525 dest.writeInt(densityDpi);
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001526 dest.writeInt(compatScreenWidthDp);
1527 dest.writeInt(compatScreenHeightDp);
1528 dest.writeInt(compatSmallestScreenWidthDp);
Wale Ogunwale822e5122017-07-26 06:02:24 -07001529 dest.writeValue(windowConfiguration);
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001530 dest.writeInt(assetsSeq);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001531 dest.writeInt(seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532 }
1533
Dianne Hackborn694f79b2010-03-17 19:44:59 -07001534 public void readFromParcel(Parcel source) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001535 fontScale = source.readFloat();
1536 mcc = source.readInt();
1537 mnc = source.readInt();
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001538
1539 final int localeListSize = source.readInt();
1540 final Locale[] localeArray = new Locale[localeListSize];
1541 for (int i = 0; i < localeListSize; ++i) {
1542 localeArray[i] = Locale.forLanguageTag(source.readString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001543 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001544 mLocaleList = new LocaleList(localeArray);
Roozbeh Pournaderfee44842016-02-04 15:24:24 -08001545 locale = mLocaleList.get(0);
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001546
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001547 userSetLocale = (source.readInt()==1);
1548 touchscreen = source.readInt();
1549 keyboard = source.readInt();
1550 keyboardHidden = source.readInt();
1551 hardKeyboardHidden = source.readInt();
1552 navigation = source.readInt();
Dianne Hackborn93e462b2009-09-15 22:50:40 -07001553 navigationHidden = source.readInt();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001554 orientation = source.readInt();
Dianne Hackborn723738c2009-06-25 19:48:04 -07001555 screenLayout = source.readInt();
Romain Guy48327452017-01-23 17:03:35 -08001556 colorMode = source.readInt();
Tobias Haamel27b28b32010-02-09 23:09:17 +01001557 uiMode = source.readInt();
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001558 screenWidthDp = source.readInt();
1559 screenHeightDp = source.readInt();
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001560 smallestScreenWidthDp = source.readInt();
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001561 densityDpi = source.readInt();
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001562 compatScreenWidthDp = source.readInt();
1563 compatScreenHeightDp = source.readInt();
1564 compatSmallestScreenWidthDp = source.readInt();
Wale Ogunwale822e5122017-07-26 06:02:24 -07001565 windowConfiguration.setTo((WindowConfiguration) source.readValue(null));
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001566 assetsSeq = source.readInt();
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001567 seq = source.readInt();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001568 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -07001569
Dianne Hackborn694f79b2010-03-17 19:44:59 -07001570 public static final Parcelable.Creator<Configuration> CREATOR
1571 = new Parcelable.Creator<Configuration>() {
1572 public Configuration createFromParcel(Parcel source) {
1573 return new Configuration(source);
1574 }
1575
1576 public Configuration[] newArray(int size) {
1577 return new Configuration[size];
1578 }
1579 };
1580
1581 /**
1582 * Construct this Configuration object, reading from the Parcel.
1583 */
1584 private Configuration(Parcel source) {
1585 readFromParcel(source);
1586 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001587
1588 public int compareTo(Configuration that) {
1589 int n;
1590 float a = this.fontScale;
1591 float b = that.fontScale;
1592 if (a < b) return -1;
1593 if (a > b) return 1;
1594 n = this.mcc - that.mcc;
1595 if (n != 0) return n;
1596 n = this.mnc - that.mnc;
1597 if (n != 0) return n;
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001598
1599 fixUpLocaleList();
1600 that.fixUpLocaleList();
1601 // for backward compatibility, we consider an empty locale list to be greater
1602 // than any non-empty locale list.
1603 if (this.mLocaleList.isEmpty()) {
1604 if (!that.mLocaleList.isEmpty()) return 1;
1605 } else if (that.mLocaleList.isEmpty()) {
Dianne Hackborna8397032010-03-12 10:52:22 -08001606 return -1;
1607 } else {
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001608 final int minSize = Math.min(this.mLocaleList.size(), that.mLocaleList.size());
1609 for (int i = 0; i < minSize; ++i) {
1610 final Locale thisLocale = this.mLocaleList.get(i);
1611 final Locale thatLocale = that.mLocaleList.get(i);
1612 n = thisLocale.getLanguage().compareTo(thatLocale.getLanguage());
1613 if (n != 0) return n;
1614 n = thisLocale.getCountry().compareTo(thatLocale.getCountry());
1615 if (n != 0) return n;
1616 n = thisLocale.getVariant().compareTo(thatLocale.getVariant());
1617 if (n != 0) return n;
1618 n = thisLocale.toLanguageTag().compareTo(thatLocale.toLanguageTag());
1619 if (n != 0) return n;
1620 }
1621 n = this.mLocaleList.size() - that.mLocaleList.size();
Dianne Hackborna8397032010-03-12 10:52:22 -08001622 if (n != 0) return n;
1623 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001624
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001625 n = this.touchscreen - that.touchscreen;
1626 if (n != 0) return n;
1627 n = this.keyboard - that.keyboard;
1628 if (n != 0) return n;
1629 n = this.keyboardHidden - that.keyboardHidden;
1630 if (n != 0) return n;
1631 n = this.hardKeyboardHidden - that.hardKeyboardHidden;
1632 if (n != 0) return n;
1633 n = this.navigation - that.navigation;
1634 if (n != 0) return n;
Dianne Hackborn93e462b2009-09-15 22:50:40 -07001635 n = this.navigationHidden - that.navigationHidden;
1636 if (n != 0) return n;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001637 n = this.orientation - that.orientation;
Dianne Hackborn723738c2009-06-25 19:48:04 -07001638 if (n != 0) return n;
Romain Guy48327452017-01-23 17:03:35 -08001639 n = this.colorMode - that.colorMode;
Romain Guyc9ba5592017-01-18 16:34:42 -08001640 if (n != 0) return n;
Dianne Hackborn723738c2009-06-25 19:48:04 -07001641 n = this.screenLayout - that.screenLayout;
Tobias Haamel27b28b32010-02-09 23:09:17 +01001642 if (n != 0) return n;
1643 n = this.uiMode - that.uiMode;
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001644 if (n != 0) return n;
1645 n = this.screenWidthDp - that.screenWidthDp;
1646 if (n != 0) return n;
1647 n = this.screenHeightDp - that.screenHeightDp;
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001648 if (n != 0) return n;
1649 n = this.smallestScreenWidthDp - that.smallestScreenWidthDp;
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001650 if (n != 0) return n;
1651 n = this.densityDpi - that.densityDpi;
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001652 if (n != 0) return n;
1653 n = this.assetsSeq - that.assetsSeq;
Bryce Leec5fe0ee2017-06-30 09:03:09 -07001654 if (n != 0) return n;
Wale Ogunwale822e5122017-07-26 06:02:24 -07001655 n = windowConfiguration.compareTo(that.windowConfiguration);
1656 if (n != 0) return n;
Bryce Leec5fe0ee2017-06-30 09:03:09 -07001657
1658 // if (n != 0) return n;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001659 return n;
1660 }
1661
1662 public boolean equals(Configuration that) {
1663 if (that == null) return false;
1664 if (that == this) return true;
1665 return this.compareTo(that) == 0;
1666 }
1667
1668 public boolean equals(Object that) {
1669 try {
1670 return equals((Configuration)that);
1671 } catch (ClassCastException e) {
1672 }
1673 return false;
1674 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001676 public int hashCode() {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001677 int result = 17;
1678 result = 31 * result + Float.floatToIntBits(fontScale);
1679 result = 31 * result + mcc;
1680 result = 31 * result + mnc;
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001681 result = 31 * result + mLocaleList.hashCode();
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001682 result = 31 * result + touchscreen;
1683 result = 31 * result + keyboard;
1684 result = 31 * result + keyboardHidden;
1685 result = 31 * result + hardKeyboardHidden;
1686 result = 31 * result + navigation;
1687 result = 31 * result + navigationHidden;
1688 result = 31 * result + orientation;
1689 result = 31 * result + screenLayout;
Romain Guy48327452017-01-23 17:03:35 -08001690 result = 31 * result + colorMode;
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001691 result = 31 * result + uiMode;
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001692 result = 31 * result + screenWidthDp;
1693 result = 31 * result + screenHeightDp;
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001694 result = 31 * result + smallestScreenWidthDp;
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001695 result = 31 * result + densityDpi;
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001696 result = 31 * result + assetsSeq;
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001697 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001698 }
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001699
1700 /**
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001701 * Get the locale list. This is the preferred way for getting the locales (instead of using
1702 * the direct accessor to {@link #locale}, which would only provide the primary locale).
1703 *
1704 * @return The locale list.
1705 */
Adam Lesinskib61e4052016-05-19 18:23:05 -07001706 public @NonNull LocaleList getLocales() {
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001707 fixUpLocaleList();
1708 return mLocaleList;
1709 }
1710
1711 /**
1712 * Set the locale list. This is the preferred way for setting up the locales (instead of using
1713 * the direct accessor or {@link #setLocale(Locale)}). This will also set the layout direction
1714 * according to the first locale in the list.
1715 *
1716 * Note that the layout direction will always come from the first locale in the locale list,
1717 * even if the locale is not supported by the resources (the resources may only support
1718 * another locale further down the list which has a different direction).
1719 *
1720 * @param locales The locale list. If null, an empty LocaleList will be assigned.
1721 */
1722 public void setLocales(@Nullable LocaleList locales) {
1723 mLocaleList = locales == null ? LocaleList.getEmptyLocaleList() : locales;
Roozbeh Pournaderfee44842016-02-04 15:24:24 -08001724 locale = mLocaleList.get(0);
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001725 setLayoutDirection(locale);
1726 }
1727
1728 /**
1729 * Set the locale list to a list of just one locale. This will also set the layout direction
1730 * according to the locale.
1731 *
1732 * Note that after this is run, calling <code>.equals()</code> on the input locale and the
1733 * {@link #locale} attribute would return <code>true</code> if they are not null, but there is
1734 * no guarantee that they would be the same object.
1735 *
1736 * See also the note about layout direction in {@link #setLocales(LocaleList)}.
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001737 *
1738 * @param loc The locale. Can be null.
1739 */
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001740 public void setLocale(@Nullable Locale loc) {
Raph Levien10ea92a2016-05-02 12:56:01 -07001741 setLocales(loc == null ? LocaleList.getEmptyLocaleList() : new LocaleList(loc));
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001742 }
1743
1744 /**
Seigo Nonakabd5cac62016-05-13 15:11:37 +09001745 * @hide
1746 *
1747 * Clears the locale without changing layout direction.
1748 */
1749 public void clearLocales() {
1750 mLocaleList = LocaleList.getEmptyLocaleList();
1751 locale = null;
1752 }
1753
1754 /**
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001755 * Return the layout direction. Will be either {@link View#LAYOUT_DIRECTION_LTR} or
1756 * {@link View#LAYOUT_DIRECTION_RTL}.
1757 *
Dianne Hackbornf1ae2692013-04-19 14:09:37 -07001758 * @return Returns {@link View#LAYOUT_DIRECTION_RTL} if the configuration
1759 * is {@link #SCREENLAYOUT_LAYOUTDIR_RTL}, otherwise {@link View#LAYOUT_DIRECTION_LTR}.
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001760 */
1761 public int getLayoutDirection() {
Dianne Hackbornf1ae2692013-04-19 14:09:37 -07001762 return (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK) == SCREENLAYOUT_LAYOUTDIR_RTL
1763 ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001764 }
1765
1766 /**
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001767 * Set the layout direction from a Locale.
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001768 *
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001769 * @param loc The Locale. If null will set the layout direction to
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001770 * {@link View#LAYOUT_DIRECTION_LTR}. If not null will set it to the layout direction
1771 * corresponding to the Locale.
1772 *
John Spurlockbc4cf002015-03-24 21:51:20 -04001773 * @see View#LAYOUT_DIRECTION_LTR
1774 * @see View#LAYOUT_DIRECTION_RTL
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001775 */
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001776 public void setLayoutDirection(Locale loc) {
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001777 // There is a "1" difference between the configuration values for
1778 // layout direction and View constants for layout direction, just add "1".
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001779 final int layoutDirection = 1 + TextUtils.getLayoutDirectionFromLocale(loc);
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001780 screenLayout = (screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK)|
1781 (layoutDirection << SCREENLAYOUT_LAYOUTDIR_SHIFT);
1782 }
1783
1784 private static int getScreenLayoutNoDirection(int screenLayout) {
1785 return screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK;
1786 }
Adam Lesinski2c749d22014-06-04 13:00:29 -07001787
1788 /**
Adam Powell49e7ff92015-05-14 16:18:53 -07001789 * Return whether the screen has a round shape. Apps may choose to change styling based
1790 * on this property, such as the alignment or layout of text or informational icons.
1791 *
1792 * @return true if the screen is rounded, false otherwise
1793 */
1794 public boolean isScreenRound() {
1795 return (screenLayout & SCREENLAYOUT_ROUND_MASK) == SCREENLAYOUT_ROUND_YES;
1796 }
1797
1798 /**
Romain Guye89d0bb2017-06-20 12:23:42 -07001799 * Return whether the screen has a wide color gamut and wide color gamut rendering
1800 * is supported by this device.
Romain Guyc9ba5592017-01-18 16:34:42 -08001801 *
Romain Guye89d0bb2017-06-20 12:23:42 -07001802 * @return true if the screen has a wide color gamut and wide color gamut rendering
1803 * is supported, false otherwise
Romain Guyc9ba5592017-01-18 16:34:42 -08001804 */
1805 public boolean isScreenWideColorGamut() {
Romain Guy48327452017-01-23 17:03:35 -08001806 return (colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) == COLOR_MODE_WIDE_COLOR_GAMUT_YES;
Romain Guyc9ba5592017-01-18 16:34:42 -08001807 }
1808
1809 /**
1810 * Return whether the screen has a high dynamic range.
1811 *
1812 * @return true if the screen has a high dynamic range, false otherwise
1813 */
1814 public boolean isScreenHdr() {
Romain Guy48327452017-01-23 17:03:35 -08001815 return (colorMode & COLOR_MODE_HDR_MASK) == COLOR_MODE_HDR_YES;
Romain Guyc9ba5592017-01-18 16:34:42 -08001816 }
1817
1818 /**
Adam Lesinski2c749d22014-06-04 13:00:29 -07001819 *
1820 * @hide
1821 */
Roozbeh Pournader47f71a62015-11-07 11:55:38 -08001822 public static String localesToResourceQualifier(LocaleList locs) {
Roozbeh Pournader309ebd62016-06-17 22:13:12 -07001823 final StringBuilder sb = new StringBuilder();
Roozbeh Pournader47f71a62015-11-07 11:55:38 -08001824 for (int i = 0; i < locs.size(); i++) {
Roozbeh Pournader309ebd62016-06-17 22:13:12 -07001825 final Locale loc = locs.get(i);
1826 final int l = loc.getLanguage().length();
1827 if (l == 0) {
1828 continue;
1829 }
1830 final int s = loc.getScript().length();
1831 final int c = loc.getCountry().length();
1832 final int v = loc.getVariant().length();
1833 // We ignore locale extensions, since they are not supported by AAPT
1834
1835 if (sb.length() != 0) {
1836 sb.append(",");
1837 }
1838 if (l == 2 && s == 0 && (c == 0 || c == 2) && v == 0) {
1839 // Traditional locale format: xx or xx-rYY
Roozbeh Pournader47f71a62015-11-07 11:55:38 -08001840 sb.append(loc.getLanguage());
Roozbeh Pournader309ebd62016-06-17 22:13:12 -07001841 if (c == 2) {
Roozbeh Pournader47f71a62015-11-07 11:55:38 -08001842 sb.append("-r").append(loc.getCountry());
Roozbeh Pournader309ebd62016-06-17 22:13:12 -07001843 }
1844 } else {
1845 sb.append("b+");
1846 sb.append(loc.getLanguage());
1847 if (s != 0) {
1848 sb.append("+");
1849 sb.append(loc.getScript());
1850 }
1851 if (c != 0) {
1852 sb.append("+");
1853 sb.append(loc.getCountry());
1854 }
1855 if (v != 0) {
1856 sb.append("+");
1857 sb.append(loc.getVariant());
Adam Lesinski2c749d22014-06-04 13:00:29 -07001858 }
1859 }
1860 }
1861 return sb.toString();
1862 }
1863
1864
1865 /**
1866 * Returns a string representation of the configuration that can be parsed
1867 * by build tools (like AAPT).
1868 *
Adam Lesinski2c749d22014-06-04 13:00:29 -07001869 * @hide
1870 */
1871 public static String resourceQualifierString(Configuration config) {
1872 ArrayList<String> parts = new ArrayList<String>();
1873
1874 if (config.mcc != 0) {
Adam Lesinski90865622014-10-16 18:18:10 -07001875 parts.add("mcc" + config.mcc);
Adam Lesinski2c749d22014-06-04 13:00:29 -07001876 if (config.mnc != 0) {
Adam Lesinski90865622014-10-16 18:18:10 -07001877 parts.add("mnc" + config.mnc);
Adam Lesinski2c749d22014-06-04 13:00:29 -07001878 }
1879 }
1880
Roozbeh Pournader47f71a62015-11-07 11:55:38 -08001881 if (!config.mLocaleList.isEmpty()) {
Roozbeh Pournader417bbe02015-11-09 17:09:15 -08001882 final String resourceQualifier = localesToResourceQualifier(config.mLocaleList);
1883 if (!resourceQualifier.isEmpty()) {
1884 parts.add(resourceQualifier);
1885 }
Adam Lesinski2c749d22014-06-04 13:00:29 -07001886 }
1887
1888 switch (config.screenLayout & Configuration.SCREENLAYOUT_LAYOUTDIR_MASK) {
1889 case Configuration.SCREENLAYOUT_LAYOUTDIR_LTR:
1890 parts.add("ldltr");
1891 break;
1892 case Configuration.SCREENLAYOUT_LAYOUTDIR_RTL:
1893 parts.add("ldrtl");
1894 break;
1895 default:
1896 break;
1897 }
1898
1899 if (config.smallestScreenWidthDp != 0) {
1900 parts.add("sw" + config.smallestScreenWidthDp + "dp");
1901 }
1902
1903 if (config.screenWidthDp != 0) {
1904 parts.add("w" + config.screenWidthDp + "dp");
1905 }
1906
1907 if (config.screenHeightDp != 0) {
1908 parts.add("h" + config.screenHeightDp + "dp");
1909 }
1910
1911 switch (config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) {
1912 case Configuration.SCREENLAYOUT_SIZE_SMALL:
1913 parts.add("small");
1914 break;
1915 case Configuration.SCREENLAYOUT_SIZE_NORMAL:
1916 parts.add("normal");
1917 break;
1918 case Configuration.SCREENLAYOUT_SIZE_LARGE:
1919 parts.add("large");
1920 break;
1921 case Configuration.SCREENLAYOUT_SIZE_XLARGE:
1922 parts.add("xlarge");
1923 break;
1924 default:
1925 break;
1926 }
1927
1928 switch (config.screenLayout & Configuration.SCREENLAYOUT_LONG_MASK) {
1929 case Configuration.SCREENLAYOUT_LONG_YES:
1930 parts.add("long");
1931 break;
1932 case Configuration.SCREENLAYOUT_LONG_NO:
1933 parts.add("notlong");
1934 break;
1935 default:
1936 break;
1937 }
1938
Adam Powell49e7ff92015-05-14 16:18:53 -07001939 switch (config.screenLayout & Configuration.SCREENLAYOUT_ROUND_MASK) {
1940 case Configuration.SCREENLAYOUT_ROUND_YES:
1941 parts.add("round");
1942 break;
1943 case Configuration.SCREENLAYOUT_ROUND_NO:
1944 parts.add("notround");
1945 break;
1946 default:
1947 break;
1948 }
1949
Romain Guy48327452017-01-23 17:03:35 -08001950 switch (config.colorMode & Configuration.COLOR_MODE_HDR_MASK) {
1951 case Configuration.COLOR_MODE_HDR_YES:
Romain Guyc9ba5592017-01-18 16:34:42 -08001952 parts.add("highdr");
1953 break;
Romain Guy48327452017-01-23 17:03:35 -08001954 case Configuration.COLOR_MODE_HDR_NO:
Romain Guyc9ba5592017-01-18 16:34:42 -08001955 parts.add("lowdr");
1956 break;
1957 default:
1958 break;
1959 }
1960
Romain Guy48327452017-01-23 17:03:35 -08001961 switch (config.colorMode & Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_MASK) {
1962 case Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_YES:
Romain Guyc9ba5592017-01-18 16:34:42 -08001963 parts.add("widecg");
1964 break;
Romain Guy48327452017-01-23 17:03:35 -08001965 case Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_NO:
Romain Guyc9ba5592017-01-18 16:34:42 -08001966 parts.add("nowidecg");
1967 break;
1968 default:
1969 break;
1970 }
1971
Adam Lesinski2c749d22014-06-04 13:00:29 -07001972 switch (config.orientation) {
1973 case Configuration.ORIENTATION_LANDSCAPE:
1974 parts.add("land");
1975 break;
1976 case Configuration.ORIENTATION_PORTRAIT:
1977 parts.add("port");
1978 break;
1979 default:
1980 break;
1981 }
1982
1983 switch (config.uiMode & Configuration.UI_MODE_TYPE_MASK) {
1984 case Configuration.UI_MODE_TYPE_APPLIANCE:
1985 parts.add("appliance");
1986 break;
1987 case Configuration.UI_MODE_TYPE_DESK:
1988 parts.add("desk");
1989 break;
1990 case Configuration.UI_MODE_TYPE_TELEVISION:
1991 parts.add("television");
1992 break;
1993 case Configuration.UI_MODE_TYPE_CAR:
1994 parts.add("car");
1995 break;
1996 case Configuration.UI_MODE_TYPE_WATCH:
1997 parts.add("watch");
1998 break;
Zak Cohen1a6acdb2016-12-12 15:21:21 -08001999 case Configuration.UI_MODE_TYPE_VR_HEADSET:
2000 parts.add("vrheadset");
2001 break;
Adam Lesinski2c749d22014-06-04 13:00:29 -07002002 default:
2003 break;
2004 }
2005
2006 switch (config.uiMode & Configuration.UI_MODE_NIGHT_MASK) {
2007 case Configuration.UI_MODE_NIGHT_YES:
2008 parts.add("night");
2009 break;
2010 case Configuration.UI_MODE_NIGHT_NO:
2011 parts.add("notnight");
2012 break;
2013 default:
2014 break;
2015 }
2016
2017 switch (config.densityDpi) {
Adam Lesinski31245b42014-08-22 19:10:56 -07002018 case DENSITY_DPI_UNDEFINED:
Adam Lesinski2c749d22014-06-04 13:00:29 -07002019 break;
2020 case 120:
2021 parts.add("ldpi");
2022 break;
2023 case 160:
2024 parts.add("mdpi");
2025 break;
2026 case 213:
2027 parts.add("tvdpi");
2028 break;
2029 case 240:
2030 parts.add("hdpi");
2031 break;
2032 case 320:
2033 parts.add("xhdpi");
2034 break;
Adam Lesinskiebc3e4c2014-08-21 12:21:45 -07002035 case 480:
2036 parts.add("xxhdpi");
2037 break;
2038 case 640:
2039 parts.add("xxxhdpi");
2040 break;
Adam Lesinski31245b42014-08-22 19:10:56 -07002041 case DENSITY_DPI_ANY:
2042 parts.add("anydpi");
2043 break;
2044 case DENSITY_DPI_NONE:
2045 parts.add("nodpi");
Adam Lesinski2c749d22014-06-04 13:00:29 -07002046 default:
2047 parts.add(config.densityDpi + "dpi");
2048 break;
2049 }
2050
2051 switch (config.touchscreen) {
2052 case Configuration.TOUCHSCREEN_NOTOUCH:
2053 parts.add("notouch");
2054 break;
2055 case Configuration.TOUCHSCREEN_FINGER:
2056 parts.add("finger");
2057 break;
2058 default:
2059 break;
2060 }
2061
2062 switch (config.keyboardHidden) {
2063 case Configuration.KEYBOARDHIDDEN_NO:
2064 parts.add("keysexposed");
2065 break;
2066 case Configuration.KEYBOARDHIDDEN_YES:
2067 parts.add("keyshidden");
2068 break;
2069 case Configuration.KEYBOARDHIDDEN_SOFT:
2070 parts.add("keyssoft");
2071 break;
2072 default:
2073 break;
2074 }
2075
2076 switch (config.keyboard) {
2077 case Configuration.KEYBOARD_NOKEYS:
2078 parts.add("nokeys");
2079 break;
2080 case Configuration.KEYBOARD_QWERTY:
2081 parts.add("qwerty");
2082 break;
2083 case Configuration.KEYBOARD_12KEY:
2084 parts.add("12key");
2085 break;
2086 default:
2087 break;
2088 }
2089
2090 switch (config.navigationHidden) {
2091 case Configuration.NAVIGATIONHIDDEN_NO:
2092 parts.add("navexposed");
2093 break;
2094 case Configuration.NAVIGATIONHIDDEN_YES:
2095 parts.add("navhidden");
2096 break;
2097 default:
2098 break;
2099 }
2100
2101 switch (config.navigation) {
2102 case Configuration.NAVIGATION_NONAV:
2103 parts.add("nonav");
2104 break;
2105 case Configuration.NAVIGATION_DPAD:
2106 parts.add("dpad");
2107 break;
2108 case Configuration.NAVIGATION_TRACKBALL:
2109 parts.add("trackball");
2110 break;
2111 case Configuration.NAVIGATION_WHEEL:
2112 parts.add("wheel");
2113 break;
2114 default:
2115 break;
2116 }
2117
Adam Lesinskiebc3e4c2014-08-21 12:21:45 -07002118 parts.add("v" + Build.VERSION.RESOURCES_SDK_INT);
Adam Lesinski2c749d22014-06-04 13:00:29 -07002119 return TextUtils.join("-", parts);
2120 }
Adam Lesinski7f61e962014-09-02 16:43:52 -07002121
2122 /**
2123 * Generate a delta Configuration between <code>base</code> and <code>change</code>. The
2124 * resulting delta can be used with {@link #updateFrom(Configuration)}.
2125 * <p />
2126 * Caveat: If the any of the Configuration's members becomes undefined, then
2127 * {@link #updateFrom(Configuration)} will treat it as a no-op and not update that member.
2128 *
2129 * This is fine for device configurations as no member is ever undefined.
2130 * {@hide}
2131 */
2132 public static Configuration generateDelta(Configuration base, Configuration change) {
2133 final Configuration delta = new Configuration();
2134 if (base.fontScale != change.fontScale) {
2135 delta.fontScale = change.fontScale;
2136 }
2137
2138 if (base.mcc != change.mcc) {
2139 delta.mcc = change.mcc;
2140 }
2141
2142 if (base.mnc != change.mnc) {
2143 delta.mnc = change.mnc;
2144 }
2145
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002146 base.fixUpLocaleList();
2147 change.fixUpLocaleList();
2148 if (!base.mLocaleList.equals(change.mLocaleList)) {
2149 delta.mLocaleList = change.mLocaleList;
Adam Lesinski7f61e962014-09-02 16:43:52 -07002150 delta.locale = change.locale;
2151 }
2152
2153 if (base.touchscreen != change.touchscreen) {
2154 delta.touchscreen = change.touchscreen;
2155 }
2156
2157 if (base.keyboard != change.keyboard) {
2158 delta.keyboard = change.keyboard;
2159 }
2160
2161 if (base.keyboardHidden != change.keyboardHidden) {
2162 delta.keyboardHidden = change.keyboardHidden;
2163 }
2164
2165 if (base.navigation != change.navigation) {
2166 delta.navigation = change.navigation;
2167 }
2168
2169 if (base.navigationHidden != change.navigationHidden) {
2170 delta.navigationHidden = change.navigationHidden;
2171 }
2172
2173 if (base.orientation != change.orientation) {
2174 delta.orientation = change.orientation;
2175 }
2176
2177 if ((base.screenLayout & SCREENLAYOUT_SIZE_MASK) !=
2178 (change.screenLayout & SCREENLAYOUT_SIZE_MASK)) {
2179 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_SIZE_MASK;
2180 }
2181
2182 if ((base.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK) !=
2183 (change.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) {
2184 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
2185 }
2186
2187 if ((base.screenLayout & SCREENLAYOUT_LONG_MASK) !=
2188 (change.screenLayout & SCREENLAYOUT_LONG_MASK)) {
2189 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_LONG_MASK;
2190 }
2191
Adam Powell49e7ff92015-05-14 16:18:53 -07002192 if ((base.screenLayout & SCREENLAYOUT_ROUND_MASK) !=
2193 (change.screenLayout & SCREENLAYOUT_ROUND_MASK)) {
2194 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_ROUND_MASK;
2195 }
2196
Romain Guy48327452017-01-23 17:03:35 -08002197 if ((base.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) !=
2198 (change.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) {
2199 delta.colorMode |= change.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK;
Romain Guyc9ba5592017-01-18 16:34:42 -08002200 }
2201
Romain Guy48327452017-01-23 17:03:35 -08002202 if ((base.colorMode & COLOR_MODE_HDR_MASK) !=
2203 (change.colorMode & COLOR_MODE_HDR_MASK)) {
2204 delta.colorMode |= change.colorMode & COLOR_MODE_HDR_MASK;
Romain Guyc9ba5592017-01-18 16:34:42 -08002205 }
2206
Adam Lesinski7f61e962014-09-02 16:43:52 -07002207 if ((base.uiMode & UI_MODE_TYPE_MASK) != (change.uiMode & UI_MODE_TYPE_MASK)) {
2208 delta.uiMode |= change.uiMode & UI_MODE_TYPE_MASK;
2209 }
2210
2211 if ((base.uiMode & UI_MODE_NIGHT_MASK) != (change.uiMode & UI_MODE_NIGHT_MASK)) {
2212 delta.uiMode |= change.uiMode & UI_MODE_NIGHT_MASK;
2213 }
2214
2215 if (base.screenWidthDp != change.screenWidthDp) {
2216 delta.screenWidthDp = change.screenWidthDp;
2217 }
2218
2219 if (base.screenHeightDp != change.screenHeightDp) {
2220 delta.screenHeightDp = change.screenHeightDp;
2221 }
2222
2223 if (base.smallestScreenWidthDp != change.smallestScreenWidthDp) {
2224 delta.smallestScreenWidthDp = change.smallestScreenWidthDp;
2225 }
2226
2227 if (base.densityDpi != change.densityDpi) {
2228 delta.densityDpi = change.densityDpi;
2229 }
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01002230
2231 if (base.assetsSeq != change.assetsSeq) {
2232 delta.assetsSeq = change.assetsSeq;
2233 }
Wale Ogunwale822e5122017-07-26 06:02:24 -07002234
2235 if (!base.windowConfiguration.equals(change.windowConfiguration)) {
2236 delta.windowConfiguration.setTo(change.windowConfiguration);
2237 }
Adam Lesinski7f61e962014-09-02 16:43:52 -07002238 return delta;
2239 }
2240
2241 private static final String XML_ATTR_FONT_SCALE = "fs";
2242 private static final String XML_ATTR_MCC = "mcc";
2243 private static final String XML_ATTR_MNC = "mnc";
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002244 private static final String XML_ATTR_LOCALES = "locales";
Adam Lesinski7f61e962014-09-02 16:43:52 -07002245 private static final String XML_ATTR_TOUCHSCREEN = "touch";
2246 private static final String XML_ATTR_KEYBOARD = "key";
2247 private static final String XML_ATTR_KEYBOARD_HIDDEN = "keyHid";
2248 private static final String XML_ATTR_HARD_KEYBOARD_HIDDEN = "hardKeyHid";
2249 private static final String XML_ATTR_NAVIGATION = "nav";
2250 private static final String XML_ATTR_NAVIGATION_HIDDEN = "navHid";
2251 private static final String XML_ATTR_ORIENTATION = "ori";
Bryce Leec1f2f2a2017-06-22 15:29:42 -07002252 private static final String XML_ATTR_ROTATION = "rot";
Adam Lesinski7f61e962014-09-02 16:43:52 -07002253 private static final String XML_ATTR_SCREEN_LAYOUT = "scrLay";
Romain Guy48327452017-01-23 17:03:35 -08002254 private static final String XML_ATTR_COLOR_MODE = "clrMod";
Adam Lesinski7f61e962014-09-02 16:43:52 -07002255 private static final String XML_ATTR_UI_MODE = "ui";
2256 private static final String XML_ATTR_SCREEN_WIDTH = "width";
2257 private static final String XML_ATTR_SCREEN_HEIGHT = "height";
2258 private static final String XML_ATTR_SMALLEST_WIDTH = "sw";
2259 private static final String XML_ATTR_DENSITY = "density";
Bryce Lee7566d762017-03-30 09:34:15 -07002260 private static final String XML_ATTR_APP_BOUNDS = "app_bounds";
Adam Lesinski7f61e962014-09-02 16:43:52 -07002261
2262 /**
2263 * Reads the attributes corresponding to Configuration member fields from the Xml parser.
2264 * The parser is expected to be on a tag which has Configuration attributes.
2265 *
2266 * @param parser The Xml parser from which to read attributes.
2267 * @param configOut The Configuration to populate from the Xml attributes.
2268 * {@hide}
2269 */
2270 public static void readXmlAttrs(XmlPullParser parser, Configuration configOut)
2271 throws XmlPullParserException, IOException {
2272 configOut.fontScale = Float.intBitsToFloat(
2273 XmlUtils.readIntAttribute(parser, XML_ATTR_FONT_SCALE, 0));
2274 configOut.mcc = XmlUtils.readIntAttribute(parser, XML_ATTR_MCC, 0);
2275 configOut.mnc = XmlUtils.readIntAttribute(parser, XML_ATTR_MNC, 0);
2276
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002277 final String localesStr = XmlUtils.readStringAttribute(parser, XML_ATTR_LOCALES);
2278 configOut.mLocaleList = LocaleList.forLanguageTags(localesStr);
Roozbeh Pournaderfee44842016-02-04 15:24:24 -08002279 configOut.locale = configOut.mLocaleList.get(0);
Adam Lesinski7f61e962014-09-02 16:43:52 -07002280
2281 configOut.touchscreen = XmlUtils.readIntAttribute(parser, XML_ATTR_TOUCHSCREEN,
2282 TOUCHSCREEN_UNDEFINED);
2283 configOut.keyboard = XmlUtils.readIntAttribute(parser, XML_ATTR_KEYBOARD,
2284 KEYBOARD_UNDEFINED);
2285 configOut.keyboardHidden = XmlUtils.readIntAttribute(parser, XML_ATTR_KEYBOARD_HIDDEN,
2286 KEYBOARDHIDDEN_UNDEFINED);
2287 configOut.hardKeyboardHidden =
2288 XmlUtils.readIntAttribute(parser, XML_ATTR_HARD_KEYBOARD_HIDDEN,
2289 HARDKEYBOARDHIDDEN_UNDEFINED);
2290 configOut.navigation = XmlUtils.readIntAttribute(parser, XML_ATTR_NAVIGATION,
2291 NAVIGATION_UNDEFINED);
2292 configOut.navigationHidden = XmlUtils.readIntAttribute(parser, XML_ATTR_NAVIGATION_HIDDEN,
2293 NAVIGATIONHIDDEN_UNDEFINED);
2294 configOut.orientation = XmlUtils.readIntAttribute(parser, XML_ATTR_ORIENTATION,
2295 ORIENTATION_UNDEFINED);
2296 configOut.screenLayout = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_LAYOUT,
2297 SCREENLAYOUT_UNDEFINED);
Romain Guy48327452017-01-23 17:03:35 -08002298 configOut.colorMode = XmlUtils.readIntAttribute(parser, XML_ATTR_COLOR_MODE,
2299 COLOR_MODE_UNDEFINED);
Adam Lesinski7f61e962014-09-02 16:43:52 -07002300 configOut.uiMode = XmlUtils.readIntAttribute(parser, XML_ATTR_UI_MODE, 0);
2301 configOut.screenWidthDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_WIDTH,
2302 SCREEN_WIDTH_DP_UNDEFINED);
2303 configOut.screenHeightDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_HEIGHT,
2304 SCREEN_HEIGHT_DP_UNDEFINED);
2305 configOut.smallestScreenWidthDp =
2306 XmlUtils.readIntAttribute(parser, XML_ATTR_SMALLEST_WIDTH,
2307 SMALLEST_SCREEN_WIDTH_DP_UNDEFINED);
2308 configOut.densityDpi = XmlUtils.readIntAttribute(parser, XML_ATTR_DENSITY,
2309 DENSITY_DPI_UNDEFINED);
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01002310
Wale Ogunwale822e5122017-07-26 06:02:24 -07002311 // For persistence, we don't care about assetsSeq and WindowConfiguration, so do not read it
2312 // out.
Adam Lesinski7f61e962014-09-02 16:43:52 -07002313 }
2314
2315
2316 /**
2317 * Writes the Configuration's member fields as attributes into the XmlSerializer.
2318 * The serializer is expected to have already started a tag so that attributes can be
2319 * immediately written.
2320 *
2321 * @param xml The serializer to which to write the attributes.
2322 * @param config The Configuration whose member fields to write.
2323 * {@hide}
2324 */
2325 public static void writeXmlAttrs(XmlSerializer xml, Configuration config) throws IOException {
2326 XmlUtils.writeIntAttribute(xml, XML_ATTR_FONT_SCALE,
2327 Float.floatToIntBits(config.fontScale));
2328 if (config.mcc != 0) {
2329 XmlUtils.writeIntAttribute(xml, XML_ATTR_MCC, config.mcc);
2330 }
2331 if (config.mnc != 0) {
2332 XmlUtils.writeIntAttribute(xml, XML_ATTR_MNC, config.mnc);
2333 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002334 config.fixUpLocaleList();
2335 if (!config.mLocaleList.isEmpty()) {
2336 XmlUtils.writeStringAttribute(xml, XML_ATTR_LOCALES, config.mLocaleList.toLanguageTags());
Adam Lesinski7f61e962014-09-02 16:43:52 -07002337 }
2338 if (config.touchscreen != TOUCHSCREEN_UNDEFINED) {
2339 XmlUtils.writeIntAttribute(xml, XML_ATTR_TOUCHSCREEN, config.touchscreen);
2340 }
2341 if (config.keyboard != KEYBOARD_UNDEFINED) {
2342 XmlUtils.writeIntAttribute(xml, XML_ATTR_KEYBOARD, config.keyboard);
2343 }
2344 if (config.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED) {
2345 XmlUtils.writeIntAttribute(xml, XML_ATTR_KEYBOARD_HIDDEN, config.keyboardHidden);
2346 }
2347 if (config.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED) {
2348 XmlUtils.writeIntAttribute(xml, XML_ATTR_HARD_KEYBOARD_HIDDEN,
2349 config.hardKeyboardHidden);
2350 }
2351 if (config.navigation != NAVIGATION_UNDEFINED) {
2352 XmlUtils.writeIntAttribute(xml, XML_ATTR_NAVIGATION, config.navigation);
2353 }
2354 if (config.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED) {
2355 XmlUtils.writeIntAttribute(xml, XML_ATTR_NAVIGATION_HIDDEN, config.navigationHidden);
2356 }
2357 if (config.orientation != ORIENTATION_UNDEFINED) {
2358 XmlUtils.writeIntAttribute(xml, XML_ATTR_ORIENTATION, config.orientation);
2359 }
2360 if (config.screenLayout != SCREENLAYOUT_UNDEFINED) {
2361 XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_LAYOUT, config.screenLayout);
2362 }
Romain Guy48327452017-01-23 17:03:35 -08002363 if (config.colorMode != COLOR_MODE_UNDEFINED) {
2364 XmlUtils.writeIntAttribute(xml, XML_ATTR_COLOR_MODE, config.colorMode);
Romain Guyc9ba5592017-01-18 16:34:42 -08002365 }
Adam Lesinski7f61e962014-09-02 16:43:52 -07002366 if (config.uiMode != 0) {
2367 XmlUtils.writeIntAttribute(xml, XML_ATTR_UI_MODE, config.uiMode);
2368 }
2369 if (config.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
2370 XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_WIDTH, config.screenWidthDp);
2371 }
2372 if (config.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
2373 XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_HEIGHT, config.screenHeightDp);
2374 }
2375 if (config.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
2376 XmlUtils.writeIntAttribute(xml, XML_ATTR_SMALLEST_WIDTH, config.smallestScreenWidthDp);
2377 }
2378 if (config.densityDpi != DENSITY_DPI_UNDEFINED) {
2379 XmlUtils.writeIntAttribute(xml, XML_ATTR_DENSITY, config.densityDpi);
2380 }
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01002381
Wale Ogunwale822e5122017-07-26 06:02:24 -07002382 // For persistence, we do not care about assetsSeq and window configuration, so do not write
2383 // it out.
Adam Lesinski7f61e962014-09-02 16:43:52 -07002384 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002385}