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"/>

  • 源码:/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);
     }
 }

密度缩放等级描述"小,默认,大,较大,最大" 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;
    }

首先读取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");
                 }
             });
 }
  • 源码:/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);
     }
 }
  • 源码:/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);
 }
  • 源码:/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);
 }

根据设置的屏幕密度值重新计算显示配置,最后修改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);               
  • 源码:/frameworks/base/packages/SettingsProvider/res/values/defaults.xml
 <string name="def_display_density_forced">204</string>

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

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

C:\Users\dell>

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

  • 源码:/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;
 }

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

猜你喜欢

转载自blog.csdn.net/wxd_csdn_2016/article/details/131244878