blob: f7cccd56f07951def7fedc26196a851a4fef2761 [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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import android.content.pm.ActivityInfo;
Alan Viveretteac85f902016-03-11 15:15:51 -050023import android.content.pm.ActivityInfo.Config;
Romain Guye89d0bb2017-06-20 12:23:42 -070024import android.graphics.Rect;
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;
Romain Guye89d0bb2017-06-20 12:23:42 -070030import android.view.DisplayInfo;
Fabrice Di Meglio3fb824b2012-02-28 17:58:31 -080031import android.view.View;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032
Romain Guye89d0bb2017-06-20 12:23:42 -070033import com.android.internal.util.XmlUtils;
34
35import org.xmlpull.v1.XmlPullParser;
36import org.xmlpull.v1.XmlPullParserException;
37import org.xmlpull.v1.XmlSerializer;
38
Adam Lesinski7f61e962014-09-02 16:43:52 -070039import java.io.IOException;
Alan Viveretteac85f902016-03-11 15:15:51 -050040import java.lang.annotation.Retention;
41import java.lang.annotation.RetentionPolicy;
Adam Lesinski2c749d22014-06-04 13:00:29 -070042import java.util.ArrayList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import java.util.Locale;
44
Bryce Leec1f2f2a2017-06-22 15:29:42 -070045
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046/**
47 * This class describes all device configuration information that can
48 * impact the resources the application retrieves. This includes both
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -070049 * user-specified configuration options (locale list and scaling) as well
Scott Main63848e32011-04-20 22:20:46 -070050 * as device configurations (such as input modes, screen size and screen orientation).
51 * <p>You can acquire this object from {@link Resources}, using {@link
52 * Resources#getConfiguration}. Thus, from an activity, you can get it by chaining the request
53 * with {@link android.app.Activity#getResources}:</p>
54 * <pre>Configuration config = getResources().getConfiguration();</pre>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055 */
56public final class Configuration implements Parcelable, Comparable<Configuration> {
Dianne Hackborn756220b2012-08-14 16:45:30 -070057 /** @hide */
58 public static final Configuration EMPTY = new Configuration();
59
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060 /**
61 * Current user preference for the scaling factor for fonts, relative
62 * to the base density scaling.
63 */
64 public float fontScale;
65
66 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -070067 * IMSI MCC (Mobile Country Code), corresponding to
68 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#MccQualifier">mcc</a>
69 * resource qualifier. 0 if undefined.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070 */
71 public int mcc;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -070072
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -070074 * IMSI MNC (Mobile Network Code), corresponding to
75 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#MccQualifier">mnc</a>
Mattias Petersson1d766b52011-10-07 09:33:52 +020076 * resource qualifier. 0 if undefined. Note that the actual MNC may be 0; in order to check
77 * for this use the {@link #MNC_ZERO} symbol.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078 */
79 public int mnc;
Mattias Petersson1d766b52011-10-07 09:33:52 +020080
81 /**
82 * Constant used to to represent MNC (Mobile Network Code) zero.
83 * 0 cannot be used, since it is used to represent an undefined MNC.
84 */
85 public static final int MNC_ZERO = 0xffff;
86
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -070088 * Current user preference for the locale, corresponding to
89 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#LocaleQualifier">locale</a>
90 * resource qualifier.
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -070091 *
92 * @deprecated Do not set or read this directly. Use {@link #getLocales()} and
Raph Levienb1638702016-04-27 11:02:12 -070093 * {@link #setLocales(LocaleList)}. If only the primary locale is needed,
94 * <code>getLocales().get(0)</code> is now the preferred accessor.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095 */
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -070096 @Deprecated public Locale locale;
97
98 private LocaleList mLocaleList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099
100 /**
Andy Stadlerf8a7cea2009-04-10 16:24:47 -0700101 * Locale should persist on setting. This is hidden because it is really
102 * questionable whether this is the right way to expose the functionality.
103 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104 */
105 public boolean userSetLocale;
106
Romain Guyc9ba5592017-01-18 16:34:42 -0800107
Romain Guy48327452017-01-23 17:03:35 -0800108 /** Constant for {@link #colorMode}: bits that encode whether the screen is wide gamut. */
109 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_MASK = 0x3;
Romain Guyc9ba5592017-01-18 16:34:42 -0800110 /**
Romain Guy48327452017-01-23 17:03:35 -0800111 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800112 * indicating that it is unknown whether or not the screen is wide gamut.
113 */
Romain Guy48327452017-01-23 17:03:35 -0800114 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED = 0x0;
Romain Guyc9ba5592017-01-18 16:34:42 -0800115 /**
Romain Guy48327452017-01-23 17:03:35 -0800116 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800117 * indicating that the screen is not wide gamut.
118 * <p>Corresponds to the <code>-nowidecg</code> resource qualifier.</p>
119 */
Romain Guy48327452017-01-23 17:03:35 -0800120 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_NO = 0x1;
Romain Guyc9ba5592017-01-18 16:34:42 -0800121 /**
Romain Guy48327452017-01-23 17:03:35 -0800122 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800123 * indicating that the screen is wide gamut.
124 * <p>Corresponds to the <code>-widecg</code> resource qualifier.</p>
125 */
Romain Guy48327452017-01-23 17:03:35 -0800126 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_YES = 0x2;
Romain Guyc9ba5592017-01-18 16:34:42 -0800127
Romain Guyb3f69262017-04-13 20:06:41 -0700128 /** Constant for {@link #colorMode}: bits that encode the dynamic range of the screen. */
Romain Guy48327452017-01-23 17:03:35 -0800129 public static final int COLOR_MODE_HDR_MASK = 0xc;
130 /** Constant for {@link #colorMode}: bits shift to get the screen dynamic range. */
131 public static final int COLOR_MODE_HDR_SHIFT = 2;
Romain Guyc9ba5592017-01-18 16:34:42 -0800132 /**
Romain Guy48327452017-01-23 17:03:35 -0800133 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_HDR_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800134 * indicating that it is unknown whether or not the screen is HDR.
135 */
Romain Guy48327452017-01-23 17:03:35 -0800136 public static final int COLOR_MODE_HDR_UNDEFINED = 0x0;
Romain Guyc9ba5592017-01-18 16:34:42 -0800137 /**
Romain Guy48327452017-01-23 17:03:35 -0800138 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_HDR_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800139 * indicating that the screen is not HDR (low/standard dynamic range).
140 * <p>Corresponds to the <code>-lowdr</code> resource qualifier.</p>
141 */
Romain Guy48327452017-01-23 17:03:35 -0800142 public static final int COLOR_MODE_HDR_NO = 0x1 << COLOR_MODE_HDR_SHIFT;
Romain Guyc9ba5592017-01-18 16:34:42 -0800143 /**
Romain Guy48327452017-01-23 17:03:35 -0800144 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_HDR_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800145 * indicating that the screen is HDR (dynamic range).
146 * <p>Corresponds to the <code>-highdr</code> resource qualifier.</p>
147 */
Romain Guy48327452017-01-23 17:03:35 -0800148 public static final int COLOR_MODE_HDR_YES = 0x2 << COLOR_MODE_HDR_SHIFT;
Romain Guyc9ba5592017-01-18 16:34:42 -0800149
Romain Guy48327452017-01-23 17:03:35 -0800150 /** Constant for {@link #colorMode}: a value indicating that the color mode is undefined */
Romain Guyc9ba5592017-01-18 16:34:42 -0800151 @SuppressWarnings("PointlessBitwiseExpression")
Romain Guy48327452017-01-23 17:03:35 -0800152 public static final int COLOR_MODE_UNDEFINED = COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED |
153 COLOR_MODE_HDR_UNDEFINED;
Romain Guyc9ba5592017-01-18 16:34:42 -0800154
155 /**
Romain Guyb3f69262017-04-13 20:06:41 -0700156 * Bit mask of color capabilities of the screen. Currently there are two fields:
Romain Guy48327452017-01-23 17:03:35 -0800157 * <p>The {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} bits define the color gamut of
Romain Guyc9ba5592017-01-18 16:34:42 -0800158 * the screen. They may be one of
Romain Guy48327452017-01-23 17:03:35 -0800159 * {@link #COLOR_MODE_WIDE_COLOR_GAMUT_NO} or {@link #COLOR_MODE_WIDE_COLOR_GAMUT_YES}.</p>
Romain Guyc9ba5592017-01-18 16:34:42 -0800160 *
Romain Guy48327452017-01-23 17:03:35 -0800161 * <p>The {@link #COLOR_MODE_HDR_MASK} defines the dynamic range of the screen. They may be
162 * one of {@link #COLOR_MODE_HDR_NO} or {@link #COLOR_MODE_HDR_YES}.</p>
Romain Guyc9ba5592017-01-18 16:34:42 -0800163 *
164 * <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
165 * Multiple Screens</a> for more information.</p>
166 */
Romain Guy48327452017-01-23 17:03:35 -0800167 public int colorMode;
Romain Guyc9ba5592017-01-18 16:34:42 -0800168
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700169 /** Constant for {@link #screenLayout}: bits that encode the size. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700170 public static final int SCREENLAYOUT_SIZE_MASK = 0x0f;
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700171 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
172 * value indicating that no size has been set. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700173 public static final int SCREENLAYOUT_SIZE_UNDEFINED = 0x00;
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700174 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700175 * value indicating the screen is at least approximately 320x426 dp units,
176 * corresponds to the
177 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">small</a>
178 * resource qualifier.
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700179 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
180 * Multiple Screens</a> for more information. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700181 public static final int SCREENLAYOUT_SIZE_SMALL = 0x01;
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700182 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700183 * value indicating the screen is at least approximately 320x470 dp units,
184 * corresponds to the
185 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">normal</a>
186 * resource qualifier.
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700187 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
188 * Multiple Screens</a> for more information. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700189 public static final int SCREENLAYOUT_SIZE_NORMAL = 0x02;
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700190 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700191 * value indicating the screen is at least approximately 480x640 dp units,
192 * corresponds to the
193 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">large</a>
194 * resource qualifier.
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700195 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
196 * Multiple Screens</a> for more information. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700197 public static final int SCREENLAYOUT_SIZE_LARGE = 0x03;
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700198 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700199 * value indicating the screen is at least approximately 720x960 dp units,
200 * corresponds to the
201 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">xlarge</a>
202 * resource qualifier.
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700203 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
204 * Multiple Screens</a> for more information.*/
Dianne Hackborn14cee9f2010-04-23 17:51:26 -0700205 public static final int SCREENLAYOUT_SIZE_XLARGE = 0x04;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700206
207 /** Constant for {@link #screenLayout}: bits that encode the aspect ratio. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700208 public static final int SCREENLAYOUT_LONG_MASK = 0x30;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700209 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
210 * value indicating that no size has been set. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700211 public static final int SCREENLAYOUT_LONG_UNDEFINED = 0x00;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700212 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
213 * value that corresponds to the
214 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenAspectQualifier">notlong</a>
215 * resource qualifier. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700216 public static final int SCREENLAYOUT_LONG_NO = 0x10;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700217 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
218 * value that corresponds to the
219 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenAspectQualifier">long</a>
220 * resource qualifier. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700221 public static final int SCREENLAYOUT_LONG_YES = 0x20;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700222
223 /** Constant for {@link #screenLayout}: bits that encode the layout direction. */
224 public static final int SCREENLAYOUT_LAYOUTDIR_MASK = 0xC0;
225 /** Constant for {@link #screenLayout}: bits shift to get the layout direction. */
226 public static final int SCREENLAYOUT_LAYOUTDIR_SHIFT = 6;
227 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
228 * value indicating that no layout dir has been set. */
229 public static final int SCREENLAYOUT_LAYOUTDIR_UNDEFINED = 0x00;
230 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
231 * value indicating that a layout dir has been set to LTR. */
232 public static final int SCREENLAYOUT_LAYOUTDIR_LTR = 0x01 << SCREENLAYOUT_LAYOUTDIR_SHIFT;
233 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
234 * value indicating that a layout dir has been set to RTL. */
235 public static final int SCREENLAYOUT_LAYOUTDIR_RTL = 0x02 << SCREENLAYOUT_LAYOUTDIR_SHIFT;
236
Adam Powell49e7ff92015-05-14 16:18:53 -0700237 /** Constant for {@link #screenLayout}: bits that encode roundness of the screen. */
238 public static final int SCREENLAYOUT_ROUND_MASK = 0x300;
239 /** @hide Constant for {@link #screenLayout}: bit shift to get to screen roundness bits */
240 public static final int SCREENLAYOUT_ROUND_SHIFT = 8;
241 /**
242 * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating
243 * that it is unknown whether or not the screen has a round shape.
244 */
245 public static final int SCREENLAYOUT_ROUND_UNDEFINED = 0x00;
246 /**
247 * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating
248 * that the screen does not have a rounded shape.
249 */
250 public static final int SCREENLAYOUT_ROUND_NO = 0x1 << SCREENLAYOUT_ROUND_SHIFT;
251 /**
252 * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating
253 * that the screen has a rounded shape. Corners may not be visible to the user;
254 * developers should pay special attention to the {@link android.view.WindowInsets} delivered
255 * to views for more information about ensuring content is not obscured.
256 *
257 * <p>Corresponds to the <code>-round</code> resource qualifier.</p>
258 */
259 public static final int SCREENLAYOUT_ROUND_YES = 0x2 << SCREENLAYOUT_ROUND_SHIFT;
260
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700261 /** Constant for {@link #screenLayout}: a value indicating that screenLayout is undefined */
262 public static final int SCREENLAYOUT_UNDEFINED = SCREENLAYOUT_SIZE_UNDEFINED |
Adam Powell49e7ff92015-05-14 16:18:53 -0700263 SCREENLAYOUT_LONG_UNDEFINED | SCREENLAYOUT_LAYOUTDIR_UNDEFINED |
264 SCREENLAYOUT_ROUND_UNDEFINED;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700265
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700266 /**
267 * Special flag we generate to indicate that the screen layout requires
268 * us to use a compatibility mode for apps that are not modern layout
269 * aware.
270 * @hide
271 */
272 public static final int SCREENLAYOUT_COMPAT_NEEDED = 0x10000000;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700273
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700274 /**
Andrii Kulianf12fce12016-05-27 17:30:16 -0700275 * Bit mask of overall layout of the screen. Currently there are four
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700276 * fields:
277 * <p>The {@link #SCREENLAYOUT_SIZE_MASK} bits define the overall size
278 * of the screen. They may be one of
279 * {@link #SCREENLAYOUT_SIZE_SMALL}, {@link #SCREENLAYOUT_SIZE_NORMAL},
Adam Powell49e7ff92015-05-14 16:18:53 -0700280 * {@link #SCREENLAYOUT_SIZE_LARGE}, or {@link #SCREENLAYOUT_SIZE_XLARGE}.</p>
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700281 *
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700282 * <p>The {@link #SCREENLAYOUT_LONG_MASK} defines whether the screen
283 * is wider/taller than normal. They may be one of
Adam Powell49e7ff92015-05-14 16:18:53 -0700284 * {@link #SCREENLAYOUT_LONG_NO} or {@link #SCREENLAYOUT_LONG_YES}.</p>
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700285 *
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700286 * <p>The {@link #SCREENLAYOUT_LAYOUTDIR_MASK} defines whether the screen layout
287 * is either LTR or RTL. They may be one of
Adam Powell49e7ff92015-05-14 16:18:53 -0700288 * {@link #SCREENLAYOUT_LAYOUTDIR_LTR} or {@link #SCREENLAYOUT_LAYOUTDIR_RTL}.</p>
289 *
290 * <p>The {@link #SCREENLAYOUT_ROUND_MASK} defines whether the screen has a rounded
291 * shape. They may be one of {@link #SCREENLAYOUT_ROUND_NO} or {@link #SCREENLAYOUT_ROUND_YES}.
292 * </p>
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700293 *
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700294 * <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
Adam Powell49e7ff92015-05-14 16:18:53 -0700295 * Multiple Screens</a> for more information.</p>
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700296 */
297 public int screenLayout;
Dianne Hackbornfe37f8f2012-09-30 12:24:33 -0700298
Bryce Lee7566d762017-03-30 09:34:15 -0700299 /**
300 * @hide
301 * {@link android.graphics.Rect} defining app bounds. The dimensions override usages of
302 * {@link DisplayInfo#appHeight} and {@link DisplayInfo#appWidth} and mirrors these values at
303 * the display level. Lower levels can override these values to provide custom bounds to enforce
304 * features such as a max aspect ratio.
305 * TODO(b/36812336): Move appBounds out of {@link Configuration}.
306 */
307 public Rect appBounds;
308
Dianne Hackbornfe37f8f2012-09-30 12:24:33 -0700309 /** @hide */
310 static public int resetScreenLayout(int curLayout) {
311 return (curLayout&~(SCREENLAYOUT_LONG_MASK | SCREENLAYOUT_SIZE_MASK
312 | SCREENLAYOUT_COMPAT_NEEDED))
313 | (SCREENLAYOUT_LONG_YES | SCREENLAYOUT_SIZE_XLARGE);
314 }
315
316 /** @hide */
317 static public int reduceScreenLayout(int curLayout, int longSizeDp, int shortSizeDp) {
318 int screenLayoutSize;
319 boolean screenLayoutLong;
320 boolean screenLayoutCompatNeeded;
321
322 // These semi-magic numbers define our compatibility modes for
323 // applications with different screens. These are guarantees to
324 // app developers about the space they can expect for a particular
325 // configuration. DO NOT CHANGE!
326 if (longSizeDp < 470) {
327 // This is shorter than an HVGA normal density screen (which
328 // is 480 pixels on its long side).
329 screenLayoutSize = SCREENLAYOUT_SIZE_SMALL;
330 screenLayoutLong = false;
331 screenLayoutCompatNeeded = false;
332 } else {
333 // What size is this screen screen?
334 if (longSizeDp >= 960 && shortSizeDp >= 720) {
335 // 1.5xVGA or larger screens at medium density are the point
336 // at which we consider it to be an extra large screen.
337 screenLayoutSize = SCREENLAYOUT_SIZE_XLARGE;
338 } else if (longSizeDp >= 640 && shortSizeDp >= 480) {
339 // VGA or larger screens at medium density are the point
340 // at which we consider it to be a large screen.
341 screenLayoutSize = SCREENLAYOUT_SIZE_LARGE;
342 } else {
343 screenLayoutSize = SCREENLAYOUT_SIZE_NORMAL;
344 }
345
346 // If this screen is wider than normal HVGA, or taller
347 // than FWVGA, then for old apps we want to run in size
348 // compatibility mode.
349 if (shortSizeDp > 321 || longSizeDp > 570) {
350 screenLayoutCompatNeeded = true;
351 } else {
352 screenLayoutCompatNeeded = false;
353 }
354
355 // Is this a long screen?
356 if (((longSizeDp*3)/5) >= (shortSizeDp-1)) {
357 // Anything wider than WVGA (5:3) is considering to be long.
358 screenLayoutLong = true;
359 } else {
360 screenLayoutLong = false;
361 }
362 }
363
364 // Now reduce the last screenLayout to not be better than what we
365 // have found.
366 if (!screenLayoutLong) {
367 curLayout = (curLayout&~SCREENLAYOUT_LONG_MASK) | SCREENLAYOUT_LONG_NO;
368 }
369 if (screenLayoutCompatNeeded) {
370 curLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
371 }
372 int curSize = curLayout&SCREENLAYOUT_SIZE_MASK;
373 if (screenLayoutSize < curSize) {
374 curLayout = (curLayout&~SCREENLAYOUT_SIZE_MASK) | screenLayoutSize;
375 }
376 return curLayout;
377 }
378
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700379 /** @hide */
380 public static String configurationDiffToString(int diff) {
381 ArrayList<String> list = new ArrayList<>();
382 if ((diff & ActivityInfo.CONFIG_MCC) != 0) {
383 list.add("CONFIG_MCC");
384 }
385 if ((diff & ActivityInfo.CONFIG_MNC) != 0) {
386 list.add("CONFIG_MNC");
387 }
388 if ((diff & ActivityInfo.CONFIG_LOCALE) != 0) {
389 list.add("CONFIG_LOCALE");
390 }
391 if ((diff & ActivityInfo.CONFIG_TOUCHSCREEN) != 0) {
392 list.add("CONFIG_TOUCHSCREEN");
393 }
394 if ((diff & ActivityInfo.CONFIG_KEYBOARD) != 0) {
395 list.add("CONFIG_KEYBOARD");
396 }
397 if ((diff & ActivityInfo.CONFIG_KEYBOARD_HIDDEN) != 0) {
398 list.add("CONFIG_KEYBOARD_HIDDEN");
399 }
400 if ((diff & ActivityInfo.CONFIG_NAVIGATION) != 0) {
401 list.add("CONFIG_NAVIGATION");
402 }
403 if ((diff & ActivityInfo.CONFIG_ORIENTATION) != 0) {
404 list.add("CONFIG_ORIENTATION");
405 }
406 if ((diff & ActivityInfo.CONFIG_SCREEN_LAYOUT) != 0) {
407 list.add("CONFIG_SCREEN_LAYOUT");
408 }
Romain Guy48327452017-01-23 17:03:35 -0800409 if ((diff & ActivityInfo.CONFIG_COLOR_MODE) != 0) {
410 list.add("CONFIG_COLOR_MODE");
Romain Guyc9ba5592017-01-18 16:34:42 -0800411 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700412 if ((diff & ActivityInfo.CONFIG_UI_MODE) != 0) {
413 list.add("CONFIG_UI_MODE");
414 }
415 if ((diff & ActivityInfo.CONFIG_SCREEN_SIZE) != 0) {
416 list.add("CONFIG_SCREEN_SIZE");
417 }
418 if ((diff & ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE) != 0) {
419 list.add("CONFIG_SMALLEST_SCREEN_SIZE");
420 }
421 if ((diff & ActivityInfo.CONFIG_LAYOUT_DIRECTION) != 0) {
422 list.add("CONFIG_LAYOUT_DIRECTION");
423 }
424 if ((diff & ActivityInfo.CONFIG_FONT_SCALE) != 0) {
425 list.add("CONFIG_FONT_SCALE");
426 }
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +0100427 if ((diff & ActivityInfo.CONFIG_ASSETS_PATHS) != 0) {
428 list.add("CONFIG_ASSETS_PATHS");
429 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700430 StringBuilder builder = new StringBuilder("{");
431 for (int i = 0, n = list.size(); i < n; i++) {
432 builder.append(list.get(i));
433 if (i != n - 1) {
434 builder.append(", ");
435 }
436 }
437 builder.append("}");
438 return builder.toString();
439 }
440
Dianne Hackborn711e62a2010-11-29 16:38:22 -0800441 /**
442 * Check if the Configuration's current {@link #screenLayout} is at
443 * least the given size.
444 *
445 * @param size The desired size, either {@link #SCREENLAYOUT_SIZE_SMALL},
446 * {@link #SCREENLAYOUT_SIZE_NORMAL}, {@link #SCREENLAYOUT_SIZE_LARGE}, or
447 * {@link #SCREENLAYOUT_SIZE_XLARGE}.
448 * @return Returns true if the current screen layout size is at least
449 * the given size.
450 */
451 public boolean isLayoutSizeAtLeast(int size) {
452 int cur = screenLayout&SCREENLAYOUT_SIZE_MASK;
453 if (cur == SCREENLAYOUT_SIZE_UNDEFINED) return false;
Dianne Hackborn7d3a5bc2010-11-29 22:52:12 -0800454 return cur >= size;
Dianne Hackborn711e62a2010-11-29 16:38:22 -0800455 }
456
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700457 /** Constant for {@link #touchscreen}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 public static final int TOUCHSCREEN_UNDEFINED = 0;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700459 /** Constant for {@link #touchscreen}, value corresponding to the
460 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#TouchscreenQualifier">notouch</a>
461 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800462 public static final int TOUCHSCREEN_NOTOUCH = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700463 /** @deprecated Not currently supported or used. */
464 @Deprecated public static final int TOUCHSCREEN_STYLUS = 2;
465 /** Constant for {@link #touchscreen}, value corresponding to the
466 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#TouchscreenQualifier">finger</a>
467 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800468 public static final int TOUCHSCREEN_FINGER = 3;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700469
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800470 /**
471 * The kind of touch screen attached to the device.
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700472 * One of: {@link #TOUCHSCREEN_NOTOUCH}, {@link #TOUCHSCREEN_FINGER}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800473 */
474 public int touchscreen;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700475
476 /** Constant for {@link #keyboard}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800477 public static final int KEYBOARD_UNDEFINED = 0;
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">nokeys</a>
480 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 public static final int KEYBOARD_NOKEYS = 1;
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">qwerty</a>
484 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800485 public static final int KEYBOARD_QWERTY = 2;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700486 /** Constant for {@link #keyboard}, value corresponding to the
487 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">12key</a>
488 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800489 public static final int KEYBOARD_12KEY = 3;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700490
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800491 /**
492 * The kind of keyboard attached to the device.
Kenny Root507f8ed2009-06-09 11:21:11 -0500493 * One of: {@link #KEYBOARD_NOKEYS}, {@link #KEYBOARD_QWERTY},
494 * {@link #KEYBOARD_12KEY}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495 */
496 public int keyboard;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700497
498 /** Constant for {@link #keyboardHidden}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800499 public static final int KEYBOARDHIDDEN_UNDEFINED = 0;
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">keysexposed</a>
502 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 public static final int KEYBOARDHIDDEN_NO = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700504 /** Constant for {@link #keyboardHidden}, value corresponding to the
505 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keyshidden</a>
506 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800507 public static final int KEYBOARDHIDDEN_YES = 2;
508 /** Constant matching actual resource implementation. {@hide} */
509 public static final int KEYBOARDHIDDEN_SOFT = 3;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700510
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800511 /**
512 * A flag indicating whether any keyboard is available. Unlike
513 * {@link #hardKeyboardHidden}, this also takes into account a soft
514 * keyboard, so if the hard keyboard is hidden but there is soft
515 * keyboard available, it will be set to NO. Value is one of:
516 * {@link #KEYBOARDHIDDEN_NO}, {@link #KEYBOARDHIDDEN_YES}.
517 */
518 public int keyboardHidden;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700519
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700520 /** Constant for {@link #hardKeyboardHidden}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800521 public static final int HARDKEYBOARDHIDDEN_UNDEFINED = 0;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700522 /** Constant for {@link #hardKeyboardHidden}, value corresponding to the
523 * physical keyboard being exposed. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800524 public static final int HARDKEYBOARDHIDDEN_NO = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700525 /** Constant for {@link #hardKeyboardHidden}, value corresponding to the
526 * physical keyboard being hidden. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800527 public static final int HARDKEYBOARDHIDDEN_YES = 2;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700528
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800529 /**
530 * A flag indicating whether the hard keyboard has been hidden. This will
531 * be set on a device with a mechanism to hide the keyboard from the
532 * user, when that mechanism is closed. One of:
533 * {@link #HARDKEYBOARDHIDDEN_NO}, {@link #HARDKEYBOARDHIDDEN_YES}.
534 */
535 public int hardKeyboardHidden;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700536
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700537 /** Constant for {@link #navigation}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800538 public static final int NAVIGATION_UNDEFINED = 0;
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">nonav</a>
541 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800542 public static final int NAVIGATION_NONAV = 1;
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">dpad</a>
545 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546 public static final int NAVIGATION_DPAD = 2;
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">trackball</a>
549 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550 public static final int NAVIGATION_TRACKBALL = 3;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700551 /** Constant for {@link #navigation}, value corresponding to the
552 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">wheel</a>
553 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800554 public static final int NAVIGATION_WHEEL = 4;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 /**
557 * The kind of navigation method available on the device.
Kenny Root507f8ed2009-06-09 11:21:11 -0500558 * One of: {@link #NAVIGATION_NONAV}, {@link #NAVIGATION_DPAD},
559 * {@link #NAVIGATION_TRACKBALL}, {@link #NAVIGATION_WHEEL}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800560 */
561 public int navigation;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700562
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700563 /** Constant for {@link #navigationHidden}: a value indicating that no value has been set. */
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700564 public static final int NAVIGATIONHIDDEN_UNDEFINED = 0;
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">navexposed</a>
567 * resource qualifier. */
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700568 public static final int NAVIGATIONHIDDEN_NO = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700569 /** Constant for {@link #navigationHidden}, value corresponding to the
570 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavAvailQualifier">navhidden</a>
571 * resource qualifier. */
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700572 public static final int NAVIGATIONHIDDEN_YES = 2;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700573
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700574 /**
575 * A flag indicating whether any 5-way or DPAD navigation available.
576 * This will be set on a device with a mechanism to hide the navigation
577 * controls from the user, when that mechanism is closed. One of:
578 * {@link #NAVIGATIONHIDDEN_NO}, {@link #NAVIGATIONHIDDEN_YES}.
579 */
580 public int navigationHidden;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700581
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700582 /** Constant for {@link #orientation}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800583 public static final int ORIENTATION_UNDEFINED = 0;
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">port</a>
586 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800587 public static final int ORIENTATION_PORTRAIT = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700588 /** Constant for {@link #orientation}, value corresponding to the
589 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#OrientationQualifier">land</a>
590 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800591 public static final int ORIENTATION_LANDSCAPE = 2;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700592 /** @deprecated Not currently supported or used. */
593 @Deprecated public static final int ORIENTATION_SQUARE = 3;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595 /**
596 * Overall orientation of the screen. May be one of
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700597 * {@link #ORIENTATION_LANDSCAPE}, {@link #ORIENTATION_PORTRAIT}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800598 */
599 public int orientation;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100600
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700601 /** Constant for {@link #uiMode}: bits that encode the mode type. */
Tobias Haamel27b28b32010-02-09 23:09:17 +0100602 public static final int UI_MODE_TYPE_MASK = 0x0f;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700603 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
604 * value indicating that no mode type has been set. */
Dianne Hackbornef05e072010-03-01 17:43:39 -0800605 public static final int UI_MODE_TYPE_UNDEFINED = 0x00;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700606 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
607 * value that corresponds to
608 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">no
609 * UI mode</a> resource qualifier specified. */
Dianne Hackbornef05e072010-03-01 17:43:39 -0800610 public static final int UI_MODE_TYPE_NORMAL = 0x01;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700611 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
612 * value that corresponds to the
613 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">desk</a>
614 * resource qualifier. */
Dianne Hackborn7299c412010-03-04 18:41:49 -0800615 public static final int UI_MODE_TYPE_DESK = 0x02;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700616 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
617 * value that corresponds to the
618 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">car</a>
619 * resource qualifier. */
Dianne Hackborn7299c412010-03-04 18:41:49 -0800620 public static final int UI_MODE_TYPE_CAR = 0x03;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700621 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
622 * value that corresponds to the
623 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">television</a>
624 * resource qualifier. */
Dianne Hackborne360bb62011-05-20 16:11:04 -0700625 public static final int UI_MODE_TYPE_TELEVISION = 0x04;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700626 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
627 * value that corresponds to the
628 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">appliance</a>
629 * resource qualifier. */
Joe Onorato44fcb832011-12-14 20:59:30 -0800630 public static final int UI_MODE_TYPE_APPLIANCE = 0x05;
John Spurlock6c191292014-04-03 16:37:27 -0400631 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
632 * value that corresponds to the
633 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">watch</a>
634 * resource qualifier. */
635 public static final int UI_MODE_TYPE_WATCH = 0x06;
Zak Cohen1a6acdb2016-12-12 15:21:21 -0800636 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
637 * value that corresponds to the
638 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">vrheadset</a>
639 * resource qualifier. */
640 public static final int UI_MODE_TYPE_VR_HEADSET = 0x07;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100641
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700642 /** Constant for {@link #uiMode}: bits that encode the night mode. */
Tobias Haamel27b28b32010-02-09 23:09:17 +0100643 public static final int UI_MODE_NIGHT_MASK = 0x30;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700644 /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
645 * value indicating that no mode type has been set. */
Tobias Haamel27b28b32010-02-09 23:09:17 +0100646 public static final int UI_MODE_NIGHT_UNDEFINED = 0x00;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700647 /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
648 * value that corresponds to the
649 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NightQualifier">notnight</a>
650 * resource qualifier. */
Tobias Haamel27b28b32010-02-09 23:09:17 +0100651 public static final int UI_MODE_NIGHT_NO = 0x10;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700652 /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
653 * value that corresponds to the
654 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NightQualifier">night</a>
655 * resource qualifier. */
Tobias Haamel27b28b32010-02-09 23:09:17 +0100656 public static final int UI_MODE_NIGHT_YES = 0x20;
657
658 /**
659 * Bit mask of the ui mode. Currently there are two fields:
660 * <p>The {@link #UI_MODE_TYPE_MASK} bits define the overall ui mode of the
Dianne Hackborn7299c412010-03-04 18:41:49 -0800661 * device. They may be one of {@link #UI_MODE_TYPE_UNDEFINED},
662 * {@link #UI_MODE_TYPE_NORMAL}, {@link #UI_MODE_TYPE_DESK},
John Spurlock6c191292014-04-03 16:37:27 -0400663 * {@link #UI_MODE_TYPE_CAR}, {@link #UI_MODE_TYPE_TELEVISION},
Zak Cohen1a6acdb2016-12-12 15:21:21 -0800664 * {@link #UI_MODE_TYPE_APPLIANCE}, {@link #UI_MODE_TYPE_WATCH},
665 * or {@link #UI_MODE_TYPE_VR_HEADSET}.
Tobias Haamel27b28b32010-02-09 23:09:17 +0100666 *
667 * <p>The {@link #UI_MODE_NIGHT_MASK} defines whether the screen
Dianne Hackborn7299c412010-03-04 18:41:49 -0800668 * is in a special mode. They may be one of {@link #UI_MODE_NIGHT_UNDEFINED},
Tobias Haamel27b28b32010-02-09 23:09:17 +0100669 * {@link #UI_MODE_NIGHT_NO} or {@link #UI_MODE_NIGHT_YES}.
Tobias Haamel27b28b32010-02-09 23:09:17 +0100670 */
671 public int uiMode;
672
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700673 /**
674 * Default value for {@link #screenWidthDp} indicating that no width
675 * has been specified.
676 */
Dianne Hackbornebff8f92011-05-12 18:07:47 -0700677 public static final int SCREEN_WIDTH_DP_UNDEFINED = 0;
678
679 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700680 * The current width of the available screen space, in dp units,
681 * corresponding to
682 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenWidthQualifier">screen
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700683 * width</a> resource qualifier. Set to
684 * {@link #SCREEN_WIDTH_DP_UNDEFINED} if no width is specified.
Dianne Hackbornebff8f92011-05-12 18:07:47 -0700685 */
686 public int screenWidthDp;
687
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700688 /**
689 * Default value for {@link #screenHeightDp} indicating that no width
690 * has been specified.
691 */
Dianne Hackbornebff8f92011-05-12 18:07:47 -0700692 public static final int SCREEN_HEIGHT_DP_UNDEFINED = 0;
693
694 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700695 * The current height of the available screen space, in dp units,
696 * corresponding to
697 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenHeightQualifier">screen
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700698 * height</a> resource qualifier. Set to
699 * {@link #SCREEN_HEIGHT_DP_UNDEFINED} if no height is specified.
Dianne Hackbornebff8f92011-05-12 18:07:47 -0700700 */
701 public int screenHeightDp;
702
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700703 /**
704 * Default value for {@link #smallestScreenWidthDp} indicating that no width
705 * has been specified.
706 */
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700707 public static final int SMALLEST_SCREEN_WIDTH_DP_UNDEFINED = 0;
708
709 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700710 * The smallest screen size an application will see in normal operation,
711 * corresponding to
712 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#SmallestScreenWidthQualifier">smallest
713 * screen width</a> resource qualifier.
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700714 * This is the smallest value of both screenWidthDp and screenHeightDp
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700715 * in both portrait and landscape. Set to
716 * {@link #SMALLEST_SCREEN_WIDTH_DP_UNDEFINED} if no width is specified.
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700717 */
718 public int smallestScreenWidthDp;
719
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700720 /**
721 * Default value for {@link #densityDpi} indicating that no width
722 * has been specified.
723 */
724 public static final int DENSITY_DPI_UNDEFINED = 0;
725
726 /**
Adam Lesinski31245b42014-08-22 19:10:56 -0700727 * Value for {@link #densityDpi} for resources that scale to any density (vector drawables).
728 * {@hide}
729 */
730 public static final int DENSITY_DPI_ANY = 0xfffe;
731
732 /**
733 * Value for {@link #densityDpi} for resources that are not meant to be scaled.
734 * {@hide}
735 */
736 public static final int DENSITY_DPI_NONE = 0xffff;
737
738 /**
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700739 * The target screen density being rendered to,
740 * corresponding to
741 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#DensityQualifier">density</a>
742 * resource qualifier. Set to
743 * {@link #DENSITY_DPI_UNDEFINED} if no density is specified.
744 */
745 public int densityDpi;
746
Dianne Hackborn5fd21692011-06-07 14:09:47 -0700747 /** @hide Hack to get this information from WM to app running in compat mode. */
748 public int compatScreenWidthDp;
749 /** @hide Hack to get this information from WM to app running in compat mode. */
750 public int compatScreenHeightDp;
751 /** @hide Hack to get this information from WM to app running in compat mode. */
752 public int compatSmallestScreenWidthDp;
753
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800754 /**
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +0100755 * An undefined assetsSeq. This will not override an existing assetsSeq.
756 * @hide
757 */
758 public static final int ASSETS_SEQ_UNDEFINED = 0;
759
760 /**
761 * Internal counter that allows us to piggyback off the configuration change mechanism to
762 * signal to apps that the the assets for an Application have changed. A difference in these
763 * between two Configurations will yield a diff flag of
764 * {@link ActivityInfo#CONFIG_ASSETS_PATHS}.
765 * @hide
766 */
767 public int assetsSeq;
768
769 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800770 * @hide Internal book-keeping.
771 */
772 public int seq;
Dianne Hackborn1d0b1772013-09-06 14:02:54 -0700773
Alan Viveretteac85f902016-03-11 15:15:51 -0500774 /** @hide */
775 @IntDef(flag = true,
776 value = {
777 NATIVE_CONFIG_MCC,
778 NATIVE_CONFIG_MNC,
779 NATIVE_CONFIG_LOCALE,
780 NATIVE_CONFIG_TOUCHSCREEN,
781 NATIVE_CONFIG_KEYBOARD,
782 NATIVE_CONFIG_KEYBOARD_HIDDEN,
783 NATIVE_CONFIG_NAVIGATION,
784 NATIVE_CONFIG_ORIENTATION,
785 NATIVE_CONFIG_DENSITY,
786 NATIVE_CONFIG_SCREEN_SIZE,
787 NATIVE_CONFIG_VERSION,
788 NATIVE_CONFIG_SCREEN_LAYOUT,
789 NATIVE_CONFIG_UI_MODE,
790 NATIVE_CONFIG_SMALLEST_SCREEN_SIZE,
791 NATIVE_CONFIG_LAYOUTDIR,
Romain Guy48327452017-01-23 17:03:35 -0800792 NATIVE_CONFIG_COLOR_MODE,
Alan Viveretteac85f902016-03-11 15:15:51 -0500793 })
794 @Retention(RetentionPolicy.SOURCE)
795 public @interface NativeConfig {}
796
Dianne Hackborn1d0b1772013-09-06 14:02:54 -0700797 /** @hide Native-specific bit mask for MCC config; DO NOT USE UNLESS YOU ARE SURE. */
798 public static final int NATIVE_CONFIG_MCC = 0x0001;
799 /** @hide Native-specific bit mask for MNC config; DO NOT USE UNLESS YOU ARE SURE. */
800 public static final int NATIVE_CONFIG_MNC = 0x0002;
801 /** @hide Native-specific bit mask for LOCALE config; DO NOT USE UNLESS YOU ARE SURE. */
802 public static final int NATIVE_CONFIG_LOCALE = 0x0004;
803 /** @hide Native-specific bit mask for TOUCHSCREEN config; DO NOT USE UNLESS YOU ARE SURE. */
804 public static final int NATIVE_CONFIG_TOUCHSCREEN = 0x0008;
805 /** @hide Native-specific bit mask for KEYBOARD config; DO NOT USE UNLESS YOU ARE SURE. */
806 public static final int NATIVE_CONFIG_KEYBOARD = 0x0010;
807 /** @hide Native-specific bit mask for KEYBOARD_HIDDEN config; DO NOT USE UNLESS YOU
808 * ARE SURE. */
809 public static final int NATIVE_CONFIG_KEYBOARD_HIDDEN = 0x0020;
810 /** @hide Native-specific bit mask for NAVIGATION config; DO NOT USE UNLESS YOU ARE SURE. */
811 public static final int NATIVE_CONFIG_NAVIGATION = 0x0040;
812 /** @hide Native-specific bit mask for ORIENTATION config; DO NOT USE UNLESS YOU ARE SURE. */
813 public static final int NATIVE_CONFIG_ORIENTATION = 0x0080;
814 /** @hide Native-specific bit mask for DENSITY config; DO NOT USE UNLESS YOU ARE SURE. */
815 public static final int NATIVE_CONFIG_DENSITY = 0x0100;
816 /** @hide Native-specific bit mask for SCREEN_SIZE config; DO NOT USE UNLESS YOU ARE SURE. */
817 public static final int NATIVE_CONFIG_SCREEN_SIZE = 0x0200;
818 /** @hide Native-specific bit mask for VERSION config; DO NOT USE UNLESS YOU ARE SURE. */
819 public static final int NATIVE_CONFIG_VERSION = 0x0400;
820 /** @hide Native-specific bit mask for SCREEN_LAYOUT config; DO NOT USE UNLESS YOU ARE SURE. */
821 public static final int NATIVE_CONFIG_SCREEN_LAYOUT = 0x0800;
822 /** @hide Native-specific bit mask for UI_MODE config; DO NOT USE UNLESS YOU ARE SURE. */
823 public static final int NATIVE_CONFIG_UI_MODE = 0x1000;
824 /** @hide Native-specific bit mask for SMALLEST_SCREEN_SIZE config; DO NOT USE UNLESS YOU
825 * ARE SURE. */
826 public static final int NATIVE_CONFIG_SMALLEST_SCREEN_SIZE = 0x2000;
827 /** @hide Native-specific bit mask for LAYOUTDIR config ; DO NOT USE UNLESS YOU ARE SURE.*/
828 public static final int NATIVE_CONFIG_LAYOUTDIR = 0x4000;
Romain Guy48327452017-01-23 17:03:35 -0800829 /** @hide Native-specific bit mask for COLOR_MODE config ; DO NOT USE UNLESS YOU ARE SURE.*/
830 public static final int NATIVE_CONFIG_COLOR_MODE = 0x10000;
Dianne Hackborn1d0b1772013-09-06 14:02:54 -0700831
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800832 /**
Adam Lesinskibad43fc2016-07-19 13:35:01 -0700833 * <p>Construct an invalid Configuration. This state is only suitable for constructing a
834 * Configuration delta that will be applied to some valid Configuration object. In order to
835 * create a valid standalone Configuration, you must call {@link #setToDefaults}. </p>
836 *
837 * <p>Example:</p>
838 * <pre class="prettyprint">
839 * Configuration validConfig = new Configuration();
840 * validConfig.setToDefaults();
841 *
842 * Configuration deltaOnlyConfig = new Configuration();
843 * deltaOnlyConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
844 *
845 * validConfig.updateFrom(deltaOnlyConfig);
846 * </pre>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800847 */
848 public Configuration() {
Adam Lesinskibad43fc2016-07-19 13:35:01 -0700849 unset();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800850 }
851
852 /**
853 * Makes a deep copy suitable for modification.
854 */
855 public Configuration(Configuration o) {
Dianne Hackborn694f79b2010-03-17 19:44:59 -0700856 setTo(o);
857 }
858
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700859 /* This brings mLocaleList in sync with locale in case a user of the older API who doesn't know
860 * about setLocales() has changed locale directly. */
861 private void fixUpLocaleList() {
862 if ((locale == null && !mLocaleList.isEmpty()) ||
Roozbeh Pournaderfee44842016-02-04 15:24:24 -0800863 (locale != null && !locale.equals(mLocaleList.get(0)))) {
Raph Levien10ea92a2016-05-02 12:56:01 -0700864 mLocaleList = locale == null ? LocaleList.getEmptyLocaleList() : new LocaleList(locale);
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700865 }
866 }
867
Chet Haased30149e2017-01-13 12:55:16 -0800868 /**
869 * Sets the fields in this object to those in the given Configuration.
870 *
871 * @param o The Configuration object used to set the values of this Configuration's fields.
872 */
Dianne Hackborn694f79b2010-03-17 19:44:59 -0700873 public void setTo(Configuration o) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800874 fontScale = o.fontScale;
875 mcc = o.mcc;
876 mnc = o.mnc;
Roozbeh Pournader8a412e02015-12-02 18:39:50 -0800877 locale = o.locale == null ? null : (Locale) o.locale.clone();
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700878 o.fixUpLocaleList();
879 mLocaleList = o.mLocaleList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800880 userSetLocale = o.userSetLocale;
881 touchscreen = o.touchscreen;
882 keyboard = o.keyboard;
883 keyboardHidden = o.keyboardHidden;
884 hardKeyboardHidden = o.hardKeyboardHidden;
885 navigation = o.navigation;
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700886 navigationHidden = o.navigationHidden;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800887 orientation = o.orientation;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700888 screenLayout = o.screenLayout;
Romain Guy48327452017-01-23 17:03:35 -0800889 colorMode = o.colorMode;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100890 uiMode = o.uiMode;
Dianne Hackbornebff8f92011-05-12 18:07:47 -0700891 screenWidthDp = o.screenWidthDp;
892 screenHeightDp = o.screenHeightDp;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700893 smallestScreenWidthDp = o.smallestScreenWidthDp;
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700894 densityDpi = o.densityDpi;
Dianne Hackborn5fd21692011-06-07 14:09:47 -0700895 compatScreenWidthDp = o.compatScreenWidthDp;
896 compatScreenHeightDp = o.compatScreenHeightDp;
897 compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp;
Bryce Lee7566d762017-03-30 09:34:15 -0700898 setAppBounds(o.appBounds);
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +0100899 assetsSeq = o.assetsSeq;
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800900 seq = o.seq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800901 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700902
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800903 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700904 StringBuilder sb = new StringBuilder(128);
Dianne Hackborn29735682011-04-21 17:26:39 -0700905 sb.append("{");
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700906 sb.append(fontScale);
Dianne Hackborn5be8de32011-05-24 18:11:57 -0700907 sb.append(" ");
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700908 if (mcc != 0) {
909 sb.append(mcc);
910 sb.append("mcc");
911 } else {
912 sb.append("?mcc");
913 }
914 if (mnc != 0) {
915 sb.append(mnc);
916 sb.append("mnc");
917 } else {
918 sb.append("?mnc");
919 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700920 fixUpLocaleList();
921 if (!mLocaleList.isEmpty()) {
Dianne Hackborn9a849832011-04-07 15:11:57 -0700922 sb.append(" ");
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700923 sb.append(mLocaleList);
Dianne Hackborn9a849832011-04-07 15:11:57 -0700924 } else {
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700925 sb.append(" ?localeList");
Daniel Sandler7d6bddc2010-07-22 16:11:55 -0400926 }
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700927 int layoutDir = (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK);
928 switch (layoutDir) {
929 case SCREENLAYOUT_LAYOUTDIR_UNDEFINED: sb.append(" ?layoutDir"); break;
Fabrice Di Meglio8a802db2012-09-05 13:12:02 -0700930 case SCREENLAYOUT_LAYOUTDIR_LTR: sb.append(" ldltr"); break;
931 case SCREENLAYOUT_LAYOUTDIR_RTL: sb.append(" ldrtl"); break;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700932 default: sb.append(" layoutDir=");
933 sb.append(layoutDir >> SCREENLAYOUT_LAYOUTDIR_SHIFT); break;
Fabrice Di Meglio7a736fb2011-06-09 20:20:36 -0700934 }
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700935 if (smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
936 sb.append(" sw"); sb.append(smallestScreenWidthDp); sb.append("dp");
937 } else {
Dianne Hackborn2f0b1752011-05-31 17:59:49 -0700938 sb.append(" ?swdp");
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700939 }
940 if (screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
941 sb.append(" w"); sb.append(screenWidthDp); sb.append("dp");
942 } else {
Dianne Hackborn2f0b1752011-05-31 17:59:49 -0700943 sb.append(" ?wdp");
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700944 }
945 if (screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
946 sb.append(" h"); sb.append(screenHeightDp); sb.append("dp");
947 } else {
Dianne Hackborn2f0b1752011-05-31 17:59:49 -0700948 sb.append(" ?hdp");
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700949 }
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700950 if (densityDpi != DENSITY_DPI_UNDEFINED) {
951 sb.append(" "); sb.append(densityDpi); sb.append("dpi");
952 } else {
953 sb.append(" ?density");
954 }
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700955 switch ((screenLayout&SCREENLAYOUT_SIZE_MASK)) {
956 case SCREENLAYOUT_SIZE_UNDEFINED: sb.append(" ?lsize"); break;
957 case SCREENLAYOUT_SIZE_SMALL: sb.append(" smll"); break;
958 case SCREENLAYOUT_SIZE_NORMAL: sb.append(" nrml"); break;
959 case SCREENLAYOUT_SIZE_LARGE: sb.append(" lrg"); break;
960 case SCREENLAYOUT_SIZE_XLARGE: sb.append(" xlrg"); break;
961 default: sb.append(" layoutSize=");
962 sb.append(screenLayout&SCREENLAYOUT_SIZE_MASK); break;
963 }
964 switch ((screenLayout&SCREENLAYOUT_LONG_MASK)) {
965 case SCREENLAYOUT_LONG_UNDEFINED: sb.append(" ?long"); break;
966 case SCREENLAYOUT_LONG_NO: /* not-long is not interesting to print */ break;
967 case SCREENLAYOUT_LONG_YES: sb.append(" long"); break;
968 default: sb.append(" layoutLong=");
969 sb.append(screenLayout&SCREENLAYOUT_LONG_MASK); break;
970 }
Romain Guy48327452017-01-23 17:03:35 -0800971 switch ((colorMode &COLOR_MODE_HDR_MASK)) {
972 case COLOR_MODE_HDR_UNDEFINED: sb.append(" ?ldr"); break; // most likely not HDR
973 case COLOR_MODE_HDR_NO: /* ldr is not interesting to print */ break;
974 case COLOR_MODE_HDR_YES: sb.append(" hdr"); break;
Romain Guyc9ba5592017-01-18 16:34:42 -0800975 default: sb.append(" dynamicRange=");
Romain Guy48327452017-01-23 17:03:35 -0800976 sb.append(colorMode &COLOR_MODE_HDR_MASK); break;
Romain Guyc9ba5592017-01-18 16:34:42 -0800977 }
Romain Guy48327452017-01-23 17:03:35 -0800978 switch ((colorMode &COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) {
979 case COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED: sb.append(" ?wideColorGamut"); break;
980 case COLOR_MODE_WIDE_COLOR_GAMUT_NO: /* not wide is not interesting to print */ break;
981 case COLOR_MODE_WIDE_COLOR_GAMUT_YES: sb.append(" widecg"); break;
Romain Guyc9ba5592017-01-18 16:34:42 -0800982 default: sb.append(" wideColorGamut=");
Romain Guy48327452017-01-23 17:03:35 -0800983 sb.append(colorMode &COLOR_MODE_WIDE_COLOR_GAMUT_MASK); break;
Romain Guyc9ba5592017-01-18 16:34:42 -0800984 }
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700985 switch (orientation) {
986 case ORIENTATION_UNDEFINED: sb.append(" ?orien"); break;
987 case ORIENTATION_LANDSCAPE: sb.append(" land"); break;
988 case ORIENTATION_PORTRAIT: sb.append(" port"); break;
989 default: sb.append(" orien="); sb.append(orientation); break;
990 }
991 switch ((uiMode&UI_MODE_TYPE_MASK)) {
992 case UI_MODE_TYPE_UNDEFINED: sb.append(" ?uimode"); break;
993 case UI_MODE_TYPE_NORMAL: /* normal is not interesting to print */ break;
994 case UI_MODE_TYPE_DESK: sb.append(" desk"); break;
995 case UI_MODE_TYPE_CAR: sb.append(" car"); break;
Dianne Hackborne360bb62011-05-20 16:11:04 -0700996 case UI_MODE_TYPE_TELEVISION: sb.append(" television"); break;
Joe Onorato44fcb832011-12-14 20:59:30 -0800997 case UI_MODE_TYPE_APPLIANCE: sb.append(" appliance"); break;
John Spurlock6c191292014-04-03 16:37:27 -0400998 case UI_MODE_TYPE_WATCH: sb.append(" watch"); break;
Zak Cohen1a6acdb2016-12-12 15:21:21 -0800999 case UI_MODE_TYPE_VR_HEADSET: sb.append(" vrheadset"); break;
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001000 default: sb.append(" uimode="); sb.append(uiMode&UI_MODE_TYPE_MASK); break;
1001 }
1002 switch ((uiMode&UI_MODE_NIGHT_MASK)) {
1003 case UI_MODE_NIGHT_UNDEFINED: sb.append(" ?night"); break;
1004 case UI_MODE_NIGHT_NO: /* not-night is not interesting to print */ break;
1005 case UI_MODE_NIGHT_YES: sb.append(" night"); break;
1006 default: sb.append(" night="); sb.append(uiMode&UI_MODE_NIGHT_MASK); break;
1007 }
Dianne Hackborn9a849832011-04-07 15:11:57 -07001008 switch (touchscreen) {
1009 case TOUCHSCREEN_UNDEFINED: sb.append(" ?touch"); break;
1010 case TOUCHSCREEN_NOTOUCH: sb.append(" -touch"); break;
1011 case TOUCHSCREEN_STYLUS: sb.append(" stylus"); break;
1012 case TOUCHSCREEN_FINGER: sb.append(" finger"); break;
1013 default: sb.append(" touch="); sb.append(touchscreen); break;
1014 }
1015 switch (keyboard) {
1016 case KEYBOARD_UNDEFINED: sb.append(" ?keyb"); break;
1017 case KEYBOARD_NOKEYS: sb.append(" -keyb"); break;
1018 case KEYBOARD_QWERTY: sb.append(" qwerty"); break;
1019 case KEYBOARD_12KEY: sb.append(" 12key"); break;
1020 default: sb.append(" keys="); sb.append(keyboard); break;
1021 }
1022 switch (keyboardHidden) {
1023 case KEYBOARDHIDDEN_UNDEFINED: sb.append("/?"); break;
1024 case KEYBOARDHIDDEN_NO: sb.append("/v"); break;
1025 case KEYBOARDHIDDEN_YES: sb.append("/h"); break;
1026 case KEYBOARDHIDDEN_SOFT: sb.append("/s"); break;
1027 default: sb.append("/"); sb.append(keyboardHidden); break;
1028 }
1029 switch (hardKeyboardHidden) {
1030 case HARDKEYBOARDHIDDEN_UNDEFINED: sb.append("/?"); break;
1031 case HARDKEYBOARDHIDDEN_NO: sb.append("/v"); break;
1032 case HARDKEYBOARDHIDDEN_YES: sb.append("/h"); break;
1033 default: sb.append("/"); sb.append(hardKeyboardHidden); break;
1034 }
1035 switch (navigation) {
1036 case NAVIGATION_UNDEFINED: sb.append(" ?nav"); break;
1037 case NAVIGATION_NONAV: sb.append(" -nav"); break;
1038 case NAVIGATION_DPAD: sb.append(" dpad"); break;
1039 case NAVIGATION_TRACKBALL: sb.append(" tball"); break;
1040 case NAVIGATION_WHEEL: sb.append(" wheel"); break;
1041 default: sb.append(" nav="); sb.append(navigation); break;
1042 }
1043 switch (navigationHidden) {
1044 case NAVIGATIONHIDDEN_UNDEFINED: sb.append("/?"); break;
1045 case NAVIGATIONHIDDEN_NO: sb.append("/v"); break;
1046 case NAVIGATIONHIDDEN_YES: sb.append("/h"); break;
1047 default: sb.append("/"); sb.append(navigationHidden); break;
1048 }
Bryce Lee7566d762017-03-30 09:34:15 -07001049 if (appBounds != null) {
1050 sb.append(" appBounds="); sb.append(appBounds);
1051 }
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001052 if (assetsSeq != 0) {
1053 sb.append(" as.").append(assetsSeq);
1054 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001055 if (seq != 0) {
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001056 sb.append(" s.").append(seq);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001057 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001058 sb.append('}');
1059 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001060 }
1061
1062 /**
1063 * Set this object to the system defaults.
1064 */
1065 public void setToDefaults() {
1066 fontScale = 1;
1067 mcc = mnc = 0;
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001068 mLocaleList = LocaleList.getEmptyLocaleList();
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001069 locale = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001070 userSetLocale = false;
1071 touchscreen = TOUCHSCREEN_UNDEFINED;
1072 keyboard = KEYBOARD_UNDEFINED;
1073 keyboardHidden = KEYBOARDHIDDEN_UNDEFINED;
1074 hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED;
1075 navigation = NAVIGATION_UNDEFINED;
Dianne Hackborn93e462b2009-09-15 22:50:40 -07001076 navigationHidden = NAVIGATIONHIDDEN_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001077 orientation = ORIENTATION_UNDEFINED;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001078 screenLayout = SCREENLAYOUT_UNDEFINED;
Romain Guy48327452017-01-23 17:03:35 -08001079 colorMode = COLOR_MODE_UNDEFINED;
Dianne Hackborn7299c412010-03-04 18:41:49 -08001080 uiMode = UI_MODE_TYPE_UNDEFINED;
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001081 screenWidthDp = compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED;
1082 screenHeightDp = compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED;
1083 smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001084 densityDpi = DENSITY_DPI_UNDEFINED;
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001085 assetsSeq = ASSETS_SEQ_UNDEFINED;
Bryce Lee7566d762017-03-30 09:34:15 -07001086 appBounds = null;
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001087 seq = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 }
1089
Adam Lesinskibad43fc2016-07-19 13:35:01 -07001090 /**
1091 * Set this object to completely undefined.
1092 * @hide
1093 */
1094 public void unset() {
1095 setToDefaults();
1096 fontScale = 0;
1097 }
1098
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001099 /** {@hide} */
1100 @Deprecated public void makeDefault() {
1101 setToDefaults();
1102 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -07001103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 /**
Alan Viveretteac85f902016-03-11 15:15:51 -05001105 * Copies the fields from delta into this Configuration object, keeping
1106 * track of which ones have changed. Any undefined fields in {@code delta}
1107 * are ignored and not copied in to the current Configuration.
1108 *
1109 * @return a bit mask of the changed fields, as per {@link #diff}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001110 */
Alan Viveretteac85f902016-03-11 15:15:51 -05001111 public @Config int updateFrom(@NonNull Configuration delta) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001112 int changed = 0;
1113 if (delta.fontScale > 0 && fontScale != delta.fontScale) {
1114 changed |= ActivityInfo.CONFIG_FONT_SCALE;
1115 fontScale = delta.fontScale;
1116 }
1117 if (delta.mcc != 0 && mcc != delta.mcc) {
1118 changed |= ActivityInfo.CONFIG_MCC;
1119 mcc = delta.mcc;
1120 }
1121 if (delta.mnc != 0 && mnc != delta.mnc) {
1122 changed |= ActivityInfo.CONFIG_MNC;
1123 mnc = delta.mnc;
1124 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001125 fixUpLocaleList();
1126 delta.fixUpLocaleList();
1127 if (!delta.mLocaleList.isEmpty() && !mLocaleList.equals(delta.mLocaleList)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128 changed |= ActivityInfo.CONFIG_LOCALE;
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001129 mLocaleList = delta.mLocaleList;
1130 // delta.locale can't be null, since delta.mLocaleList is not empty.
1131 if (!delta.locale.equals(locale)) {
1132 locale = (Locale) delta.locale.clone();
1133 // If locale has changed, then layout direction is also changed ...
1134 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
1135 // ... and we need to update the layout direction (represented by the first
1136 // 2 most significant bits in screenLayout).
1137 setLayoutDirection(locale);
1138 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001139 }
Craig Mautner31678b52013-08-12 17:56:34 -07001140 final int deltaScreenLayoutDir = delta.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
1141 if (deltaScreenLayoutDir != SCREENLAYOUT_LAYOUTDIR_UNDEFINED &&
1142 deltaScreenLayoutDir != (screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) {
1143 screenLayout = (screenLayout & ~SCREENLAYOUT_LAYOUTDIR_MASK) | deltaScreenLayoutDir;
Amith Yamasanid8415f42013-08-07 20:15:10 -07001144 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
Amith Yamasanid8415f42013-08-07 20:15:10 -07001145 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001146 if (delta.userSetLocale && (!userSetLocale || ((changed & ActivityInfo.CONFIG_LOCALE) != 0)))
1147 {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001148 changed |= ActivityInfo.CONFIG_LOCALE;
Amith Yamasanid8415f42013-08-07 20:15:10 -07001149 userSetLocale = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001150 }
1151 if (delta.touchscreen != TOUCHSCREEN_UNDEFINED
1152 && touchscreen != delta.touchscreen) {
1153 changed |= ActivityInfo.CONFIG_TOUCHSCREEN;
1154 touchscreen = delta.touchscreen;
1155 }
1156 if (delta.keyboard != KEYBOARD_UNDEFINED
1157 && keyboard != delta.keyboard) {
1158 changed |= ActivityInfo.CONFIG_KEYBOARD;
1159 keyboard = delta.keyboard;
1160 }
1161 if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED
1162 && keyboardHidden != delta.keyboardHidden) {
1163 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1164 keyboardHidden = delta.keyboardHidden;
1165 }
1166 if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED
1167 && hardKeyboardHidden != delta.hardKeyboardHidden) {
1168 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1169 hardKeyboardHidden = delta.hardKeyboardHidden;
1170 }
1171 if (delta.navigation != NAVIGATION_UNDEFINED
1172 && navigation != delta.navigation) {
1173 changed |= ActivityInfo.CONFIG_NAVIGATION;
1174 navigation = delta.navigation;
1175 }
Dianne Hackborn93e462b2009-09-15 22:50:40 -07001176 if (delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED
1177 && navigationHidden != delta.navigationHidden) {
1178 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1179 navigationHidden = delta.navigationHidden;
1180 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001181 if (delta.orientation != ORIENTATION_UNDEFINED
1182 && orientation != delta.orientation) {
1183 changed |= ActivityInfo.CONFIG_ORIENTATION;
1184 orientation = delta.orientation;
1185 }
Robert Carrdf259d32016-12-05 20:33:10 -08001186
1187 if (((delta.screenLayout & SCREENLAYOUT_SIZE_MASK) != SCREENLAYOUT_SIZE_UNDEFINED)
1188 && (delta.screenLayout & SCREENLAYOUT_SIZE_MASK)
1189 != (screenLayout & SCREENLAYOUT_SIZE_MASK)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07001190 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
Robert Carrdf259d32016-12-05 20:33:10 -08001191 screenLayout = (screenLayout & ~SCREENLAYOUT_SIZE_MASK)
1192 | (delta.screenLayout & SCREENLAYOUT_SIZE_MASK);
Dianne Hackborn723738c2009-06-25 19:48:04 -07001193 }
Robert Carrdf259d32016-12-05 20:33:10 -08001194 if (((delta.screenLayout & SCREENLAYOUT_LONG_MASK) != SCREENLAYOUT_LONG_UNDEFINED)
1195 && (delta.screenLayout & SCREENLAYOUT_LONG_MASK)
1196 != (screenLayout & SCREENLAYOUT_LONG_MASK)) {
1197 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
1198 screenLayout = (screenLayout & ~SCREENLAYOUT_LONG_MASK)
1199 | (delta.screenLayout & SCREENLAYOUT_LONG_MASK);
1200 }
1201 if (((delta.screenLayout & SCREENLAYOUT_ROUND_MASK) != SCREENLAYOUT_ROUND_UNDEFINED)
1202 && (delta.screenLayout & SCREENLAYOUT_ROUND_MASK)
1203 != (screenLayout & SCREENLAYOUT_ROUND_MASK)) {
1204 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
1205 screenLayout = (screenLayout & ~SCREENLAYOUT_ROUND_MASK)
1206 | (delta.screenLayout & SCREENLAYOUT_ROUND_MASK);
1207 }
1208 if ((delta.screenLayout & SCREENLAYOUT_COMPAT_NEEDED)
1209 != (screenLayout & SCREENLAYOUT_COMPAT_NEEDED)
1210 && delta.screenLayout != 0) {
1211 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
1212 screenLayout = (screenLayout & ~SCREENLAYOUT_COMPAT_NEEDED)
1213 | (delta.screenLayout & SCREENLAYOUT_COMPAT_NEEDED);
1214 }
1215
Romain Guy48327452017-01-23 17:03:35 -08001216 if (((delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) !=
1217 COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED)
1218 && (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK)
1219 != (colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) {
1220 changed |= ActivityInfo.CONFIG_COLOR_MODE;
1221 colorMode = (colorMode & ~COLOR_MODE_WIDE_COLOR_GAMUT_MASK)
1222 | (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK);
Romain Guyc9ba5592017-01-18 16:34:42 -08001223 }
1224
Romain Guy48327452017-01-23 17:03:35 -08001225 if (((delta.colorMode & COLOR_MODE_HDR_MASK) != COLOR_MODE_HDR_UNDEFINED)
1226 && (delta.colorMode & COLOR_MODE_HDR_MASK)
1227 != (colorMode & COLOR_MODE_HDR_MASK)) {
1228 changed |= ActivityInfo.CONFIG_COLOR_MODE;
1229 colorMode = (colorMode & ~COLOR_MODE_HDR_MASK)
1230 | (delta.colorMode & COLOR_MODE_HDR_MASK);
Romain Guyc9ba5592017-01-18 16:34:42 -08001231 }
1232
Dianne Hackborn7299c412010-03-04 18:41:49 -08001233 if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)
Tobias Haamel27b28b32010-02-09 23:09:17 +01001234 && uiMode != delta.uiMode) {
1235 changed |= ActivityInfo.CONFIG_UI_MODE;
Dianne Hackborn7299c412010-03-04 18:41:49 -08001236 if ((delta.uiMode&UI_MODE_TYPE_MASK) != UI_MODE_TYPE_UNDEFINED) {
1237 uiMode = (uiMode&~UI_MODE_TYPE_MASK)
1238 | (delta.uiMode&UI_MODE_TYPE_MASK);
1239 }
1240 if ((delta.uiMode&UI_MODE_NIGHT_MASK) != UI_MODE_NIGHT_UNDEFINED) {
1241 uiMode = (uiMode&~UI_MODE_NIGHT_MASK)
1242 | (delta.uiMode&UI_MODE_NIGHT_MASK);
1243 }
Tobias Haamel27b28b32010-02-09 23:09:17 +01001244 }
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001245 if (delta.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED
1246 && screenWidthDp != delta.screenWidthDp) {
1247 changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1248 screenWidthDp = delta.screenWidthDp;
1249 }
1250 if (delta.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED
1251 && screenHeightDp != delta.screenHeightDp) {
1252 changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1253 screenHeightDp = delta.screenHeightDp;
1254 }
Danny Baumanne7123a62013-05-15 10:21:40 +02001255 if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
1256 && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
1257 changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001258 smallestScreenWidthDp = delta.smallestScreenWidthDp;
1259 }
Danny Baumanne7123a62013-05-15 10:21:40 +02001260 if (delta.densityDpi != DENSITY_DPI_UNDEFINED &&
1261 densityDpi != delta.densityDpi) {
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001262 changed |= ActivityInfo.CONFIG_DENSITY;
1263 densityDpi = delta.densityDpi;
1264 }
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001265 if (delta.compatScreenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
1266 compatScreenWidthDp = delta.compatScreenWidthDp;
1267 }
1268 if (delta.compatScreenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
1269 compatScreenHeightDp = delta.compatScreenHeightDp;
1270 }
1271 if (delta.compatSmallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
1272 compatSmallestScreenWidthDp = delta.compatSmallestScreenWidthDp;
1273 }
Bryce Lee7566d762017-03-30 09:34:15 -07001274 if (delta.appBounds != null && !delta.appBounds.equals(appBounds)) {
1275 changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1276 setAppBounds(delta.appBounds);
1277 }
Adam Lesinski4eb41292017-07-06 12:06:13 -07001278 if (delta.assetsSeq != ASSETS_SEQ_UNDEFINED && delta.assetsSeq != assetsSeq) {
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001279 changed |= ActivityInfo.CONFIG_ASSETS_PATHS;
1280 assetsSeq = delta.assetsSeq;
1281 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001282 if (delta.seq != 0) {
1283 seq = delta.seq;
1284 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -07001285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001286 return changed;
1287 }
1288
1289 /**
1290 * Return a bit mask of the differences between this Configuration
1291 * object and the given one. Does not change the values of either. Any
1292 * undefined fields in <var>delta</var> are ignored.
1293 * @return Returns a bit mask indicating which configuration
1294 * values has changed, containing any combination of
1295 * {@link android.content.pm.ActivityInfo#CONFIG_FONT_SCALE
1296 * PackageManager.ActivityInfo.CONFIG_FONT_SCALE},
1297 * {@link android.content.pm.ActivityInfo#CONFIG_MCC
1298 * PackageManager.ActivityInfo.CONFIG_MCC},
1299 * {@link android.content.pm.ActivityInfo#CONFIG_MNC
1300 * PackageManager.ActivityInfo.CONFIG_MNC},
1301 * {@link android.content.pm.ActivityInfo#CONFIG_LOCALE
1302 * PackageManager.ActivityInfo.CONFIG_LOCALE},
1303 * {@link android.content.pm.ActivityInfo#CONFIG_TOUCHSCREEN
1304 * PackageManager.ActivityInfo.CONFIG_TOUCHSCREEN},
1305 * {@link android.content.pm.ActivityInfo#CONFIG_KEYBOARD
1306 * PackageManager.ActivityInfo.CONFIG_KEYBOARD},
1307 * {@link android.content.pm.ActivityInfo#CONFIG_NAVIGATION
Dianne Hackborn723738c2009-06-25 19:48:04 -07001308 * PackageManager.ActivityInfo.CONFIG_NAVIGATION},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001309 * {@link android.content.pm.ActivityInfo#CONFIG_ORIENTATION
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001310 * PackageManager.ActivityInfo.CONFIG_ORIENTATION},
Dianne Hackborn723738c2009-06-25 19:48:04 -07001311 * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_LAYOUT
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001312 * PackageManager.ActivityInfo.CONFIG_SCREEN_LAYOUT}, or
1313 * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_SIZE
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001314 * PackageManager.ActivityInfo.CONFIG_SCREEN_SIZE}, or
1315 * {@link android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE
1316 * PackageManager.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE}.
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001317 * {@link android.content.pm.ActivityInfo#CONFIG_LAYOUT_DIRECTION
1318 * PackageManager.ActivityInfo.CONFIG_LAYOUT_DIRECTION}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001319 */
1320 public int diff(Configuration delta) {
Bryce Lee658d9842017-07-28 08:33:36 -07001321 return diff(delta, false /* compareUndefined */, false /* publicOnly */);
1322 }
1323
1324 /**
1325 * Returns the diff against the provided {@link Configuration} excluding values that would
1326 * publicly be equivalent, such as appBounds.
1327 * @param delta {@link Configuration} to compare to.
1328 *
1329 * TODO(b/36812336): Remove once appBounds has been moved out of Configuration.
1330 * {@hide}
1331 */
1332 public int diffPublicOnly(Configuration delta) {
1333 return diff(delta, false /* compareUndefined */, true /* publicOnly */);
Andrii Kulianb10330d2016-09-16 13:51:46 -07001334 }
1335
1336 /**
1337 * Variation of {@link #diff(Configuration)} with an option to skip checks for undefined values.
1338 *
1339 * @hide
1340 */
Bryce Lee658d9842017-07-28 08:33:36 -07001341 public int diff(Configuration delta, boolean compareUndefined, boolean publicOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001342 int changed = 0;
Andrii Kulianb10330d2016-09-16 13:51:46 -07001343 if ((compareUndefined || delta.fontScale > 0) && fontScale != delta.fontScale) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001344 changed |= ActivityInfo.CONFIG_FONT_SCALE;
1345 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001346 if ((compareUndefined || delta.mcc != 0) && mcc != delta.mcc) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001347 changed |= ActivityInfo.CONFIG_MCC;
1348 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001349 if ((compareUndefined || delta.mnc != 0) && mnc != delta.mnc) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001350 changed |= ActivityInfo.CONFIG_MNC;
1351 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001352 fixUpLocaleList();
1353 delta.fixUpLocaleList();
Andrii Kulianb10330d2016-09-16 13:51:46 -07001354 if ((compareUndefined || !delta.mLocaleList.isEmpty())
1355 && !mLocaleList.equals(delta.mLocaleList)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001356 changed |= ActivityInfo.CONFIG_LOCALE;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001357 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001358 }
Craig Mautner31678b52013-08-12 17:56:34 -07001359 final int deltaScreenLayoutDir = delta.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
Andrii Kulianb10330d2016-09-16 13:51:46 -07001360 if ((compareUndefined || deltaScreenLayoutDir != SCREENLAYOUT_LAYOUTDIR_UNDEFINED)
1361 && deltaScreenLayoutDir != (screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) {
Amith Yamasanid8415f42013-08-07 20:15:10 -07001362 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
1363 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001364 if ((compareUndefined || delta.touchscreen != TOUCHSCREEN_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001365 && touchscreen != delta.touchscreen) {
1366 changed |= ActivityInfo.CONFIG_TOUCHSCREEN;
1367 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001368 if ((compareUndefined || delta.keyboard != KEYBOARD_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369 && keyboard != delta.keyboard) {
1370 changed |= ActivityInfo.CONFIG_KEYBOARD;
1371 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001372 if ((compareUndefined || delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001373 && keyboardHidden != delta.keyboardHidden) {
1374 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1375 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001376 if ((compareUndefined || delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001377 && hardKeyboardHidden != delta.hardKeyboardHidden) {
1378 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1379 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001380 if ((compareUndefined || delta.navigation != NAVIGATION_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 && navigation != delta.navigation) {
1382 changed |= ActivityInfo.CONFIG_NAVIGATION;
1383 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001384 if ((compareUndefined || delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED)
Dianne Hackborn93e462b2009-09-15 22:50:40 -07001385 && navigationHidden != delta.navigationHidden) {
1386 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1387 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001388 if ((compareUndefined || delta.orientation != ORIENTATION_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389 && orientation != delta.orientation) {
1390 changed |= ActivityInfo.CONFIG_ORIENTATION;
1391 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001392 if ((compareUndefined || getScreenLayoutNoDirection(delta.screenLayout) !=
1393 (SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED))
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001394 && getScreenLayoutNoDirection(screenLayout) !=
Andrii Kulianb10330d2016-09-16 13:51:46 -07001395 getScreenLayoutNoDirection(delta.screenLayout)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07001396 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
1397 }
Romain Guyc9ba5592017-01-18 16:34:42 -08001398 if ((compareUndefined ||
Romain Guy48327452017-01-23 17:03:35 -08001399 (delta.colorMode & COLOR_MODE_HDR_MASK) != COLOR_MODE_HDR_UNDEFINED)
1400 && (colorMode & COLOR_MODE_HDR_MASK) !=
1401 (delta.colorMode & COLOR_MODE_HDR_MASK)) {
1402 changed |= ActivityInfo.CONFIG_COLOR_MODE;
Romain Guyc9ba5592017-01-18 16:34:42 -08001403 }
1404 if ((compareUndefined ||
Romain Guy48327452017-01-23 17:03:35 -08001405 (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) !=
1406 COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED)
1407 && (colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) !=
1408 (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) {
1409 changed |= ActivityInfo.CONFIG_COLOR_MODE;
Romain Guyc9ba5592017-01-18 16:34:42 -08001410 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001411 if ((compareUndefined || delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED))
Tobias Haamel27b28b32010-02-09 23:09:17 +01001412 && uiMode != delta.uiMode) {
1413 changed |= ActivityInfo.CONFIG_UI_MODE;
1414 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001415 if ((compareUndefined || delta.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED)
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001416 && screenWidthDp != delta.screenWidthDp) {
1417 changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1418 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001419 if ((compareUndefined || delta.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED)
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001420 && screenHeightDp != delta.screenHeightDp) {
1421 changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1422 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001423 if ((compareUndefined || delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED)
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001424 && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
1425 changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
1426 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001427 if ((compareUndefined || delta.densityDpi != DENSITY_DPI_UNDEFINED)
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001428 && densityDpi != delta.densityDpi) {
1429 changed |= ActivityInfo.CONFIG_DENSITY;
1430 }
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001431 if ((compareUndefined || delta.assetsSeq != ASSETS_SEQ_UNDEFINED)
1432 && assetsSeq != delta.assetsSeq) {
1433 changed |= ActivityInfo.CONFIG_ASSETS_PATHS;
1434 }
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001435
Bryce Lee7566d762017-03-30 09:34:15 -07001436 // Make sure that one of the values is not null and that they are not equal.
1437 if ((compareUndefined || delta.appBounds != null)
1438 && appBounds != delta.appBounds
Bryce Lee658d9842017-07-28 08:33:36 -07001439 && (appBounds == null || (!publicOnly && !appBounds.equals(delta.appBounds))
1440 || (publicOnly && (appBounds.width() != delta.appBounds.width()
1441 || appBounds.height() != delta.appBounds.height())))) {
Bryce Lee0e4a6df2017-07-27 14:06:22 -07001442 changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
Bryce Lee7566d762017-03-30 09:34:15 -07001443 }
1444
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001445 return changed;
1446 }
1447
1448 /**
Alan Viveretteac85f902016-03-11 15:15:51 -05001449 * Determines if a new resource needs to be loaded from the bit set of
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001450 * configuration changes returned by {@link #updateFrom(Configuration)}.
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -07001451 *
Alan Viveretteac85f902016-03-11 15:15:51 -05001452 * @param configChanges the mask of changes configurations as returned by
1453 * {@link #updateFrom(Configuration)}
1454 * @param interestingChanges the configuration changes that the resource
1455 * can handle as given in
1456 * {@link android.util.TypedValue#changingConfigurations}
1457 * @return {@code true} if the resource needs to be loaded, {@code false}
1458 * otherwise
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001459 */
Alan Viveretteac85f902016-03-11 15:15:51 -05001460 public static boolean needNewResources(@Config int configChanges,
1461 @Config int interestingChanges) {
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001462 // CONFIG_ASSETS_PATHS and CONFIG_FONT_SCALE are higher level configuration changes that
1463 // all resources are subject to change with.
1464 interestingChanges = interestingChanges | ActivityInfo.CONFIG_ASSETS_PATHS
1465 | ActivityInfo.CONFIG_FONT_SCALE;
1466 return (configChanges & interestingChanges) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 }
Amith Yamasanid8415f42013-08-07 20:15:10 -07001468
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001470 * @hide Return true if the sequence of 'other' is better than this. Assumes
1471 * that 'this' is your current sequence and 'other' is a new one you have
1472 * received some how and want to compare with what you have.
1473 */
1474 public boolean isOtherSeqNewer(Configuration other) {
1475 if (other == null) {
1476 // Sanity check.
1477 return false;
1478 }
1479 if (other.seq == 0) {
1480 // If the other sequence is not specified, then we must assume
1481 // it is newer since we don't know any better.
1482 return true;
1483 }
1484 if (seq == 0) {
1485 // If this sequence is not specified, then we also consider the
1486 // other is better. Yes we have a preference for other. Sue us.
1487 return true;
1488 }
1489 int diff = other.seq - seq;
1490 if (diff > 0x10000) {
1491 // If there has been a sufficiently large jump, assume the
1492 // sequence has wrapped around.
1493 return false;
1494 }
1495 return diff > 0;
1496 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -07001497
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001498 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001499 * Parcelable methods
1500 */
1501 public int describeContents() {
1502 return 0;
1503 }
1504
1505 public void writeToParcel(Parcel dest, int flags) {
1506 dest.writeFloat(fontScale);
1507 dest.writeInt(mcc);
1508 dest.writeInt(mnc);
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001509
1510 fixUpLocaleList();
1511 final int localeListSize = mLocaleList.size();
1512 dest.writeInt(localeListSize);
1513 for (int i = 0; i < localeListSize; ++i) {
1514 final Locale l = mLocaleList.get(i);
1515 dest.writeString(l.toLanguageTag());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001517
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001518 if(userSetLocale) {
1519 dest.writeInt(1);
1520 } else {
1521 dest.writeInt(0);
1522 }
1523 dest.writeInt(touchscreen);
1524 dest.writeInt(keyboard);
1525 dest.writeInt(keyboardHidden);
1526 dest.writeInt(hardKeyboardHidden);
1527 dest.writeInt(navigation);
Dianne Hackborn93e462b2009-09-15 22:50:40 -07001528 dest.writeInt(navigationHidden);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001529 dest.writeInt(orientation);
Dianne Hackborn723738c2009-06-25 19:48:04 -07001530 dest.writeInt(screenLayout);
Romain Guy48327452017-01-23 17:03:35 -08001531 dest.writeInt(colorMode);
Tobias Haamel27b28b32010-02-09 23:09:17 +01001532 dest.writeInt(uiMode);
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001533 dest.writeInt(screenWidthDp);
1534 dest.writeInt(screenHeightDp);
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001535 dest.writeInt(smallestScreenWidthDp);
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001536 dest.writeInt(densityDpi);
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001537 dest.writeInt(compatScreenWidthDp);
1538 dest.writeInt(compatScreenHeightDp);
1539 dest.writeInt(compatSmallestScreenWidthDp);
Bryce Lee7566d762017-03-30 09:34:15 -07001540 dest.writeValue(appBounds);
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001541 dest.writeInt(assetsSeq);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001542 dest.writeInt(seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001543 }
1544
Dianne Hackborn694f79b2010-03-17 19:44:59 -07001545 public void readFromParcel(Parcel source) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001546 fontScale = source.readFloat();
1547 mcc = source.readInt();
1548 mnc = source.readInt();
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001549
1550 final int localeListSize = source.readInt();
1551 final Locale[] localeArray = new Locale[localeListSize];
1552 for (int i = 0; i < localeListSize; ++i) {
1553 localeArray[i] = Locale.forLanguageTag(source.readString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001554 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001555 mLocaleList = new LocaleList(localeArray);
Roozbeh Pournaderfee44842016-02-04 15:24:24 -08001556 locale = mLocaleList.get(0);
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001557
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 userSetLocale = (source.readInt()==1);
1559 touchscreen = source.readInt();
1560 keyboard = source.readInt();
1561 keyboardHidden = source.readInt();
1562 hardKeyboardHidden = source.readInt();
1563 navigation = source.readInt();
Dianne Hackborn93e462b2009-09-15 22:50:40 -07001564 navigationHidden = source.readInt();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001565 orientation = source.readInt();
Dianne Hackborn723738c2009-06-25 19:48:04 -07001566 screenLayout = source.readInt();
Romain Guy48327452017-01-23 17:03:35 -08001567 colorMode = source.readInt();
Tobias Haamel27b28b32010-02-09 23:09:17 +01001568 uiMode = source.readInt();
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001569 screenWidthDp = source.readInt();
1570 screenHeightDp = source.readInt();
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001571 smallestScreenWidthDp = source.readInt();
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001572 densityDpi = source.readInt();
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001573 compatScreenWidthDp = source.readInt();
1574 compatScreenHeightDp = source.readInt();
1575 compatSmallestScreenWidthDp = source.readInt();
Bryce Lee7566d762017-03-30 09:34:15 -07001576 appBounds = (Rect) source.readValue(null);
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001577 assetsSeq = source.readInt();
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001578 seq = source.readInt();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001579 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -07001580
Dianne Hackborn694f79b2010-03-17 19:44:59 -07001581 public static final Parcelable.Creator<Configuration> CREATOR
1582 = new Parcelable.Creator<Configuration>() {
1583 public Configuration createFromParcel(Parcel source) {
1584 return new Configuration(source);
1585 }
1586
1587 public Configuration[] newArray(int size) {
1588 return new Configuration[size];
1589 }
1590 };
1591
1592 /**
1593 * Construct this Configuration object, reading from the Parcel.
1594 */
1595 private Configuration(Parcel source) {
1596 readFromParcel(source);
1597 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001598
1599 public int compareTo(Configuration that) {
1600 int n;
1601 float a = this.fontScale;
1602 float b = that.fontScale;
1603 if (a < b) return -1;
1604 if (a > b) return 1;
1605 n = this.mcc - that.mcc;
1606 if (n != 0) return n;
1607 n = this.mnc - that.mnc;
1608 if (n != 0) return n;
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001609
1610 fixUpLocaleList();
1611 that.fixUpLocaleList();
1612 // for backward compatibility, we consider an empty locale list to be greater
1613 // than any non-empty locale list.
1614 if (this.mLocaleList.isEmpty()) {
1615 if (!that.mLocaleList.isEmpty()) return 1;
1616 } else if (that.mLocaleList.isEmpty()) {
Dianne Hackborna8397032010-03-12 10:52:22 -08001617 return -1;
1618 } else {
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001619 final int minSize = Math.min(this.mLocaleList.size(), that.mLocaleList.size());
1620 for (int i = 0; i < minSize; ++i) {
1621 final Locale thisLocale = this.mLocaleList.get(i);
1622 final Locale thatLocale = that.mLocaleList.get(i);
1623 n = thisLocale.getLanguage().compareTo(thatLocale.getLanguage());
1624 if (n != 0) return n;
1625 n = thisLocale.getCountry().compareTo(thatLocale.getCountry());
1626 if (n != 0) return n;
1627 n = thisLocale.getVariant().compareTo(thatLocale.getVariant());
1628 if (n != 0) return n;
1629 n = thisLocale.toLanguageTag().compareTo(thatLocale.toLanguageTag());
1630 if (n != 0) return n;
1631 }
1632 n = this.mLocaleList.size() - that.mLocaleList.size();
Dianne Hackborna8397032010-03-12 10:52:22 -08001633 if (n != 0) return n;
1634 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001635
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001636 n = this.touchscreen - that.touchscreen;
1637 if (n != 0) return n;
1638 n = this.keyboard - that.keyboard;
1639 if (n != 0) return n;
1640 n = this.keyboardHidden - that.keyboardHidden;
1641 if (n != 0) return n;
1642 n = this.hardKeyboardHidden - that.hardKeyboardHidden;
1643 if (n != 0) return n;
1644 n = this.navigation - that.navigation;
1645 if (n != 0) return n;
Dianne Hackborn93e462b2009-09-15 22:50:40 -07001646 n = this.navigationHidden - that.navigationHidden;
1647 if (n != 0) return n;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001648 n = this.orientation - that.orientation;
Dianne Hackborn723738c2009-06-25 19:48:04 -07001649 if (n != 0) return n;
Romain Guy48327452017-01-23 17:03:35 -08001650 n = this.colorMode - that.colorMode;
Romain Guyc9ba5592017-01-18 16:34:42 -08001651 if (n != 0) return n;
Dianne Hackborn723738c2009-06-25 19:48:04 -07001652 n = this.screenLayout - that.screenLayout;
Tobias Haamel27b28b32010-02-09 23:09:17 +01001653 if (n != 0) return n;
1654 n = this.uiMode - that.uiMode;
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001655 if (n != 0) return n;
1656 n = this.screenWidthDp - that.screenWidthDp;
1657 if (n != 0) return n;
1658 n = this.screenHeightDp - that.screenHeightDp;
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001659 if (n != 0) return n;
1660 n = this.smallestScreenWidthDp - that.smallestScreenWidthDp;
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001661 if (n != 0) return n;
1662 n = this.densityDpi - that.densityDpi;
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001663 if (n != 0) return n;
1664 n = this.assetsSeq - that.assetsSeq;
Bryce Leec5fe0ee2017-06-30 09:03:09 -07001665 if (n != 0) return n;
1666
1667 if (this.appBounds == null && that.appBounds != null) {
1668 return 1;
1669 } else if (this.appBounds != null && that.appBounds == null) {
1670 return -1;
1671 } else if (this.appBounds != null && that.appBounds != null) {
1672 n = this.appBounds.left - that.appBounds.left;
1673 if (n != 0) return n;
1674 n = this.appBounds.top - that.appBounds.top;
1675 if (n != 0) return n;
1676 n = this.appBounds.right - that.appBounds.right;
1677 if (n != 0) return n;
1678 n = this.appBounds.bottom - that.appBounds.bottom;
1679 if (n != 0) return n;
1680 }
1681
1682 // if (n != 0) return n;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001683 return n;
1684 }
1685
1686 public boolean equals(Configuration that) {
1687 if (that == null) return false;
1688 if (that == this) return true;
1689 return this.compareTo(that) == 0;
1690 }
1691
1692 public boolean equals(Object that) {
1693 try {
1694 return equals((Configuration)that);
1695 } catch (ClassCastException e) {
1696 }
1697 return false;
1698 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001699
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001700 public int hashCode() {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001701 int result = 17;
1702 result = 31 * result + Float.floatToIntBits(fontScale);
1703 result = 31 * result + mcc;
1704 result = 31 * result + mnc;
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001705 result = 31 * result + mLocaleList.hashCode();
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001706 result = 31 * result + touchscreen;
1707 result = 31 * result + keyboard;
1708 result = 31 * result + keyboardHidden;
1709 result = 31 * result + hardKeyboardHidden;
1710 result = 31 * result + navigation;
1711 result = 31 * result + navigationHidden;
1712 result = 31 * result + orientation;
1713 result = 31 * result + screenLayout;
Romain Guy48327452017-01-23 17:03:35 -08001714 result = 31 * result + colorMode;
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001715 result = 31 * result + uiMode;
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001716 result = 31 * result + screenWidthDp;
1717 result = 31 * result + screenHeightDp;
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001718 result = 31 * result + smallestScreenWidthDp;
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001719 result = 31 * result + densityDpi;
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001720 result = 31 * result + assetsSeq;
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001721 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001722 }
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001723
1724 /**
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001725 * Get the locale list. This is the preferred way for getting the locales (instead of using
1726 * the direct accessor to {@link #locale}, which would only provide the primary locale).
1727 *
1728 * @return The locale list.
1729 */
Adam Lesinskib61e4052016-05-19 18:23:05 -07001730 public @NonNull LocaleList getLocales() {
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001731 fixUpLocaleList();
1732 return mLocaleList;
1733 }
1734
1735 /**
1736 * Set the locale list. This is the preferred way for setting up the locales (instead of using
1737 * the direct accessor or {@link #setLocale(Locale)}). This will also set the layout direction
1738 * according to the first locale in the list.
1739 *
1740 * Note that the layout direction will always come from the first locale in the locale list,
1741 * even if the locale is not supported by the resources (the resources may only support
1742 * another locale further down the list which has a different direction).
1743 *
1744 * @param locales The locale list. If null, an empty LocaleList will be assigned.
1745 */
1746 public void setLocales(@Nullable LocaleList locales) {
1747 mLocaleList = locales == null ? LocaleList.getEmptyLocaleList() : locales;
Roozbeh Pournaderfee44842016-02-04 15:24:24 -08001748 locale = mLocaleList.get(0);
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001749 setLayoutDirection(locale);
1750 }
1751
1752 /**
1753 * Set the locale list to a list of just one locale. This will also set the layout direction
1754 * according to the locale.
1755 *
1756 * Note that after this is run, calling <code>.equals()</code> on the input locale and the
1757 * {@link #locale} attribute would return <code>true</code> if they are not null, but there is
1758 * no guarantee that they would be the same object.
1759 *
1760 * See also the note about layout direction in {@link #setLocales(LocaleList)}.
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001761 *
1762 * @param loc The locale. Can be null.
1763 */
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001764 public void setLocale(@Nullable Locale loc) {
Raph Levien10ea92a2016-05-02 12:56:01 -07001765 setLocales(loc == null ? LocaleList.getEmptyLocaleList() : new LocaleList(loc));
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001766 }
1767
1768 /**
Seigo Nonakabd5cac62016-05-13 15:11:37 +09001769 * @hide
1770 *
Bryce Lee7566d762017-03-30 09:34:15 -07001771 * Helper method for setting the app bounds.
1772 */
1773 public void setAppBounds(Rect rect) {
1774 if (rect == null) {
1775 appBounds = null;
1776 return;
1777 }
1778
1779 setAppBounds(rect.left, rect.top, rect.right, rect.bottom);
1780 }
1781
1782 /**
1783 * @hide
1784 *
1785 * Helper method for setting the app bounds.
1786 */
1787 public void setAppBounds(int left, int top, int right, int bottom) {
1788 if (appBounds == null) {
1789 appBounds = new Rect();
1790 }
1791
1792 appBounds.set(left, top, right, bottom);
1793 }
1794
1795 /**
1796 * @hide
1797 *
Seigo Nonakabd5cac62016-05-13 15:11:37 +09001798 * Clears the locale without changing layout direction.
1799 */
1800 public void clearLocales() {
1801 mLocaleList = LocaleList.getEmptyLocaleList();
1802 locale = null;
1803 }
1804
1805 /**
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001806 * Return the layout direction. Will be either {@link View#LAYOUT_DIRECTION_LTR} or
1807 * {@link View#LAYOUT_DIRECTION_RTL}.
1808 *
Dianne Hackbornf1ae2692013-04-19 14:09:37 -07001809 * @return Returns {@link View#LAYOUT_DIRECTION_RTL} if the configuration
1810 * is {@link #SCREENLAYOUT_LAYOUTDIR_RTL}, otherwise {@link View#LAYOUT_DIRECTION_LTR}.
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001811 */
1812 public int getLayoutDirection() {
Dianne Hackbornf1ae2692013-04-19 14:09:37 -07001813 return (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK) == SCREENLAYOUT_LAYOUTDIR_RTL
1814 ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001815 }
1816
1817 /**
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001818 * Set the layout direction from a Locale.
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001819 *
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001820 * @param loc The Locale. If null will set the layout direction to
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001821 * {@link View#LAYOUT_DIRECTION_LTR}. If not null will set it to the layout direction
1822 * corresponding to the Locale.
1823 *
John Spurlockbc4cf002015-03-24 21:51:20 -04001824 * @see View#LAYOUT_DIRECTION_LTR
1825 * @see View#LAYOUT_DIRECTION_RTL
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001826 */
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001827 public void setLayoutDirection(Locale loc) {
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001828 // There is a "1" difference between the configuration values for
1829 // layout direction and View constants for layout direction, just add "1".
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001830 final int layoutDirection = 1 + TextUtils.getLayoutDirectionFromLocale(loc);
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001831 screenLayout = (screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK)|
1832 (layoutDirection << SCREENLAYOUT_LAYOUTDIR_SHIFT);
1833 }
1834
1835 private static int getScreenLayoutNoDirection(int screenLayout) {
1836 return screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK;
1837 }
Adam Lesinski2c749d22014-06-04 13:00:29 -07001838
1839 /**
Adam Powell49e7ff92015-05-14 16:18:53 -07001840 * Return whether the screen has a round shape. Apps may choose to change styling based
1841 * on this property, such as the alignment or layout of text or informational icons.
1842 *
1843 * @return true if the screen is rounded, false otherwise
1844 */
1845 public boolean isScreenRound() {
1846 return (screenLayout & SCREENLAYOUT_ROUND_MASK) == SCREENLAYOUT_ROUND_YES;
1847 }
1848
1849 /**
Romain Guye89d0bb2017-06-20 12:23:42 -07001850 * Return whether the screen has a wide color gamut and wide color gamut rendering
1851 * is supported by this device.
Romain Guyc9ba5592017-01-18 16:34:42 -08001852 *
Romain Guye89d0bb2017-06-20 12:23:42 -07001853 * @return true if the screen has a wide color gamut and wide color gamut rendering
1854 * is supported, false otherwise
Romain Guyc9ba5592017-01-18 16:34:42 -08001855 */
1856 public boolean isScreenWideColorGamut() {
Romain Guy48327452017-01-23 17:03:35 -08001857 return (colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) == COLOR_MODE_WIDE_COLOR_GAMUT_YES;
Romain Guyc9ba5592017-01-18 16:34:42 -08001858 }
1859
1860 /**
1861 * Return whether the screen has a high dynamic range.
1862 *
1863 * @return true if the screen has a high dynamic range, false otherwise
1864 */
1865 public boolean isScreenHdr() {
Romain Guy48327452017-01-23 17:03:35 -08001866 return (colorMode & COLOR_MODE_HDR_MASK) == COLOR_MODE_HDR_YES;
Romain Guyc9ba5592017-01-18 16:34:42 -08001867 }
1868
1869 /**
Adam Lesinski2c749d22014-06-04 13:00:29 -07001870 *
1871 * @hide
1872 */
Roozbeh Pournader47f71a62015-11-07 11:55:38 -08001873 public static String localesToResourceQualifier(LocaleList locs) {
Roozbeh Pournader309ebd62016-06-17 22:13:12 -07001874 final StringBuilder sb = new StringBuilder();
Roozbeh Pournader47f71a62015-11-07 11:55:38 -08001875 for (int i = 0; i < locs.size(); i++) {
Roozbeh Pournader309ebd62016-06-17 22:13:12 -07001876 final Locale loc = locs.get(i);
1877 final int l = loc.getLanguage().length();
1878 if (l == 0) {
1879 continue;
1880 }
1881 final int s = loc.getScript().length();
1882 final int c = loc.getCountry().length();
1883 final int v = loc.getVariant().length();
1884 // We ignore locale extensions, since they are not supported by AAPT
1885
1886 if (sb.length() != 0) {
1887 sb.append(",");
1888 }
1889 if (l == 2 && s == 0 && (c == 0 || c == 2) && v == 0) {
1890 // Traditional locale format: xx or xx-rYY
Roozbeh Pournader47f71a62015-11-07 11:55:38 -08001891 sb.append(loc.getLanguage());
Roozbeh Pournader309ebd62016-06-17 22:13:12 -07001892 if (c == 2) {
Roozbeh Pournader47f71a62015-11-07 11:55:38 -08001893 sb.append("-r").append(loc.getCountry());
Roozbeh Pournader309ebd62016-06-17 22:13:12 -07001894 }
1895 } else {
1896 sb.append("b+");
1897 sb.append(loc.getLanguage());
1898 if (s != 0) {
1899 sb.append("+");
1900 sb.append(loc.getScript());
1901 }
1902 if (c != 0) {
1903 sb.append("+");
1904 sb.append(loc.getCountry());
1905 }
1906 if (v != 0) {
1907 sb.append("+");
1908 sb.append(loc.getVariant());
Adam Lesinski2c749d22014-06-04 13:00:29 -07001909 }
1910 }
1911 }
1912 return sb.toString();
1913 }
1914
1915
1916 /**
1917 * Returns a string representation of the configuration that can be parsed
1918 * by build tools (like AAPT).
1919 *
Adam Lesinski2c749d22014-06-04 13:00:29 -07001920 * @hide
1921 */
1922 public static String resourceQualifierString(Configuration config) {
1923 ArrayList<String> parts = new ArrayList<String>();
1924
1925 if (config.mcc != 0) {
Adam Lesinski90865622014-10-16 18:18:10 -07001926 parts.add("mcc" + config.mcc);
Adam Lesinski2c749d22014-06-04 13:00:29 -07001927 if (config.mnc != 0) {
Adam Lesinski90865622014-10-16 18:18:10 -07001928 parts.add("mnc" + config.mnc);
Adam Lesinski2c749d22014-06-04 13:00:29 -07001929 }
1930 }
1931
Roozbeh Pournader47f71a62015-11-07 11:55:38 -08001932 if (!config.mLocaleList.isEmpty()) {
Roozbeh Pournader417bbe02015-11-09 17:09:15 -08001933 final String resourceQualifier = localesToResourceQualifier(config.mLocaleList);
1934 if (!resourceQualifier.isEmpty()) {
1935 parts.add(resourceQualifier);
1936 }
Adam Lesinski2c749d22014-06-04 13:00:29 -07001937 }
1938
1939 switch (config.screenLayout & Configuration.SCREENLAYOUT_LAYOUTDIR_MASK) {
1940 case Configuration.SCREENLAYOUT_LAYOUTDIR_LTR:
1941 parts.add("ldltr");
1942 break;
1943 case Configuration.SCREENLAYOUT_LAYOUTDIR_RTL:
1944 parts.add("ldrtl");
1945 break;
1946 default:
1947 break;
1948 }
1949
1950 if (config.smallestScreenWidthDp != 0) {
1951 parts.add("sw" + config.smallestScreenWidthDp + "dp");
1952 }
1953
1954 if (config.screenWidthDp != 0) {
1955 parts.add("w" + config.screenWidthDp + "dp");
1956 }
1957
1958 if (config.screenHeightDp != 0) {
1959 parts.add("h" + config.screenHeightDp + "dp");
1960 }
1961
1962 switch (config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) {
1963 case Configuration.SCREENLAYOUT_SIZE_SMALL:
1964 parts.add("small");
1965 break;
1966 case Configuration.SCREENLAYOUT_SIZE_NORMAL:
1967 parts.add("normal");
1968 break;
1969 case Configuration.SCREENLAYOUT_SIZE_LARGE:
1970 parts.add("large");
1971 break;
1972 case Configuration.SCREENLAYOUT_SIZE_XLARGE:
1973 parts.add("xlarge");
1974 break;
1975 default:
1976 break;
1977 }
1978
1979 switch (config.screenLayout & Configuration.SCREENLAYOUT_LONG_MASK) {
1980 case Configuration.SCREENLAYOUT_LONG_YES:
1981 parts.add("long");
1982 break;
1983 case Configuration.SCREENLAYOUT_LONG_NO:
1984 parts.add("notlong");
1985 break;
1986 default:
1987 break;
1988 }
1989
Adam Powell49e7ff92015-05-14 16:18:53 -07001990 switch (config.screenLayout & Configuration.SCREENLAYOUT_ROUND_MASK) {
1991 case Configuration.SCREENLAYOUT_ROUND_YES:
1992 parts.add("round");
1993 break;
1994 case Configuration.SCREENLAYOUT_ROUND_NO:
1995 parts.add("notround");
1996 break;
1997 default:
1998 break;
1999 }
2000
Romain Guy48327452017-01-23 17:03:35 -08002001 switch (config.colorMode & Configuration.COLOR_MODE_HDR_MASK) {
2002 case Configuration.COLOR_MODE_HDR_YES:
Romain Guyc9ba5592017-01-18 16:34:42 -08002003 parts.add("highdr");
2004 break;
Romain Guy48327452017-01-23 17:03:35 -08002005 case Configuration.COLOR_MODE_HDR_NO:
Romain Guyc9ba5592017-01-18 16:34:42 -08002006 parts.add("lowdr");
2007 break;
2008 default:
2009 break;
2010 }
2011
Romain Guy48327452017-01-23 17:03:35 -08002012 switch (config.colorMode & Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_MASK) {
2013 case Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_YES:
Romain Guyc9ba5592017-01-18 16:34:42 -08002014 parts.add("widecg");
2015 break;
Romain Guy48327452017-01-23 17:03:35 -08002016 case Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_NO:
Romain Guyc9ba5592017-01-18 16:34:42 -08002017 parts.add("nowidecg");
2018 break;
2019 default:
2020 break;
2021 }
2022
Adam Lesinski2c749d22014-06-04 13:00:29 -07002023 switch (config.orientation) {
2024 case Configuration.ORIENTATION_LANDSCAPE:
2025 parts.add("land");
2026 break;
2027 case Configuration.ORIENTATION_PORTRAIT:
2028 parts.add("port");
2029 break;
2030 default:
2031 break;
2032 }
2033
2034 switch (config.uiMode & Configuration.UI_MODE_TYPE_MASK) {
2035 case Configuration.UI_MODE_TYPE_APPLIANCE:
2036 parts.add("appliance");
2037 break;
2038 case Configuration.UI_MODE_TYPE_DESK:
2039 parts.add("desk");
2040 break;
2041 case Configuration.UI_MODE_TYPE_TELEVISION:
2042 parts.add("television");
2043 break;
2044 case Configuration.UI_MODE_TYPE_CAR:
2045 parts.add("car");
2046 break;
2047 case Configuration.UI_MODE_TYPE_WATCH:
2048 parts.add("watch");
2049 break;
Zak Cohen1a6acdb2016-12-12 15:21:21 -08002050 case Configuration.UI_MODE_TYPE_VR_HEADSET:
2051 parts.add("vrheadset");
2052 break;
Adam Lesinski2c749d22014-06-04 13:00:29 -07002053 default:
2054 break;
2055 }
2056
2057 switch (config.uiMode & Configuration.UI_MODE_NIGHT_MASK) {
2058 case Configuration.UI_MODE_NIGHT_YES:
2059 parts.add("night");
2060 break;
2061 case Configuration.UI_MODE_NIGHT_NO:
2062 parts.add("notnight");
2063 break;
2064 default:
2065 break;
2066 }
2067
2068 switch (config.densityDpi) {
Adam Lesinski31245b42014-08-22 19:10:56 -07002069 case DENSITY_DPI_UNDEFINED:
Adam Lesinski2c749d22014-06-04 13:00:29 -07002070 break;
2071 case 120:
2072 parts.add("ldpi");
2073 break;
2074 case 160:
2075 parts.add("mdpi");
2076 break;
2077 case 213:
2078 parts.add("tvdpi");
2079 break;
2080 case 240:
2081 parts.add("hdpi");
2082 break;
2083 case 320:
2084 parts.add("xhdpi");
2085 break;
Adam Lesinskiebc3e4c2014-08-21 12:21:45 -07002086 case 480:
2087 parts.add("xxhdpi");
2088 break;
2089 case 640:
2090 parts.add("xxxhdpi");
2091 break;
Adam Lesinski31245b42014-08-22 19:10:56 -07002092 case DENSITY_DPI_ANY:
2093 parts.add("anydpi");
2094 break;
2095 case DENSITY_DPI_NONE:
2096 parts.add("nodpi");
Adam Lesinski2c749d22014-06-04 13:00:29 -07002097 default:
2098 parts.add(config.densityDpi + "dpi");
2099 break;
2100 }
2101
2102 switch (config.touchscreen) {
2103 case Configuration.TOUCHSCREEN_NOTOUCH:
2104 parts.add("notouch");
2105 break;
2106 case Configuration.TOUCHSCREEN_FINGER:
2107 parts.add("finger");
2108 break;
2109 default:
2110 break;
2111 }
2112
2113 switch (config.keyboardHidden) {
2114 case Configuration.KEYBOARDHIDDEN_NO:
2115 parts.add("keysexposed");
2116 break;
2117 case Configuration.KEYBOARDHIDDEN_YES:
2118 parts.add("keyshidden");
2119 break;
2120 case Configuration.KEYBOARDHIDDEN_SOFT:
2121 parts.add("keyssoft");
2122 break;
2123 default:
2124 break;
2125 }
2126
2127 switch (config.keyboard) {
2128 case Configuration.KEYBOARD_NOKEYS:
2129 parts.add("nokeys");
2130 break;
2131 case Configuration.KEYBOARD_QWERTY:
2132 parts.add("qwerty");
2133 break;
2134 case Configuration.KEYBOARD_12KEY:
2135 parts.add("12key");
2136 break;
2137 default:
2138 break;
2139 }
2140
2141 switch (config.navigationHidden) {
2142 case Configuration.NAVIGATIONHIDDEN_NO:
2143 parts.add("navexposed");
2144 break;
2145 case Configuration.NAVIGATIONHIDDEN_YES:
2146 parts.add("navhidden");
2147 break;
2148 default:
2149 break;
2150 }
2151
2152 switch (config.navigation) {
2153 case Configuration.NAVIGATION_NONAV:
2154 parts.add("nonav");
2155 break;
2156 case Configuration.NAVIGATION_DPAD:
2157 parts.add("dpad");
2158 break;
2159 case Configuration.NAVIGATION_TRACKBALL:
2160 parts.add("trackball");
2161 break;
2162 case Configuration.NAVIGATION_WHEEL:
2163 parts.add("wheel");
2164 break;
2165 default:
2166 break;
2167 }
2168
Adam Lesinskiebc3e4c2014-08-21 12:21:45 -07002169 parts.add("v" + Build.VERSION.RESOURCES_SDK_INT);
Adam Lesinski2c749d22014-06-04 13:00:29 -07002170 return TextUtils.join("-", parts);
2171 }
Adam Lesinski7f61e962014-09-02 16:43:52 -07002172
2173 /**
2174 * Generate a delta Configuration between <code>base</code> and <code>change</code>. The
2175 * resulting delta can be used with {@link #updateFrom(Configuration)}.
2176 * <p />
2177 * Caveat: If the any of the Configuration's members becomes undefined, then
2178 * {@link #updateFrom(Configuration)} will treat it as a no-op and not update that member.
2179 *
2180 * This is fine for device configurations as no member is ever undefined.
2181 * {@hide}
2182 */
2183 public static Configuration generateDelta(Configuration base, Configuration change) {
2184 final Configuration delta = new Configuration();
2185 if (base.fontScale != change.fontScale) {
2186 delta.fontScale = change.fontScale;
2187 }
2188
2189 if (base.mcc != change.mcc) {
2190 delta.mcc = change.mcc;
2191 }
2192
2193 if (base.mnc != change.mnc) {
2194 delta.mnc = change.mnc;
2195 }
2196
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002197 base.fixUpLocaleList();
2198 change.fixUpLocaleList();
2199 if (!base.mLocaleList.equals(change.mLocaleList)) {
2200 delta.mLocaleList = change.mLocaleList;
Adam Lesinski7f61e962014-09-02 16:43:52 -07002201 delta.locale = change.locale;
2202 }
2203
2204 if (base.touchscreen != change.touchscreen) {
2205 delta.touchscreen = change.touchscreen;
2206 }
2207
2208 if (base.keyboard != change.keyboard) {
2209 delta.keyboard = change.keyboard;
2210 }
2211
2212 if (base.keyboardHidden != change.keyboardHidden) {
2213 delta.keyboardHidden = change.keyboardHidden;
2214 }
2215
2216 if (base.navigation != change.navigation) {
2217 delta.navigation = change.navigation;
2218 }
2219
2220 if (base.navigationHidden != change.navigationHidden) {
2221 delta.navigationHidden = change.navigationHidden;
2222 }
2223
2224 if (base.orientation != change.orientation) {
2225 delta.orientation = change.orientation;
2226 }
2227
2228 if ((base.screenLayout & SCREENLAYOUT_SIZE_MASK) !=
2229 (change.screenLayout & SCREENLAYOUT_SIZE_MASK)) {
2230 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_SIZE_MASK;
2231 }
2232
2233 if ((base.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK) !=
2234 (change.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) {
2235 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
2236 }
2237
2238 if ((base.screenLayout & SCREENLAYOUT_LONG_MASK) !=
2239 (change.screenLayout & SCREENLAYOUT_LONG_MASK)) {
2240 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_LONG_MASK;
2241 }
2242
Adam Powell49e7ff92015-05-14 16:18:53 -07002243 if ((base.screenLayout & SCREENLAYOUT_ROUND_MASK) !=
2244 (change.screenLayout & SCREENLAYOUT_ROUND_MASK)) {
2245 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_ROUND_MASK;
2246 }
2247
Romain Guy48327452017-01-23 17:03:35 -08002248 if ((base.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) !=
2249 (change.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) {
2250 delta.colorMode |= change.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK;
Romain Guyc9ba5592017-01-18 16:34:42 -08002251 }
2252
Romain Guy48327452017-01-23 17:03:35 -08002253 if ((base.colorMode & COLOR_MODE_HDR_MASK) !=
2254 (change.colorMode & COLOR_MODE_HDR_MASK)) {
2255 delta.colorMode |= change.colorMode & COLOR_MODE_HDR_MASK;
Romain Guyc9ba5592017-01-18 16:34:42 -08002256 }
2257
Adam Lesinski7f61e962014-09-02 16:43:52 -07002258 if ((base.uiMode & UI_MODE_TYPE_MASK) != (change.uiMode & UI_MODE_TYPE_MASK)) {
2259 delta.uiMode |= change.uiMode & UI_MODE_TYPE_MASK;
2260 }
2261
2262 if ((base.uiMode & UI_MODE_NIGHT_MASK) != (change.uiMode & UI_MODE_NIGHT_MASK)) {
2263 delta.uiMode |= change.uiMode & UI_MODE_NIGHT_MASK;
2264 }
2265
2266 if (base.screenWidthDp != change.screenWidthDp) {
2267 delta.screenWidthDp = change.screenWidthDp;
2268 }
2269
2270 if (base.screenHeightDp != change.screenHeightDp) {
2271 delta.screenHeightDp = change.screenHeightDp;
2272 }
2273
2274 if (base.smallestScreenWidthDp != change.smallestScreenWidthDp) {
2275 delta.smallestScreenWidthDp = change.smallestScreenWidthDp;
2276 }
2277
2278 if (base.densityDpi != change.densityDpi) {
2279 delta.densityDpi = change.densityDpi;
2280 }
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01002281
2282 if (base.assetsSeq != change.assetsSeq) {
2283 delta.assetsSeq = change.assetsSeq;
2284 }
Adam Lesinski7f61e962014-09-02 16:43:52 -07002285 return delta;
2286 }
2287
2288 private static final String XML_ATTR_FONT_SCALE = "fs";
2289 private static final String XML_ATTR_MCC = "mcc";
2290 private static final String XML_ATTR_MNC = "mnc";
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002291 private static final String XML_ATTR_LOCALES = "locales";
Adam Lesinski7f61e962014-09-02 16:43:52 -07002292 private static final String XML_ATTR_TOUCHSCREEN = "touch";
2293 private static final String XML_ATTR_KEYBOARD = "key";
2294 private static final String XML_ATTR_KEYBOARD_HIDDEN = "keyHid";
2295 private static final String XML_ATTR_HARD_KEYBOARD_HIDDEN = "hardKeyHid";
2296 private static final String XML_ATTR_NAVIGATION = "nav";
2297 private static final String XML_ATTR_NAVIGATION_HIDDEN = "navHid";
2298 private static final String XML_ATTR_ORIENTATION = "ori";
Bryce Leec1f2f2a2017-06-22 15:29:42 -07002299 private static final String XML_ATTR_ROTATION = "rot";
Adam Lesinski7f61e962014-09-02 16:43:52 -07002300 private static final String XML_ATTR_SCREEN_LAYOUT = "scrLay";
Romain Guy48327452017-01-23 17:03:35 -08002301 private static final String XML_ATTR_COLOR_MODE = "clrMod";
Adam Lesinski7f61e962014-09-02 16:43:52 -07002302 private static final String XML_ATTR_UI_MODE = "ui";
2303 private static final String XML_ATTR_SCREEN_WIDTH = "width";
2304 private static final String XML_ATTR_SCREEN_HEIGHT = "height";
2305 private static final String XML_ATTR_SMALLEST_WIDTH = "sw";
2306 private static final String XML_ATTR_DENSITY = "density";
Bryce Lee7566d762017-03-30 09:34:15 -07002307 private static final String XML_ATTR_APP_BOUNDS = "app_bounds";
Adam Lesinski7f61e962014-09-02 16:43:52 -07002308
2309 /**
2310 * Reads the attributes corresponding to Configuration member fields from the Xml parser.
2311 * The parser is expected to be on a tag which has Configuration attributes.
2312 *
2313 * @param parser The Xml parser from which to read attributes.
2314 * @param configOut The Configuration to populate from the Xml attributes.
2315 * {@hide}
2316 */
2317 public static void readXmlAttrs(XmlPullParser parser, Configuration configOut)
2318 throws XmlPullParserException, IOException {
2319 configOut.fontScale = Float.intBitsToFloat(
2320 XmlUtils.readIntAttribute(parser, XML_ATTR_FONT_SCALE, 0));
2321 configOut.mcc = XmlUtils.readIntAttribute(parser, XML_ATTR_MCC, 0);
2322 configOut.mnc = XmlUtils.readIntAttribute(parser, XML_ATTR_MNC, 0);
2323
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002324 final String localesStr = XmlUtils.readStringAttribute(parser, XML_ATTR_LOCALES);
2325 configOut.mLocaleList = LocaleList.forLanguageTags(localesStr);
Roozbeh Pournaderfee44842016-02-04 15:24:24 -08002326 configOut.locale = configOut.mLocaleList.get(0);
Adam Lesinski7f61e962014-09-02 16:43:52 -07002327
2328 configOut.touchscreen = XmlUtils.readIntAttribute(parser, XML_ATTR_TOUCHSCREEN,
2329 TOUCHSCREEN_UNDEFINED);
2330 configOut.keyboard = XmlUtils.readIntAttribute(parser, XML_ATTR_KEYBOARD,
2331 KEYBOARD_UNDEFINED);
2332 configOut.keyboardHidden = XmlUtils.readIntAttribute(parser, XML_ATTR_KEYBOARD_HIDDEN,
2333 KEYBOARDHIDDEN_UNDEFINED);
2334 configOut.hardKeyboardHidden =
2335 XmlUtils.readIntAttribute(parser, XML_ATTR_HARD_KEYBOARD_HIDDEN,
2336 HARDKEYBOARDHIDDEN_UNDEFINED);
2337 configOut.navigation = XmlUtils.readIntAttribute(parser, XML_ATTR_NAVIGATION,
2338 NAVIGATION_UNDEFINED);
2339 configOut.navigationHidden = XmlUtils.readIntAttribute(parser, XML_ATTR_NAVIGATION_HIDDEN,
2340 NAVIGATIONHIDDEN_UNDEFINED);
2341 configOut.orientation = XmlUtils.readIntAttribute(parser, XML_ATTR_ORIENTATION,
2342 ORIENTATION_UNDEFINED);
2343 configOut.screenLayout = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_LAYOUT,
2344 SCREENLAYOUT_UNDEFINED);
Romain Guy48327452017-01-23 17:03:35 -08002345 configOut.colorMode = XmlUtils.readIntAttribute(parser, XML_ATTR_COLOR_MODE,
2346 COLOR_MODE_UNDEFINED);
Adam Lesinski7f61e962014-09-02 16:43:52 -07002347 configOut.uiMode = XmlUtils.readIntAttribute(parser, XML_ATTR_UI_MODE, 0);
2348 configOut.screenWidthDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_WIDTH,
2349 SCREEN_WIDTH_DP_UNDEFINED);
2350 configOut.screenHeightDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_HEIGHT,
2351 SCREEN_HEIGHT_DP_UNDEFINED);
2352 configOut.smallestScreenWidthDp =
2353 XmlUtils.readIntAttribute(parser, XML_ATTR_SMALLEST_WIDTH,
2354 SMALLEST_SCREEN_WIDTH_DP_UNDEFINED);
2355 configOut.densityDpi = XmlUtils.readIntAttribute(parser, XML_ATTR_DENSITY,
2356 DENSITY_DPI_UNDEFINED);
Bryce Lee7566d762017-03-30 09:34:15 -07002357 configOut.appBounds =
2358 Rect.unflattenFromString(XmlUtils.readStringAttribute(parser, XML_ATTR_APP_BOUNDS));
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01002359
2360 // For persistence, we don't care about assetsSeq, so do not read it out.
Adam Lesinski7f61e962014-09-02 16:43:52 -07002361 }
2362
2363
2364 /**
2365 * Writes the Configuration's member fields as attributes into the XmlSerializer.
2366 * The serializer is expected to have already started a tag so that attributes can be
2367 * immediately written.
2368 *
2369 * @param xml The serializer to which to write the attributes.
2370 * @param config The Configuration whose member fields to write.
2371 * {@hide}
2372 */
2373 public static void writeXmlAttrs(XmlSerializer xml, Configuration config) throws IOException {
2374 XmlUtils.writeIntAttribute(xml, XML_ATTR_FONT_SCALE,
2375 Float.floatToIntBits(config.fontScale));
2376 if (config.mcc != 0) {
2377 XmlUtils.writeIntAttribute(xml, XML_ATTR_MCC, config.mcc);
2378 }
2379 if (config.mnc != 0) {
2380 XmlUtils.writeIntAttribute(xml, XML_ATTR_MNC, config.mnc);
2381 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002382 config.fixUpLocaleList();
2383 if (!config.mLocaleList.isEmpty()) {
2384 XmlUtils.writeStringAttribute(xml, XML_ATTR_LOCALES, config.mLocaleList.toLanguageTags());
Adam Lesinski7f61e962014-09-02 16:43:52 -07002385 }
2386 if (config.touchscreen != TOUCHSCREEN_UNDEFINED) {
2387 XmlUtils.writeIntAttribute(xml, XML_ATTR_TOUCHSCREEN, config.touchscreen);
2388 }
2389 if (config.keyboard != KEYBOARD_UNDEFINED) {
2390 XmlUtils.writeIntAttribute(xml, XML_ATTR_KEYBOARD, config.keyboard);
2391 }
2392 if (config.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED) {
2393 XmlUtils.writeIntAttribute(xml, XML_ATTR_KEYBOARD_HIDDEN, config.keyboardHidden);
2394 }
2395 if (config.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED) {
2396 XmlUtils.writeIntAttribute(xml, XML_ATTR_HARD_KEYBOARD_HIDDEN,
2397 config.hardKeyboardHidden);
2398 }
2399 if (config.navigation != NAVIGATION_UNDEFINED) {
2400 XmlUtils.writeIntAttribute(xml, XML_ATTR_NAVIGATION, config.navigation);
2401 }
2402 if (config.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED) {
2403 XmlUtils.writeIntAttribute(xml, XML_ATTR_NAVIGATION_HIDDEN, config.navigationHidden);
2404 }
2405 if (config.orientation != ORIENTATION_UNDEFINED) {
2406 XmlUtils.writeIntAttribute(xml, XML_ATTR_ORIENTATION, config.orientation);
2407 }
2408 if (config.screenLayout != SCREENLAYOUT_UNDEFINED) {
2409 XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_LAYOUT, config.screenLayout);
2410 }
Romain Guy48327452017-01-23 17:03:35 -08002411 if (config.colorMode != COLOR_MODE_UNDEFINED) {
2412 XmlUtils.writeIntAttribute(xml, XML_ATTR_COLOR_MODE, config.colorMode);
Romain Guyc9ba5592017-01-18 16:34:42 -08002413 }
Adam Lesinski7f61e962014-09-02 16:43:52 -07002414 if (config.uiMode != 0) {
2415 XmlUtils.writeIntAttribute(xml, XML_ATTR_UI_MODE, config.uiMode);
2416 }
2417 if (config.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
2418 XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_WIDTH, config.screenWidthDp);
2419 }
2420 if (config.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
2421 XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_HEIGHT, config.screenHeightDp);
2422 }
2423 if (config.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
2424 XmlUtils.writeIntAttribute(xml, XML_ATTR_SMALLEST_WIDTH, config.smallestScreenWidthDp);
2425 }
2426 if (config.densityDpi != DENSITY_DPI_UNDEFINED) {
2427 XmlUtils.writeIntAttribute(xml, XML_ATTR_DENSITY, config.densityDpi);
2428 }
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01002429
Bryce Lee7566d762017-03-30 09:34:15 -07002430 if (config.appBounds != null) {
2431 XmlUtils.writeStringAttribute(xml, XML_ATTR_APP_BOUNDS,
2432 config.appBounds.flattenToString());
2433 }
2434
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01002435 // For persistence, we do not care about assetsSeq, so do not write it out.
Adam Lesinski7f61e962014-09-02 16:43:52 -07002436 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002437}