Android Configuration相关
log打印
在日志中经常可以看到打印
WindowManager: Override config changes=20005df8 {0.0 ?mcc?mnc ?localeList ?layoutDir sw294dp w294dp h654dp 587dpi nrml long port ?uimode ?night -touch -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1080, 2400) mAppBounds=Rect(0, 0 - 1080, 2400) mMaxBounds=Rect(0, 0 - 1080, 2400) mDisplayRotation=ROTATION_0 mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_0} ?fontWeightAdjustment} for displayId=2
代码路径:frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
int performDisplayOverrideConfigUpdate(Configuration values) {
mTempConfig.setTo(getRequestedOverrideConfiguration());
final int changes = mTempConfig.updateFrom(values);
if (changes != 0) {
Slog.i(TAG, "Override config changes=" + Integer.toHexString(changes) + " "
+ mTempConfig + " for displayId=" + mDisplayId);
if (isReady() && mTransitionController.isShellTransitionsEnabled()) {
requestChangeTransitionIfNeeded(changes, null /* displayChange */);
}
onRequestedOverrideConfigurationChanged(mTempConfig);
final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
if (isDensityChange && mDisplayId == DEFAULT_DISPLAY) {
mAtmService.mAppWarnings.onDensityChanged();
// Post message to start process to avoid possible deadlock of calling into AMS with
// the ATMS lock held.
final Message msg = PooledLambda.obtainMessage(
ActivityManagerInternal::killAllBackgroundProcessesExcept,
mAtmService.mAmInternal, N,
ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
mAtmService.mH.sendMessage(msg);
}
mWmService.mDisplayNotificationController.dispatchDisplayChanged(
this, getConfiguration());
}
return changes;
}
一般来说Configuration发生变化时,便会刷新打印关键log:Override config changes
这里的mTempConfig
就是Configuration
对象,其对应
Configuration
Configuration类则用于描述整个设备或应用的配置信息。它包含了更广泛的属性,如屏幕方向、触摸方式、字体缩放比例、MCC(移动国家码)、MNC(移动网络码)、地区设置、屏幕分辨率(以dp为单位)以及屏幕密度(以dpi为单位)等。
代码路径:frameworks/base/core/java/android/content/res/Configuration.java
/**
* This class describes all device configuration information that can
* impact the resources the application retrieves. This includes both
* user-specified configuration options (locale list and scaling) as well
* as device configurations (such as input modes, screen size and screen orientation).
* <p>You can acquire this object from {@link Resources}, using {@link
* Resources#getConfiguration}. Thus, from an activity, you can get it by chaining the request
* with {@link android.app.Activity#getResources}:</p>
* <pre>Configuration config = getResources().getConfiguration();</pre>
*/
public final class Configuration implements Parcelable, Comparable<Configuration> {
public String toString() {
StringBuilder sb = new StringBuilder(128);
sb.append("{");
sb.append(fontScale);
sb.append(" ");
if (mcc != 0) {
sb.append(mcc);
sb.append("mcc");
} else {
sb.append("?mcc");
}
if (mnc != MNC_ZERO) {
sb.append(mnc);
sb.append("mnc");
} else {
sb.append("?mnc");
}
fixUpLocaleList();
if (!mLocaleList.isEmpty()) {
sb.append(" ");
sb.append(mLocaleList);
} else {
sb.append(" ?localeList");
}
if (mGrammaticalGender != 0) {
switch (mGrammaticalGender) {
case GRAMMATICAL_GENDER_NEUTRAL: sb.append(" neuter"); break;
case GRAMMATICAL_GENDER_FEMININE: sb.append(" feminine"); break;
case GRAMMATICAL_GENDER_MASCULINE: sb.append(" masculine"); break;
case GRAMMATICAL_GENDER_NOT_SPECIFIED: sb.append(" ?grgend"); break;
}
}
int layoutDir = (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK);
switch (layoutDir) {
case SCREENLAYOUT_LAYOUTDIR_UNDEFINED: sb.append(" ?layoutDir"); break;
case SCREENLAYOUT_LAYOUTDIR_LTR: sb.append(" ldltr"); break;
case SCREENLAYOUT_LAYOUTDIR_RTL: sb.append(" ldrtl"); break;
default: sb.append(" layoutDir=");
sb.append(layoutDir >> SCREENLAYOUT_LAYOUTDIR_SHIFT); break;
}
if (smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
sb.append(" sw"); sb.append(smallestScreenWidthDp); sb.append("dp");
} else {
sb.append(" ?swdp");
}
if (screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
sb.append(" w"); sb.append(screenWidthDp); sb.append("dp");
} else {
sb.append(" ?wdp");
}
if (screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
sb.append(" h"); sb.append(screenHeightDp); sb.append("dp");
} else {
sb.append(" ?hdp");
}
if (densityDpi != DENSITY_DPI_UNDEFINED) {
sb.append(" "); sb.append(densityDpi); sb.append("dpi");
} else {
sb.append(" ?density");
}
switch ((screenLayout&SCREENLAYOUT_SIZE_MASK)) {
case SCREENLAYOUT_SIZE_UNDEFINED: sb.append(" ?lsize"); break;
case SCREENLAYOUT_SIZE_SMALL: sb.append(" smll"); break;
case SCREENLAYOUT_SIZE_NORMAL: sb.append(" nrml"); break;
case SCREENLAYOUT_SIZE_LARGE: sb.append(" lrg"); break;
case SCREENLAYOUT_SIZE_XLARGE: sb.append(" xlrg"); break;
default: sb.append(" layoutSize=");
sb.append(screenLayout&SCREENLAYOUT_SIZE_MASK); break;
}
switch ((screenLayout&SCREENLAYOUT_LONG_MASK)) {
case SCREENLAYOUT_LONG_UNDEFINED: sb.append(" ?long"); break;
case SCREENLAYOUT_LONG_NO: /* not-long is not interesting to print */ break;
case SCREENLAYOUT_LONG_YES: sb.append(" long"); break;
default: sb.append(" layoutLong=");
sb.append(screenLayout&SCREENLAYOUT_LONG_MASK); break;
}
switch ((colorMode &COLOR_MODE_HDR_MASK)) {
case COLOR_MODE_HDR_UNDEFINED: sb.append(" ?ldr"); break; // most likely not HDR
case COLOR_MODE_HDR_NO: /* ldr is not interesting to print */ break;
case COLOR_MODE_HDR_YES: sb.append(" hdr"); break;
default: sb.append(" dynamicRange=");
sb.append(colorMode &COLOR_MODE_HDR_MASK); break;
}
switch ((colorMode &COLOR_MODE_WIDE_COLOR_GAMUT_MASK)) {
case COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED: sb.append(" ?wideColorGamut"); break;
case COLOR_MODE_WIDE_COLOR_GAMUT_NO: /* not wide is not interesting to print */ break;
case COLOR_MODE_WIDE_COLOR_GAMUT_YES: sb.append(" widecg"); break;
default: sb.append(" wideColorGamut=");
sb.append(colorMode &COLOR_MODE_WIDE_COLOR_GAMUT_MASK); break;
}
switch (orientation) {
case ORIENTATION_UNDEFINED: sb.append(" ?orien"); break;
case ORIENTATION_LANDSCAPE: sb.append(" land"); break;
case ORIENTATION_PORTRAIT: sb.append(" port"); break;
default: sb.append(" orien="); sb.append(orientation); break;
}
switch ((uiMode&UI_MODE_TYPE_MASK)) {
case UI_MODE_TYPE_UNDEFINED: sb.append(" ?uimode"); break;
case UI_MODE_TYPE_NORMAL: /* normal is not interesting to print */ break;
case UI_MODE_TYPE_DESK: sb.append(" desk"); break;
case UI_MODE_TYPE_CAR: sb.append(" car"); break;
case UI_MODE_TYPE_TELEVISION: sb.append(" television"); break;
case UI_MODE_TYPE_APPLIANCE: sb.append(" appliance"); break;
case UI_MODE_TYPE_WATCH: sb.append(" watch"); break;
case UI_MODE_TYPE_VR_HEADSET: sb.append(" vrheadset"); break;
default: sb.append(" uimode="); sb.append(uiMode&UI_MODE_TYPE_MASK); break;
}
switch ((uiMode&UI_MODE_NIGHT_MASK)) {
case UI_MODE_NIGHT_UNDEFINED: sb.append(" ?night"); break;
case UI_MODE_NIGHT_NO: /* not-night is not interesting to print */ break;
case UI_MODE_NIGHT_YES: sb.append(" night"); break;
default: sb.append(" night="); sb.append(uiMode&UI_MODE_NIGHT_MASK); break;
}
switch (touchscreen) {
case TOUCHSCREEN_UNDEFINED: sb.append(" ?touch"); break;
case TOUCHSCREEN_NOTOUCH: sb.append(" -touch"); break;
case TOUCHSCREEN_STYLUS: sb.append(" stylus"); break;
case TOUCHSCREEN_FINGER: sb.append(" finger"); break;
default: sb.append(" touch="); sb.append(touchscreen); break;
}
switch (keyboard) {
case KEYBOARD_UNDEFINED: sb.append(" ?keyb"); break;
case KEYBOARD_NOKEYS: sb.append(" -keyb"); break;
case KEYBOARD_QWERTY: sb.append(" qwerty"); break;
case KEYBOARD_12KEY: sb.append(" 12key"); break;
default: sb.append(" keys="); sb.append(keyboard); break;
}
switch (keyboardHidden) {
case KEYBOARDHIDDEN_UNDEFINED: sb.append("/?"); break;
case KEYBOARDHIDDEN_NO: sb.append("/v"); break;
case KEYBOARDHIDDEN_YES: sb.append("/h"); break;
case KEYBOARDHIDDEN_SOFT: sb.append("/s"); break;
default: sb.append("/"); sb.append(keyboardHidden); break;
}
switch (hardKeyboardHidden) {
case HARDKEYBOARDHIDDEN_UNDEFINED: sb.append("/?"); break;
case HARDKEYBOARDHIDDEN_NO: sb.append("/v"); break;
case HARDKEYBOARDHIDDEN_YES: sb.append("/h"); break;
default: sb.append("/"); sb.append(hardKeyboardHidden); break;
}
switch (navigation) {
case NAVIGATION_UNDEFINED: sb.append(" ?nav"); break;
case NAVIGATION_NONAV: sb.append(" -nav"); break;
case NAVIGATION_DPAD: sb.append(" dpad"); break;
case NAVIGATION_TRACKBALL: sb.append(" tball"); break;
case NAVIGATION_WHEEL: sb.append(" wheel"); break;
default: sb.append(" nav="); sb.append(navigation); break;
}
switch (navigationHidden) {
case NAVIGATIONHIDDEN_UNDEFINED: sb.append("/?"); break;
case NAVIGATIONHIDDEN_NO: sb.append("/v"); break;
case NAVIGATIONHIDDEN_YES: sb.append("/h"); break;
default: sb.append("/"); sb.append(navigationHidden); break;
}
sb.append(" winConfig="); sb.append(windowConfiguration);
if (assetsSeq != 0) {
sb.append(" as.").append(assetsSeq);
}
if (seq != 0) {
sb.append(" s.").append(seq);
}
if (fontWeightAdjustment != FONT_WEIGHT_ADJUSTMENT_UNDEFINED) {
sb.append(" fontWeightAdjustment=");
sb.append(fontWeightAdjustment);
} else {
sb.append(" ?fontWeightAdjustment");
}
sb.append('}');
return sb.toString();
}
常见参数介绍:
- fontScale:当前用户设置的字体的缩放因子
- mcc:获取移动信号的国家码
- mnc:获取移动信号的网络码
- locale:获取用户当前的语言环境
- densityDpi:屏幕密度
- navigation:判断系统上方向导航设备的类型。该属性的返回值:NAVIGATION_NONAV(无导航)、 NAVIGATION_DPAD(DPAD导航)NAVIGATION_TRACKBALL(轨迹球导航)、NAVIGATION_WHEEL(滚轮导航)
orientation:获取系统屏幕的方向。该属性的返回值:ORIENTATION_LANDSCAPE(横向屏幕)、ORIENTATION_PORTRAIT(竖向屏幕) - screenHeightDp,screenWidthDp:屏幕可用高和宽,用dp表示
- touchscreen:获取系统触摸屏的触摸方式。该属性的返回值:TOUCHSCREEN_NOTOUCH(无触摸屏)、TOUCHSCREEN_STYLUS(触摸笔式触摸屏)、TOUCHSCREEN_FINGER(接收手指的触摸屏)
- windowConfiguration:窗口相关信息
windowConfiguration
WindowConfiguration是用来描述窗口的配置信息的类,包括窗口的大小、位置、方向、可见性等。WindowConfiguration会在以下情况下更新:
- 屏幕方向改变:当设备的屏幕方向发生改变时,WindowConfiguration会更新以反映新的方向。
- 窗口大小改变:当窗口的大小发生改变时,WindowConfiguration会更新以反映新的大小。
- 窗口位置改变:当窗口的位置发生改变时,WindowConfiguration会更新以反映新的位置。
- 窗口可见性改变:当窗口的可见性发生改变时,WindowConfiguration会更新以反映新的可见性。
- 窗口类型改变:当窗口的类型发生改变时,WindowConfiguration会更新以反映新的类型。
总之,当窗口的任何配置信息发生改变时,WindowConfiguration都会更新以反映新的配置信息
代码路径:frameworks/base/core/java/android/app/WindowConfiguration.java
/**
* Class that contains windowing configuration/state for other objects that contain windows directly
* or indirectly. E.g. Activities, Task, Displays, ...
* The test class is {@link com.android.server.wm.WindowConfigurationTests} which must be kept
* up-to-date and ran anytime changes are made to this class.
* @hide
*/
@TestApi
public class WindowConfiguration implements Parcelable, Comparable<WindowConfiguration> {
@Override
public String toString() {
return "{ mBounds=" + mBounds
+ " mAppBounds=" + mAppBounds
+ " mMaxBounds=" + mMaxBounds
+ " mDisplayRotation=" + (mRotation == ROTATION_UNDEFINED
? "undefined" : rotationToString(mDisplayRotation))
+ " mWindowingMode=" + windowingModeToString(mWindowingMode)
+ " mDisplayWindowingMode=" + windowingModeToString(mDisplayWindowingMode)
+ " mActivityType=" + activityTypeToString(mActivityType)
+ " mAlwaysOnTop=" + alwaysOnTopToString(mAlwaysOnTop)
+ " mRotation=" + (mRotation == ROTATION_UNDEFINED
? "undefined" : rotationToString(mRotation))
+ "}";
}
常见参数介绍:
- mWindowingMode:窗口模式,用于描述窗口的显示方式,包括以下几种模式: - WINDOWING_MODE_UNDEFINED:未定义的窗口模式。 - WINDOWING_MODE_FULLSCREEN:全屏模式,窗口将占据整个屏幕。 - WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:分屏模式,窗口将占据屏幕的一半。 - WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:分屏模式,窗口将占据屏幕的另一半。 - WINDOWING_MODE_FREEFORM:自由形式模式,窗口可以自由调整大小和位置。
- mActivityType:活动类型,用于描述窗口所属的活动类型,包括以下几种类型: - ACTIVITY_TYPE_UNDEFINED:未定义的活动类型。 - ACTIVITY_TYPE_STANDARD:标准活动类型,即普通的Activity。 - ACTIVITY_TYPE_HOME:主页活动类型,即Launcher。 - ACTIVITY_TYPE_RECENTS:最近使用的活动类型,即Recents。 - ACTIVITY_TYPE_ASSISTANT:助手活动类型,即Assistant。
- mRotation:屏幕方向,用于描述窗口所处的屏幕方向,包括以下几种方向: - ROTATION_UNDEFINED:未定义的屏幕方向。 - ROTATION_0:竖屏方向。 - ROTATION_90:横屏方向。 - ROTATION_180:反向竖屏方向。 - ROTATION_270:反向横屏方向。
- mBounds:窗口边界,用于描述窗口的位置和大小。
- mAppBounds:应用边界,用于描述应用的位置和大小。
- mAlwaysOnTop:是否始终置顶,用于描述窗口是否始终置顶。
isAlwaysOnTop():判断是否置顶 - isFloating():是否浮动,用于描述窗口是否浮动。