blob: fa5ad39789ddb54c71b2e479644bdc36cc7229af [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
Dianne Hackborn337e01a2018-02-27 17:16:37 -080019import static android.content.ConfigurationProto.COLOR_MODE;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070020import static android.content.ConfigurationProto.DENSITY_DPI;
21import static android.content.ConfigurationProto.FONT_SCALE;
Dianne Hackbornbf5ba6b2018-02-20 10:31:02 -080022import static android.content.ConfigurationProto.HARD_KEYBOARD_HIDDEN;
Dianne Hackborn337e01a2018-02-27 17:16:37 -080023import static android.content.ConfigurationProto.KEYBOARD;
Dianne Hackbornbf5ba6b2018-02-20 10:31:02 -080024import static android.content.ConfigurationProto.KEYBOARD_HIDDEN;
25import static android.content.ConfigurationProto.LOCALES;
Varun Shahbd0ce4d2019-09-10 15:51:37 -040026import static android.content.ConfigurationProto.LOCALE_LIST;
Dianne Hackbornbf5ba6b2018-02-20 10:31:02 -080027import static android.content.ConfigurationProto.MCC;
28import static android.content.ConfigurationProto.MNC;
29import static android.content.ConfigurationProto.NAVIGATION;
30import static android.content.ConfigurationProto.NAVIGATION_HIDDEN;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070031import static android.content.ConfigurationProto.ORIENTATION;
32import static android.content.ConfigurationProto.SCREEN_HEIGHT_DP;
33import static android.content.ConfigurationProto.SCREEN_LAYOUT;
34import static android.content.ConfigurationProto.SCREEN_WIDTH_DP;
35import static android.content.ConfigurationProto.SMALLEST_SCREEN_WIDTH_DP;
Dianne Hackbornbf5ba6b2018-02-20 10:31:02 -080036import static android.content.ConfigurationProto.TOUCHSCREEN;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070037import static android.content.ConfigurationProto.UI_MODE;
38import static android.content.ConfigurationProto.WINDOW_CONFIGURATION;
Dianne Hackbornbf5ba6b2018-02-20 10:31:02 -080039import static android.content.ResourcesConfigurationProto.CONFIGURATION;
40import static android.content.ResourcesConfigurationProto.SCREEN_HEIGHT_PX;
41import static android.content.ResourcesConfigurationProto.SCREEN_WIDTH_PX;
42import static android.content.ResourcesConfigurationProto.SDK_VERSION;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070043
Alan Viveretteac85f902016-03-11 15:15:51 -050044import android.annotation.IntDef;
45import android.annotation.NonNull;
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -070046import android.annotation.Nullable;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070047import android.annotation.TestApi;
Mathew Inwood5c0d3542018-08-14 13:54:31 +010048import android.annotation.UnsupportedAppUsage;
Wale Ogunwale822e5122017-07-26 06:02:24 -070049import android.app.WindowConfiguration;
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -070050import android.content.LocaleProto;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051import android.content.pm.ActivityInfo;
Alan Viveretteac85f902016-03-11 15:15:51 -050052import android.content.pm.ActivityInfo.Config;
Adam Lesinski2c749d22014-06-04 13:00:29 -070053import android.os.Build;
Yohei Yukawa23cbe852016-05-17 16:42:58 -070054import android.os.LocaleList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.os.Parcel;
56import android.os.Parcelable;
Fabrice Di Megliod3d9f3f2012-09-18 12:55:32 -070057import android.text.TextUtils;
Dianne Hackbornbf5ba6b2018-02-20 10:31:02 -080058import android.util.DisplayMetrics;
Varun Shah95fabaf2019-05-01 12:45:37 -070059import android.util.Slog;
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -070060import android.util.proto.ProtoInputStream;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070061import android.util.proto.ProtoOutputStream;
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -070062import android.util.proto.WireTypeMismatchException;
Fabrice Di Meglio3fb824b2012-02-28 17:58:31 -080063import android.view.View;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064
Romain Guye89d0bb2017-06-20 12:23:42 -070065import com.android.internal.util.XmlUtils;
66
67import org.xmlpull.v1.XmlPullParser;
68import org.xmlpull.v1.XmlPullParserException;
Romain Guye89d0bb2017-06-20 12:23:42 -070069
Adam Lesinski7f61e962014-09-02 16:43:52 -070070import java.io.IOException;
Alan Viveretteac85f902016-03-11 15:15:51 -050071import java.lang.annotation.Retention;
72import java.lang.annotation.RetentionPolicy;
Adam Lesinski2c749d22014-06-04 13:00:29 -070073import java.util.ArrayList;
Varun Shah95fabaf2019-05-01 12:45:37 -070074import java.util.IllformedLocaleException;
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -070075import java.util.List;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076import java.util.Locale;
77
78/**
79 * This class describes all device configuration information that can
80 * impact the resources the application retrieves. This includes both
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -070081 * user-specified configuration options (locale list and scaling) as well
Scott Main63848e32011-04-20 22:20:46 -070082 * as device configurations (such as input modes, screen size and screen orientation).
83 * <p>You can acquire this object from {@link Resources}, using {@link
84 * Resources#getConfiguration}. Thus, from an activity, you can get it by chaining the request
85 * with {@link android.app.Activity#getResources}:</p>
86 * <pre>Configuration config = getResources().getConfiguration();</pre>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087 */
88public final class Configuration implements Parcelable, Comparable<Configuration> {
Dianne Hackborn756220b2012-08-14 16:45:30 -070089 /** @hide */
90 public static final Configuration EMPTY = new Configuration();
91
Varun Shah95fabaf2019-05-01 12:45:37 -070092 private static final String TAG = "Configuration";
93
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094 /**
95 * Current user preference for the scaling factor for fonts, relative
96 * to the base density scaling.
97 */
98 public float fontScale;
99
100 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700101 * IMSI MCC (Mobile Country Code), corresponding to
102 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#MccQualifier">mcc</a>
103 * resource qualifier. 0 if undefined.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104 */
105 public int mcc;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700108 * IMSI MNC (Mobile Network Code), corresponding to
109 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#MccQualifier">mnc</a>
Mattias Petersson1d766b52011-10-07 09:33:52 +0200110 * resource qualifier. 0 if undefined. Note that the actual MNC may be 0; in order to check
111 * for this use the {@link #MNC_ZERO} symbol.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112 */
113 public int mnc;
Mattias Petersson1d766b52011-10-07 09:33:52 +0200114
115 /**
116 * Constant used to to represent MNC (Mobile Network Code) zero.
117 * 0 cannot be used, since it is used to represent an undefined MNC.
118 */
119 public static final int MNC_ZERO = 0xffff;
120
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700122 * Current user preference for the locale, corresponding to
123 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#LocaleQualifier">locale</a>
124 * resource qualifier.
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700125 *
126 * @deprecated Do not set or read this directly. Use {@link #getLocales()} and
Raph Levienb1638702016-04-27 11:02:12 -0700127 * {@link #setLocales(LocaleList)}. If only the primary locale is needed,
128 * <code>getLocales().get(0)</code> is now the preferred accessor.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129 */
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700130 @Deprecated public Locale locale;
131
132 private LocaleList mLocaleList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133
134 /**
Andy Stadlerf8a7cea2009-04-10 16:24:47 -0700135 * Locale should persist on setting. This is hidden because it is really
136 * questionable whether this is the right way to expose the functionality.
137 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100139 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 public boolean userSetLocale;
141
Romain Guyc9ba5592017-01-18 16:34:42 -0800142
Romain Guy48327452017-01-23 17:03:35 -0800143 /** Constant for {@link #colorMode}: bits that encode whether the screen is wide gamut. */
144 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_MASK = 0x3;
Romain Guyc9ba5592017-01-18 16:34:42 -0800145 /**
Romain Guy48327452017-01-23 17:03:35 -0800146 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800147 * indicating that it is unknown whether or not the screen is wide gamut.
148 */
Romain Guy48327452017-01-23 17:03:35 -0800149 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED = 0x0;
Romain Guyc9ba5592017-01-18 16:34:42 -0800150 /**
Romain Guy48327452017-01-23 17:03:35 -0800151 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800152 * indicating that the screen is not wide gamut.
153 * <p>Corresponds to the <code>-nowidecg</code> resource qualifier.</p>
154 */
Romain Guy48327452017-01-23 17:03:35 -0800155 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_NO = 0x1;
Romain Guyc9ba5592017-01-18 16:34:42 -0800156 /**
Romain Guy48327452017-01-23 17:03:35 -0800157 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800158 * indicating that the screen is wide gamut.
159 * <p>Corresponds to the <code>-widecg</code> resource qualifier.</p>
160 */
Romain Guy48327452017-01-23 17:03:35 -0800161 public static final int COLOR_MODE_WIDE_COLOR_GAMUT_YES = 0x2;
Romain Guyc9ba5592017-01-18 16:34:42 -0800162
Romain Guyb3f69262017-04-13 20:06:41 -0700163 /** Constant for {@link #colorMode}: bits that encode the dynamic range of the screen. */
Romain Guy48327452017-01-23 17:03:35 -0800164 public static final int COLOR_MODE_HDR_MASK = 0xc;
165 /** Constant for {@link #colorMode}: bits shift to get the screen dynamic range. */
166 public static final int COLOR_MODE_HDR_SHIFT = 2;
Romain Guyc9ba5592017-01-18 16:34:42 -0800167 /**
Romain Guy48327452017-01-23 17:03:35 -0800168 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_HDR_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800169 * indicating that it is unknown whether or not the screen is HDR.
170 */
Romain Guy48327452017-01-23 17:03:35 -0800171 public static final int COLOR_MODE_HDR_UNDEFINED = 0x0;
Romain Guyc9ba5592017-01-18 16:34:42 -0800172 /**
Romain Guy48327452017-01-23 17:03:35 -0800173 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_HDR_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800174 * indicating that the screen is not HDR (low/standard dynamic range).
175 * <p>Corresponds to the <code>-lowdr</code> resource qualifier.</p>
176 */
Romain Guy48327452017-01-23 17:03:35 -0800177 public static final int COLOR_MODE_HDR_NO = 0x1 << COLOR_MODE_HDR_SHIFT;
Romain Guyc9ba5592017-01-18 16:34:42 -0800178 /**
Romain Guy48327452017-01-23 17:03:35 -0800179 * Constant for {@link #colorMode}: a {@link #COLOR_MODE_HDR_MASK} value
Romain Guyc9ba5592017-01-18 16:34:42 -0800180 * indicating that the screen is HDR (dynamic range).
181 * <p>Corresponds to the <code>-highdr</code> resource qualifier.</p>
182 */
Romain Guy48327452017-01-23 17:03:35 -0800183 public static final int COLOR_MODE_HDR_YES = 0x2 << COLOR_MODE_HDR_SHIFT;
Romain Guyc9ba5592017-01-18 16:34:42 -0800184
Romain Guy48327452017-01-23 17:03:35 -0800185 /** Constant for {@link #colorMode}: a value indicating that the color mode is undefined */
Romain Guyc9ba5592017-01-18 16:34:42 -0800186 @SuppressWarnings("PointlessBitwiseExpression")
Romain Guy48327452017-01-23 17:03:35 -0800187 public static final int COLOR_MODE_UNDEFINED = COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED |
188 COLOR_MODE_HDR_UNDEFINED;
Romain Guyc9ba5592017-01-18 16:34:42 -0800189
190 /**
Romain Guyb3f69262017-04-13 20:06:41 -0700191 * Bit mask of color capabilities of the screen. Currently there are two fields:
Romain Guy48327452017-01-23 17:03:35 -0800192 * <p>The {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} bits define the color gamut of
Romain Guyc9ba5592017-01-18 16:34:42 -0800193 * the screen. They may be one of
Romain Guy48327452017-01-23 17:03:35 -0800194 * {@link #COLOR_MODE_WIDE_COLOR_GAMUT_NO} or {@link #COLOR_MODE_WIDE_COLOR_GAMUT_YES}.</p>
Romain Guyc9ba5592017-01-18 16:34:42 -0800195 *
Romain Guy48327452017-01-23 17:03:35 -0800196 * <p>The {@link #COLOR_MODE_HDR_MASK} defines the dynamic range of the screen. They may be
197 * one of {@link #COLOR_MODE_HDR_NO} or {@link #COLOR_MODE_HDR_YES}.</p>
Romain Guyc9ba5592017-01-18 16:34:42 -0800198 *
199 * <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
200 * Multiple Screens</a> for more information.</p>
201 */
Romain Guy48327452017-01-23 17:03:35 -0800202 public int colorMode;
Romain Guyc9ba5592017-01-18 16:34:42 -0800203
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700204 /** Constant for {@link #screenLayout}: bits that encode the size. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700205 public static final int SCREENLAYOUT_SIZE_MASK = 0x0f;
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700206 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
207 * value indicating that no size has been set. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700208 public static final int SCREENLAYOUT_SIZE_UNDEFINED = 0x00;
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700209 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700210 * value indicating the screen is at least approximately 320x426 dp units,
211 * corresponds to the
212 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">small</a>
213 * resource qualifier.
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700214 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
215 * Multiple Screens</a> for more information. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700216 public static final int SCREENLAYOUT_SIZE_SMALL = 0x01;
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700217 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700218 * value indicating the screen is at least approximately 320x470 dp units,
219 * corresponds to the
220 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">normal</a>
221 * resource qualifier.
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700222 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
223 * Multiple Screens</a> for more information. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700224 public static final int SCREENLAYOUT_SIZE_NORMAL = 0x02;
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700225 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700226 * value indicating the screen is at least approximately 480x640 dp units,
227 * corresponds to the
228 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">large</a>
229 * resource qualifier.
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700230 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
231 * Multiple Screens</a> for more information. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700232 public static final int SCREENLAYOUT_SIZE_LARGE = 0x03;
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700233 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700234 * value indicating the screen is at least approximately 720x960 dp units,
235 * corresponds to the
236 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">xlarge</a>
237 * resource qualifier.
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700238 * See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
239 * Multiple Screens</a> for more information.*/
Dianne Hackborn14cee9f2010-04-23 17:51:26 -0700240 public static final int SCREENLAYOUT_SIZE_XLARGE = 0x04;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700241
242 /** Constant for {@link #screenLayout}: bits that encode the aspect ratio. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700243 public static final int SCREENLAYOUT_LONG_MASK = 0x30;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700244 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
245 * value indicating that no size has been set. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700246 public static final int SCREENLAYOUT_LONG_UNDEFINED = 0x00;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700247 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
248 * value that corresponds to the
249 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenAspectQualifier">notlong</a>
250 * resource qualifier. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700251 public static final int SCREENLAYOUT_LONG_NO = 0x10;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700252 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LONG_MASK}
253 * value that corresponds to the
254 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenAspectQualifier">long</a>
255 * resource qualifier. */
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700256 public static final int SCREENLAYOUT_LONG_YES = 0x20;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700257
258 /** Constant for {@link #screenLayout}: bits that encode the layout direction. */
259 public static final int SCREENLAYOUT_LAYOUTDIR_MASK = 0xC0;
260 /** Constant for {@link #screenLayout}: bits shift to get the layout direction. */
261 public static final int SCREENLAYOUT_LAYOUTDIR_SHIFT = 6;
262 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
263 * value indicating that no layout dir has been set. */
264 public static final int SCREENLAYOUT_LAYOUTDIR_UNDEFINED = 0x00;
265 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
266 * value indicating that a layout dir has been set to LTR. */
267 public static final int SCREENLAYOUT_LAYOUTDIR_LTR = 0x01 << SCREENLAYOUT_LAYOUTDIR_SHIFT;
268 /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
269 * value indicating that a layout dir has been set to RTL. */
270 public static final int SCREENLAYOUT_LAYOUTDIR_RTL = 0x02 << SCREENLAYOUT_LAYOUTDIR_SHIFT;
271
Adam Powell49e7ff92015-05-14 16:18:53 -0700272 /** Constant for {@link #screenLayout}: bits that encode roundness of the screen. */
273 public static final int SCREENLAYOUT_ROUND_MASK = 0x300;
274 /** @hide Constant for {@link #screenLayout}: bit shift to get to screen roundness bits */
275 public static final int SCREENLAYOUT_ROUND_SHIFT = 8;
276 /**
277 * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating
278 * that it is unknown whether or not the screen has a round shape.
279 */
280 public static final int SCREENLAYOUT_ROUND_UNDEFINED = 0x00;
281 /**
282 * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating
283 * that the screen does not have a rounded shape.
284 */
285 public static final int SCREENLAYOUT_ROUND_NO = 0x1 << SCREENLAYOUT_ROUND_SHIFT;
286 /**
287 * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating
288 * that the screen has a rounded shape. Corners may not be visible to the user;
289 * developers should pay special attention to the {@link android.view.WindowInsets} delivered
290 * to views for more information about ensuring content is not obscured.
291 *
292 * <p>Corresponds to the <code>-round</code> resource qualifier.</p>
293 */
294 public static final int SCREENLAYOUT_ROUND_YES = 0x2 << SCREENLAYOUT_ROUND_SHIFT;
295
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700296 /** Constant for {@link #screenLayout}: a value indicating that screenLayout is undefined */
297 public static final int SCREENLAYOUT_UNDEFINED = SCREENLAYOUT_SIZE_UNDEFINED |
Adam Powell49e7ff92015-05-14 16:18:53 -0700298 SCREENLAYOUT_LONG_UNDEFINED | SCREENLAYOUT_LAYOUTDIR_UNDEFINED |
299 SCREENLAYOUT_ROUND_UNDEFINED;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700300
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700301 /**
302 * Special flag we generate to indicate that the screen layout requires
303 * us to use a compatibility mode for apps that are not modern layout
304 * aware.
305 * @hide
306 */
307 public static final int SCREENLAYOUT_COMPAT_NEEDED = 0x10000000;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700308
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700309 /**
Andrii Kulianf12fce12016-05-27 17:30:16 -0700310 * Bit mask of overall layout of the screen. Currently there are four
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700311 * fields:
312 * <p>The {@link #SCREENLAYOUT_SIZE_MASK} bits define the overall size
313 * of the screen. They may be one of
314 * {@link #SCREENLAYOUT_SIZE_SMALL}, {@link #SCREENLAYOUT_SIZE_NORMAL},
Adam Powell49e7ff92015-05-14 16:18:53 -0700315 * {@link #SCREENLAYOUT_SIZE_LARGE}, or {@link #SCREENLAYOUT_SIZE_XLARGE}.</p>
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700316 *
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700317 * <p>The {@link #SCREENLAYOUT_LONG_MASK} defines whether the screen
318 * is wider/taller than normal. They may be one of
Adam Powell49e7ff92015-05-14 16:18:53 -0700319 * {@link #SCREENLAYOUT_LONG_NO} or {@link #SCREENLAYOUT_LONG_YES}.</p>
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700320 *
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700321 * <p>The {@link #SCREENLAYOUT_LAYOUTDIR_MASK} defines whether the screen layout
322 * is either LTR or RTL. They may be one of
Adam Powell49e7ff92015-05-14 16:18:53 -0700323 * {@link #SCREENLAYOUT_LAYOUTDIR_LTR} or {@link #SCREENLAYOUT_LAYOUTDIR_RTL}.</p>
324 *
325 * <p>The {@link #SCREENLAYOUT_ROUND_MASK} defines whether the screen has a rounded
326 * shape. They may be one of {@link #SCREENLAYOUT_ROUND_NO} or {@link #SCREENLAYOUT_ROUND_YES}.
327 * </p>
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700328 *
Dianne Hackborn2f98f262011-03-28 18:28:35 -0700329 * <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
Adam Powell49e7ff92015-05-14 16:18:53 -0700330 * Multiple Screens</a> for more information.</p>
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700331 */
332 public int screenLayout;
Dianne Hackbornfe37f8f2012-09-30 12:24:33 -0700333
Bryce Lee7566d762017-03-30 09:34:15 -0700334 /**
Wale Ogunwale822e5122017-07-26 06:02:24 -0700335 * Configuration relating to the windowing state of the object associated with this
336 * Configuration. Contents of this field are not intended to affect resources, but need to be
337 * communicated and propagated at the same time as the rest of Configuration.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -0700338 * @hide
Bryce Lee7566d762017-03-30 09:34:15 -0700339 */
Wale Ogunwale0d5609b2017-09-13 05:55:07 -0700340 @TestApi
Wale Ogunwale822e5122017-07-26 06:02:24 -0700341 public final WindowConfiguration windowConfiguration = new WindowConfiguration();
Bryce Lee7566d762017-03-30 09:34:15 -0700342
Dianne Hackbornfe37f8f2012-09-30 12:24:33 -0700343 /** @hide */
344 static public int resetScreenLayout(int curLayout) {
345 return (curLayout&~(SCREENLAYOUT_LONG_MASK | SCREENLAYOUT_SIZE_MASK
346 | SCREENLAYOUT_COMPAT_NEEDED))
347 | (SCREENLAYOUT_LONG_YES | SCREENLAYOUT_SIZE_XLARGE);
348 }
349
350 /** @hide */
351 static public int reduceScreenLayout(int curLayout, int longSizeDp, int shortSizeDp) {
352 int screenLayoutSize;
353 boolean screenLayoutLong;
354 boolean screenLayoutCompatNeeded;
355
356 // These semi-magic numbers define our compatibility modes for
357 // applications with different screens. These are guarantees to
358 // app developers about the space they can expect for a particular
359 // configuration. DO NOT CHANGE!
360 if (longSizeDp < 470) {
361 // This is shorter than an HVGA normal density screen (which
362 // is 480 pixels on its long side).
363 screenLayoutSize = SCREENLAYOUT_SIZE_SMALL;
364 screenLayoutLong = false;
365 screenLayoutCompatNeeded = false;
366 } else {
367 // What size is this screen screen?
368 if (longSizeDp >= 960 && shortSizeDp >= 720) {
369 // 1.5xVGA or larger screens at medium density are the point
370 // at which we consider it to be an extra large screen.
371 screenLayoutSize = SCREENLAYOUT_SIZE_XLARGE;
372 } else if (longSizeDp >= 640 && shortSizeDp >= 480) {
373 // VGA or larger screens at medium density are the point
374 // at which we consider it to be a large screen.
375 screenLayoutSize = SCREENLAYOUT_SIZE_LARGE;
376 } else {
377 screenLayoutSize = SCREENLAYOUT_SIZE_NORMAL;
378 }
379
380 // If this screen is wider than normal HVGA, or taller
381 // than FWVGA, then for old apps we want to run in size
382 // compatibility mode.
383 if (shortSizeDp > 321 || longSizeDp > 570) {
384 screenLayoutCompatNeeded = true;
385 } else {
386 screenLayoutCompatNeeded = false;
387 }
388
389 // Is this a long screen?
390 if (((longSizeDp*3)/5) >= (shortSizeDp-1)) {
391 // Anything wider than WVGA (5:3) is considering to be long.
392 screenLayoutLong = true;
393 } else {
394 screenLayoutLong = false;
395 }
396 }
397
398 // Now reduce the last screenLayout to not be better than what we
399 // have found.
400 if (!screenLayoutLong) {
401 curLayout = (curLayout&~SCREENLAYOUT_LONG_MASK) | SCREENLAYOUT_LONG_NO;
402 }
403 if (screenLayoutCompatNeeded) {
404 curLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
405 }
406 int curSize = curLayout&SCREENLAYOUT_SIZE_MASK;
407 if (screenLayoutSize < curSize) {
408 curLayout = (curLayout&~SCREENLAYOUT_SIZE_MASK) | screenLayoutSize;
409 }
410 return curLayout;
411 }
412
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700413 /** @hide */
414 public static String configurationDiffToString(int diff) {
415 ArrayList<String> list = new ArrayList<>();
416 if ((diff & ActivityInfo.CONFIG_MCC) != 0) {
417 list.add("CONFIG_MCC");
418 }
419 if ((diff & ActivityInfo.CONFIG_MNC) != 0) {
420 list.add("CONFIG_MNC");
421 }
422 if ((diff & ActivityInfo.CONFIG_LOCALE) != 0) {
423 list.add("CONFIG_LOCALE");
424 }
425 if ((diff & ActivityInfo.CONFIG_TOUCHSCREEN) != 0) {
426 list.add("CONFIG_TOUCHSCREEN");
427 }
428 if ((diff & ActivityInfo.CONFIG_KEYBOARD) != 0) {
429 list.add("CONFIG_KEYBOARD");
430 }
431 if ((diff & ActivityInfo.CONFIG_KEYBOARD_HIDDEN) != 0) {
432 list.add("CONFIG_KEYBOARD_HIDDEN");
433 }
434 if ((diff & ActivityInfo.CONFIG_NAVIGATION) != 0) {
435 list.add("CONFIG_NAVIGATION");
436 }
437 if ((diff & ActivityInfo.CONFIG_ORIENTATION) != 0) {
438 list.add("CONFIG_ORIENTATION");
439 }
440 if ((diff & ActivityInfo.CONFIG_SCREEN_LAYOUT) != 0) {
441 list.add("CONFIG_SCREEN_LAYOUT");
442 }
Romain Guy48327452017-01-23 17:03:35 -0800443 if ((diff & ActivityInfo.CONFIG_COLOR_MODE) != 0) {
444 list.add("CONFIG_COLOR_MODE");
Romain Guyc9ba5592017-01-18 16:34:42 -0800445 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700446 if ((diff & ActivityInfo.CONFIG_UI_MODE) != 0) {
447 list.add("CONFIG_UI_MODE");
448 }
449 if ((diff & ActivityInfo.CONFIG_SCREEN_SIZE) != 0) {
450 list.add("CONFIG_SCREEN_SIZE");
451 }
452 if ((diff & ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE) != 0) {
453 list.add("CONFIG_SMALLEST_SCREEN_SIZE");
454 }
Riddle Hsu7f704b52019-12-10 23:10:45 +0800455 if ((diff & ActivityInfo.CONFIG_DENSITY) != 0) {
456 list.add("CONFIG_DENSITY");
457 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700458 if ((diff & ActivityInfo.CONFIG_LAYOUT_DIRECTION) != 0) {
459 list.add("CONFIG_LAYOUT_DIRECTION");
460 }
461 if ((diff & ActivityInfo.CONFIG_FONT_SCALE) != 0) {
462 list.add("CONFIG_FONT_SCALE");
463 }
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +0100464 if ((diff & ActivityInfo.CONFIG_ASSETS_PATHS) != 0) {
465 list.add("CONFIG_ASSETS_PATHS");
466 }
Riddle Hsu7f704b52019-12-10 23:10:45 +0800467 if ((diff & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0) {
468 list.add("CONFIG_WINDOW_CONFIGURATION");
469 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700470 StringBuilder builder = new StringBuilder("{");
471 for (int i = 0, n = list.size(); i < n; i++) {
472 builder.append(list.get(i));
473 if (i != n - 1) {
474 builder.append(", ");
475 }
476 }
477 builder.append("}");
478 return builder.toString();
479 }
480
Dianne Hackborn711e62a2010-11-29 16:38:22 -0800481 /**
482 * Check if the Configuration's current {@link #screenLayout} is at
483 * least the given size.
484 *
485 * @param size The desired size, either {@link #SCREENLAYOUT_SIZE_SMALL},
486 * {@link #SCREENLAYOUT_SIZE_NORMAL}, {@link #SCREENLAYOUT_SIZE_LARGE}, or
487 * {@link #SCREENLAYOUT_SIZE_XLARGE}.
488 * @return Returns true if the current screen layout size is at least
489 * the given size.
490 */
491 public boolean isLayoutSizeAtLeast(int size) {
492 int cur = screenLayout&SCREENLAYOUT_SIZE_MASK;
493 if (cur == SCREENLAYOUT_SIZE_UNDEFINED) return false;
Dianne Hackborn7d3a5bc2010-11-29 22:52:12 -0800494 return cur >= size;
Dianne Hackborn711e62a2010-11-29 16:38:22 -0800495 }
496
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700497 /** Constant for {@link #touchscreen}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800498 public static final int TOUCHSCREEN_UNDEFINED = 0;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700499 /** Constant for {@link #touchscreen}, value corresponding to the
500 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#TouchscreenQualifier">notouch</a>
501 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800502 public static final int TOUCHSCREEN_NOTOUCH = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700503 /** @deprecated Not currently supported or used. */
504 @Deprecated public static final int TOUCHSCREEN_STYLUS = 2;
505 /** Constant for {@link #touchscreen}, value corresponding to the
506 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#TouchscreenQualifier">finger</a>
507 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800508 public static final int TOUCHSCREEN_FINGER = 3;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800510 /**
511 * The kind of touch screen attached to the device.
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700512 * One of: {@link #TOUCHSCREEN_NOTOUCH}, {@link #TOUCHSCREEN_FINGER}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800513 */
514 public int touchscreen;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700515
516 /** Constant for {@link #keyboard}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800517 public static final int KEYBOARD_UNDEFINED = 0;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700518 /** Constant for {@link #keyboard}, value corresponding to the
519 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">nokeys</a>
520 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800521 public static final int KEYBOARD_NOKEYS = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700522 /** Constant for {@link #keyboard}, value corresponding to the
523 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">qwerty</a>
524 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525 public static final int KEYBOARD_QWERTY = 2;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700526 /** Constant for {@link #keyboard}, value corresponding to the
527 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">12key</a>
528 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800529 public static final int KEYBOARD_12KEY = 3;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700530
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800531 /**
532 * The kind of keyboard attached to the device.
Kenny Root507f8ed2009-06-09 11:21:11 -0500533 * One of: {@link #KEYBOARD_NOKEYS}, {@link #KEYBOARD_QWERTY},
534 * {@link #KEYBOARD_12KEY}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800535 */
536 public int keyboard;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700537
538 /** Constant for {@link #keyboardHidden}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800539 public static final int KEYBOARDHIDDEN_UNDEFINED = 0;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700540 /** Constant for {@link #keyboardHidden}, value corresponding to the
541 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keysexposed</a>
542 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800543 public static final int KEYBOARDHIDDEN_NO = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700544 /** Constant for {@link #keyboardHidden}, value corresponding to the
545 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keyshidden</a>
546 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800547 public static final int KEYBOARDHIDDEN_YES = 2;
548 /** Constant matching actual resource implementation. {@hide} */
549 public static final int KEYBOARDHIDDEN_SOFT = 3;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800551 /**
552 * A flag indicating whether any keyboard is available. Unlike
553 * {@link #hardKeyboardHidden}, this also takes into account a soft
554 * keyboard, so if the hard keyboard is hidden but there is soft
555 * keyboard available, it will be set to NO. Value is one of:
556 * {@link #KEYBOARDHIDDEN_NO}, {@link #KEYBOARDHIDDEN_YES}.
557 */
558 public int keyboardHidden;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700559
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700560 /** Constant for {@link #hardKeyboardHidden}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800561 public static final int HARDKEYBOARDHIDDEN_UNDEFINED = 0;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700562 /** Constant for {@link #hardKeyboardHidden}, value corresponding to the
563 * physical keyboard being exposed. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800564 public static final int HARDKEYBOARDHIDDEN_NO = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700565 /** Constant for {@link #hardKeyboardHidden}, value corresponding to the
566 * physical keyboard being hidden. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800567 public static final int HARDKEYBOARDHIDDEN_YES = 2;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800569 /**
570 * A flag indicating whether the hard keyboard has been hidden. This will
571 * be set on a device with a mechanism to hide the keyboard from the
572 * user, when that mechanism is closed. One of:
573 * {@link #HARDKEYBOARDHIDDEN_NO}, {@link #HARDKEYBOARDHIDDEN_YES}.
574 */
575 public int hardKeyboardHidden;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700576
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700577 /** Constant for {@link #navigation}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800578 public static final int NAVIGATION_UNDEFINED = 0;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700579 /** Constant for {@link #navigation}, value corresponding to the
580 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">nonav</a>
581 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800582 public static final int NAVIGATION_NONAV = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700583 /** Constant for {@link #navigation}, value corresponding to the
584 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">dpad</a>
585 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800586 public static final int NAVIGATION_DPAD = 2;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700587 /** Constant for {@link #navigation}, value corresponding to the
588 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">trackball</a>
589 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800590 public static final int NAVIGATION_TRACKBALL = 3;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700591 /** Constant for {@link #navigation}, value corresponding to the
592 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">wheel</a>
593 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800594 public static final int NAVIGATION_WHEEL = 4;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700595
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800596 /**
597 * The kind of navigation method available on the device.
Kenny Root507f8ed2009-06-09 11:21:11 -0500598 * One of: {@link #NAVIGATION_NONAV}, {@link #NAVIGATION_DPAD},
599 * {@link #NAVIGATION_TRACKBALL}, {@link #NAVIGATION_WHEEL}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800600 */
601 public int navigation;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700602
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700603 /** Constant for {@link #navigationHidden}: a value indicating that no value has been set. */
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700604 public static final int NAVIGATIONHIDDEN_UNDEFINED = 0;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700605 /** Constant for {@link #navigationHidden}, value corresponding to the
606 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavAvailQualifier">navexposed</a>
607 * resource qualifier. */
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700608 public static final int NAVIGATIONHIDDEN_NO = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700609 /** Constant for {@link #navigationHidden}, value corresponding to the
610 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavAvailQualifier">navhidden</a>
611 * resource qualifier. */
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700612 public static final int NAVIGATIONHIDDEN_YES = 2;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700613
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700614 /**
615 * A flag indicating whether any 5-way or DPAD navigation available.
616 * This will be set on a device with a mechanism to hide the navigation
617 * controls from the user, when that mechanism is closed. One of:
618 * {@link #NAVIGATIONHIDDEN_NO}, {@link #NAVIGATIONHIDDEN_YES}.
619 */
620 public int navigationHidden;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700621
Vadim Caen600e4902019-10-17 13:02:24 +0200622 /** @hide **/
623 @IntDef(prefix = {"ORIENTATION_"}, value = {
624 ORIENTATION_UNDEFINED,
625 ORIENTATION_PORTRAIT,
626 ORIENTATION_LANDSCAPE,
627 ORIENTATION_SQUARE
628 })
629 public @interface Orientation {
630 }
631
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700632 /** Constant for {@link #orientation}: a value indicating that no value has been set. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800633 public static final int ORIENTATION_UNDEFINED = 0;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700634 /** Constant for {@link #orientation}, value corresponding to the
635 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#OrientationQualifier">port</a>
636 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800637 public static final int ORIENTATION_PORTRAIT = 1;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700638 /** Constant for {@link #orientation}, value corresponding to the
639 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#OrientationQualifier">land</a>
640 * resource qualifier. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800641 public static final int ORIENTATION_LANDSCAPE = 2;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700642 /** @deprecated Not currently supported or used. */
643 @Deprecated public static final int ORIENTATION_SQUARE = 3;
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700644
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800645 /**
646 * Overall orientation of the screen. May be one of
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700647 * {@link #ORIENTATION_LANDSCAPE}, {@link #ORIENTATION_PORTRAIT}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800648 */
Vadim Caen600e4902019-10-17 13:02:24 +0200649 @Orientation
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800650 public int orientation;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100651
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700652 /** Constant for {@link #uiMode}: bits that encode the mode type. */
Tobias Haamel27b28b32010-02-09 23:09:17 +0100653 public static final int UI_MODE_TYPE_MASK = 0x0f;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700654 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
655 * value indicating that no mode type has been set. */
Dianne Hackbornef05e072010-03-01 17:43:39 -0800656 public static final int UI_MODE_TYPE_UNDEFINED = 0x00;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700657 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
658 * value that corresponds to
659 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">no
660 * UI mode</a> resource qualifier specified. */
Dianne Hackbornef05e072010-03-01 17:43:39 -0800661 public static final int UI_MODE_TYPE_NORMAL = 0x01;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700662 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
663 * value that corresponds to the
664 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">desk</a>
665 * resource qualifier. */
Dianne Hackborn7299c412010-03-04 18:41:49 -0800666 public static final int UI_MODE_TYPE_DESK = 0x02;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700667 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
668 * value that corresponds to the
669 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">car</a>
670 * resource qualifier. */
Dianne Hackborn7299c412010-03-04 18:41:49 -0800671 public static final int UI_MODE_TYPE_CAR = 0x03;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700672 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
673 * value that corresponds to the
674 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">television</a>
675 * resource qualifier. */
Dianne Hackborne360bb62011-05-20 16:11:04 -0700676 public static final int UI_MODE_TYPE_TELEVISION = 0x04;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700677 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
678 * value that corresponds to the
679 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">appliance</a>
680 * resource qualifier. */
Joe Onorato44fcb832011-12-14 20:59:30 -0800681 public static final int UI_MODE_TYPE_APPLIANCE = 0x05;
John Spurlock6c191292014-04-03 16:37:27 -0400682 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
683 * value that corresponds to the
684 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">watch</a>
685 * resource qualifier. */
686 public static final int UI_MODE_TYPE_WATCH = 0x06;
Zak Cohen1a6acdb2016-12-12 15:21:21 -0800687 /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
688 * value that corresponds to the
689 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">vrheadset</a>
690 * resource qualifier. */
691 public static final int UI_MODE_TYPE_VR_HEADSET = 0x07;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100692
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700693 /** Constant for {@link #uiMode}: bits that encode the night mode. */
Tobias Haamel27b28b32010-02-09 23:09:17 +0100694 public static final int UI_MODE_NIGHT_MASK = 0x30;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700695 /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
696 * value indicating that no mode type has been set. */
Tobias Haamel27b28b32010-02-09 23:09:17 +0100697 public static final int UI_MODE_NIGHT_UNDEFINED = 0x00;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700698 /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
699 * value that corresponds to the
700 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NightQualifier">notnight</a>
701 * resource qualifier. */
Tobias Haamel27b28b32010-02-09 23:09:17 +0100702 public static final int UI_MODE_NIGHT_NO = 0x10;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700703 /** Constant for {@link #uiMode}: a {@link #UI_MODE_NIGHT_MASK}
704 * value that corresponds to the
705 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#NightQualifier">night</a>
706 * resource qualifier. */
Tobias Haamel27b28b32010-02-09 23:09:17 +0100707 public static final int UI_MODE_NIGHT_YES = 0x20;
708
709 /**
710 * Bit mask of the ui mode. Currently there are two fields:
711 * <p>The {@link #UI_MODE_TYPE_MASK} bits define the overall ui mode of the
Dianne Hackborn7299c412010-03-04 18:41:49 -0800712 * device. They may be one of {@link #UI_MODE_TYPE_UNDEFINED},
713 * {@link #UI_MODE_TYPE_NORMAL}, {@link #UI_MODE_TYPE_DESK},
John Spurlock6c191292014-04-03 16:37:27 -0400714 * {@link #UI_MODE_TYPE_CAR}, {@link #UI_MODE_TYPE_TELEVISION},
Zak Cohen1a6acdb2016-12-12 15:21:21 -0800715 * {@link #UI_MODE_TYPE_APPLIANCE}, {@link #UI_MODE_TYPE_WATCH},
716 * or {@link #UI_MODE_TYPE_VR_HEADSET}.
Tobias Haamel27b28b32010-02-09 23:09:17 +0100717 *
718 * <p>The {@link #UI_MODE_NIGHT_MASK} defines whether the screen
Dianne Hackborn7299c412010-03-04 18:41:49 -0800719 * is in a special mode. They may be one of {@link #UI_MODE_NIGHT_UNDEFINED},
Tobias Haamel27b28b32010-02-09 23:09:17 +0100720 * {@link #UI_MODE_NIGHT_NO} or {@link #UI_MODE_NIGHT_YES}.
Tobias Haamel27b28b32010-02-09 23:09:17 +0100721 */
722 public int uiMode;
723
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700724 /**
725 * Default value for {@link #screenWidthDp} indicating that no width
726 * has been specified.
727 */
Dianne Hackbornebff8f92011-05-12 18:07:47 -0700728 public static final int SCREEN_WIDTH_DP_UNDEFINED = 0;
729
730 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700731 * The current width of the available screen space, in dp units,
732 * corresponding to
733 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenWidthQualifier">screen
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700734 * width</a> resource qualifier. Set to
735 * {@link #SCREEN_WIDTH_DP_UNDEFINED} if no width is specified.
Dianne Hackbornebff8f92011-05-12 18:07:47 -0700736 */
737 public int screenWidthDp;
738
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700739 /**
740 * Default value for {@link #screenHeightDp} indicating that no width
741 * has been specified.
742 */
Dianne Hackbornebff8f92011-05-12 18:07:47 -0700743 public static final int SCREEN_HEIGHT_DP_UNDEFINED = 0;
744
745 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700746 * The current height of the available screen space, in dp units,
747 * corresponding to
748 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenHeightQualifier">screen
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700749 * height</a> resource qualifier. Set to
750 * {@link #SCREEN_HEIGHT_DP_UNDEFINED} if no height is specified.
Dianne Hackbornebff8f92011-05-12 18:07:47 -0700751 */
752 public int screenHeightDp;
753
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700754 /**
755 * Default value for {@link #smallestScreenWidthDp} indicating that no width
756 * has been specified.
757 */
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700758 public static final int SMALLEST_SCREEN_WIDTH_DP_UNDEFINED = 0;
759
760 /**
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700761 * The smallest screen size an application will see in normal operation,
762 * corresponding to
763 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#SmallestScreenWidthQualifier">smallest
764 * screen width</a> resource qualifier.
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700765 * This is the smallest value of both screenWidthDp and screenHeightDp
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700766 * in both portrait and landscape. Set to
767 * {@link #SMALLEST_SCREEN_WIDTH_DP_UNDEFINED} if no width is specified.
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700768 */
769 public int smallestScreenWidthDp;
770
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700771 /**
772 * Default value for {@link #densityDpi} indicating that no width
773 * has been specified.
774 */
775 public static final int DENSITY_DPI_UNDEFINED = 0;
776
777 /**
Adam Lesinski31245b42014-08-22 19:10:56 -0700778 * Value for {@link #densityDpi} for resources that scale to any density (vector drawables).
779 * {@hide}
780 */
781 public static final int DENSITY_DPI_ANY = 0xfffe;
782
783 /**
784 * Value for {@link #densityDpi} for resources that are not meant to be scaled.
785 * {@hide}
786 */
787 public static final int DENSITY_DPI_NONE = 0xffff;
788
789 /**
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700790 * The target screen density being rendered to,
791 * corresponding to
792 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#DensityQualifier">density</a>
793 * resource qualifier. Set to
794 * {@link #DENSITY_DPI_UNDEFINED} if no density is specified.
795 */
796 public int densityDpi;
797
Dianne Hackborn5fd21692011-06-07 14:09:47 -0700798 /** @hide Hack to get this information from WM to app running in compat mode. */
799 public int compatScreenWidthDp;
800 /** @hide Hack to get this information from WM to app running in compat mode. */
801 public int compatScreenHeightDp;
802 /** @hide Hack to get this information from WM to app running in compat mode. */
803 public int compatSmallestScreenWidthDp;
804
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800805 /**
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +0100806 * An undefined assetsSeq. This will not override an existing assetsSeq.
807 * @hide
808 */
809 public static final int ASSETS_SEQ_UNDEFINED = 0;
810
811 /**
812 * Internal counter that allows us to piggyback off the configuration change mechanism to
813 * signal to apps that the the assets for an Application have changed. A difference in these
814 * between two Configurations will yield a diff flag of
815 * {@link ActivityInfo#CONFIG_ASSETS_PATHS}.
816 * @hide
817 */
Artur Satayevf0b7d0b2019-11-04 11:16:45 +0000818 @UnsupportedAppUsage
Riddle Hsue716d722019-01-09 15:56:46 +0800819 @TestApi
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +0100820 public int assetsSeq;
821
822 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800823 * @hide Internal book-keeping.
824 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100825 @UnsupportedAppUsage
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800826 public int seq;
Dianne Hackborn1d0b1772013-09-06 14:02:54 -0700827
Alan Viveretteac85f902016-03-11 15:15:51 -0500828 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700829 @IntDef(flag = true, prefix = { "NATIVE_CONFIG_" }, value = {
830 NATIVE_CONFIG_MCC,
831 NATIVE_CONFIG_MNC,
832 NATIVE_CONFIG_LOCALE,
833 NATIVE_CONFIG_TOUCHSCREEN,
834 NATIVE_CONFIG_KEYBOARD,
835 NATIVE_CONFIG_KEYBOARD_HIDDEN,
836 NATIVE_CONFIG_NAVIGATION,
837 NATIVE_CONFIG_ORIENTATION,
838 NATIVE_CONFIG_DENSITY,
839 NATIVE_CONFIG_SCREEN_SIZE,
840 NATIVE_CONFIG_VERSION,
841 NATIVE_CONFIG_SCREEN_LAYOUT,
842 NATIVE_CONFIG_UI_MODE,
843 NATIVE_CONFIG_SMALLEST_SCREEN_SIZE,
844 NATIVE_CONFIG_LAYOUTDIR,
845 NATIVE_CONFIG_COLOR_MODE,
846 })
Alan Viveretteac85f902016-03-11 15:15:51 -0500847 @Retention(RetentionPolicy.SOURCE)
848 public @interface NativeConfig {}
849
Dianne Hackborn1d0b1772013-09-06 14:02:54 -0700850 /** @hide Native-specific bit mask for MCC config; DO NOT USE UNLESS YOU ARE SURE. */
851 public static final int NATIVE_CONFIG_MCC = 0x0001;
852 /** @hide Native-specific bit mask for MNC config; DO NOT USE UNLESS YOU ARE SURE. */
853 public static final int NATIVE_CONFIG_MNC = 0x0002;
854 /** @hide Native-specific bit mask for LOCALE config; DO NOT USE UNLESS YOU ARE SURE. */
855 public static final int NATIVE_CONFIG_LOCALE = 0x0004;
856 /** @hide Native-specific bit mask for TOUCHSCREEN config; DO NOT USE UNLESS YOU ARE SURE. */
857 public static final int NATIVE_CONFIG_TOUCHSCREEN = 0x0008;
858 /** @hide Native-specific bit mask for KEYBOARD config; DO NOT USE UNLESS YOU ARE SURE. */
859 public static final int NATIVE_CONFIG_KEYBOARD = 0x0010;
860 /** @hide Native-specific bit mask for KEYBOARD_HIDDEN config; DO NOT USE UNLESS YOU
861 * ARE SURE. */
862 public static final int NATIVE_CONFIG_KEYBOARD_HIDDEN = 0x0020;
863 /** @hide Native-specific bit mask for NAVIGATION config; DO NOT USE UNLESS YOU ARE SURE. */
864 public static final int NATIVE_CONFIG_NAVIGATION = 0x0040;
865 /** @hide Native-specific bit mask for ORIENTATION config; DO NOT USE UNLESS YOU ARE SURE. */
866 public static final int NATIVE_CONFIG_ORIENTATION = 0x0080;
867 /** @hide Native-specific bit mask for DENSITY config; DO NOT USE UNLESS YOU ARE SURE. */
868 public static final int NATIVE_CONFIG_DENSITY = 0x0100;
869 /** @hide Native-specific bit mask for SCREEN_SIZE config; DO NOT USE UNLESS YOU ARE SURE. */
870 public static final int NATIVE_CONFIG_SCREEN_SIZE = 0x0200;
871 /** @hide Native-specific bit mask for VERSION config; DO NOT USE UNLESS YOU ARE SURE. */
872 public static final int NATIVE_CONFIG_VERSION = 0x0400;
873 /** @hide Native-specific bit mask for SCREEN_LAYOUT config; DO NOT USE UNLESS YOU ARE SURE. */
874 public static final int NATIVE_CONFIG_SCREEN_LAYOUT = 0x0800;
875 /** @hide Native-specific bit mask for UI_MODE config; DO NOT USE UNLESS YOU ARE SURE. */
876 public static final int NATIVE_CONFIG_UI_MODE = 0x1000;
877 /** @hide Native-specific bit mask for SMALLEST_SCREEN_SIZE config; DO NOT USE UNLESS YOU
878 * ARE SURE. */
879 public static final int NATIVE_CONFIG_SMALLEST_SCREEN_SIZE = 0x2000;
880 /** @hide Native-specific bit mask for LAYOUTDIR config ; DO NOT USE UNLESS YOU ARE SURE.*/
881 public static final int NATIVE_CONFIG_LAYOUTDIR = 0x4000;
Romain Guy48327452017-01-23 17:03:35 -0800882 /** @hide Native-specific bit mask for COLOR_MODE config ; DO NOT USE UNLESS YOU ARE SURE.*/
883 public static final int NATIVE_CONFIG_COLOR_MODE = 0x10000;
Dianne Hackborn1d0b1772013-09-06 14:02:54 -0700884
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800885 /**
Adam Lesinskibad43fc2016-07-19 13:35:01 -0700886 * <p>Construct an invalid Configuration. This state is only suitable for constructing a
887 * Configuration delta that will be applied to some valid Configuration object. In order to
888 * create a valid standalone Configuration, you must call {@link #setToDefaults}. </p>
889 *
890 * <p>Example:</p>
891 * <pre class="prettyprint">
892 * Configuration validConfig = new Configuration();
893 * validConfig.setToDefaults();
894 *
895 * Configuration deltaOnlyConfig = new Configuration();
896 * deltaOnlyConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
897 *
898 * validConfig.updateFrom(deltaOnlyConfig);
899 * </pre>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800900 */
901 public Configuration() {
Adam Lesinskibad43fc2016-07-19 13:35:01 -0700902 unset();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800903 }
904
905 /**
906 * Makes a deep copy suitable for modification.
907 */
908 public Configuration(Configuration o) {
Dianne Hackborn694f79b2010-03-17 19:44:59 -0700909 setTo(o);
910 }
911
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700912 /* This brings mLocaleList in sync with locale in case a user of the older API who doesn't know
913 * about setLocales() has changed locale directly. */
914 private void fixUpLocaleList() {
915 if ((locale == null && !mLocaleList.isEmpty()) ||
Roozbeh Pournaderfee44842016-02-04 15:24:24 -0800916 (locale != null && !locale.equals(mLocaleList.get(0)))) {
Raph Levien10ea92a2016-05-02 12:56:01 -0700917 mLocaleList = locale == null ? LocaleList.getEmptyLocaleList() : new LocaleList(locale);
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700918 }
919 }
920
Chet Haased30149e2017-01-13 12:55:16 -0800921 /**
922 * Sets the fields in this object to those in the given Configuration.
923 *
924 * @param o The Configuration object used to set the values of this Configuration's fields.
925 */
Dianne Hackborn694f79b2010-03-17 19:44:59 -0700926 public void setTo(Configuration o) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800927 fontScale = o.fontScale;
928 mcc = o.mcc;
929 mnc = o.mnc;
Roozbeh Pournader8a412e02015-12-02 18:39:50 -0800930 locale = o.locale == null ? null : (Locale) o.locale.clone();
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700931 o.fixUpLocaleList();
932 mLocaleList = o.mLocaleList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800933 userSetLocale = o.userSetLocale;
934 touchscreen = o.touchscreen;
935 keyboard = o.keyboard;
936 keyboardHidden = o.keyboardHidden;
937 hardKeyboardHidden = o.hardKeyboardHidden;
938 navigation = o.navigation;
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700939 navigationHidden = o.navigationHidden;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800940 orientation = o.orientation;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700941 screenLayout = o.screenLayout;
Romain Guy48327452017-01-23 17:03:35 -0800942 colorMode = o.colorMode;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100943 uiMode = o.uiMode;
Dianne Hackbornebff8f92011-05-12 18:07:47 -0700944 screenWidthDp = o.screenWidthDp;
945 screenHeightDp = o.screenHeightDp;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700946 smallestScreenWidthDp = o.smallestScreenWidthDp;
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700947 densityDpi = o.densityDpi;
Dianne Hackborn5fd21692011-06-07 14:09:47 -0700948 compatScreenWidthDp = o.compatScreenWidthDp;
949 compatScreenHeightDp = o.compatScreenHeightDp;
950 compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp;
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +0100951 assetsSeq = o.assetsSeq;
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800952 seq = o.seq;
Wale Ogunwale822e5122017-07-26 06:02:24 -0700953 windowConfiguration.setTo(o.windowConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -0700955
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700957 StringBuilder sb = new StringBuilder(128);
Dianne Hackborn29735682011-04-21 17:26:39 -0700958 sb.append("{");
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700959 sb.append(fontScale);
Dianne Hackborn5be8de32011-05-24 18:11:57 -0700960 sb.append(" ");
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700961 if (mcc != 0) {
962 sb.append(mcc);
963 sb.append("mcc");
964 } else {
965 sb.append("?mcc");
966 }
967 if (mnc != 0) {
968 sb.append(mnc);
969 sb.append("mnc");
970 } else {
971 sb.append("?mnc");
972 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700973 fixUpLocaleList();
974 if (!mLocaleList.isEmpty()) {
Dianne Hackborn9a849832011-04-07 15:11:57 -0700975 sb.append(" ");
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700976 sb.append(mLocaleList);
Dianne Hackborn9a849832011-04-07 15:11:57 -0700977 } else {
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -0700978 sb.append(" ?localeList");
Daniel Sandler7d6bddc2010-07-22 16:11:55 -0400979 }
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700980 int layoutDir = (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK);
981 switch (layoutDir) {
982 case SCREENLAYOUT_LAYOUTDIR_UNDEFINED: sb.append(" ?layoutDir"); break;
Fabrice Di Meglio8a802db2012-09-05 13:12:02 -0700983 case SCREENLAYOUT_LAYOUTDIR_LTR: sb.append(" ldltr"); break;
984 case SCREENLAYOUT_LAYOUTDIR_RTL: sb.append(" ldrtl"); break;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -0700985 default: sb.append(" layoutDir=");
986 sb.append(layoutDir >> SCREENLAYOUT_LAYOUTDIR_SHIFT); break;
Fabrice Di Meglio7a736fb2011-06-09 20:20:36 -0700987 }
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700988 if (smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
989 sb.append(" sw"); sb.append(smallestScreenWidthDp); sb.append("dp");
990 } else {
Dianne Hackborn2f0b1752011-05-31 17:59:49 -0700991 sb.append(" ?swdp");
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700992 }
993 if (screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
994 sb.append(" w"); sb.append(screenWidthDp); sb.append("dp");
995 } else {
Dianne Hackborn2f0b1752011-05-31 17:59:49 -0700996 sb.append(" ?wdp");
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700997 }
998 if (screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
999 sb.append(" h"); sb.append(screenHeightDp); sb.append("dp");
1000 } else {
Dianne Hackborn2f0b1752011-05-31 17:59:49 -07001001 sb.append(" ?hdp");
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001002 }
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001003 if (densityDpi != DENSITY_DPI_UNDEFINED) {
1004 sb.append(" "); sb.append(densityDpi); sb.append("dpi");
1005 } else {
1006 sb.append(" ?density");
1007 }
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001008 switch ((screenLayout&SCREENLAYOUT_SIZE_MASK)) {
1009 case SCREENLAYOUT_SIZE_UNDEFINED: sb.append(" ?lsize"); break;
1010 case SCREENLAYOUT_SIZE_SMALL: sb.append(" smll"); break;
1011 case SCREENLAYOUT_SIZE_NORMAL: sb.append(" nrml"); break;
1012 case SCREENLAYOUT_SIZE_LARGE: sb.append(" lrg"); break;
1013 case SCREENLAYOUT_SIZE_XLARGE: sb.append(" xlrg"); break;
1014 default: sb.append(" layoutSize=");
1015 sb.append(screenLayout&SCREENLAYOUT_SIZE_MASK); break;
1016 }
1017 switch ((screenLayout&SCREENLAYOUT_LONG_MASK)) {
1018 case SCREENLAYOUT_LONG_UNDEFINED: sb.append(" ?long"); break;
1019 case SCREENLAYOUT_LONG_NO: /* not-long is not interesting to print */ break;
1020 case SCREENLAYOUT_LONG_YES: sb.append(" long"); break;
1021 default: sb.append(" layoutLong=");
1022 sb.append(screenLayout&SCREENLAYOUT_LONG_MASK); break;
1023 }
Romain Guy48327452017-01-23 17:03:35 -08001024 switch ((colorMode &COLOR_MODE_HDR_MASK)) {
1025 case COLOR_MODE_HDR_UNDEFINED: sb.append(" ?ldr"); break; // most likely not HDR
1026 case COLOR_MODE_HDR_NO: /* ldr is not interesting to print */ break;
1027 case COLOR_MODE_HDR_YES: sb.append(" hdr"); break;
Romain Guyc9ba5592017-01-18 16:34:42 -08001028 default: sb.append(" dynamicRange=");
Romain Guy48327452017-01-23 17:03:35 -08001029 sb.append(colorMode &COLOR_MODE_HDR_MASK); break;
Romain Guyc9ba5592017-01-18 16:34:42 -08001030 }
Romain Guy48327452017-01-23 17:03:35 -08001031 switch ((colorMode &COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) {
1032 case COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED: sb.append(" ?wideColorGamut"); break;
1033 case COLOR_MODE_WIDE_COLOR_GAMUT_NO: /* not wide is not interesting to print */ break;
1034 case COLOR_MODE_WIDE_COLOR_GAMUT_YES: sb.append(" widecg"); break;
Romain Guyc9ba5592017-01-18 16:34:42 -08001035 default: sb.append(" wideColorGamut=");
Romain Guy48327452017-01-23 17:03:35 -08001036 sb.append(colorMode &COLOR_MODE_WIDE_COLOR_GAMUT_MASK); break;
Romain Guyc9ba5592017-01-18 16:34:42 -08001037 }
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001038 switch (orientation) {
1039 case ORIENTATION_UNDEFINED: sb.append(" ?orien"); break;
1040 case ORIENTATION_LANDSCAPE: sb.append(" land"); break;
1041 case ORIENTATION_PORTRAIT: sb.append(" port"); break;
1042 default: sb.append(" orien="); sb.append(orientation); break;
1043 }
1044 switch ((uiMode&UI_MODE_TYPE_MASK)) {
1045 case UI_MODE_TYPE_UNDEFINED: sb.append(" ?uimode"); break;
1046 case UI_MODE_TYPE_NORMAL: /* normal is not interesting to print */ break;
1047 case UI_MODE_TYPE_DESK: sb.append(" desk"); break;
1048 case UI_MODE_TYPE_CAR: sb.append(" car"); break;
Dianne Hackborne360bb62011-05-20 16:11:04 -07001049 case UI_MODE_TYPE_TELEVISION: sb.append(" television"); break;
Joe Onorato44fcb832011-12-14 20:59:30 -08001050 case UI_MODE_TYPE_APPLIANCE: sb.append(" appliance"); break;
John Spurlock6c191292014-04-03 16:37:27 -04001051 case UI_MODE_TYPE_WATCH: sb.append(" watch"); break;
Zak Cohen1a6acdb2016-12-12 15:21:21 -08001052 case UI_MODE_TYPE_VR_HEADSET: sb.append(" vrheadset"); break;
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001053 default: sb.append(" uimode="); sb.append(uiMode&UI_MODE_TYPE_MASK); break;
1054 }
1055 switch ((uiMode&UI_MODE_NIGHT_MASK)) {
1056 case UI_MODE_NIGHT_UNDEFINED: sb.append(" ?night"); break;
1057 case UI_MODE_NIGHT_NO: /* not-night is not interesting to print */ break;
1058 case UI_MODE_NIGHT_YES: sb.append(" night"); break;
1059 default: sb.append(" night="); sb.append(uiMode&UI_MODE_NIGHT_MASK); break;
1060 }
Dianne Hackborn9a849832011-04-07 15:11:57 -07001061 switch (touchscreen) {
1062 case TOUCHSCREEN_UNDEFINED: sb.append(" ?touch"); break;
1063 case TOUCHSCREEN_NOTOUCH: sb.append(" -touch"); break;
1064 case TOUCHSCREEN_STYLUS: sb.append(" stylus"); break;
1065 case TOUCHSCREEN_FINGER: sb.append(" finger"); break;
1066 default: sb.append(" touch="); sb.append(touchscreen); break;
1067 }
1068 switch (keyboard) {
1069 case KEYBOARD_UNDEFINED: sb.append(" ?keyb"); break;
1070 case KEYBOARD_NOKEYS: sb.append(" -keyb"); break;
1071 case KEYBOARD_QWERTY: sb.append(" qwerty"); break;
1072 case KEYBOARD_12KEY: sb.append(" 12key"); break;
1073 default: sb.append(" keys="); sb.append(keyboard); break;
1074 }
1075 switch (keyboardHidden) {
1076 case KEYBOARDHIDDEN_UNDEFINED: sb.append("/?"); break;
1077 case KEYBOARDHIDDEN_NO: sb.append("/v"); break;
1078 case KEYBOARDHIDDEN_YES: sb.append("/h"); break;
1079 case KEYBOARDHIDDEN_SOFT: sb.append("/s"); break;
1080 default: sb.append("/"); sb.append(keyboardHidden); break;
1081 }
1082 switch (hardKeyboardHidden) {
1083 case HARDKEYBOARDHIDDEN_UNDEFINED: sb.append("/?"); break;
1084 case HARDKEYBOARDHIDDEN_NO: sb.append("/v"); break;
1085 case HARDKEYBOARDHIDDEN_YES: sb.append("/h"); break;
1086 default: sb.append("/"); sb.append(hardKeyboardHidden); break;
1087 }
1088 switch (navigation) {
1089 case NAVIGATION_UNDEFINED: sb.append(" ?nav"); break;
1090 case NAVIGATION_NONAV: sb.append(" -nav"); break;
1091 case NAVIGATION_DPAD: sb.append(" dpad"); break;
1092 case NAVIGATION_TRACKBALL: sb.append(" tball"); break;
1093 case NAVIGATION_WHEEL: sb.append(" wheel"); break;
1094 default: sb.append(" nav="); sb.append(navigation); break;
1095 }
1096 switch (navigationHidden) {
1097 case NAVIGATIONHIDDEN_UNDEFINED: sb.append("/?"); break;
1098 case NAVIGATIONHIDDEN_NO: sb.append("/v"); break;
1099 case NAVIGATIONHIDDEN_YES: sb.append("/h"); break;
1100 default: sb.append("/"); sb.append(navigationHidden); break;
1101 }
Wale Ogunwale822e5122017-07-26 06:02:24 -07001102 sb.append(" winConfig="); sb.append(windowConfiguration);
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001103 if (assetsSeq != 0) {
1104 sb.append(" as.").append(assetsSeq);
1105 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001106 if (seq != 0) {
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001107 sb.append(" s.").append(seq);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001108 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001109 sb.append('}');
1110 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 }
1112
1113 /**
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001114 * Write to a protocol buffer output stream.
1115 * Protocol buffer message definition at {@link android.content.ConfigurationProto}
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -07001116 * Has the option to ignore fields that don't need to be persisted to disk.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001117 *
1118 * @param protoOutputStream Stream to write the Configuration object to.
1119 * @param fieldId Field Id of the Configuration as defined in the parent message
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -07001120 * @param persisted Note if this proto will be persisted to disk
Nataniel Borges023ecb52019-01-16 14:15:43 -08001121 * @param critical If true, reduce amount of data written.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001122 * @hide
1123 */
Jeffrey Huangcb782852019-12-05 11:28:11 -08001124 public void dumpDebug(ProtoOutputStream protoOutputStream, long fieldId, boolean persisted,
Nataniel Borges023ecb52019-01-16 14:15:43 -08001125 boolean critical) {
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001126 final long token = protoOutputStream.start(fieldId);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001127 if (!critical) {
1128 protoOutputStream.write(FONT_SCALE, fontScale);
1129 protoOutputStream.write(MCC, mcc);
1130 protoOutputStream.write(MNC, mnc);
1131 if (mLocaleList != null) {
Varun Shahbd0ce4d2019-09-10 15:51:37 -04001132 protoOutputStream.write(LOCALE_LIST, mLocaleList.toLanguageTags());
Nataniel Borges023ecb52019-01-16 14:15:43 -08001133 }
1134 protoOutputStream.write(SCREEN_LAYOUT, screenLayout);
1135 protoOutputStream.write(COLOR_MODE, colorMode);
1136 protoOutputStream.write(TOUCHSCREEN, touchscreen);
1137 protoOutputStream.write(KEYBOARD, keyboard);
1138 protoOutputStream.write(KEYBOARD_HIDDEN, keyboardHidden);
1139 protoOutputStream.write(HARD_KEYBOARD_HIDDEN, hardKeyboardHidden);
1140 protoOutputStream.write(NAVIGATION, navigation);
1141 protoOutputStream.write(NAVIGATION_HIDDEN, navigationHidden);
1142 protoOutputStream.write(UI_MODE, uiMode);
1143 protoOutputStream.write(SMALLEST_SCREEN_WIDTH_DP, smallestScreenWidthDp);
1144 protoOutputStream.write(DENSITY_DPI, densityDpi);
1145 // For persistence, we do not care about window configuration
1146 if (!persisted && windowConfiguration != null) {
Jeffrey Huangcb782852019-12-05 11:28:11 -08001147 windowConfiguration.dumpDebug(protoOutputStream, WINDOW_CONFIGURATION);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001148 }
Kweku Adams15afdeb2018-09-04 11:54:46 -07001149 }
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001150 protoOutputStream.write(ORIENTATION, orientation);
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001151 protoOutputStream.write(SCREEN_WIDTH_DP, screenWidthDp);
1152 protoOutputStream.write(SCREEN_HEIGHT_DP, screenHeightDp);
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001153 protoOutputStream.end(token);
1154 }
1155
1156 /**
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -07001157 * Write to a protocol buffer output stream.
1158 * Protocol buffer message definition at {@link android.content.ConfigurationProto}
1159 *
1160 * @param protoOutputStream Stream to write the Configuration object to.
1161 * @param fieldId Field Id of the Configuration as defined in the parent message
1162 * @hide
1163 */
Jeffrey Huangcb782852019-12-05 11:28:11 -08001164 public void dumpDebug(ProtoOutputStream protoOutputStream, long fieldId) {
1165 dumpDebug(protoOutputStream, fieldId, false /* persisted */, false /* critical */);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001166 }
1167
1168 /**
1169 * Write to a protocol buffer output stream.
1170 * Protocol buffer message definition at {@link android.content.ConfigurationProto}
1171 *
1172 * @param protoOutputStream Stream to write the Configuration object to.
1173 * @param fieldId Field Id of the Configuration as defined in the parent message
1174 * @param critical If true, reduce amount of data written.
1175 * @hide
1176 */
Jeffrey Huangcb782852019-12-05 11:28:11 -08001177 public void dumpDebug(ProtoOutputStream protoOutputStream, long fieldId, boolean critical) {
1178 dumpDebug(protoOutputStream, fieldId, false /* persisted */, critical);
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -07001179 }
1180
1181 /**
1182 * Read from a protocol buffer output stream.
1183 * Protocol buffer message definition at {@link android.content.ConfigurationProto}
1184 *
1185 * @param protoInputStream Stream to read the Configuration object from.
1186 * @param fieldId Field Id of the Configuration as defined in the parent message
1187 * @hide
1188 */
1189 public void readFromProto(ProtoInputStream protoInputStream, long fieldId) throws IOException {
1190 final long token = protoInputStream.start(fieldId);
1191 final List<Locale> list = new ArrayList();
1192 try {
1193 while (protoInputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
1194 switch (protoInputStream.getFieldNumber()) {
1195 case (int) FONT_SCALE:
1196 fontScale = protoInputStream.readFloat(FONT_SCALE);
1197 break;
1198 case (int) MCC:
1199 mcc = protoInputStream.readInt(MCC);
1200 break;
1201 case (int) MNC:
1202 mnc = protoInputStream.readInt(MNC);
1203 break;
1204 case (int) LOCALES:
1205 // Parse the Locale here to handle all the repeated Locales
1206 // The LocaleList will be created when the message is completed
1207 final long localeToken = protoInputStream.start(LOCALES);
1208 String language = "";
1209 String country = "";
1210 String variant = "";
Varun Shah95fabaf2019-05-01 12:45:37 -07001211 String script = "";
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -07001212 try {
1213 while (protoInputStream.nextField()
1214 != ProtoInputStream.NO_MORE_FIELDS) {
1215 switch (protoInputStream.getFieldNumber()) {
1216 case (int) LocaleProto.LANGUAGE:
1217 language = protoInputStream.readString(
1218 LocaleProto.LANGUAGE);
1219 break;
1220 case (int) LocaleProto.COUNTRY:
1221 country = protoInputStream.readString(LocaleProto.COUNTRY);
1222 break;
1223 case (int) LocaleProto.VARIANT:
1224 variant = protoInputStream.readString(LocaleProto.VARIANT);
1225 break;
Varun Shah95fabaf2019-05-01 12:45:37 -07001226 case (int) LocaleProto.SCRIPT:
1227 script = protoInputStream.readString(LocaleProto.SCRIPT);
1228 break;
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -07001229 }
1230 }
1231 } catch (WireTypeMismatchException wtme) {
1232 // rethrow for caller deal with
1233 throw wtme;
1234 } finally {
1235 protoInputStream.end(localeToken);
Varun Shah95fabaf2019-05-01 12:45:37 -07001236 try {
1237 final Locale locale = new Locale.Builder()
1238 .setLanguage(language)
1239 .setRegion(country)
1240 .setVariant(variant)
1241 .setScript(script)
1242 .build();
Varun Shah5d9031d2019-09-04 12:04:02 -07001243 // Log a WTF here if a repeated locale is found to avoid throwing an
1244 // exception in system server when LocaleList is created below
1245 final int inListIndex = list.indexOf(locale);
1246 if (inListIndex != -1) {
1247 Slog.wtf(TAG, "Repeated locale (" + list.get(inListIndex) + ")"
1248 + " found when trying to add: " + locale.toString());
1249 } else {
1250 list.add(locale);
1251 }
Varun Shah95fabaf2019-05-01 12:45:37 -07001252 } catch (IllformedLocaleException e) {
1253 Slog.e(TAG, "readFromProto error building locale with: "
1254 + "language-" + language + ";country-" + country
1255 + ";variant-" + variant + ";script-" + script);
1256 }
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -07001257 }
1258 break;
1259 case (int) SCREEN_LAYOUT:
1260 screenLayout = protoInputStream.readInt(SCREEN_LAYOUT);
1261 break;
1262 case (int) COLOR_MODE:
1263 colorMode = protoInputStream.readInt(COLOR_MODE);
1264 break;
1265 case (int) TOUCHSCREEN:
1266 touchscreen = protoInputStream.readInt(TOUCHSCREEN);
1267 break;
1268 case (int) KEYBOARD:
1269 keyboard = protoInputStream.readInt(KEYBOARD);
1270 break;
1271 case (int) KEYBOARD_HIDDEN:
1272 keyboardHidden = protoInputStream.readInt(KEYBOARD_HIDDEN);
1273 break;
1274 case (int) HARD_KEYBOARD_HIDDEN:
1275 hardKeyboardHidden = protoInputStream.readInt(HARD_KEYBOARD_HIDDEN);
1276 break;
1277 case (int) NAVIGATION:
1278 navigation = protoInputStream.readInt(NAVIGATION);
1279 break;
1280 case (int) NAVIGATION_HIDDEN:
1281 navigationHidden = protoInputStream.readInt(NAVIGATION_HIDDEN);
1282 break;
1283 case (int) ORIENTATION:
1284 orientation = protoInputStream.readInt(ORIENTATION);
1285 break;
1286 case (int) UI_MODE:
1287 uiMode = protoInputStream.readInt(UI_MODE);
1288 break;
1289 case (int) SCREEN_WIDTH_DP:
1290 screenWidthDp = protoInputStream.readInt(SCREEN_WIDTH_DP);
1291 break;
1292 case (int) SCREEN_HEIGHT_DP:
1293 screenHeightDp = protoInputStream.readInt(SCREEN_HEIGHT_DP);
1294 break;
1295 case (int) SMALLEST_SCREEN_WIDTH_DP:
1296 smallestScreenWidthDp = protoInputStream.readInt(SMALLEST_SCREEN_WIDTH_DP);
1297 break;
1298 case (int) DENSITY_DPI:
1299 densityDpi = protoInputStream.readInt(DENSITY_DPI);
1300 break;
1301 case (int) WINDOW_CONFIGURATION:
1302 windowConfiguration.readFromProto(protoInputStream, WINDOW_CONFIGURATION);
1303 break;
Varun Shahbd0ce4d2019-09-10 15:51:37 -04001304 case (int) LOCALE_LIST:
1305 try {
1306 setLocales(LocaleList.forLanguageTags(protoInputStream.readString(
1307 LOCALE_LIST)));
1308 } catch (Exception e) {
1309 Slog.e(TAG, "error parsing locale list in configuration.", e);
1310 }
1311 break;
Michael Wachenschwanzc8c26362018-09-07 14:59:25 -07001312 }
1313 }
1314 } finally {
1315 // Let caller handle any exceptions
1316 if (list.size() > 0) {
1317 //Create the LocaleList from the collected Locales
1318 setLocales(new LocaleList(list.toArray(new Locale[list.size()])));
1319 }
1320 protoInputStream.end(token);
1321 }
1322 }
1323
1324 /**
Dianne Hackbornbf5ba6b2018-02-20 10:31:02 -08001325 * Write full {@link android.content.ResourcesConfigurationProto} to protocol buffer output
1326 * stream.
1327 *
1328 * @param protoOutputStream Stream to write the Configuration object to.
1329 * @param fieldId Field Id of the Configuration as defined in the parent message
1330 * @param metrics Current display information
1331 * @hide
1332 */
1333 public void writeResConfigToProto(ProtoOutputStream protoOutputStream, long fieldId,
1334 DisplayMetrics metrics) {
1335 final int width, height;
1336 if (metrics.widthPixels >= metrics.heightPixels) {
1337 width = metrics.widthPixels;
1338 height = metrics.heightPixels;
1339 } else {
1340 //noinspection SuspiciousNameCombination
1341 width = metrics.heightPixels;
1342 //noinspection SuspiciousNameCombination
1343 height = metrics.widthPixels;
1344 }
1345
1346 final long token = protoOutputStream.start(fieldId);
Jeffrey Huangcb782852019-12-05 11:28:11 -08001347 dumpDebug(protoOutputStream, CONFIGURATION);
Dianne Hackbornbf5ba6b2018-02-20 10:31:02 -08001348 protoOutputStream.write(SDK_VERSION, Build.VERSION.RESOURCES_SDK_INT);
1349 protoOutputStream.write(SCREEN_WIDTH_PX, width);
1350 protoOutputStream.write(SCREEN_HEIGHT_PX, height);
1351 protoOutputStream.end(token);
1352 }
1353
1354 /**
Michael Wright19859762017-09-18 20:57:58 +01001355 * Convert the UI mode to a human readable format.
1356 * @hide
1357 */
1358 public static String uiModeToString(int uiMode) {
1359 switch (uiMode) {
1360 case UI_MODE_TYPE_UNDEFINED:
1361 return "UI_MODE_TYPE_UNDEFINED";
1362 case UI_MODE_TYPE_NORMAL:
1363 return "UI_MODE_TYPE_NORMAL";
1364 case UI_MODE_TYPE_DESK:
1365 return "UI_MODE_TYPE_DESK";
1366 case UI_MODE_TYPE_CAR:
1367 return "UI_MODE_TYPE_CAR";
1368 case UI_MODE_TYPE_TELEVISION:
1369 return "UI_MODE_TYPE_TELEVISION";
1370 case UI_MODE_TYPE_APPLIANCE:
1371 return "UI_MODE_TYPE_APPLIANCE";
1372 case UI_MODE_TYPE_WATCH:
1373 return "UI_MODE_TYPE_WATCH";
1374 case UI_MODE_TYPE_VR_HEADSET:
1375 return "UI_MODE_TYPE_VR_HEADSET";
1376 default:
1377 return Integer.toString(uiMode);
1378 }
1379 }
1380
1381 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001382 * Set this object to the system defaults.
1383 */
1384 public void setToDefaults() {
1385 fontScale = 1;
1386 mcc = mnc = 0;
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001387 mLocaleList = LocaleList.getEmptyLocaleList();
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001388 locale = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389 userSetLocale = false;
1390 touchscreen = TOUCHSCREEN_UNDEFINED;
1391 keyboard = KEYBOARD_UNDEFINED;
1392 keyboardHidden = KEYBOARDHIDDEN_UNDEFINED;
1393 hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED;
1394 navigation = NAVIGATION_UNDEFINED;
Dianne Hackborn93e462b2009-09-15 22:50:40 -07001395 navigationHidden = NAVIGATIONHIDDEN_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001396 orientation = ORIENTATION_UNDEFINED;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001397 screenLayout = SCREENLAYOUT_UNDEFINED;
Romain Guy48327452017-01-23 17:03:35 -08001398 colorMode = COLOR_MODE_UNDEFINED;
Dianne Hackborn7299c412010-03-04 18:41:49 -08001399 uiMode = UI_MODE_TYPE_UNDEFINED;
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001400 screenWidthDp = compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED;
1401 screenHeightDp = compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED;
1402 smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001403 densityDpi = DENSITY_DPI_UNDEFINED;
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001404 assetsSeq = ASSETS_SEQ_UNDEFINED;
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001405 seq = 0;
Wale Ogunwale822e5122017-07-26 06:02:24 -07001406 windowConfiguration.setToDefaults();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001407 }
1408
Adam Lesinskibad43fc2016-07-19 13:35:01 -07001409 /**
1410 * Set this object to completely undefined.
1411 * @hide
1412 */
1413 public void unset() {
1414 setToDefaults();
1415 fontScale = 0;
1416 }
1417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001418 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001419 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001420 @Deprecated public void makeDefault() {
1421 setToDefaults();
1422 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -07001423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001424 /**
Alan Viveretteac85f902016-03-11 15:15:51 -05001425 * Copies the fields from delta into this Configuration object, keeping
1426 * track of which ones have changed. Any undefined fields in {@code delta}
1427 * are ignored and not copied in to the current Configuration.
1428 *
1429 * @return a bit mask of the changed fields, as per {@link #diff}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001430 */
Alan Viveretteac85f902016-03-11 15:15:51 -05001431 public @Config int updateFrom(@NonNull Configuration delta) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001432 int changed = 0;
1433 if (delta.fontScale > 0 && fontScale != delta.fontScale) {
1434 changed |= ActivityInfo.CONFIG_FONT_SCALE;
1435 fontScale = delta.fontScale;
1436 }
1437 if (delta.mcc != 0 && mcc != delta.mcc) {
1438 changed |= ActivityInfo.CONFIG_MCC;
1439 mcc = delta.mcc;
1440 }
1441 if (delta.mnc != 0 && mnc != delta.mnc) {
1442 changed |= ActivityInfo.CONFIG_MNC;
1443 mnc = delta.mnc;
1444 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001445 fixUpLocaleList();
1446 delta.fixUpLocaleList();
1447 if (!delta.mLocaleList.isEmpty() && !mLocaleList.equals(delta.mLocaleList)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001448 changed |= ActivityInfo.CONFIG_LOCALE;
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001449 mLocaleList = delta.mLocaleList;
1450 // delta.locale can't be null, since delta.mLocaleList is not empty.
1451 if (!delta.locale.equals(locale)) {
1452 locale = (Locale) delta.locale.clone();
1453 // If locale has changed, then layout direction is also changed ...
1454 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
1455 // ... and we need to update the layout direction (represented by the first
1456 // 2 most significant bits in screenLayout).
1457 setLayoutDirection(locale);
1458 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001459 }
Craig Mautner31678b52013-08-12 17:56:34 -07001460 final int deltaScreenLayoutDir = delta.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
1461 if (deltaScreenLayoutDir != SCREENLAYOUT_LAYOUTDIR_UNDEFINED &&
1462 deltaScreenLayoutDir != (screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) {
1463 screenLayout = (screenLayout & ~SCREENLAYOUT_LAYOUTDIR_MASK) | deltaScreenLayoutDir;
Amith Yamasanid8415f42013-08-07 20:15:10 -07001464 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
Amith Yamasanid8415f42013-08-07 20:15:10 -07001465 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001466 if (delta.userSetLocale && (!userSetLocale || ((changed & ActivityInfo.CONFIG_LOCALE) != 0)))
1467 {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001468 changed |= ActivityInfo.CONFIG_LOCALE;
Amith Yamasanid8415f42013-08-07 20:15:10 -07001469 userSetLocale = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470 }
1471 if (delta.touchscreen != TOUCHSCREEN_UNDEFINED
1472 && touchscreen != delta.touchscreen) {
1473 changed |= ActivityInfo.CONFIG_TOUCHSCREEN;
1474 touchscreen = delta.touchscreen;
1475 }
1476 if (delta.keyboard != KEYBOARD_UNDEFINED
1477 && keyboard != delta.keyboard) {
1478 changed |= ActivityInfo.CONFIG_KEYBOARD;
1479 keyboard = delta.keyboard;
1480 }
1481 if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED
1482 && keyboardHidden != delta.keyboardHidden) {
1483 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1484 keyboardHidden = delta.keyboardHidden;
1485 }
1486 if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED
1487 && hardKeyboardHidden != delta.hardKeyboardHidden) {
1488 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1489 hardKeyboardHidden = delta.hardKeyboardHidden;
1490 }
1491 if (delta.navigation != NAVIGATION_UNDEFINED
1492 && navigation != delta.navigation) {
1493 changed |= ActivityInfo.CONFIG_NAVIGATION;
1494 navigation = delta.navigation;
1495 }
Dianne Hackborn93e462b2009-09-15 22:50:40 -07001496 if (delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED
1497 && navigationHidden != delta.navigationHidden) {
1498 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1499 navigationHidden = delta.navigationHidden;
1500 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 if (delta.orientation != ORIENTATION_UNDEFINED
1502 && orientation != delta.orientation) {
1503 changed |= ActivityInfo.CONFIG_ORIENTATION;
1504 orientation = delta.orientation;
1505 }
Robert Carrdf259d32016-12-05 20:33:10 -08001506 if (((delta.screenLayout & SCREENLAYOUT_SIZE_MASK) != SCREENLAYOUT_SIZE_UNDEFINED)
1507 && (delta.screenLayout & SCREENLAYOUT_SIZE_MASK)
1508 != (screenLayout & SCREENLAYOUT_SIZE_MASK)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07001509 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
Robert Carrdf259d32016-12-05 20:33:10 -08001510 screenLayout = (screenLayout & ~SCREENLAYOUT_SIZE_MASK)
1511 | (delta.screenLayout & SCREENLAYOUT_SIZE_MASK);
Dianne Hackborn723738c2009-06-25 19:48:04 -07001512 }
Robert Carrdf259d32016-12-05 20:33:10 -08001513 if (((delta.screenLayout & SCREENLAYOUT_LONG_MASK) != SCREENLAYOUT_LONG_UNDEFINED)
1514 && (delta.screenLayout & SCREENLAYOUT_LONG_MASK)
1515 != (screenLayout & SCREENLAYOUT_LONG_MASK)) {
1516 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
1517 screenLayout = (screenLayout & ~SCREENLAYOUT_LONG_MASK)
1518 | (delta.screenLayout & SCREENLAYOUT_LONG_MASK);
1519 }
1520 if (((delta.screenLayout & SCREENLAYOUT_ROUND_MASK) != SCREENLAYOUT_ROUND_UNDEFINED)
1521 && (delta.screenLayout & SCREENLAYOUT_ROUND_MASK)
1522 != (screenLayout & SCREENLAYOUT_ROUND_MASK)) {
1523 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
1524 screenLayout = (screenLayout & ~SCREENLAYOUT_ROUND_MASK)
1525 | (delta.screenLayout & SCREENLAYOUT_ROUND_MASK);
1526 }
1527 if ((delta.screenLayout & SCREENLAYOUT_COMPAT_NEEDED)
1528 != (screenLayout & SCREENLAYOUT_COMPAT_NEEDED)
1529 && delta.screenLayout != 0) {
1530 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
1531 screenLayout = (screenLayout & ~SCREENLAYOUT_COMPAT_NEEDED)
1532 | (delta.screenLayout & SCREENLAYOUT_COMPAT_NEEDED);
1533 }
1534
Romain Guy48327452017-01-23 17:03:35 -08001535 if (((delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) !=
1536 COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED)
1537 && (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK)
1538 != (colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) {
1539 changed |= ActivityInfo.CONFIG_COLOR_MODE;
1540 colorMode = (colorMode & ~COLOR_MODE_WIDE_COLOR_GAMUT_MASK)
1541 | (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK);
Romain Guyc9ba5592017-01-18 16:34:42 -08001542 }
1543
Romain Guy48327452017-01-23 17:03:35 -08001544 if (((delta.colorMode & COLOR_MODE_HDR_MASK) != COLOR_MODE_HDR_UNDEFINED)
1545 && (delta.colorMode & COLOR_MODE_HDR_MASK)
1546 != (colorMode & COLOR_MODE_HDR_MASK)) {
1547 changed |= ActivityInfo.CONFIG_COLOR_MODE;
1548 colorMode = (colorMode & ~COLOR_MODE_HDR_MASK)
1549 | (delta.colorMode & COLOR_MODE_HDR_MASK);
Romain Guyc9ba5592017-01-18 16:34:42 -08001550 }
1551
Dianne Hackborn7299c412010-03-04 18:41:49 -08001552 if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)
Tobias Haamel27b28b32010-02-09 23:09:17 +01001553 && uiMode != delta.uiMode) {
1554 changed |= ActivityInfo.CONFIG_UI_MODE;
Dianne Hackborn7299c412010-03-04 18:41:49 -08001555 if ((delta.uiMode&UI_MODE_TYPE_MASK) != UI_MODE_TYPE_UNDEFINED) {
1556 uiMode = (uiMode&~UI_MODE_TYPE_MASK)
1557 | (delta.uiMode&UI_MODE_TYPE_MASK);
1558 }
1559 if ((delta.uiMode&UI_MODE_NIGHT_MASK) != UI_MODE_NIGHT_UNDEFINED) {
1560 uiMode = (uiMode&~UI_MODE_NIGHT_MASK)
1561 | (delta.uiMode&UI_MODE_NIGHT_MASK);
1562 }
Tobias Haamel27b28b32010-02-09 23:09:17 +01001563 }
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001564 if (delta.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED
1565 && screenWidthDp != delta.screenWidthDp) {
1566 changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1567 screenWidthDp = delta.screenWidthDp;
1568 }
1569 if (delta.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED
1570 && screenHeightDp != delta.screenHeightDp) {
1571 changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1572 screenHeightDp = delta.screenHeightDp;
1573 }
Danny Baumanne7123a62013-05-15 10:21:40 +02001574 if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
1575 && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
1576 changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001577 smallestScreenWidthDp = delta.smallestScreenWidthDp;
1578 }
Danny Baumanne7123a62013-05-15 10:21:40 +02001579 if (delta.densityDpi != DENSITY_DPI_UNDEFINED &&
1580 densityDpi != delta.densityDpi) {
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001581 changed |= ActivityInfo.CONFIG_DENSITY;
1582 densityDpi = delta.densityDpi;
1583 }
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001584 if (delta.compatScreenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
1585 compatScreenWidthDp = delta.compatScreenWidthDp;
1586 }
1587 if (delta.compatScreenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
1588 compatScreenHeightDp = delta.compatScreenHeightDp;
1589 }
1590 if (delta.compatSmallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
1591 compatSmallestScreenWidthDp = delta.compatSmallestScreenWidthDp;
1592 }
Adam Lesinski4eb41292017-07-06 12:06:13 -07001593 if (delta.assetsSeq != ASSETS_SEQ_UNDEFINED && delta.assetsSeq != assetsSeq) {
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001594 changed |= ActivityInfo.CONFIG_ASSETS_PATHS;
1595 assetsSeq = delta.assetsSeq;
1596 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001597 if (delta.seq != 0) {
1598 seq = delta.seq;
1599 }
Wale Ogunwale822e5122017-07-26 06:02:24 -07001600 if (windowConfiguration.updateFrom(delta.windowConfiguration) != 0) {
1601 changed |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
1602 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -07001603
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001604 return changed;
1605 }
1606
1607 /**
Evan Roskyddedfd42019-10-04 13:38:38 -07001608 * Copies the fields specified by mask from delta into this Configuration object. This will
1609 * copy anything allowed by the mask (including undefined values).
1610 * @hide
1611 */
1612 public void setTo(@NonNull Configuration delta, @Config int mask,
1613 @WindowConfiguration.WindowConfig int windowMask) {
1614 if ((mask & ActivityInfo.CONFIG_FONT_SCALE) != 0) {
1615 fontScale = delta.fontScale;
1616 }
1617 if ((mask & ActivityInfo.CONFIG_MCC) != 0) {
1618 mcc = delta.mcc;
1619 }
1620 if ((mask & ActivityInfo.CONFIG_MNC) != 0) {
1621 mnc = delta.mnc;
1622 }
1623 if ((mask & ActivityInfo.CONFIG_LOCALE) != 0) {
1624 mLocaleList = delta.mLocaleList;
1625 if (!mLocaleList.isEmpty()) {
1626 locale = (Locale) delta.locale.clone();
1627 }
1628 }
1629 if ((mask & ActivityInfo.CONFIG_LAYOUT_DIRECTION) != 0) {
1630 final int deltaScreenLayoutDir = delta.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
1631 screenLayout = (screenLayout & ~SCREENLAYOUT_LAYOUTDIR_MASK) | deltaScreenLayoutDir;
1632 }
1633 if ((mask & ActivityInfo.CONFIG_LOCALE) != 0) {
1634 userSetLocale = delta.userSetLocale;
1635 }
1636 if ((mask & ActivityInfo.CONFIG_TOUCHSCREEN) != 0) {
1637 touchscreen = delta.touchscreen;
1638 }
1639 if ((mask & ActivityInfo.CONFIG_KEYBOARD) != 0) {
1640 keyboard = delta.keyboard;
1641 }
1642 if ((mask & ActivityInfo.CONFIG_KEYBOARD_HIDDEN) != 0) {
1643 keyboardHidden = delta.keyboardHidden;
1644 hardKeyboardHidden = delta.hardKeyboardHidden;
1645 navigationHidden = delta.navigationHidden;
1646 }
1647 if ((mask & ActivityInfo.CONFIG_NAVIGATION) != 0) {
1648 navigation = delta.navigation;
1649 }
1650 if ((mask & ActivityInfo.CONFIG_ORIENTATION) != 0) {
1651 orientation = delta.orientation;
1652 }
1653 if ((mask & ActivityInfo.CONFIG_SCREEN_LAYOUT) != 0) {
1654 // Not enough granularity for each component unfortunately.
1655 screenLayout = screenLayout | (delta.screenLayout & ~SCREENLAYOUT_LAYOUTDIR_MASK);
1656 }
1657 if ((mask & ActivityInfo.CONFIG_COLOR_MODE) != 0) {
1658 colorMode = delta.colorMode;
1659 }
1660 if ((mask & ActivityInfo.CONFIG_UI_MODE) != 0) {
1661 uiMode = delta.uiMode;
1662 }
1663 if ((mask & ActivityInfo.CONFIG_SCREEN_SIZE) != 0) {
1664 screenWidthDp = delta.screenWidthDp;
1665 screenHeightDp = delta.screenHeightDp;
1666 }
1667 if ((mask & ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE) != 0) {
1668 smallestScreenWidthDp = delta.smallestScreenWidthDp;
1669 }
1670 if ((mask & ActivityInfo.CONFIG_DENSITY) != 0) {
1671 densityDpi = delta.densityDpi;
1672 }
1673 if ((mask & ActivityInfo.CONFIG_ASSETS_PATHS) != 0) {
1674 assetsSeq = delta.assetsSeq;
1675 }
1676 if ((mask & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0) {
1677 windowConfiguration.setTo(delta.windowConfiguration, windowMask);
1678 }
1679 }
1680
1681 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682 * Return a bit mask of the differences between this Configuration
1683 * object and the given one. Does not change the values of either. Any
1684 * undefined fields in <var>delta</var> are ignored.
1685 * @return Returns a bit mask indicating which configuration
1686 * values has changed, containing any combination of
1687 * {@link android.content.pm.ActivityInfo#CONFIG_FONT_SCALE
1688 * PackageManager.ActivityInfo.CONFIG_FONT_SCALE},
1689 * {@link android.content.pm.ActivityInfo#CONFIG_MCC
1690 * PackageManager.ActivityInfo.CONFIG_MCC},
1691 * {@link android.content.pm.ActivityInfo#CONFIG_MNC
1692 * PackageManager.ActivityInfo.CONFIG_MNC},
1693 * {@link android.content.pm.ActivityInfo#CONFIG_LOCALE
1694 * PackageManager.ActivityInfo.CONFIG_LOCALE},
1695 * {@link android.content.pm.ActivityInfo#CONFIG_TOUCHSCREEN
1696 * PackageManager.ActivityInfo.CONFIG_TOUCHSCREEN},
1697 * {@link android.content.pm.ActivityInfo#CONFIG_KEYBOARD
1698 * PackageManager.ActivityInfo.CONFIG_KEYBOARD},
1699 * {@link android.content.pm.ActivityInfo#CONFIG_NAVIGATION
Dianne Hackborn723738c2009-06-25 19:48:04 -07001700 * PackageManager.ActivityInfo.CONFIG_NAVIGATION},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001701 * {@link android.content.pm.ActivityInfo#CONFIG_ORIENTATION
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001702 * PackageManager.ActivityInfo.CONFIG_ORIENTATION},
Dianne Hackborn723738c2009-06-25 19:48:04 -07001703 * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_LAYOUT
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001704 * PackageManager.ActivityInfo.CONFIG_SCREEN_LAYOUT}, or
1705 * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_SIZE
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001706 * PackageManager.ActivityInfo.CONFIG_SCREEN_SIZE}, or
1707 * {@link android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE
1708 * PackageManager.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE}.
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001709 * {@link android.content.pm.ActivityInfo#CONFIG_LAYOUT_DIRECTION
1710 * PackageManager.ActivityInfo.CONFIG_LAYOUT_DIRECTION}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001711 */
1712 public int diff(Configuration delta) {
Bryce Lee658d9842017-07-28 08:33:36 -07001713 return diff(delta, false /* compareUndefined */, false /* publicOnly */);
1714 }
1715
1716 /**
1717 * Returns the diff against the provided {@link Configuration} excluding values that would
1718 * publicly be equivalent, such as appBounds.
1719 * @param delta {@link Configuration} to compare to.
1720 *
1721 * TODO(b/36812336): Remove once appBounds has been moved out of Configuration.
1722 * {@hide}
1723 */
1724 public int diffPublicOnly(Configuration delta) {
1725 return diff(delta, false /* compareUndefined */, true /* publicOnly */);
Andrii Kulianb10330d2016-09-16 13:51:46 -07001726 }
1727
1728 /**
1729 * Variation of {@link #diff(Configuration)} with an option to skip checks for undefined values.
1730 *
1731 * @hide
1732 */
Bryce Lee658d9842017-07-28 08:33:36 -07001733 public int diff(Configuration delta, boolean compareUndefined, boolean publicOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001734 int changed = 0;
Andrii Kulianb10330d2016-09-16 13:51:46 -07001735 if ((compareUndefined || delta.fontScale > 0) && fontScale != delta.fontScale) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001736 changed |= ActivityInfo.CONFIG_FONT_SCALE;
1737 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001738 if ((compareUndefined || delta.mcc != 0) && mcc != delta.mcc) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001739 changed |= ActivityInfo.CONFIG_MCC;
1740 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001741 if ((compareUndefined || delta.mnc != 0) && mnc != delta.mnc) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001742 changed |= ActivityInfo.CONFIG_MNC;
1743 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001744 fixUpLocaleList();
1745 delta.fixUpLocaleList();
Andrii Kulianb10330d2016-09-16 13:51:46 -07001746 if ((compareUndefined || !delta.mLocaleList.isEmpty())
1747 && !mLocaleList.equals(delta.mLocaleList)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001748 changed |= ActivityInfo.CONFIG_LOCALE;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001749 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001750 }
Craig Mautner31678b52013-08-12 17:56:34 -07001751 final int deltaScreenLayoutDir = delta.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
Andrii Kulianb10330d2016-09-16 13:51:46 -07001752 if ((compareUndefined || deltaScreenLayoutDir != SCREENLAYOUT_LAYOUTDIR_UNDEFINED)
1753 && deltaScreenLayoutDir != (screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) {
Amith Yamasanid8415f42013-08-07 20:15:10 -07001754 changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
1755 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001756 if ((compareUndefined || delta.touchscreen != TOUCHSCREEN_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001757 && touchscreen != delta.touchscreen) {
1758 changed |= ActivityInfo.CONFIG_TOUCHSCREEN;
1759 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001760 if ((compareUndefined || delta.keyboard != KEYBOARD_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001761 && keyboard != delta.keyboard) {
1762 changed |= ActivityInfo.CONFIG_KEYBOARD;
1763 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001764 if ((compareUndefined || delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001765 && keyboardHidden != delta.keyboardHidden) {
1766 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1767 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001768 if ((compareUndefined || delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001769 && hardKeyboardHidden != delta.hardKeyboardHidden) {
1770 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1771 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001772 if ((compareUndefined || delta.navigation != NAVIGATION_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001773 && navigation != delta.navigation) {
1774 changed |= ActivityInfo.CONFIG_NAVIGATION;
1775 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001776 if ((compareUndefined || delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED)
Dianne Hackborn93e462b2009-09-15 22:50:40 -07001777 && navigationHidden != delta.navigationHidden) {
1778 changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
1779 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001780 if ((compareUndefined || delta.orientation != ORIENTATION_UNDEFINED)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001781 && orientation != delta.orientation) {
1782 changed |= ActivityInfo.CONFIG_ORIENTATION;
1783 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001784 if ((compareUndefined || getScreenLayoutNoDirection(delta.screenLayout) !=
1785 (SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED))
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001786 && getScreenLayoutNoDirection(screenLayout) !=
Andrii Kulianb10330d2016-09-16 13:51:46 -07001787 getScreenLayoutNoDirection(delta.screenLayout)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07001788 changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
1789 }
Romain Guyc9ba5592017-01-18 16:34:42 -08001790 if ((compareUndefined ||
Romain Guy48327452017-01-23 17:03:35 -08001791 (delta.colorMode & COLOR_MODE_HDR_MASK) != COLOR_MODE_HDR_UNDEFINED)
1792 && (colorMode & COLOR_MODE_HDR_MASK) !=
1793 (delta.colorMode & COLOR_MODE_HDR_MASK)) {
1794 changed |= ActivityInfo.CONFIG_COLOR_MODE;
Romain Guyc9ba5592017-01-18 16:34:42 -08001795 }
1796 if ((compareUndefined ||
Romain Guy48327452017-01-23 17:03:35 -08001797 (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) !=
1798 COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED)
1799 && (colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) !=
1800 (delta.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) {
1801 changed |= ActivityInfo.CONFIG_COLOR_MODE;
Romain Guyc9ba5592017-01-18 16:34:42 -08001802 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001803 if ((compareUndefined || delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED))
Tobias Haamel27b28b32010-02-09 23:09:17 +01001804 && uiMode != delta.uiMode) {
1805 changed |= ActivityInfo.CONFIG_UI_MODE;
1806 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001807 if ((compareUndefined || delta.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED)
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001808 && screenWidthDp != delta.screenWidthDp) {
1809 changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1810 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001811 if ((compareUndefined || delta.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED)
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001812 && screenHeightDp != delta.screenHeightDp) {
1813 changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
1814 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001815 if ((compareUndefined || delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED)
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001816 && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
1817 changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
1818 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001819 if ((compareUndefined || delta.densityDpi != DENSITY_DPI_UNDEFINED)
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001820 && densityDpi != delta.densityDpi) {
1821 changed |= ActivityInfo.CONFIG_DENSITY;
1822 }
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001823 if ((compareUndefined || delta.assetsSeq != ASSETS_SEQ_UNDEFINED)
1824 && assetsSeq != delta.assetsSeq) {
1825 changed |= ActivityInfo.CONFIG_ASSETS_PATHS;
1826 }
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07001827
Wale Ogunwale822e5122017-07-26 06:02:24 -07001828 // WindowConfiguration differences aren't considered public...
1829 if (!publicOnly
1830 && windowConfiguration.diff(delta.windowConfiguration, compareUndefined) != 0) {
1831 changed |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
Bryce Lee7566d762017-03-30 09:34:15 -07001832 }
1833
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001834 return changed;
1835 }
1836
1837 /**
Alan Viveretteac85f902016-03-11 15:15:51 -05001838 * Determines if a new resource needs to be loaded from the bit set of
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001839 * configuration changes returned by {@link #updateFrom(Configuration)}.
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -07001840 *
Alan Viveretteac85f902016-03-11 15:15:51 -05001841 * @param configChanges the mask of changes configurations as returned by
1842 * {@link #updateFrom(Configuration)}
1843 * @param interestingChanges the configuration changes that the resource
1844 * can handle as given in
1845 * {@link android.util.TypedValue#changingConfigurations}
1846 * @return {@code true} if the resource needs to be loaded, {@code false}
1847 * otherwise
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001848 */
Alan Viveretteac85f902016-03-11 15:15:51 -05001849 public static boolean needNewResources(@Config int configChanges,
1850 @Config int interestingChanges) {
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001851 // CONFIG_ASSETS_PATHS and CONFIG_FONT_SCALE are higher level configuration changes that
1852 // all resources are subject to change with.
1853 interestingChanges = interestingChanges | ActivityInfo.CONFIG_ASSETS_PATHS
1854 | ActivityInfo.CONFIG_FONT_SCALE;
1855 return (configChanges & interestingChanges) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001856 }
Amith Yamasanid8415f42013-08-07 20:15:10 -07001857
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001858 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001859 * @hide Return true if the sequence of 'other' is better than this. Assumes
1860 * that 'this' is your current sequence and 'other' is a new one you have
1861 * received some how and want to compare with what you have.
1862 */
1863 public boolean isOtherSeqNewer(Configuration other) {
1864 if (other == null) {
1865 // Sanity check.
1866 return false;
1867 }
1868 if (other.seq == 0) {
1869 // If the other sequence is not specified, then we must assume
1870 // it is newer since we don't know any better.
1871 return true;
1872 }
1873 if (seq == 0) {
1874 // If this sequence is not specified, then we also consider the
1875 // other is better. Yes we have a preference for other. Sue us.
1876 return true;
1877 }
1878 int diff = other.seq - seq;
1879 if (diff > 0x10000) {
1880 // If there has been a sufficiently large jump, assume the
1881 // sequence has wrapped around.
1882 return false;
1883 }
1884 return diff > 0;
1885 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -07001886
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001887 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001888 * Parcelable methods
1889 */
1890 public int describeContents() {
1891 return 0;
1892 }
1893
1894 public void writeToParcel(Parcel dest, int flags) {
1895 dest.writeFloat(fontScale);
1896 dest.writeInt(mcc);
1897 dest.writeInt(mnc);
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001898
1899 fixUpLocaleList();
Siyamed Sinir27ddd8a2018-02-27 13:07:22 -08001900 dest.writeParcelable(mLocaleList, flags);
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001902 if(userSetLocale) {
1903 dest.writeInt(1);
1904 } else {
1905 dest.writeInt(0);
1906 }
1907 dest.writeInt(touchscreen);
1908 dest.writeInt(keyboard);
1909 dest.writeInt(keyboardHidden);
1910 dest.writeInt(hardKeyboardHidden);
1911 dest.writeInt(navigation);
Dianne Hackborn93e462b2009-09-15 22:50:40 -07001912 dest.writeInt(navigationHidden);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001913 dest.writeInt(orientation);
Dianne Hackborn723738c2009-06-25 19:48:04 -07001914 dest.writeInt(screenLayout);
Romain Guy48327452017-01-23 17:03:35 -08001915 dest.writeInt(colorMode);
Tobias Haamel27b28b32010-02-09 23:09:17 +01001916 dest.writeInt(uiMode);
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001917 dest.writeInt(screenWidthDp);
1918 dest.writeInt(screenHeightDp);
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001919 dest.writeInt(smallestScreenWidthDp);
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001920 dest.writeInt(densityDpi);
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001921 dest.writeInt(compatScreenWidthDp);
1922 dest.writeInt(compatScreenHeightDp);
1923 dest.writeInt(compatSmallestScreenWidthDp);
Wale Ogunwale822e5122017-07-26 06:02:24 -07001924 dest.writeValue(windowConfiguration);
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001925 dest.writeInt(assetsSeq);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001926 dest.writeInt(seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001927 }
1928
Dianne Hackborn694f79b2010-03-17 19:44:59 -07001929 public void readFromParcel(Parcel source) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001930 fontScale = source.readFloat();
1931 mcc = source.readInt();
1932 mnc = source.readInt();
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001933
Siyamed Sinir27ddd8a2018-02-27 13:07:22 -08001934 mLocaleList = source.readParcelable(LocaleList.class.getClassLoader());
Roozbeh Pournaderfee44842016-02-04 15:24:24 -08001935 locale = mLocaleList.get(0);
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001936
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001937 userSetLocale = (source.readInt()==1);
1938 touchscreen = source.readInt();
1939 keyboard = source.readInt();
1940 keyboardHidden = source.readInt();
1941 hardKeyboardHidden = source.readInt();
1942 navigation = source.readInt();
Dianne Hackborn93e462b2009-09-15 22:50:40 -07001943 navigationHidden = source.readInt();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001944 orientation = source.readInt();
Dianne Hackborn723738c2009-06-25 19:48:04 -07001945 screenLayout = source.readInt();
Romain Guy48327452017-01-23 17:03:35 -08001946 colorMode = source.readInt();
Tobias Haamel27b28b32010-02-09 23:09:17 +01001947 uiMode = source.readInt();
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001948 screenWidthDp = source.readInt();
1949 screenHeightDp = source.readInt();
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001950 smallestScreenWidthDp = source.readInt();
Dianne Hackborn908aecc2012-07-31 16:37:34 -07001951 densityDpi = source.readInt();
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001952 compatScreenWidthDp = source.readInt();
1953 compatScreenHeightDp = source.readInt();
1954 compatSmallestScreenWidthDp = source.readInt();
Wale Ogunwale822e5122017-07-26 06:02:24 -07001955 windowConfiguration.setTo((WindowConfiguration) source.readValue(null));
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01001956 assetsSeq = source.readInt();
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001957 seq = source.readInt();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001958 }
Filip Gruszczynskibc5a6c52015-09-22 13:13:24 -07001959
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07001960 public static final @android.annotation.NonNull Parcelable.Creator<Configuration> CREATOR
Dianne Hackborn694f79b2010-03-17 19:44:59 -07001961 = new Parcelable.Creator<Configuration>() {
1962 public Configuration createFromParcel(Parcel source) {
1963 return new Configuration(source);
1964 }
1965
1966 public Configuration[] newArray(int size) {
1967 return new Configuration[size];
1968 }
1969 };
1970
1971 /**
1972 * Construct this Configuration object, reading from the Parcel.
1973 */
1974 private Configuration(Parcel source) {
1975 readFromParcel(source);
1976 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001977
1978 public int compareTo(Configuration that) {
1979 int n;
1980 float a = this.fontScale;
1981 float b = that.fontScale;
1982 if (a < b) return -1;
1983 if (a > b) return 1;
1984 n = this.mcc - that.mcc;
1985 if (n != 0) return n;
1986 n = this.mnc - that.mnc;
1987 if (n != 0) return n;
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001988
1989 fixUpLocaleList();
1990 that.fixUpLocaleList();
1991 // for backward compatibility, we consider an empty locale list to be greater
1992 // than any non-empty locale list.
1993 if (this.mLocaleList.isEmpty()) {
1994 if (!that.mLocaleList.isEmpty()) return 1;
1995 } else if (that.mLocaleList.isEmpty()) {
Dianne Hackborna8397032010-03-12 10:52:22 -08001996 return -1;
1997 } else {
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07001998 final int minSize = Math.min(this.mLocaleList.size(), that.mLocaleList.size());
1999 for (int i = 0; i < minSize; ++i) {
2000 final Locale thisLocale = this.mLocaleList.get(i);
2001 final Locale thatLocale = that.mLocaleList.get(i);
2002 n = thisLocale.getLanguage().compareTo(thatLocale.getLanguage());
2003 if (n != 0) return n;
2004 n = thisLocale.getCountry().compareTo(thatLocale.getCountry());
2005 if (n != 0) return n;
2006 n = thisLocale.getVariant().compareTo(thatLocale.getVariant());
2007 if (n != 0) return n;
2008 n = thisLocale.toLanguageTag().compareTo(thatLocale.toLanguageTag());
2009 if (n != 0) return n;
2010 }
2011 n = this.mLocaleList.size() - that.mLocaleList.size();
Dianne Hackborna8397032010-03-12 10:52:22 -08002012 if (n != 0) return n;
2013 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002015 n = this.touchscreen - that.touchscreen;
2016 if (n != 0) return n;
2017 n = this.keyboard - that.keyboard;
2018 if (n != 0) return n;
2019 n = this.keyboardHidden - that.keyboardHidden;
2020 if (n != 0) return n;
2021 n = this.hardKeyboardHidden - that.hardKeyboardHidden;
2022 if (n != 0) return n;
2023 n = this.navigation - that.navigation;
2024 if (n != 0) return n;
Dianne Hackborn93e462b2009-09-15 22:50:40 -07002025 n = this.navigationHidden - that.navigationHidden;
2026 if (n != 0) return n;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002027 n = this.orientation - that.orientation;
Dianne Hackborn723738c2009-06-25 19:48:04 -07002028 if (n != 0) return n;
Romain Guy48327452017-01-23 17:03:35 -08002029 n = this.colorMode - that.colorMode;
Romain Guyc9ba5592017-01-18 16:34:42 -08002030 if (n != 0) return n;
Dianne Hackborn723738c2009-06-25 19:48:04 -07002031 n = this.screenLayout - that.screenLayout;
Tobias Haamel27b28b32010-02-09 23:09:17 +01002032 if (n != 0) return n;
2033 n = this.uiMode - that.uiMode;
Dianne Hackbornebff8f92011-05-12 18:07:47 -07002034 if (n != 0) return n;
2035 n = this.screenWidthDp - that.screenWidthDp;
2036 if (n != 0) return n;
2037 n = this.screenHeightDp - that.screenHeightDp;
Dianne Hackborn69cb8752011-05-19 18:13:32 -07002038 if (n != 0) return n;
2039 n = this.smallestScreenWidthDp - that.smallestScreenWidthDp;
Dianne Hackborn908aecc2012-07-31 16:37:34 -07002040 if (n != 0) return n;
2041 n = this.densityDpi - that.densityDpi;
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01002042 if (n != 0) return n;
2043 n = this.assetsSeq - that.assetsSeq;
Bryce Leec5fe0ee2017-06-30 09:03:09 -07002044 if (n != 0) return n;
Wale Ogunwale822e5122017-07-26 06:02:24 -07002045 n = windowConfiguration.compareTo(that.windowConfiguration);
2046 if (n != 0) return n;
Bryce Leec5fe0ee2017-06-30 09:03:09 -07002047
2048 // if (n != 0) return n;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002049 return n;
2050 }
2051
2052 public boolean equals(Configuration that) {
2053 if (that == null) return false;
2054 if (that == this) return true;
2055 return this.compareTo(that) == 0;
2056 }
2057
2058 public boolean equals(Object that) {
2059 try {
2060 return equals((Configuration)that);
2061 } catch (ClassCastException e) {
2062 }
2063 return false;
2064 }
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002065
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002066 public int hashCode() {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002067 int result = 17;
2068 result = 31 * result + Float.floatToIntBits(fontScale);
2069 result = 31 * result + mcc;
2070 result = 31 * result + mnc;
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002071 result = 31 * result + mLocaleList.hashCode();
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002072 result = 31 * result + touchscreen;
2073 result = 31 * result + keyboard;
2074 result = 31 * result + keyboardHidden;
2075 result = 31 * result + hardKeyboardHidden;
2076 result = 31 * result + navigation;
2077 result = 31 * result + navigationHidden;
2078 result = 31 * result + orientation;
2079 result = 31 * result + screenLayout;
Romain Guy48327452017-01-23 17:03:35 -08002080 result = 31 * result + colorMode;
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002081 result = 31 * result + uiMode;
Dianne Hackbornebff8f92011-05-12 18:07:47 -07002082 result = 31 * result + screenWidthDp;
2083 result = 31 * result + screenHeightDp;
Dianne Hackborn69cb8752011-05-19 18:13:32 -07002084 result = 31 * result + smallestScreenWidthDp;
Dianne Hackborn908aecc2012-07-31 16:37:34 -07002085 result = 31 * result + densityDpi;
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01002086 result = 31 * result + assetsSeq;
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002087 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002088 }
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07002089
2090 /**
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002091 * Get the locale list. This is the preferred way for getting the locales (instead of using
2092 * the direct accessor to {@link #locale}, which would only provide the primary locale).
2093 *
2094 * @return The locale list.
2095 */
Adam Lesinskib61e4052016-05-19 18:23:05 -07002096 public @NonNull LocaleList getLocales() {
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002097 fixUpLocaleList();
2098 return mLocaleList;
2099 }
2100
2101 /**
2102 * Set the locale list. This is the preferred way for setting up the locales (instead of using
2103 * the direct accessor or {@link #setLocale(Locale)}). This will also set the layout direction
2104 * according to the first locale in the list.
2105 *
2106 * Note that the layout direction will always come from the first locale in the locale list,
2107 * even if the locale is not supported by the resources (the resources may only support
2108 * another locale further down the list which has a different direction).
2109 *
2110 * @param locales The locale list. If null, an empty LocaleList will be assigned.
2111 */
2112 public void setLocales(@Nullable LocaleList locales) {
2113 mLocaleList = locales == null ? LocaleList.getEmptyLocaleList() : locales;
Roozbeh Pournaderfee44842016-02-04 15:24:24 -08002114 locale = mLocaleList.get(0);
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002115 setLayoutDirection(locale);
2116 }
2117
2118 /**
2119 * Set the locale list to a list of just one locale. This will also set the layout direction
2120 * according to the locale.
2121 *
2122 * Note that after this is run, calling <code>.equals()</code> on the input locale and the
2123 * {@link #locale} attribute would return <code>true</code> if they are not null, but there is
2124 * no guarantee that they would be the same object.
2125 *
2126 * See also the note about layout direction in {@link #setLocales(LocaleList)}.
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07002127 *
2128 * @param loc The locale. Can be null.
2129 */
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002130 public void setLocale(@Nullable Locale loc) {
Raph Levien10ea92a2016-05-02 12:56:01 -07002131 setLocales(loc == null ? LocaleList.getEmptyLocaleList() : new LocaleList(loc));
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07002132 }
2133
2134 /**
Seigo Nonakabd5cac62016-05-13 15:11:37 +09002135 * @hide
2136 *
2137 * Clears the locale without changing layout direction.
2138 */
2139 public void clearLocales() {
2140 mLocaleList = LocaleList.getEmptyLocaleList();
2141 locale = null;
2142 }
2143
2144 /**
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07002145 * Return the layout direction. Will be either {@link View#LAYOUT_DIRECTION_LTR} or
2146 * {@link View#LAYOUT_DIRECTION_RTL}.
2147 *
Dianne Hackbornf1ae2692013-04-19 14:09:37 -07002148 * @return Returns {@link View#LAYOUT_DIRECTION_RTL} if the configuration
2149 * is {@link #SCREENLAYOUT_LAYOUTDIR_RTL}, otherwise {@link View#LAYOUT_DIRECTION_LTR}.
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07002150 */
2151 public int getLayoutDirection() {
Dianne Hackbornf1ae2692013-04-19 14:09:37 -07002152 return (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK) == SCREENLAYOUT_LAYOUTDIR_RTL
2153 ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07002154 }
2155
2156 /**
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002157 * Set the layout direction from a Locale.
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07002158 *
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002159 * @param loc The Locale. If null will set the layout direction to
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07002160 * {@link View#LAYOUT_DIRECTION_LTR}. If not null will set it to the layout direction
2161 * corresponding to the Locale.
2162 *
John Spurlockbc4cf002015-03-24 21:51:20 -04002163 * @see View#LAYOUT_DIRECTION_LTR
2164 * @see View#LAYOUT_DIRECTION_RTL
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07002165 */
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002166 public void setLayoutDirection(Locale loc) {
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07002167 // There is a "1" difference between the configuration values for
2168 // layout direction and View constants for layout direction, just add "1".
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002169 final int layoutDirection = 1 + TextUtils.getLayoutDirectionFromLocale(loc);
Fabrice Di Meglio5f797992012-06-15 20:16:41 -07002170 screenLayout = (screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK)|
2171 (layoutDirection << SCREENLAYOUT_LAYOUTDIR_SHIFT);
2172 }
2173
2174 private static int getScreenLayoutNoDirection(int screenLayout) {
2175 return screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK;
2176 }
Adam Lesinski2c749d22014-06-04 13:00:29 -07002177
2178 /**
Adam Powell49e7ff92015-05-14 16:18:53 -07002179 * Return whether the screen has a round shape. Apps may choose to change styling based
2180 * on this property, such as the alignment or layout of text or informational icons.
2181 *
2182 * @return true if the screen is rounded, false otherwise
2183 */
2184 public boolean isScreenRound() {
2185 return (screenLayout & SCREENLAYOUT_ROUND_MASK) == SCREENLAYOUT_ROUND_YES;
2186 }
2187
2188 /**
Romain Guye89d0bb2017-06-20 12:23:42 -07002189 * Return whether the screen has a wide color gamut and wide color gamut rendering
2190 * is supported by this device.
Romain Guyc9ba5592017-01-18 16:34:42 -08002191 *
Chia-I Wu53e86ba2018-05-02 10:13:22 -07002192 * When true, it implies the screen is colorspace aware but not
2193 * necessarily color-managed. The final colors may still be changed by the
2194 * screen depending on user settings.
2195 *
Romain Guye89d0bb2017-06-20 12:23:42 -07002196 * @return true if the screen has a wide color gamut and wide color gamut rendering
2197 * is supported, false otherwise
Romain Guyc9ba5592017-01-18 16:34:42 -08002198 */
2199 public boolean isScreenWideColorGamut() {
Romain Guy48327452017-01-23 17:03:35 -08002200 return (colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) == COLOR_MODE_WIDE_COLOR_GAMUT_YES;
Romain Guyc9ba5592017-01-18 16:34:42 -08002201 }
2202
2203 /**
2204 * Return whether the screen has a high dynamic range.
2205 *
2206 * @return true if the screen has a high dynamic range, false otherwise
2207 */
2208 public boolean isScreenHdr() {
Romain Guy48327452017-01-23 17:03:35 -08002209 return (colorMode & COLOR_MODE_HDR_MASK) == COLOR_MODE_HDR_YES;
Romain Guyc9ba5592017-01-18 16:34:42 -08002210 }
2211
2212 /**
Adam Lesinski2c749d22014-06-04 13:00:29 -07002213 *
2214 * @hide
2215 */
Roozbeh Pournader47f71a62015-11-07 11:55:38 -08002216 public static String localesToResourceQualifier(LocaleList locs) {
Roozbeh Pournader309ebd62016-06-17 22:13:12 -07002217 final StringBuilder sb = new StringBuilder();
Roozbeh Pournader47f71a62015-11-07 11:55:38 -08002218 for (int i = 0; i < locs.size(); i++) {
Roozbeh Pournader309ebd62016-06-17 22:13:12 -07002219 final Locale loc = locs.get(i);
2220 final int l = loc.getLanguage().length();
2221 if (l == 0) {
2222 continue;
2223 }
2224 final int s = loc.getScript().length();
2225 final int c = loc.getCountry().length();
2226 final int v = loc.getVariant().length();
2227 // We ignore locale extensions, since they are not supported by AAPT
2228
2229 if (sb.length() != 0) {
2230 sb.append(",");
2231 }
2232 if (l == 2 && s == 0 && (c == 0 || c == 2) && v == 0) {
2233 // Traditional locale format: xx or xx-rYY
Roozbeh Pournader47f71a62015-11-07 11:55:38 -08002234 sb.append(loc.getLanguage());
Roozbeh Pournader309ebd62016-06-17 22:13:12 -07002235 if (c == 2) {
Roozbeh Pournader47f71a62015-11-07 11:55:38 -08002236 sb.append("-r").append(loc.getCountry());
Roozbeh Pournader309ebd62016-06-17 22:13:12 -07002237 }
2238 } else {
2239 sb.append("b+");
2240 sb.append(loc.getLanguage());
2241 if (s != 0) {
2242 sb.append("+");
2243 sb.append(loc.getScript());
2244 }
2245 if (c != 0) {
2246 sb.append("+");
2247 sb.append(loc.getCountry());
2248 }
2249 if (v != 0) {
2250 sb.append("+");
2251 sb.append(loc.getVariant());
Adam Lesinski2c749d22014-06-04 13:00:29 -07002252 }
2253 }
2254 }
2255 return sb.toString();
2256 }
2257
2258
2259 /**
2260 * Returns a string representation of the configuration that can be parsed
Dianne Hackbornbf5ba6b2018-02-20 10:31:02 -08002261 * by build tools (like AAPT), without display metrics included
Adam Lesinski2c749d22014-06-04 13:00:29 -07002262 *
Adam Lesinski2c749d22014-06-04 13:00:29 -07002263 * @hide
2264 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01002265 @UnsupportedAppUsage
Adam Lesinski2c749d22014-06-04 13:00:29 -07002266 public static String resourceQualifierString(Configuration config) {
Dianne Hackbornbf5ba6b2018-02-20 10:31:02 -08002267 return resourceQualifierString(config, null);
2268 }
2269
2270 /**
2271 * Returns a string representation of the configuration that can be parsed
2272 * by build tools (like AAPT).
2273 *
2274 * @hide
2275 */
2276 public static String resourceQualifierString(Configuration config, DisplayMetrics metrics) {
Adam Lesinski2c749d22014-06-04 13:00:29 -07002277 ArrayList<String> parts = new ArrayList<String>();
2278
2279 if (config.mcc != 0) {
Adam Lesinski90865622014-10-16 18:18:10 -07002280 parts.add("mcc" + config.mcc);
Adam Lesinski2c749d22014-06-04 13:00:29 -07002281 if (config.mnc != 0) {
Adam Lesinski90865622014-10-16 18:18:10 -07002282 parts.add("mnc" + config.mnc);
Adam Lesinski2c749d22014-06-04 13:00:29 -07002283 }
2284 }
2285
Roozbeh Pournader47f71a62015-11-07 11:55:38 -08002286 if (!config.mLocaleList.isEmpty()) {
Roozbeh Pournader417bbe02015-11-09 17:09:15 -08002287 final String resourceQualifier = localesToResourceQualifier(config.mLocaleList);
2288 if (!resourceQualifier.isEmpty()) {
2289 parts.add(resourceQualifier);
2290 }
Adam Lesinski2c749d22014-06-04 13:00:29 -07002291 }
2292
2293 switch (config.screenLayout & Configuration.SCREENLAYOUT_LAYOUTDIR_MASK) {
2294 case Configuration.SCREENLAYOUT_LAYOUTDIR_LTR:
2295 parts.add("ldltr");
2296 break;
2297 case Configuration.SCREENLAYOUT_LAYOUTDIR_RTL:
2298 parts.add("ldrtl");
2299 break;
2300 default:
2301 break;
2302 }
2303
2304 if (config.smallestScreenWidthDp != 0) {
2305 parts.add("sw" + config.smallestScreenWidthDp + "dp");
2306 }
2307
2308 if (config.screenWidthDp != 0) {
2309 parts.add("w" + config.screenWidthDp + "dp");
2310 }
2311
2312 if (config.screenHeightDp != 0) {
2313 parts.add("h" + config.screenHeightDp + "dp");
2314 }
2315
2316 switch (config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) {
2317 case Configuration.SCREENLAYOUT_SIZE_SMALL:
2318 parts.add("small");
2319 break;
2320 case Configuration.SCREENLAYOUT_SIZE_NORMAL:
2321 parts.add("normal");
2322 break;
2323 case Configuration.SCREENLAYOUT_SIZE_LARGE:
2324 parts.add("large");
2325 break;
2326 case Configuration.SCREENLAYOUT_SIZE_XLARGE:
2327 parts.add("xlarge");
2328 break;
2329 default:
2330 break;
2331 }
2332
2333 switch (config.screenLayout & Configuration.SCREENLAYOUT_LONG_MASK) {
2334 case Configuration.SCREENLAYOUT_LONG_YES:
2335 parts.add("long");
2336 break;
2337 case Configuration.SCREENLAYOUT_LONG_NO:
2338 parts.add("notlong");
2339 break;
2340 default:
2341 break;
2342 }
2343
Adam Powell49e7ff92015-05-14 16:18:53 -07002344 switch (config.screenLayout & Configuration.SCREENLAYOUT_ROUND_MASK) {
2345 case Configuration.SCREENLAYOUT_ROUND_YES:
2346 parts.add("round");
2347 break;
2348 case Configuration.SCREENLAYOUT_ROUND_NO:
2349 parts.add("notround");
2350 break;
2351 default:
2352 break;
2353 }
2354
Romain Guy48327452017-01-23 17:03:35 -08002355 switch (config.colorMode & Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_MASK) {
2356 case Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_YES:
Romain Guyc9ba5592017-01-18 16:34:42 -08002357 parts.add("widecg");
2358 break;
Romain Guy48327452017-01-23 17:03:35 -08002359 case Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_NO:
Romain Guyc9ba5592017-01-18 16:34:42 -08002360 parts.add("nowidecg");
2361 break;
2362 default:
2363 break;
2364 }
2365
Chia-I Wu0d8acf52018-05-09 12:08:05 -07002366 switch (config.colorMode & Configuration.COLOR_MODE_HDR_MASK) {
2367 case Configuration.COLOR_MODE_HDR_YES:
2368 parts.add("highdr");
2369 break;
2370 case Configuration.COLOR_MODE_HDR_NO:
2371 parts.add("lowdr");
2372 break;
2373 default:
2374 break;
2375 }
2376
Adam Lesinski2c749d22014-06-04 13:00:29 -07002377 switch (config.orientation) {
2378 case Configuration.ORIENTATION_LANDSCAPE:
2379 parts.add("land");
2380 break;
2381 case Configuration.ORIENTATION_PORTRAIT:
2382 parts.add("port");
2383 break;
2384 default:
2385 break;
2386 }
2387
2388 switch (config.uiMode & Configuration.UI_MODE_TYPE_MASK) {
2389 case Configuration.UI_MODE_TYPE_APPLIANCE:
2390 parts.add("appliance");
2391 break;
2392 case Configuration.UI_MODE_TYPE_DESK:
2393 parts.add("desk");
2394 break;
2395 case Configuration.UI_MODE_TYPE_TELEVISION:
2396 parts.add("television");
2397 break;
2398 case Configuration.UI_MODE_TYPE_CAR:
2399 parts.add("car");
2400 break;
2401 case Configuration.UI_MODE_TYPE_WATCH:
2402 parts.add("watch");
2403 break;
Zak Cohen1a6acdb2016-12-12 15:21:21 -08002404 case Configuration.UI_MODE_TYPE_VR_HEADSET:
2405 parts.add("vrheadset");
2406 break;
Adam Lesinski2c749d22014-06-04 13:00:29 -07002407 default:
2408 break;
2409 }
2410
2411 switch (config.uiMode & Configuration.UI_MODE_NIGHT_MASK) {
2412 case Configuration.UI_MODE_NIGHT_YES:
2413 parts.add("night");
2414 break;
2415 case Configuration.UI_MODE_NIGHT_NO:
2416 parts.add("notnight");
2417 break;
2418 default:
2419 break;
2420 }
2421
2422 switch (config.densityDpi) {
Adam Lesinski31245b42014-08-22 19:10:56 -07002423 case DENSITY_DPI_UNDEFINED:
Adam Lesinski2c749d22014-06-04 13:00:29 -07002424 break;
2425 case 120:
2426 parts.add("ldpi");
2427 break;
2428 case 160:
2429 parts.add("mdpi");
2430 break;
2431 case 213:
2432 parts.add("tvdpi");
2433 break;
2434 case 240:
2435 parts.add("hdpi");
2436 break;
2437 case 320:
2438 parts.add("xhdpi");
2439 break;
Adam Lesinskiebc3e4c2014-08-21 12:21:45 -07002440 case 480:
2441 parts.add("xxhdpi");
2442 break;
2443 case 640:
2444 parts.add("xxxhdpi");
2445 break;
Adam Lesinski31245b42014-08-22 19:10:56 -07002446 case DENSITY_DPI_ANY:
2447 parts.add("anydpi");
2448 break;
2449 case DENSITY_DPI_NONE:
2450 parts.add("nodpi");
Christian Williamsb709f3c2017-11-02 17:19:27 -07002451 break;
Adam Lesinski2c749d22014-06-04 13:00:29 -07002452 default:
2453 parts.add(config.densityDpi + "dpi");
2454 break;
2455 }
2456
2457 switch (config.touchscreen) {
2458 case Configuration.TOUCHSCREEN_NOTOUCH:
2459 parts.add("notouch");
2460 break;
2461 case Configuration.TOUCHSCREEN_FINGER:
2462 parts.add("finger");
2463 break;
2464 default:
2465 break;
2466 }
2467
2468 switch (config.keyboardHidden) {
2469 case Configuration.KEYBOARDHIDDEN_NO:
2470 parts.add("keysexposed");
2471 break;
2472 case Configuration.KEYBOARDHIDDEN_YES:
2473 parts.add("keyshidden");
2474 break;
2475 case Configuration.KEYBOARDHIDDEN_SOFT:
2476 parts.add("keyssoft");
2477 break;
2478 default:
2479 break;
2480 }
2481
2482 switch (config.keyboard) {
2483 case Configuration.KEYBOARD_NOKEYS:
2484 parts.add("nokeys");
2485 break;
2486 case Configuration.KEYBOARD_QWERTY:
2487 parts.add("qwerty");
2488 break;
2489 case Configuration.KEYBOARD_12KEY:
2490 parts.add("12key");
2491 break;
2492 default:
2493 break;
2494 }
2495
2496 switch (config.navigationHidden) {
2497 case Configuration.NAVIGATIONHIDDEN_NO:
2498 parts.add("navexposed");
2499 break;
2500 case Configuration.NAVIGATIONHIDDEN_YES:
2501 parts.add("navhidden");
2502 break;
2503 default:
2504 break;
2505 }
2506
2507 switch (config.navigation) {
2508 case Configuration.NAVIGATION_NONAV:
2509 parts.add("nonav");
2510 break;
2511 case Configuration.NAVIGATION_DPAD:
2512 parts.add("dpad");
2513 break;
2514 case Configuration.NAVIGATION_TRACKBALL:
2515 parts.add("trackball");
2516 break;
2517 case Configuration.NAVIGATION_WHEEL:
2518 parts.add("wheel");
2519 break;
2520 default:
2521 break;
2522 }
2523
Dianne Hackbornbf5ba6b2018-02-20 10:31:02 -08002524 if (metrics != null) {
2525 final int width, height;
2526 if (metrics.widthPixels >= metrics.heightPixels) {
2527 width = metrics.widthPixels;
2528 height = metrics.heightPixels;
2529 } else {
2530 //noinspection SuspiciousNameCombination
2531 width = metrics.heightPixels;
2532 //noinspection SuspiciousNameCombination
2533 height = metrics.widthPixels;
2534 }
2535 parts.add(width + "x" + height);
2536 }
2537
Adam Lesinskiebc3e4c2014-08-21 12:21:45 -07002538 parts.add("v" + Build.VERSION.RESOURCES_SDK_INT);
Adam Lesinski2c749d22014-06-04 13:00:29 -07002539 return TextUtils.join("-", parts);
2540 }
Adam Lesinski7f61e962014-09-02 16:43:52 -07002541
2542 /**
2543 * Generate a delta Configuration between <code>base</code> and <code>change</code>. The
2544 * resulting delta can be used with {@link #updateFrom(Configuration)}.
2545 * <p />
2546 * Caveat: If the any of the Configuration's members becomes undefined, then
2547 * {@link #updateFrom(Configuration)} will treat it as a no-op and not update that member.
2548 *
2549 * This is fine for device configurations as no member is ever undefined.
2550 * {@hide}
2551 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01002552 @UnsupportedAppUsage
Adam Lesinski7f61e962014-09-02 16:43:52 -07002553 public static Configuration generateDelta(Configuration base, Configuration change) {
2554 final Configuration delta = new Configuration();
2555 if (base.fontScale != change.fontScale) {
2556 delta.fontScale = change.fontScale;
2557 }
2558
2559 if (base.mcc != change.mcc) {
2560 delta.mcc = change.mcc;
2561 }
2562
2563 if (base.mnc != change.mnc) {
2564 delta.mnc = change.mnc;
2565 }
2566
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002567 base.fixUpLocaleList();
2568 change.fixUpLocaleList();
2569 if (!base.mLocaleList.equals(change.mLocaleList)) {
2570 delta.mLocaleList = change.mLocaleList;
Adam Lesinski7f61e962014-09-02 16:43:52 -07002571 delta.locale = change.locale;
2572 }
2573
2574 if (base.touchscreen != change.touchscreen) {
2575 delta.touchscreen = change.touchscreen;
2576 }
2577
2578 if (base.keyboard != change.keyboard) {
2579 delta.keyboard = change.keyboard;
2580 }
2581
2582 if (base.keyboardHidden != change.keyboardHidden) {
2583 delta.keyboardHidden = change.keyboardHidden;
2584 }
2585
2586 if (base.navigation != change.navigation) {
2587 delta.navigation = change.navigation;
2588 }
2589
2590 if (base.navigationHidden != change.navigationHidden) {
2591 delta.navigationHidden = change.navigationHidden;
2592 }
2593
2594 if (base.orientation != change.orientation) {
2595 delta.orientation = change.orientation;
2596 }
2597
2598 if ((base.screenLayout & SCREENLAYOUT_SIZE_MASK) !=
2599 (change.screenLayout & SCREENLAYOUT_SIZE_MASK)) {
2600 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_SIZE_MASK;
2601 }
2602
2603 if ((base.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK) !=
2604 (change.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) {
2605 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
2606 }
2607
2608 if ((base.screenLayout & SCREENLAYOUT_LONG_MASK) !=
2609 (change.screenLayout & SCREENLAYOUT_LONG_MASK)) {
2610 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_LONG_MASK;
2611 }
2612
Adam Powell49e7ff92015-05-14 16:18:53 -07002613 if ((base.screenLayout & SCREENLAYOUT_ROUND_MASK) !=
2614 (change.screenLayout & SCREENLAYOUT_ROUND_MASK)) {
2615 delta.screenLayout |= change.screenLayout & SCREENLAYOUT_ROUND_MASK;
2616 }
2617
Romain Guy48327452017-01-23 17:03:35 -08002618 if ((base.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) !=
2619 (change.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) {
2620 delta.colorMode |= change.colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK;
Romain Guyc9ba5592017-01-18 16:34:42 -08002621 }
2622
Romain Guy48327452017-01-23 17:03:35 -08002623 if ((base.colorMode & COLOR_MODE_HDR_MASK) !=
2624 (change.colorMode & COLOR_MODE_HDR_MASK)) {
2625 delta.colorMode |= change.colorMode & COLOR_MODE_HDR_MASK;
Romain Guyc9ba5592017-01-18 16:34:42 -08002626 }
2627
Adam Lesinski7f61e962014-09-02 16:43:52 -07002628 if ((base.uiMode & UI_MODE_TYPE_MASK) != (change.uiMode & UI_MODE_TYPE_MASK)) {
2629 delta.uiMode |= change.uiMode & UI_MODE_TYPE_MASK;
2630 }
2631
2632 if ((base.uiMode & UI_MODE_NIGHT_MASK) != (change.uiMode & UI_MODE_NIGHT_MASK)) {
2633 delta.uiMode |= change.uiMode & UI_MODE_NIGHT_MASK;
2634 }
2635
2636 if (base.screenWidthDp != change.screenWidthDp) {
2637 delta.screenWidthDp = change.screenWidthDp;
2638 }
2639
2640 if (base.screenHeightDp != change.screenHeightDp) {
2641 delta.screenHeightDp = change.screenHeightDp;
2642 }
2643
2644 if (base.smallestScreenWidthDp != change.smallestScreenWidthDp) {
2645 delta.smallestScreenWidthDp = change.smallestScreenWidthDp;
2646 }
2647
2648 if (base.densityDpi != change.densityDpi) {
2649 delta.densityDpi = change.densityDpi;
2650 }
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01002651
2652 if (base.assetsSeq != change.assetsSeq) {
2653 delta.assetsSeq = change.assetsSeq;
2654 }
Wale Ogunwale822e5122017-07-26 06:02:24 -07002655
2656 if (!base.windowConfiguration.equals(change.windowConfiguration)) {
2657 delta.windowConfiguration.setTo(change.windowConfiguration);
2658 }
Adam Lesinski7f61e962014-09-02 16:43:52 -07002659 return delta;
2660 }
2661
2662 private static final String XML_ATTR_FONT_SCALE = "fs";
2663 private static final String XML_ATTR_MCC = "mcc";
2664 private static final String XML_ATTR_MNC = "mnc";
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002665 private static final String XML_ATTR_LOCALES = "locales";
Adam Lesinski7f61e962014-09-02 16:43:52 -07002666 private static final String XML_ATTR_TOUCHSCREEN = "touch";
2667 private static final String XML_ATTR_KEYBOARD = "key";
2668 private static final String XML_ATTR_KEYBOARD_HIDDEN = "keyHid";
2669 private static final String XML_ATTR_HARD_KEYBOARD_HIDDEN = "hardKeyHid";
2670 private static final String XML_ATTR_NAVIGATION = "nav";
2671 private static final String XML_ATTR_NAVIGATION_HIDDEN = "navHid";
2672 private static final String XML_ATTR_ORIENTATION = "ori";
Bryce Leec1f2f2a2017-06-22 15:29:42 -07002673 private static final String XML_ATTR_ROTATION = "rot";
Adam Lesinski7f61e962014-09-02 16:43:52 -07002674 private static final String XML_ATTR_SCREEN_LAYOUT = "scrLay";
Romain Guy48327452017-01-23 17:03:35 -08002675 private static final String XML_ATTR_COLOR_MODE = "clrMod";
Adam Lesinski7f61e962014-09-02 16:43:52 -07002676 private static final String XML_ATTR_UI_MODE = "ui";
2677 private static final String XML_ATTR_SCREEN_WIDTH = "width";
2678 private static final String XML_ATTR_SCREEN_HEIGHT = "height";
2679 private static final String XML_ATTR_SMALLEST_WIDTH = "sw";
2680 private static final String XML_ATTR_DENSITY = "density";
Bryce Lee7566d762017-03-30 09:34:15 -07002681 private static final String XML_ATTR_APP_BOUNDS = "app_bounds";
Adam Lesinski7f61e962014-09-02 16:43:52 -07002682
2683 /**
2684 * Reads the attributes corresponding to Configuration member fields from the Xml parser.
2685 * The parser is expected to be on a tag which has Configuration attributes.
2686 *
2687 * @param parser The Xml parser from which to read attributes.
2688 * @param configOut The Configuration to populate from the Xml attributes.
2689 * {@hide}
2690 */
2691 public static void readXmlAttrs(XmlPullParser parser, Configuration configOut)
2692 throws XmlPullParserException, IOException {
2693 configOut.fontScale = Float.intBitsToFloat(
2694 XmlUtils.readIntAttribute(parser, XML_ATTR_FONT_SCALE, 0));
2695 configOut.mcc = XmlUtils.readIntAttribute(parser, XML_ATTR_MCC, 0);
2696 configOut.mnc = XmlUtils.readIntAttribute(parser, XML_ATTR_MNC, 0);
2697
Roozbeh Pournaderb46fdd42015-08-19 14:56:22 -07002698 final String localesStr = XmlUtils.readStringAttribute(parser, XML_ATTR_LOCALES);
2699 configOut.mLocaleList = LocaleList.forLanguageTags(localesStr);
Roozbeh Pournaderfee44842016-02-04 15:24:24 -08002700 configOut.locale = configOut.mLocaleList.get(0);
Adam Lesinski7f61e962014-09-02 16:43:52 -07002701
2702 configOut.touchscreen = XmlUtils.readIntAttribute(parser, XML_ATTR_TOUCHSCREEN,
2703 TOUCHSCREEN_UNDEFINED);
2704 configOut.keyboard = XmlUtils.readIntAttribute(parser, XML_ATTR_KEYBOARD,
2705 KEYBOARD_UNDEFINED);
2706 configOut.keyboardHidden = XmlUtils.readIntAttribute(parser, XML_ATTR_KEYBOARD_HIDDEN,
2707 KEYBOARDHIDDEN_UNDEFINED);
2708 configOut.hardKeyboardHidden =
2709 XmlUtils.readIntAttribute(parser, XML_ATTR_HARD_KEYBOARD_HIDDEN,
2710 HARDKEYBOARDHIDDEN_UNDEFINED);
2711 configOut.navigation = XmlUtils.readIntAttribute(parser, XML_ATTR_NAVIGATION,
2712 NAVIGATION_UNDEFINED);
2713 configOut.navigationHidden = XmlUtils.readIntAttribute(parser, XML_ATTR_NAVIGATION_HIDDEN,
2714 NAVIGATIONHIDDEN_UNDEFINED);
2715 configOut.orientation = XmlUtils.readIntAttribute(parser, XML_ATTR_ORIENTATION,
2716 ORIENTATION_UNDEFINED);
2717 configOut.screenLayout = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_LAYOUT,
2718 SCREENLAYOUT_UNDEFINED);
Romain Guy48327452017-01-23 17:03:35 -08002719 configOut.colorMode = XmlUtils.readIntAttribute(parser, XML_ATTR_COLOR_MODE,
2720 COLOR_MODE_UNDEFINED);
Adam Lesinski7f61e962014-09-02 16:43:52 -07002721 configOut.uiMode = XmlUtils.readIntAttribute(parser, XML_ATTR_UI_MODE, 0);
2722 configOut.screenWidthDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_WIDTH,
2723 SCREEN_WIDTH_DP_UNDEFINED);
2724 configOut.screenHeightDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_HEIGHT,
2725 SCREEN_HEIGHT_DP_UNDEFINED);
2726 configOut.smallestScreenWidthDp =
2727 XmlUtils.readIntAttribute(parser, XML_ATTR_SMALLEST_WIDTH,
2728 SMALLEST_SCREEN_WIDTH_DP_UNDEFINED);
2729 configOut.densityDpi = XmlUtils.readIntAttribute(parser, XML_ATTR_DENSITY,
2730 DENSITY_DPI_UNDEFINED);
Mårten Kongstad49a4a1d2017-01-12 08:36:37 +01002731
Wale Ogunwale822e5122017-07-26 06:02:24 -07002732 // For persistence, we don't care about assetsSeq and WindowConfiguration, so do not read it
2733 // out.
Adam Lesinski7f61e962014-09-02 16:43:52 -07002734 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002735}