Android9.0 MTK 平板横屏方案修改(强制app横屏 + 开机logo/动画+关机充电横屏 + RecoveryUI 横屏)

摘要:
--如果为真,则应用于获取应用程序定向请求的方向反转。通常情况下,风景线与肖像线是不同的;因此,一个端口设备、一个请求端口和一个端口将导致逆时针旋转,而另一个端口和一的请求端口将导致一个逆时针旋转。此处设置为true与逻辑相反。--˃true˂!

文章较长建议先收藏再看

拆解步骤

1、app 强制横屏显示,无视 android:screenOrientation="portrait" 属性

2、屏幕触摸坐标修改为横屏

3、开机动画横屏

4、开机logo、关机充电动画横屏

5、RecoveryUI 横屏

上代码

1、app 强制横屏显示

修改 rotationForOrientationLw(), 默认返回 270

frameworksaseservicescorejavacomandroidserverpolicyPhoneWindowManager.java

 @Override
    public int rotationForOrientationLw(int orientation, int lastRotation, boolean defaultDisplay) {
        ....

        synchronized (mLock) {
		...

		default:
                    // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
                    // just return the preferred orientation we already calculated.
                    if (preferredRotation >= 0) {
                        return preferredRotation;
                    }
                    
                    // return Surface.ROTATION_0;
                    return Surface.ROTATION_270;//cczheng add for land scap
            }
        }
  }

activity 默认强制属性为 SCREEN_ORIENTATION_LANDSCAPE

frameworksaseservicescorejavacomandroidserverwmWindowManagerService.java

boolean updateOrientationFromAppTokensLocked(int displayId, boolean forceUpdate) {
        long ident = Binder.clearCallingIdentity();
        try {
            final DisplayContent dc = mRoot.getDisplayContent(displayId);
            // final int req = dc.getOrientation();
            int req = android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;//cczheng add for land scap
            if (req != dc.getLastOrientation() || forceUpdate) {
                if (DEBUG_ORIENTATION) {
                    Slog.v(TAG, "updateOrientation: req= " + req + ", mLastOrientation= "
                        + dc.getLastOrientation(), new Throwable("updateOrientation"));
                }
                dc.setLastOrientation(req);
                //send a message to Policy indicating orientation change to take
                //action like disabling/enabling sensors etc.,
                // TODO(multi-display): Implement policy for secondary displays.
                if (dc.isDefaultDisplay) {
                    mPolicy.setCurrentOrientationLw(req);
                }
                return dc.updateRotationUnchecked(forceUpdate);
            }
            return false;
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }

DisPlayContent 显示 mRotation 默认改为 3 (270)

frameworksaseservicescorejavacomandroidserverwmDisplayContent.java

/**
     * Current rotation of the display.
     * Constants as per {@link android.view.Surface.Rotation}.
     *
     * @see #updateRotationUnchecked()
     */
    // private int mRotation = 0;
    private int mRotation = 3;//cczheng add for land scap

修改默认值 config_reverseDefaultRotation 为 true,翻转显示角度

frameworksasecore es esvaluesconfig.xml

<!-- If true, the direction rotation is applied to get to an application's requested
         orientation is reversed.  Normally, the model is that landscape is
         clockwise from portrait; thus on a portrait device an app requesting
         landscape will cause a clockwise rotation, and on a landscape device an
         app requesting portrait will cause a counter-clockwise rotation.  Setting
         true here reverses that logic. -->
	<!-- cczheng add for land scap -->
    <bool name="config_reverseDefaultRotation">true</bool> 

	<!-- The number of degrees to rotate the display when the keyboard is open.
         A value of -1 means no change in orientation by default. -->
    <!-- cczheng add for land scap -->
    <integer name="config_lidOpenRotation">270</integer>

2、屏幕触摸坐标修改为横屏

对调 frame 的宽和高,设置方向为 270

frameworks ativeservicessurfaceflingerDisplayDevice.cpp


void DisplayDevice::setProjection(int orientation,
        const Rect& newViewport, const Rect& newFrame) {
    Rect viewport(newViewport);
    Rect frame(newFrame);

    const int w = mDisplayWidth;
    const int h = mDisplayHeight;

    Transform R;
    DisplayDevice::orientationToTransfrom(orientation, w, h, &R);

    if (!frame.isValid()) {
        // the destination frame can be invalid if it has never been set,
        // in that case we assume the whole display frame.
        //cczheng add for land scap
        // frame = Rect(w, h);
        if (w < h)
            frame = Rect(h, w);
        else
            frame = Rect(w, h);
    }
	....

}

// clang-format off
DisplayDevice::DisplayDevice(
        const sp<SurfaceFlinger>& flinger,
        DisplayType type,
        int32_t hwcId,
        bool isSecure,
        const wp<IBinder>& displayToken,
        const sp<ANativeWindow>& nativeWindow,
        const sp<DisplaySurface>& displaySurface,
        std::unique_ptr<RE::Surface> renderSurface,
        int displayWidth,
        int displayHeight,
        bool hasWideColorGamut,
        const HdrCapabilities& hdrCapabilities,
        const int32_t supportedPerFrameMetadata,
        const std::unordered_map<ColorMode, std::vector<RenderIntent>>& hwcColorModes,
        int initialPowerMode)

      .....

    mHdrCapabilities = HdrCapabilities(types, maxLuminance, maxAverageLuminance, minLuminance);

    // initialize the display orientation transform.
    // setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
    //cczheng add for land scap
    setProjection(DisplayState::eOrientation270, mViewport, mFrame);
#ifdef MTK_SF_DEBUG_SUPPORT
    mFps = FpsCounterLoader::getInstance().create();
#endif
}

frameworks ativeservicessurfaceflingerSurfaceFlinger.cpp

void SurfaceFlinger::onInitializeDisplays() {
    // reset screen orientation and use primary layer stack
    Vector<ComposerState> state;
    Vector<DisplayState> displays;
    DisplayState d;
    d.what = DisplayState::eDisplayProjectionChanged |
             DisplayState::eLayerStackChanged;
    d.token = mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY];
    d.layerStack = 0;
    //d.orientation = DisplayState::eOrientationDefault;
    //cczheng add for land scap
    d.orientation = DisplayState::eOrientation270;
    d.frame.makeInvalid();
    d.viewport.makeInvalid();
    d.width = 0;
    d.height = 0;
    displays.add(d);

  	....
}

3、开机动画横屏

对调 createSurface() 的 w 和 h

frameworksasecmdsootanimationBootAnimation.cpp

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

    sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(
            ISurfaceComposer::eDisplayIdMain));
    DisplayInfo dinfo;
    status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo);
    if (status)
        return -1;

    // create the native surface
    /*sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),
            dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);*/

    //cczheng add for land scap  [S]
    sp<SurfaceControl> control;
    if(dinfo.w < dinfo.h)
        control = session()->createSurface(String8("BootAnimation"),
            dinfo.h, dinfo.w, PIXEL_FORMAT_RGB_565);
    else
        control = session()->createSurface(String8("BootAnimation"),
            dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);
    //cczheng add for land scap  [E]

    SurfaceComposerClient::Transaction t;
    t.setLayer(control, 0x40000000)
        .apply();

	.....

}

开机动画制作替换后面补充。。。

4、开机logo、关机充电动画横屏

开机logo定义屏幕分辨率以对应资源文件夹的位置为

vendormediatekproprietaryootableootloaderlkprojectxxxx.mk 没有则看下面的

devicemediateksamplexxxxProjectConfig.mk

mk 中的 BOOT_LOGO = wxga

对应的资源文件位置在 vendor/mediatek/proprietary/bootable/bootloader/lk/dev/logo/wxga

可以看到 wxga 中都是竖屏的图片,而 wxganl 中已经是横屏的图片

ubWkNt.png

则我们将 BOOT_LOGO 修改为 wxganl 即可

接下来还需要继续修改显示的角度,依旧改成 270,不然会出现花屏的现象

开机第一张图片 uboot 对应显示

vendormediatekproprietaryootableootloaderlkplatformmt6765mt_logo.c

void init_fb_screen()
{
	.....

	// 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
",__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 = 270;//cczheng add for land scap
	}

	....

开机第二张图片 kernel 对应显示

vendormediatekproprietaryexternallibshowlogocharging_animation.cpp

int anim_fb_init(void)
{
   	 .....

    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
",__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 = 270;//cczheng add for land scap
    }
    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
",
                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
",__FUNCTION__,__LINE__, show_animationm_ver);
        SLOGD("[libshowlogo: %s %d]draw_anim_mode = 1, running mode %d
",__FUNCTION__,__LINE__, draw_anim_mode);
    }

    return 0;
}

如果出现充电动画图片错位的现象,多数都是因为图形绘制点和屏幕尺寸不匹配导致的。可通过调整 cust_display.h 中位置参数

Android M 后:/vendor/mediatek/proprietary/external/libshowlogo/cust_display.h

Android M 前: /vendor/mediatek/proprietary/bootable/bootloader/lk/target/${PROJECT}/include/target/cust_display.h

(1 ,使用old version动画方案的调整如下设置,

define BAR_LEFT (215) define BAR_TOP (156) define BAR_RIGHT (265) define BAR_BOTTOM (278)

可以用windows的画图软件打开第1点里提到的图片,根据电池边框的像素来调整。

这里坐标的参考原点是左上角,背景图片的左上角是(0,0),这四个值都是相对于左上角的坐标来确定的,因此RIGHT > LEFT,BOTTOM > TOP
小技巧:1)打开画图软件,选择 查看->缩放->自定义,将图片放到到800%
2)选择 查看->缩放->显示网格
这样就可以看到一个一个的像素
(2,使用new version动画方案调整如下设置:

#define CAPACITY_LEFT (278) 
#define CAPACITY_TOP (556)
#define CAPACITY_RIGHT (441)
#define CAPACITY_BOTTOM (817)

5、RecoveryUI 横屏

参考之前写的文章 MTK Recovery 模式横屏修改(适用于6.0 + 8.1+9.0)

6、系统导航栏位置调整,横屏后 navigationBarPosition 默认在左边

作为平板项目,需要将位置改为底部,直接修改 navigationBarPosition() 返回 NAV_BAR_BOTTOM

frameworksaseservicescorejavacomandroidserverpolicyPhoneWindowManager.java

@NavigationBarPosition
    private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
    	//cchzneg annotaion for land scape
        /*if (mNavigationBarCanMove && displayWidth > displayHeight) {
            if (displayRotation == Surface.ROTATION_270) {
                return NAV_BAR_LEFT;
            } else {
                return NAV_BAR_RIGHT;
            }
        }*/
        return NAV_BAR_BOTTOM;
    }

这样位置是变为底部了,但是三个按钮都重叠在一起了,需要修改 SystemUI 的布局显示

在这里插入图片描述

vendormediatekproprietarypackagesappsSystemUIsrccomandroidsystemuistatusbarphoneNavigationBarView.java

private void updateRotatedViews() {
        //cczheng change rot0 rot90 for landscape
        mRotatedViews[Surface.ROTATION_0] =
                mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot90);
                // mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
        mRotatedViews[Surface.ROTATION_270] =
                mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot0);
                // mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);        

        updateCurrentView();
    }

顺带再调整下 NavigationBarView 的默认高度和左边 Back 键区域太大的问题

vendormediatekproprietarypackagesappsSystemUIsrccomandroidsystemuistatusbarphoneNavigationBarInflaterView.java

private View createView(String buttonSpec, ViewGroup parent, LayoutInflater inflater) {
        View v = null;
        String button = extractButton(buttonSpec);
        if (LEFT.equals(button)) {
             //cchzheng change NAVSPACE to MENU_IME for small left back click area
            String s = Dependency.get(TunerService.class).getValue(NAV_BAR_LEFT, MENU_IME_ROTATE/*NAVSPACE*/);
            button = extractButton(s);
        } else if (RIGHT.equals(button)) {
            String s = Dependency.get(TunerService.class).getValue(NAV_BAR_RIGHT, MENU_IME_ROTATE);
            button = extractButton(s);
        }

		...

frameworksasecore es esvaluesdimens.xml

 <!-- Height of the bottom navigation / system bar. -->
    <!--cczheng change 48dp to 30dp-->
    <dimen name="navigation_bar_height">30dp</dimen>

ok,这样就大功告成了,完美的横屏适配

在这里插入图片描述

免责声明:文章转载自《Android9.0 MTK 平板横屏方案修改(强制app横屏 + 开机logo/动画+关机充电横屏 + RecoveryUI 横屏)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Flutter应用开发之webview_flutter插件CSM与UEFI下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Django 语法笔记

Django 语法创建项目框架 django-admin startproject 项目名 创建子app 业务分化,可以优化团队合作,可以明确找锅 python manage.py startapp 子app名 启动项目 python manage.py runserver 项目目录结构 __init__.py: 声明当前文件夹为一个可导入的包 se...

app常见性能测试点

转载链接:https://blog.csdn.net/xiaomaoxiao336368/article/details/83547318普遍的apk性能测试,主要是以下七类1、响应2、内存3、cpu4、FPS (app使用的流畅度)5、GPU过度渲染6、耗电7、耗流(app除了这些性能测试,还有:手机版本号兼容性,屏幕分辨率兼容性,稳定性测试,安全测试等...

记录uniapp的APP端分享到微信好友,链接为小程序页面,分享失败的BUG

记录uni-app的APP端分享到微信好友,链接为小程序页面,分享失败的BUG 分享到微信好友,链接为小程序端报错 16:59:19.617 fail:{"errMsg":"share:fail [Share微信分享:-6]send, http://ask.dcloud.net.cn/article/287","errCode":-100,"code":-...

[App Store Connect帮助]四、添加 App 图标、App 预览和屏幕快照(5)移除 App 预览或屏幕快照

您可以随时移除 App 预览,但仅可在 App 状态为可编辑时才能移除屏幕快照。要了解可编辑的状态,请前往 App 状态。 必要职能:“帐户持有人”职能、“管理”职能、“App 管理”职能或“营销”职能。请参见职能权限。 在首页上,点按“我的 App”,选择您的 App,然后在左列中点按平台版本。 在“App 预览和屏幕快照”部分的底部,点按“媒体管理”...

Windows上实现iOS APP自动化测试:tidevice + WDA + airtest

在Windows上实现iOS APP自动化测试:tidevice + WDA + facebook-wda / appium中介绍了使用阿里开源的tidevice 和 facebook-wda实现在Windows上进行iOS APP自动化测试。本文介绍如何使用tidevice + WDA + airtest进行iOS APP自动化测试。 目录 环境准...

软件测试计划文档

  引言 1.1编写目的 编写本测试计划的目的是: (1)     为整个测试阶段的管理工作和技术工作提供指南同时确定测试的内容和范围,为评价系统提供依据; (2)     此外还帮助安排测试活动,说明对资源的需求; (3)     说明测试结果的评价指标。 本文档的主要内容包括: (1)     测试系统登陆 (2)     测试系统界面 (3)    ...