当前位置:   article > 正文

Android11.0 修改系统默认显示大小_安卓修改屏幕显示尺寸

安卓修改屏幕显示尺寸

系统设置中的显示大小调整的就是屏幕密度,调整的越小,屏幕显示的内容就越多。
在系统中都会有定义一个默认的屏幕密度

设置中显示大小相关内容

  • 源码:/packages/apps/Settings/res/xml/display_settings.xml
 <Preference
      android:key="font_size"
      android:title="@string/title_font_size"
      android:fragment="com.android.settings.display.ToggleFontSizePreferenceFragment"
      settings:controller="com.android.settings.display.FontSizePreferenceController" />
      
 <!-- 显示大小设置-->
 <com.android.settings.display.ScreenZoomPreference
      android:key="display_settings_screen_zoom"
      android:title="@string/screen_zoom_title"
      android:fragment="com.android.settings.display.ScreenZoomSettings"/>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 源码:/packages/apps/Settings/src/com/android/settings/display/ScreenZoomSettings.java
 @Override
 public void onCreate(@Nullable Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
		
     final DisplayDensityUtils density = new DisplayDensityUtils(getContext());

     final int initialIndex = density.getCurrentIndex();
     if (initialIndex < 0) {
         // Failed to obtain default density, which means we failed to
         // connect to the window manager service. Just use the current
         // density and don't let the user change anything.
         final int densityDpi = getResources().getDisplayMetrics().densityDpi;
         mValues = new int[]{densityDpi};
         mEntries = new String[]{getString(DisplayDensityUtils.SUMMARY_DEFAULT)};
         mInitialIndex = 0;
         mDefaultDensity = densityDpi;
     } else {
         mValues = density.getValues();
         mEntries = density.getEntries();
         mInitialIndex = initialIndex;
         mDefaultDensity = density.getDefaultDensity();
     }

     getActivity().setTitle(R.string.screen_zoom_title);
 }
 
 @Override
 protected Configuration createConfig(Configuration origConfig, int index) {
     // Populate the sample layouts.
     final Configuration config = new Configuration(origConfig);
     config.densityDpi = mValues[index];
     return config;
 }

 /**
  * Persists the selected density and sends a configuration change.
  */
 @Override
 protected void commit() {
     final int densityDpi = mValues[mCurrentIndex];
     if (densityDpi == mDefaultDensity) {
         DisplayDensityConfiguration.clearForcedDisplayDensity(Display.DEFAULT_DISPLAY);
     } else {
         DisplayDensityConfiguration.setForcedDisplayDensity(Display.DEFAULT_DISPLAY, densityDpi);
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

密度缩放等级描述"小,默认,大,较大,最大" mEntries和mValues 这些配置是从DisplayDensityUtils 中获取
设置显示大小后调用DisplayDensityConfiguration.setForcedDisplayDensity方法去配置

获取显示大小等级描述

  • 源码:/frameworks/base/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java
/**
 * Utility methods for working with display density.
 */
 public class DisplayDensityUtils {
    private static final String LOG_TAG = "DisplayDensityUtils";

    /** Minimum increment between density scales. */
    private static final float MIN_SCALE_INTERVAL = 0.09f;

    /** Minimum density scale. This is available on all devices. */
    private static final float MIN_SCALE = 0.85f;

    /** Maximum density scale. The actual scale used depends on the device. */
    private static final float MAX_SCALE = 1.50f;

    /** Summary used for "default" scale. */
    public static final int SUMMARY_DEFAULT = R.string.screen_zoom_summary_default;

    /** Summary used for "custom" scale. */
    private static final int SUMMARY_CUSTOM = R.string.screen_zoom_summary_custom;
    
	/**
     * Summaries for scales smaller than "default" in order of smallest to
     * largest.
     */
     private static final int[] SUMMARIES_SMALLER = new int[] {
             R.string.screen_zoom_summary_small
     };

    /**
     * Summaries for scales larger than "default" in order of smallest to
     * largest.
     */
     private static final int[] SUMMARIES_LARGER = new int[] {
            R.string.screen_zoom_summary_large,
            R.string.screen_zoom_summary_very_large,
            R.string.screen_zoom_summary_extremely_large,
    };
    
    /**
     * Minimum allowed screen dimension, corresponds to resource qualifiers
     * "small" or "sw320dp". This value must be at least the minimum screen
     * size required by the CDD so that we meet developer expectations.
     */
     private static final int MIN_DIMENSION_DP = 320;

     private final String[] mEntries;
     private final int[] mValues;

     private final int mDefaultDensity;
     private final int mCurrentIndex;

     public DisplayDensityUtils(Context context) {
        // 获取默认的屏幕密度 ro.sf.lcd_density 
        final int defaultDensity = DisplayDensityUtils.getDefaultDisplayDensity(
                Display.DEFAULT_DISPLAY);
        if (defaultDensity <= 0) {
            mEntries = null;
            mValues = null;
            mDefaultDensity = 0;
            mCurrentIndex = -1;
            return;
        }
        final Resources res = context.getResources();
        final DisplayMetrics metrics = new DisplayMetrics();
        context.getDisplayNoVerify().getRealMetrics(metrics);
        // 当前屏幕使用的密度值
        final int currentDensity = metrics.densityDpi;
        int currentDensityIndex = -1;

        // Compute number of "larger" and "smaller" scales for this display.
        final int minDimensionPx = Math.min(metrics.widthPixels, metrics.heightPixels);
        // DisplayMetrics.DENSITY_MEDIUM = 160
        // MIN_DIMENSION_DP = 320
        final int maxDensity = DisplayMetrics.DENSITY_MEDIUM * minDimensionPx / MIN_DIMENSION_DP;
        // 屏幕密度最大的缩放是1.5
        final float maxScale = Math.min(MAX_SCALE, maxDensity / (float) defaultDensity);
        // 屏幕密度最小缩放0.85
        final float minScale = MIN_SCALE;
        // 0~3
        final int numLarger = (int) MathUtils.constrain((maxScale - 1) / MIN_SCALE_INTERVAL,
                0, SUMMARIES_LARGER.length);
        // 0~1
        final int numSmaller = (int) MathUtils.constrain((1 - minScale) / MIN_SCALE_INTERVAL,
                0, SUMMARIES_SMALLER.length);
        // {小,默认,大,较大,最大}
        // entries的内容根据numLarger和numSmaller的值来填充
        String[] entries = new String[1 + numSmaller + numLarger];
        int[] values = new int[entries.length];
        int curIndex = 0;
        
        if (numSmaller > 0) {
            final float interval = (1 - minScale) / numSmaller;
            for (int i = numSmaller - 1; i >= 0; i--) {
                // Round down to a multiple of 2 by truncating the low bit.
                final int density = ((int) (defaultDensity * (1 - (i + 1) * interval))) & ~1;
                if (currentDensity == density) {
                    currentDensityIndex = curIndex;
                }
                entries[curIndex] = res.getString(SUMMARIES_SMALLER[i]);
                values[curIndex] = density;
                curIndex++;
            }
        }
        // 如果numSmaller为0,entries{默认,..}
        if (currentDensity == defaultDensity) {
            currentDensityIndex = curIndex;
        }
        values[curIndex] = defaultDensity;
        entries[curIndex] = res.getString(SUMMARY_DEFAULT);
        curIndex++;

        if (numLarger > 0) {
            final float interval = (maxScale - 1) / numLarger;
            for (int i = 0; i < numLarger; i++) {
                // Round down to a multiple of 2 by truncating the low bit.
                final int density = ((int) (defaultDensity * (1 + (i + 1) * interval))) & ~1;
                if (currentDensity == density) {
                    currentDensityIndex = curIndex;
                }
                values[curIndex] = density;
                entries[curIndex] = res.getString(SUMMARIES_LARGER[i]);
                curIndex++;
            }
        }
        
        final int displayIndex;
        if (currentDensityIndex >= 0) {
            displayIndex = currentDensityIndex;
        } else {
            // We don't understand the current density. Must have been set by
            // someone else. Make room for another entry...
            int newLength = values.length + 1;
            values = Arrays.copyOf(values, newLength);
            values[curIndex] = currentDensity;

            entries = Arrays.copyOf(entries, newLength);
            entries[curIndex] = res.getString(SUMMARY_CUSTOM, currentDensity);

            displayIndex = curIndex;
        }

        mDefaultDensity = defaultDensity;
        mCurrentIndex = displayIndex;
        mEntries = entries;
        mValues = values;
    }

    public String[] getEntries() {
        return mEntries;
    }

    public int[] getValues() {
        return mValues;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155

首先读取ro.sf.lcd_density获得默认的屏幕密度值,然后通过metrics.densityDpi得到当前使用的屏幕密度值,根据屏幕宽高计算得到密度最大缩放值maxScale(最大为1.5);在通过计算得到numLarger和numSmaller的值然后对entries和values填充内容,得到我们看到的等级描述"小,默认,大,较大,最大"。

修改显示大小重新计算显示配置并保存值

  • 源码:/frameworks/base/packages/SettingsLib/DisplayDensityUtils/src/com/android/settingslib/display/DisplayDensityConfiguration.java
 public static void setForcedDisplayDensity(final int displayId, final int density) {
     final int userId = UserHandle.myUserId();
     AsyncTask.execute(
             () -> {
                 try {
                     final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
                     wm.setForcedDisplayDensityForUser(displayId, density, userId);
                 } catch (RemoteException exc) {
                     Log.w(LOG_TAG, "Unable to save forced display density setting");
                 }
             });
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 源码:/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
 @Override
 public void setForcedDisplayDensityForUser(int displayId, int density, int userId) {
     if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
             != PackageManager.PERMISSION_GRANTED) {
         throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
     }

     final int targetUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
             Binder.getCallingUid(), userId, false, true, "setForcedDisplayDensityForUser",
             null);
     final long ident = Binder.clearCallingIdentity();
     try {
         synchronized (mGlobalLock) {
             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
             if (displayContent != null) {
                 displayContent.setForcedDensity(density, targetUserId);
             }
         }
     } finally {
         Binder.restoreCallingIdentity(ident);
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 源码:/frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
 void setForcedDensity(int density, int userId) {
     final boolean updateCurrent = userId == UserHandle.USER_CURRENT;
     if (mWmService.mCurrentUserId == userId || updateCurrent) {
     	  // 重新赋值
         mBaseDisplayDensity = density;
         // 根据设置的值,重新计算显示配置
         reconfigureDisplayLocked();
     }
     
     if (updateCurrent) {
            // We are applying existing settings so no need to save it again.
         return;
     }

     if (density == mInitialDisplayDensity) {
         density = 0;
     }
     
     mWmService.mDisplayWindowSettings.setForcedDensity(this, density, userId);
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 源码:/frameworks/base/services/core/java/com/android/server/wm/DisplayWindowSettings.java
 void setForcedDensity(DisplayContent displayContent, int density, int userId) {
     if (displayContent.isDefaultDisplay) {
         final String densityString = density == 0 ? "" : Integer.toString(density);
         Settings.Secure.putStringForUser(mService.mContext.getContentResolver(),
                 Settings.Secure.DISPLAY_DENSITY_FORCED, densityString, userId);
         return;
     }

     final DisplayInfo displayInfo = displayContent.getDisplayInfo();
     final Entry entry = getOrCreateEntry(displayInfo);
     entry.mForcedDensity = density;
     writeSettingsIfNeeded(entry, displayInfo);
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

根据设置的屏幕密度值重新计算显示配置,最后修改Settings.Secure.DISPLAY_DENSITY_FORCED的值

修改默认显示大小

  • 源码:/frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
 private void loadSecureSettings(SQLiteDatabase db) {
     SQLiteStatement stmt = null;
     try {
         stmt = db.compileStatement("INSERT OR IGNORE INTO secure(name,value)"
                 + " VALUES(?,?);");
         ...
         loadStringSetting(stmt, Settings.Secure.DISPLAY_DENSITY_FORCED,
                    R.string.def_display_density_forced);               
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 源码:/frameworks/base/packages/SettingsProvider/res/values/defaults.xml
 <string name="def_display_density_forced">204</string>
  • 1

这种修改方式是不改变默认的屏幕密度值ro.sf.lcd_density=240,在此基础上修改屏幕显示的密度。
修改之后使用adb命令查看

C:\Users\dell>adb shell wm density
Physical density: 240
Override density: 204

C:\Users\dell>
  • 1
  • 2
  • 3
  • 4
  • 5

开机获取强制显示密度(如果有设置)

  • 源码:/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
 public void displayReady() {
     synchronized (mGlobalLock) {
         if (mMaxUiWidth > 0) {
             mRoot.forAllDisplays(displayContent -> displayContent.setMaxUiWidth(mMaxUiWidth));
         }
         applyForcedPropertiesForDefaultDisplay();
         mAnimator.ready();
         mDisplayReady = true;
        ...
 }
 
 /** The global settings only apply to default display. */
 private boolean applyForcedPropertiesForDefaultDisplay() {
     boolean changed = false;
     final DisplayContent displayContent = getDefaultDisplayContentLocked();
     ...
     // Display density.
     final int density = getForcedDisplayDensityForUserLocked(mCurrentUserId);
     if (density != 0 && density != displayContent.mBaseDisplayDensity) {
         displayContent.mBaseDisplayDensity = density;
         changed = true;
     }
     ...
 }
 
 /**
  * @param userId the ID of the user
  * @return the forced display density for the specified user, if set, or
  *         {@code 0} if not set
  */
 private int getForcedDisplayDensityForUserLocked(int userId) {
     String densityStr = Settings.Secure.getStringForUser(mContext.getContentResolver(),
             Settings.Secure.DISPLAY_DENSITY_FORCED, userId);
     if (densityStr == null || densityStr.length() == 0) {
         // String DENSITY_OVERRIDE = "ro.config.density_override";
         densityStr = SystemProperties.get(DENSITY_OVERRIDE, null);
     }
     if (densityStr != null && densityStr.length() > 0) {
         try {
             return Integer.parseInt(densityStr);
         } catch (NumberFormatException ex) {
         }
     }
     return 0;
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

在WindowManagerService启动之后,调用getForcedDisplayDensityForUserLocked方法获取强制设置的屏幕显示密度,如果有强制设置,将获取到的值赋给mBaseDisplayDensity,系统将以Settings.Secure.DISPLAY_DENSITY_FORCED的值这个密度显示。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/458145
推荐阅读
相关标签
  

闽ICP备14008679号