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

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

拆解步骤


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

2、开机动画横屏

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

4、RecoveryUI 横屏


上代码


1、app 强制横屏显示


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

frameworks\base\services\core\java\com\android\server\wm\DisplayContent.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
 boolean updateRotationUnchecked(boolean forceUpdate) {
        cczheng add for app force landscape
        if (true) {
            return true;
        }
        20200325 add for app force landscape
        ScreenRotationAnimation screenRotationAnimation;
        if (!forceUpdate) {
            if (mDeferredRotationPauseCount > 0) {
                // Rotation updates have been paused temporarily.  Defer the update until
                // updates have been resumed.
                if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, rotation is paused.");
                return false;
            }
    ......

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


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


frameworks\base\services\core\java\com\android\server\wm\DisplayPolicy.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;
    }

2、开机动画横屏


DisplayState::eOrientationDefault 修改为 3

frameworks\base\cmds\bootanimation\BootAnimation.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;
    //cczheng add for land scap  [S]
    if (2 > 1) {
        int temp = dinfo.h;
        dinfo.h = dinfo.w;
        dinfo.w = temp;
    }
    Rect destRect(dinfo.w, dinfo.h);
    //270
    t.setDisplayProjection(mDisplayToken, 3, destRect, destRect);
    t.apply();
    //cczheng add for land scap  [E]
    /// M: The tablet rotation maybe 90/270 degrees, so set the lcm config for tablet
    /*t.setDisplayProjection(mDisplayToken, DisplayState::eOrientationDefault,
        Rect(dinfo.w, dinfo.h), Rect(dinfo.w, dinfo.h));
    t.apply();*/
    // create the native surface
    sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),
            dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);
    t.setLayer(control, 0x40000000)
        .apply();
  .....
}


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


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

vendor\mediatek\proprietary\bootable\bootloader\lk\project\xxxx.mk 没有则看下面的

device\mediateksample\xxxx\ProjectConfig.mk


mk 中的 BOOT_LOGO = hdplus


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


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


aHR0cHM6Ly9zMi5heDF4LmNvbS8yMDE5LzEwLzExL3ViV2tOdC5wbmc.png

则我们将 BOOT_LOGO 修改为 wxganl 即可


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


开机第一张图片 uboot 对应显示 phical_screen.rotation = 270


vendor\mediatek\proprietary\bootable\bootloader\lk\platform\mt6765\mt_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\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 = 270;//cczheng add for land scap
  }
  ....

开机第二张图片 kernel 对应显示 phical_screen.rotation = 270

vendor\mediatek\proprietary\external\libshowlogo\charging_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\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 = 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\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;
}


关机充电动画错位问题


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


/vendor/mediatek/proprietary/external/libshowlogo/cust_display.h


之前都是通过修改 cust_display.h 文件夹中预置宏定义,10.0 中代码结构做了调整,宏定义都没了,初始化写在了 show_animation_common.c 中,修改 rotation = 3 对调 lcm_width 和 lcm_height,当 lcm_width1280 && lcm_height800 时动画就不错位了,这里根据你自己的分辨率情况自行微调,不过一般系统默认的配置值都是对了


vendor/mediatek/proprietary/external/libshowlogo/show_animation_common.c

/*
 * Fill resolution structure based on lcd size
 *
 */
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 = getValue(MTK_LCM_PHYSICAL_ROTATION_PROP, "0");
    rotation = 3;
    // cczheng add rotation = 3 for charging landscape
    if (MTK_LOG_ENABLE == 1) {
        SLOGD("[libshowlogo: %s %d]rotation = %d\n",__FUNCTION__,__LINE__, rotation);
    }
    if ((3 == rotation)|| (1 == 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);
    if(lcm_width==1080) {
      charg_anim_ui_dimen.cap_left =387;
      charg_anim_ui_dimen.cap_right= 691;
      charg_anim_ui_dimen.num_left=351+84;
      charg_anim_ui_dimen.num_right=435+84;


4、RecoveryUI 横屏


RecoveryUI 在9.0 之前安卓源码并没有为我们适配好旋转配置,之前都是通过自己新增 mt_graphic_rotate.cpp 和 mt_graphic_rotate.h 文件来实现旋转。10.0 中代码也进行了较大重构相比之前,只需修改简单配置 rotation 就能旋转为横屏。


rotation = GRRotation::LEFT; 270


rotation = GRRotation::DOWN; 180


rotation = GRRotation::RIGHT; 90


bootable\recovery\minui\graphics.cpp

int gr_init() {
  .....
  gr_backend = backend.release();
  int overscan_percent = android::base::GetIntProperty("ro.minui.overscan_percent", 0);
  overscan_offset_x = gr_draw->width * overscan_percent / 100;
  overscan_offset_y = gr_draw->height * overscan_percent / 100;
  gr_flip();
  gr_flip();
  if (!gr_draw) {
    printf("gr_init: gr_draw becomes nullptr after gr_flip\n");
    return -1;
  }
  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);
  }
  rotation = GRRotation::LEFT;
  //cczheng add rotation = 3 for recoveryUI landscape


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

目录
相关文章
|
11天前
|
ARouter IDE 开发工具
Android面试题之App的启动流程和启动速度优化
App启动流程概括: 当用户点击App图标,Launcher通过Binder IPC请求system_server启动Activity。system_server指示Zygote fork新进程,接着App进程向system_server申请启动Activity。经过Binder通信,Activity创建并回调生命周期方法。启动状态分为冷启动、温启动和热启动,其中冷启动耗时最长。优化技巧包括异步初始化、避免主线程I/O、类加载优化和简化布局。
28 3
Android面试题之App的启动流程和启动速度优化
|
7天前
|
Android开发 UED
Android Item平移动画
【6月更文挑战第18天】
|
9天前
|
缓存 JSON 网络协议
Android面试题:App性能优化之电量优化和网络优化
这篇文章讨论了Android应用的电量和网络优化。电量优化涉及Doze和Standby模式,其中应用可能需要通过用户白名单或电池广播来适应限制。Battery Historian和Android Studio的Energy Profile是电量分析工具。建议减少不必要的操作,延迟非关键任务,合并网络请求。网络优化包括HTTPDNS减少DNS解析延迟,Keep-Alive复用连接,HTTP/2实现多路复用,以及使用protobuf和gzip压缩数据。其他策略如使用WebP图像格式,按网络质量提供不同分辨率的图片,以及启用HTTP缓存也是有效手段。
29 9
|
10天前
|
XML 监控 安全
Android App性能优化之卡顿监控和卡顿优化
本文探讨了Android应用的卡顿优化,重点在于布局优化。建议包括将耗时操作移到后台、使用ViewPager2实现懒加载、减少布局嵌套并利用merge标签、使用ViewStub减少资源消耗,以及通过Layout Inspector和GPU过度绘制检测来优化。推荐使用AsyncLayoutInflater异步加载布局,但需注意线程安全和不支持特性。卡顿监控方面,提到了通过Looper、ChoreographerHelper、adb命令及第三方工具如systrace和BlockCanary。总结了Choreographer基于掉帧计算和BlockCanary基于Looper监控的原理。
20 3
|
12天前
|
安全 JavaScript 前端开发
kotlin开发安卓app,JetPack Compose框架,给webview新增一个按钮,点击刷新网页
在Kotlin中开发Android应用,使用Jetpack Compose框架时,可以通过添加一个按钮到TopAppBar来实现WebView页面的刷新功能。按钮位于右上角,点击后调用`webViewState?.reload()`来刷新网页内容。以下是代码摘要:
|
7天前
|
Java Android开发 Kotlin
Android面试题:App性能优化之Java和Kotlin常见的数据结构
Java数据结构摘要:ArrayList基于数组,适合查找和修改;LinkedList适合插入删除;HashMap1.8后用数组+链表/红黑树,初始化时预估容量可避免扩容。SparseArray优化查找,ArrayMap减少冲突。 Kotlin优化摘要:Kotlin的List用`listOf/mutableListOf`,Map用`mapOf/mutableMapOf`,支持操作符重载和扩展函数。序列提供懒加载,解构用于遍历Map,扩展函数默认参数增强灵活性。
14 0
|
9天前
|
安全 Java Android开发
安卓开发中的新趋势:Kotlin与Jetpack的完美结合
【6月更文挑战第20天】在不断进化的移动应用开发领域,Android平台以其开放性和灵活性赢得了全球开发者的青睐。然而,随着技术的迭代,传统Java语言在Android开发中逐渐显露出局限性。Kotlin,一种现代的静态类型编程语言,以其简洁、安全和高效的特性成为了Android开发中的新宠。同时,Jetpack作为一套支持库、工具和指南,旨在帮助开发者更快地打造优秀的Android应用。本文将探讨Kotlin与Jetpack如何共同推动Android开发进入一个新的时代,以及这对开发者意味着什么。
|
5天前
|
Java 开发工具 Android开发
探索Android与iOS开发的差异:平台选择对项目成功的影响
在移动应用开发的广阔天地中,Android和iOS两大平台各自占据着半壁江山。本文将深入探讨这两个平台在开发过程中的关键差异点,包括编程语言、开发工具、用户界面设计、性能优化以及市场覆盖等方面。通过对这些关键因素的比较分析,旨在为开发者提供一个清晰的指南,帮助他们根据项目需求和目标受众做出明智的平台选择。
|
5天前
|
编解码 Android开发 iOS开发
深入探索Android与iOS开发的差异与挑战
【6月更文挑战第24天】在移动应用开发的广阔舞台上,Android和iOS两大操作系统扮演着主角。它们各自拥有独特的开发环境、工具集、用户基础及市场策略。本文将深度剖析这两个平台的开发差异,并探讨开发者面临的挑战,旨在为即将踏入或已在移动开发领域奋斗的开发者提供一份实用指南。
27 13
|
4天前
|
监控 Android开发 iOS开发
探索Android与iOS开发的差异:平台、工具和用户体验的比较
【6月更文挑战第25天】在移动应用开发的广阔天地中,Android和iOS两大平台各领风骚,它们在开发环境、工具选择及用户体验设计上展现出独特的风貌。本文将深入探讨这两个操作系统在技术实现、市场定位和用户交互方面的关键差异,旨在为开发者提供一个全景式的视图,帮助他们在面对项目决策时能够更加明智地选择适合自己项目需求的平台。