Change the system display size programmatically Android N

android, android-7.0-nougat, android-settings

Solution

Just share my approach to tackle this requirement. I achieve this function by using the dirty Java reflection method - although it's not that elegant.

The main reference source code files are:

- ScreenZoomSettings.java (https://github.com/aosp-mirror/platform_packages_apps_settings/blob/master/src/com/android/settings/display/ScreenZoomSettings.java)

- DisplayDensityUtils.java (http://androidxref.com/9.0.0_r3/xref/frameworks/base/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java)

- WindowManagerGlobal.java (http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/view/WindowManagerGlobal.java)

And, follow the below steps, then you can get the required control:

- Read `ZoomScreenSettings`.java's onCreate() and commit(). They demonstrate how to correctly get and set the density value into the framework.

- Read `DisplayDensityUtils`.java. It shows how to use `WindowManagerService` to control the system density. Because we can't get the instance of `DisplayDensityUtils` via reflection, we need to understand which `WindowManagerService` methods are utilized.

- Use reflection to get `WindowManagerService`'s instance, and write a `DisplayDensityUtils`-like class into your project.

// Where wm is short for window manager
val wmGlobalClz = Class.forName("android.view.WindowManagerGlobal")
val getWmServiceMethod = wmGlobalClz.getDeclaredMethod("getWindowManagerService")
val wmService = getWmServiceMethod.invoke(wmGlobalClz)

val wmInterfaceClz = Class.forName("android.view.IWindowManager")

// Now, we already have the ability to do many things we want.
// For instance, to get the default density value.
val getInitialDisplayDensityMethod = wmInterfaceClz.getDeclaredMethod(
        "getInitialDisplayDensity", 
        Integer.TYPE
)
val defaultDensity = getInitialDisplayDensityMethod.invoke(
        wmService,
        Display.DEFAULT_DISPLAY
) as Int

- Set or get the density value with your `DisplayDensityUtils`-like class. One thing just to mention is that, if you want to pass an index value (e.g., 2 for large display size), please feed it to your `DisplayDensityUtils`-like class's `mValues` array to get the actual density value which is the right one to pass to the framework. Getting the current density index also applies the same concept.

Problem

Background: Android N comes with a feature to change system `Display Size` from settings, in addition to the previously present feature of changing `Font Size`. Change Display Size: Image Source: pcmag.com Question: If an app has `android.permission.WRITE_SETTINGS` permission to change the settings, there are ways to change the system font size programatically as mentioned in How to programmatically change font settings of Device: font style and font size?. However I couldn't find a way to change the display size programmatically. Is it possible? What I've tried? I've checked the possible options in the list of Settings.System convenience functions provided for changing settings programmatically. Update: I've opened a feature request for the same here: https://code.google.com/p/android/issues/detail?id=214124 . If you feel it would be useful please star it.

Original source