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

    文章较长建议先收藏再看

    拆解步骤

    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,这样就大功告成了,完美的横屏适配

    在这里插入图片描述

  • 相关阅读:
    Python之Pyautogui模块20180125《PYTHON快速上手让繁琐的工作自动化》18章
    〈Android 群英传-神兵利器〉第7章一个的寂寞与一群人的狂欢
    一,Android Studio笔记
    一、探索 Android Studio
    微服务之网关:Ocelot+Consul实现动态集群扩展
    MacOS任意降级
    微服务之注册服务与发现:Consul在Windows下安装使用
    .Net Core中使用 AutoMapper
    .Net Core中使用Swagger
    .NetCore中使用EF Core
  • 原文地址:https://www.cnblogs.com/cczheng-666/p/11689854.html
Copyright © 2011-2022 走看看