Android11.0 flat default horizontal screen and compatible with gravity sensor scheme

Posted by andycastle on Wed, 02 Feb 2022 08:11:43 +0100

Preface

Most of the default screens you've done before are mandatory, with automatic rotation resting because you don't have a gravity sensor. The previous changes were too violent and less orthodox,

This time, the code related to android horizontal and vertical screen control is carefully studied, and a set of appropriate modifications are arranged.

Vertical screen horizontal is a common application scenario in most cases, which should save costs, but bring a lot of trouble to system software.

In the Android version of the iteration, Google and MTK have already done a good job of rotating the screen, here is the latest source code analysis in MTK platform android11.

1. Uboot Logo direction control

MTK's UbootLogo is drawn in lk code, which is a fairly complete framework. No matter how the version iterates, it hardly changes.

The code path is as follows

vendor\mediatek\proprietary\bootable\bootloader\lk\platform\mt6765\mt_logo.c

void init_fb_screen()
{
	dprintf(INFO, "[lk logo: %s %d]\n",__FUNCTION__,__LINE__);
	unsigned int fb_size = mt_get_fb_size();
	logo_addr = mt_get_logo_db_addr();

	phical_screen.width = CFG_DISPLAY_WIDTH;
	phical_screen.height = CFG_DISPLAY_HEIGHT;
	phical_screen.fb_size = fb_size;
	phical_screen.fill_dst_bits = CFG_DISPLAY_BPP;
	phical_screen.bits_per_pixel = CFG_DISPLAY_BPP;

	// in JB2.MP need to allign width and height to 32 ,but jb5.mp needn't
	phical_screen.needAllign = 1;
	phical_screen.allignWidth = ALIGN_TO(CFG_DISPLAY_WIDTH, MTK_FB_ALIGNMENT);

	/* In GB, no need to adjust 180 showing logo ,for fb driver dealing the change */
	/* but in JB, need adjust it for screen 180 roration           */
	phical_screen.need180Adjust = 0;   // need sync with chip driver

	dprintf(INFO, "[lk logo: %s %d]MTK_LCM_PHYSICAL_ROTATION = %s\n",__FUNCTION__,__LINE__, MTK_LCM_PHYSICAL_ROTATION);

	if (0 == strncmp(MTK_LCM_PHYSICAL_ROTATION, "270", 3)) {
		phical_screen.rotation = 270;
	} else if (0 == strncmp(MTK_LCM_PHYSICAL_ROTATION, "90", 2)) {
		phical_screen.rotation = 90;
	} else if (0 == strncmp(MTK_LCM_PHYSICAL_ROTATION, "180", 3) && (phical_screen.need180Adjust == 1)) {
		phical_screen.rotation = 180;
	} else {
		phical_screen.rotation = 0;
	}

See the core method init_fb_screen(), which is based on MTK_LCM_PHYSICAL_ROTATION to set the ubootlogo rotation angle, MTK is already compatible

We just need to find MTK_ LCM_ PHYSICAL_ The ROTATION configuration is sufficient for the desired orientation angle.

Searched in project/$(PROJECT). Definition found in MK

alps\vendor\mediatek\proprietary\bootable\bootloader\lk\project\k62v1_64_bsp.mk

MTK_LCM_PHYSICAL_ROTATION = 270

Lk's Compilation Rules are defined in alpsvendor\mediatek\proprietary\bootable\bootloader\lk\makefile

include project/$(PROJECT).mk
include make/rat_config.mk
include target/$(TARGET)/rules.mk
include dev/rules.mk
include platform/$(PLATFORM)/rules.mk
ifeq ($(MTK_EMMC_SUPPORT), yes)

2. Kernel Logo direction control

Drawing KernelLogo in the libshowlogo library calls show_kernel_logo()

alps\vendor\mediatek\proprietary\external\charger\bootlogo.cpp

void bootlogo_show_kernel()
{
    KPOC_LOGI("[ChargingAnimation: %s %d] show  kernel logo \n",__FUNCTION__,__LINE__);
    show_kernel_logo();
}

alps\vendor\mediatek\proprietary\external\libshowlogo\charging_animation.cpp

int anim_fb_init(void)
{
    if (MTK_LOG_ENABLE == 1) {
        SLOGD("[libshowlogo: %s %d]\n",__FUNCTION__,__LINE__);
    }

    fb_fd = open(FB_NODE_PATH, O_RDWR);
    if(fb_fd < 0)
    {
        if (MTK_LOG_ENABLE == 1) {
            SLOGE("[libshowlogo: %s %d]open dev file fail, errno = %d \n",__FUNCTION__,__LINE__ , errno);
        }
        close(fb_fd);
        error_flag = 1;

        return -1;
    }

  ......

    phical_screen.bits_per_pixel = vinfo.bits_per_pixel;
    phical_screen.fill_dst_bits = vinfo.bits_per_pixel;
    phical_screen.red_offset = vinfo.red.offset;
    phical_screen.blue_offset = vinfo.blue.offset;

    phical_screen.width = vinfo.xres;
    phical_screen.height = vinfo.yres;

    phical_screen.allignWidth = finfo.line_length/(vinfo.bits_per_pixel/8);

    phical_screen.needAllign = 1;
    phical_screen.need180Adjust = 1;
    phical_screen.fb_size = fb_size;
    if (MTK_LOG_ENABLE == 1) {
        SLOGD("[libshowlogo: %s %d]MTK_LCM_PHYSICAL_ROTATION = %s\n",__FUNCTION__,__LINE__, MTK_LCM_PHYSICAL_ROTATION);
    }

    int rotation = getRotation();
    if (MTK_LOG_ENABLE == 1) {
        SLOGD("[libshowlogo: %s %d]rotation = %d\n",__FUNCTION__,__LINE__, rotation);
    }

    if(ORIENTATION_270 == rotation){//270
        phical_screen.rotation = 270;
    } else if(ORIENTATION_90 == rotation){//90
        phical_screen.rotation = 90;
    } else if((ORIENTATION_180 == rotation) && (phical_screen.need180Adjust == 1)){//180
        phical_screen.rotation = 180;
    } else {
        phical_screen.rotation = 0;
    }
    if (MTK_LOG_ENABLE == 1) {
        SLOGD("[libshowlogo]phical_screen: width= %d,height= %d,bits_per_pixel =%d,needAllign = %d,allignWidth=%d rotation =%d ,need180Adjust = %d\n",
                phical_screen.width, phical_screen.height,
                phical_screen.bits_per_pixel, phical_screen.needAllign,
                phical_screen.allignWidth, phical_screen.rotation, phical_screen.need180Adjust);
        SLOGD("[libshowlogo: %s %d]show old animtion= 1, running show_animationm_ver %d\n",__FUNCTION__,__LINE__, show_animationm_ver);
        SLOGD("[libshowlogo: %s %d]draw_anim_mode = 1, running mode %d\n",__FUNCTION__,__LINE__, draw_anim_mode);
    }

    return 0;
}


void show_kernel_logo()
{
    if (MTK_LOG_ENABLE == 1) {
        SLOGD("[libshowlogo: %s %d]show kernel logo, index = 38 \n",__FUNCTION__,__LINE__);
    }
	if (error_flag == 0) {
		anim_show_logo(kernel_logo_position);
    }
}

Fb_before drawing was called FD initialization, the core method is anim_fb_init(void), where int rotation = getRotation();

To set the kernellogo rotation angle, find the getRotation() implementation at

alps\vendor\mediatek\proprietary\external\libshowlogo\utils.cpp

#include "utils.h"
#include <SurfaceFlingerProperties.sysprop.h>

int getRotation() {
    using RotationValues = android::sysprop::SurfaceFlingerProperties::primary_display_orientation_values;
    auto rotation_temp = android::sysprop::SurfaceFlingerProperties::primary_display_orientation();
    int rotation = Rotation::ORIENTATION_0;
    if (rotation_temp.has_value()) {
        switch (*rotation_temp) {
            case RotationValues::ORIENTATION_0:
                rotation = Rotation::ORIENTATION_0;
                break;
            case RotationValues::ORIENTATION_90:
                rotation = Rotation::ORIENTATION_90;
                break;
            case RotationValues::ORIENTATION_180:
                rotation = Rotation::ORIENTATION_180;
                break;
            case RotationValues::ORIENTATION_270:
                rotation = Rotation::ORIENTATION_270;
                break;
            default:
                break;
        }
    }
    return rotation;
}

Read prop attribute primary_from Display_ Orientation_ Values correspond to values, continue looking for where to assign values

primary_display_orientation_values Definition

Located at alps\device\mediatek\common\device.mk

ifneq ($(strip $(MTK_LCM_PHYSICAL_ROTATION)),)
  ifeq ($(strip $(MTK_LCM_PHYSICAL_ROTATION)), 90)
    PRODUCT_PROPERTY_OVERRIDES += ro.surface_flinger.primary_display_orientation=ORIENTATION_90
  else ifeq ($(strip $(MTK_LCM_PHYSICAL_ROTATION)), 180)
    PRODUCT_PROPERTY_OVERRIDES += ro.surface_flinger.primary_display_orientation=ORIENTATION_180
  else ifeq ($(strip $(MTK_LCM_PHYSICAL_ROTATION)), 270)
    PRODUCT_PROPERTY_OVERRIDES += ro.surface_flinger.primary_display_orientation=ORIENTATION_270
  else
    PRODUCT_PROPERTY_OVERRIDES += ro.surface_flinger.primary_display_orientation=ORIENTATION_0
  endif
endif

It is not difficult to find primary_display_orientation value is defined by macro MTK_LCM_PHYSICAL_ROTATION DECISION

alps\device\mediateksample\k62v1_64_bsp\ProjectConfig.mk

MTK_LCM_PHYSICAL_ROTATION = 270

3. Shutdown Charging Logo Direction Control

Shutdown Charge Logo drawing code is also in libshowlogo

alps\vendor\mediatek\proprietary\external\libshowlogo\show_animation_common.c

void init_charging_animation_ui_dimension() {
    int lcm_width, lcm_height;
    struct fb_var_screeninfo vinfo;
    display_fd = open("/dev/graphics/fb0", O_RDONLY);
    if (display_fd < 0) {

      SLOGD("[show_animation_common: %s %d]open mtkfb fail...\n",__FUNCTION__,__LINE__);

    }

    if (ioctl(display_fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
      close(display_fd);
      SLOGD("[show_animation_common: %s %d]ioctl FBIOGET_VSCREENINFO failed\n",__FUNCTION__,__LINE__);
    }
    close(display_fd);

    lcm_width = vinfo.xres;
    lcm_height = vinfo.yres;
    int rotation = getRotation();
    if (MTK_LOG_ENABLE == 1) {
        SLOGD("[libshowlogo: %s %d]rotation = %d\n",__FUNCTION__,__LINE__, rotation);
    }
    if ((ORIENTATION_270 == rotation)|| (ORIENTATION_90 == rotation)){
        lcm_width = vinfo.yres;
        lcm_height = vinfo.xres;
    }
    SLOGD("[show_animation_common: %s %d] lcm_width and lcm_height= %d , %d \n",__FUNCTION__,__LINE__,lcm_width,lcm_height);

	.......

Also based on int rotation = getRotation(); To determine the rotation angle, as with the kernel logo above, by MTK_LCM_PHYSICAL_ROTATION Decision.

4. Direction control of startup animation

Startup animation playback code location is as follows

alps\frameworks\base\cmds\bootanimation\BootAnimation.cpp

status_t BootAnimation::readyToRun() {
    mAssets.addDefaultAssets();

    mDisplayToken = SurfaceComposerClient::getInternalDisplayToken();
    if (mDisplayToken == nullptr)
        return NAME_NOT_FOUND;

    DisplayConfig displayConfig;
    const status_t error =
            SurfaceComposerClient::getActiveDisplayConfig(mDisplayToken, &displayConfig);
    if (error != NO_ERROR)
        return error;

    mMaxWidth = android::base::GetIntProperty("ro.surface_flinger.max_graphics_width", 0);
    mMaxHeight = android::base::GetIntProperty("ro.surface_flinger.max_graphics_height", 0);
    ui::Size resolution = displayConfig.resolution;
    resolution = limitSurfaceSize(resolution.width, resolution.height);
    // create the native surface
    sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),
            resolution.getWidth(), resolution.getHeight(), PIXEL_FORMAT_RGB_565);

    SurfaceComposerClient::Transaction t;

+    Rect destRect(resolution.getWidth(), resolution.getHeight());
+    t.setDisplayProjection(mDisplayToken, ui::ROTATION_0, destRect, destRect);

    // this guest property specifies multi-display IDs to show the boot animation
    // multiple ids can be set with comma (,) as separator, for example:
    // setprop persist.boot.animation.displays 19260422155234049,19261083906282754
    Vector<uint64_t> physicalDisplayIds;
    char displayValue[PROPERTY_VALUE_MAX] = "";
    property_get(DISPLAYS_PROP_NAME, displayValue, "");

	......

The core method of playback drawing is BootAnimation::readyToRun(), where displayProjection through Transaction is available

To determine the direction. ui::ROTATION_0 ui::ROTATION_90 ui::ROTATION_180 ui::ROTATION_270

Here we add ui::ROTATION_0 To solve the incomplete display of half of the second half of the animation.

5. RecoveryUI direction control

RecoveryUI drawing code is located at alps\bootablerecovery\minui\graphics. CPP

Google has provided us with a compatible rotation display

int gr_init() {
	......

	std::string rotation_str =
      android::base::GetProperty("ro.minui.default_rotation", "ROTATION_NONE");
  if (rotation_str == "ROTATION_RIGHT") {
    gr_rotate(GRRotation::RIGHT);
  } else if (rotation_str == "ROTATION_DOWN") {
    gr_rotate(GRRotation::DOWN);
  } else if (rotation_str == "ROTATION_LEFT") {
    gr_rotate(GRRotation::LEFT);
  } else {  // "ROTATION_NONE" or unknown string
    gr_rotate(GRRotation::NONE);
  }

Core Method gr_init() reads prop ro.minui.default_rotation value determines drawing direction

After searching, we find that there is no assignment defined, so we add our own assignment to the horizontal ROTATION_LEFT

alps\device\mediateksample\k62v1_64_bsp\device.mk

PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.minui.default_rotation=ROTATION_LEFT

6. System TP Touch x y Direction Control

The core control logic is as follows

alps\kernel-4.19\drivers\input\touchscreen\mtk_tpd.c

	#ifdef CONFIG_MTK_LCM_PHYSICAL_ROTATION
	if (strncmp(CONFIG_MTK_LCM_PHYSICAL_ROTATION, "90", 2) == 0
		|| strncmp(CONFIG_MTK_LCM_PHYSICAL_ROTATION, "270", 3) == 0) {
#ifdef CONFIG_MTK_FB
/*Fix build errors,as some projects  cannot support these apis while bring up*/
		TPD_RES_Y = DISP_GetScreenWidth();
		TPD_RES_X = DISP_GetScreenHeight();
#endif
	} else
    #endif
	{

alps\kernel-4.19\drivers\input\touchscreen\GT911\gt9xx_driver.c

static void tpd_down(s32 x, s32 y, s32 size, s32 id)
{
	if ((!size) && (!id)) {
		input_report_abs(tpd->dev, ABS_MT_PRESSURE, 100);
		input_report_abs(tpd->dev, ABS_MT_TOUCH_MAJOR, 100);
	} else {
		input_report_abs(tpd->dev, ABS_MT_PRESSURE, size);
		input_report_abs(tpd->dev, ABS_MT_TOUCH_MAJOR, size);
		/* track id Start 0 */
		input_report_abs(tpd->dev, ABS_MT_TRACKING_ID, id);
	}

	input_report_key(tpd->dev, BTN_TOUCH, 1);
#if 0	
	input_report_abs(tpd->dev, ABS_MT_POSITION_X, x);
	input_report_abs(tpd->dev, ABS_MT_POSITION_Y, y);
#else
	input_report_abs(tpd->dev, ABS_MT_POSITION_X, 1280-y);
	input_report_abs(tpd->dev, ABS_MT_POSITION_Y, x);
#endif

Get CONFIG_defined by macro MTK_ LCM_ PHYSICAL_ ROTATION Determines X-y Coordinates

alps\kernel-4.19\arch\arm64\configs\k62v1_64_bsp_defconfig

CONFIG_MTK_LCM_PHYSICAL_ROTATION="270"

7. Turn on default horizontal display

After modifying the above steps, boot-up is already a horizontal screen, specific and MTK_LCM_PHYSICAL_ROTATION

Decided ro.surface_flinger.primary_display_orientation values are related

The core code is as follows

alps\hardware\interfaces\configstore\1.1\default\surfaceflinger.mk

ifneq ($(SF_PRIMARY_DISPLAY_ORIENTATION),)
    LOCAL_CFLAGS += -DPRIMARY_DISPLAY_ORIENTATION=$(SF_PRIMARY_DISPLAY_ORIENTATION)
endif


alps\hardware\interfaces\configstore\1.1\default\SurfaceFlingerConfigs.cpp

Return<void> SurfaceFlingerConfigs::primaryDisplayOrientation(
        primaryDisplayOrientation_cb _hidl_cb) {
    using ::android::hardware::configstore::V1_1::DisplayOrientation;

    bool specified = false;
    DisplayOrientation value = DisplayOrientation::ORIENTATION_0;

    int orientation = 0;
#ifdef PRIMARY_DISPLAY_ORIENTATION
    specified = true;
    orientation = PRIMARY_DISPLAY_ORIENTATION;
#endif

    switch (orientation) {
        case 0: {
            value = DisplayOrientation::ORIENTATION_0;
            break;
        }
        case 90: {
            value = DisplayOrientation::ORIENTATION_90;
            break;
        }
        case 180: {
            value = DisplayOrientation::ORIENTATION_180;
            break;
        }
        case 270: {
            value = DisplayOrientation::ORIENTATION_270;
            break;
        }
        default: {
            // statically checked above -> memory corruption
            LOG_ALWAYS_FATAL("Invalid orientation %d", orientation);
        }
    }

    _hidl_cb({specified, value});
    return Void();
}

alps\frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp

SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipInitialization) {
    ALOGI("SurfaceFlinger is starting");

    hasSyncFramework = running_without_sync_framework(true);

	......

    wideColorGamutCompositionDataspace = mWideColorGamutCompositionDataspace;
    defaultCompositionPixelFormat = static_cast<ui::PixelFormat>(
            default_composition_pixel_format(ui::PixelFormat::RGBA_8888));
    wideColorGamutCompositionPixelFormat =
            static_cast<ui::PixelFormat>(wcg_composition_pixel_format(ui::PixelFormat::RGBA_8888));

    mColorSpaceAgnosticDataspace =
            static_cast<ui::Dataspace>(color_space_agnostic_dataspace(Dataspace::UNKNOWN));

    useContextPriority = use_context_priority(true);

    using Values = SurfaceFlingerProperties::primary_display_orientation_values;
    switch (primary_display_orientation(Values::ORIENTATION_0)) {
        case Values::ORIENTATION_0:
            break;
        case Values::ORIENTATION_90:
            internalDisplayOrientation = ui::ROTATION_90;
            break;
        case Values::ORIENTATION_180:
            internalDisplayOrientation = ui::ROTATION_180;
            break;
        case Values::ORIENTATION_270:
            internalDisplayOrientation = ui::ROTATION_270;
            break;
    }
    ALOGV("Internal Display Orientation: %s", toCString(internalDisplayOrientation));

    mInternalDisplayPrimaries = sysprop::getDisplayNativePrimaries();

    // debugging stuff...
    char value[PROPERTY_VALUE_MAX];

    property_get("ro.bq.gpu_to_cpu_unsupported", value, "0");
    mGpuToCpuSupported = !atoi(value);

alps\frameworks\native\services\surfaceflinger\SurfaceFlingerProperties.cpp

SurfaceFlingerProperties::primary_display_orientation_values primary_display_orientation(
        SurfaceFlingerProperties::primary_display_orientation_values defaultValue) {
    auto temp = SurfaceFlingerProperties::primary_display_orientation();
    if (temp.has_value()) {
        return *temp;
    }
    auto configDefault = DisplayOrientation::ORIENTATION_0;
    switch (defaultValue) {
        case SurfaceFlingerProperties::primary_display_orientation_values::ORIENTATION_90:
            configDefault = DisplayOrientation::ORIENTATION_90;
            break;
        case SurfaceFlingerProperties::primary_display_orientation_values::ORIENTATION_180:
            configDefault = DisplayOrientation::ORIENTATION_180;
            break;
        case SurfaceFlingerProperties::primary_display_orientation_values::ORIENTATION_270:
            configDefault = DisplayOrientation::ORIENTATION_270;
            break;
        default:
            configDefault = DisplayOrientation::ORIENTATION_0;
            break;
    }
    DisplayOrientation result =
            getDisplayOrientation<V1_1::ISurfaceFlingerConfigs,
                                  &V1_1::ISurfaceFlingerConfigs::primaryDisplayOrientation>(
                    configDefault);
    switch (result) {
        case DisplayOrientation::ORIENTATION_90:
            return SurfaceFlingerProperties::primary_display_orientation_values::ORIENTATION_90;
        case DisplayOrientation::ORIENTATION_180:
            return SurfaceFlingerProperties::primary_display_orientation_values::ORIENTATION_180;
        case DisplayOrientation::ORIENTATION_270:
            return SurfaceFlingerProperties::primary_display_orientation_values::ORIENTATION_270;
        default:
            break;
    }
    return SurfaceFlingerProperties::primary_display_orientation_values::ORIENTATION_0;
}

8. Debugging of Gravity Sensor Drive

Refer to this article

MTK 9.0 Platform Debugging gsensor

9. Default horizontal screen compatible gravity sensor auto-rotation

Turn on the system auto-rotation button to rotate the display in the current direction

Turn off the system auto-rotation button to force all APP default horizontal displays, regardless of portrait properties

alps\frameworks\base\services\core\java\com\android\server\wm\DisplayRotation.java

 @Override
       boolean updateRotationUnchecked(boolean forceUpdate) {
        //add
		int flag = android.provider.Settings.System.getInt(mContext.getContentResolver(),
         "accelerometer_rotation", 0);
        if (flag == 0) {
            return true;
        }//end

        final int displayId = mDisplayContent.getDisplayId();
        if (!forceUpdate) {
            if (mDeferredRotationPauseCount > 0) {
                // Rotation updates have been paused temporarily. Defer the update until updates
                // have been resumed.
                ProtoLog.v(WM_DEBUG_ORIENTATION, "Deferring rotation, rotation is paused.");
                return false;
            }

frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java

    @ScreenOrientation
    @Override
    int getOrientation() {
		 //add
		int flag = android.provider.Settings.System.getInt(mContext.getContentResolver(),
         "accelerometer_rotation", 0);
        if (flag == 0) {
           return ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
        }//end
        mLastOrientationSource = null;

        if (mIgnoreRotationForApps) {
            return SCREEN_ORIENTATION_USER;
        }

        if (mWmService.mDisplayFrozen) {
            if (mWmService.mPolicy.isKeyguardLocked()) {
                // Use the last orientation the while the display is frozen with the keyguard
                // locked. This could be the keyguard forced orientation or from a SHOW_WHEN_LOCKED
                // window. We don't want to check the show when locked window directly though as
                // things aren't stable while the display is frozen, for example the window could be
                // momentarily unavailable due to activity relaunch.
                ProtoLog.v(WM_DEBUG_ORIENTATION,
                        "Display id=%d is frozen while keyguard locked, return %d",
                        mDisplayId, getLastOrientation());
                return getLastOrientation();
            }
        }
        final int rootOrientation = mRootDisplayArea.getOrientation();
        mLastOrientationSource = mRootDisplayArea.getLastOrientationSource();
        return rootOrientation;
    }

10. References

Android Screen Display Direction Analysis

Topics: mtk