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

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

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> {
java 复制代码
    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会在以下情况下更新:

  1. 屏幕方向改变:当设备的屏幕方向发生改变时,WindowConfiguration会更新以反映新的方向。
  2. 窗口大小改变:当窗口的大小发生改变时,WindowConfiguration会更新以反映新的大小。
  3. 窗口位置改变:当窗口的位置发生改变时,WindowConfiguration会更新以反映新的位置。
  4. 窗口可见性改变:当窗口的可见性发生改变时,WindowConfiguration会更新以反映新的可见性。
  5. 窗口类型改变:当窗口的类型发生改变时,WindowConfiguration会更新以反映新的类型。

总之,当窗口的任何配置信息发生改变时,WindowConfiguration都会更新以反映新的配置信息

代码路径:frameworks/base/core/java/android/app/WindowConfiguration.java

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> {
java 复制代码
    @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():是否浮动,用于描述窗口是否浮动。
相关推荐
sinat_3842410921 分钟前
带有悬浮窗功能的Android应用
android·windows·visualstudio·kotlin
红米饭配南瓜汤2 小时前
Android显示系统(01)- 架构分析
android·音视频·媒体
吃汉堡吃到饱4 小时前
【Android】MMKV—高性能轻量化存储组件
android
三火哥4 小时前
Android 11 三方应用监听关机广播ACTION_SHUTDOWN
android
二流小码农5 小时前
鸿蒙开发:异步并发操作
android·ios·harmonyos
swiftlzk8 小时前
redmi 12c 刷机
android·数据库
MavenTalk8 小时前
前端技术选型之uniapp
android·前端·flutter·ios·uni-app·前端开发
坚定信念,勇往无前8 小时前
uni-app运行 安卓模拟器 MuMu模拟器
android·uni-app
吾即是光11 小时前
[SWPUCTF 2021 新生赛]error
android