Android9.0 MTK 平板横屏方案修改(强制app横屏 + 开机logo/动画+关机充电横屏 + RecoveryUI 横屏)
文章较长建议先收藏再看
拆解步骤
1、app 强制横屏显示,无视 android:screenorientation="portrait" 属性
2、屏幕触摸坐标修改为横屏
3、开机动画横屏
4、开机logo、关机充电动画横屏
5、recoveryui 横屏
上代码
1、app 强制横屏显示
修改 rotationfororientationlw(), 默认返回 270
frameworks\base\services\core\java\com\android\server\policy\phonewindowmanager.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
frameworks\base\services\core\java\com\android\server\wm\windowmanagerservice.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)
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
修改默认值 config_reversedefaultrotation 为 true,翻转显示角度
frameworks\base\core\res\res\values\config.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\native\services\surfaceflinger\displaydevice.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\native\services\surfaceflinger\surfaceflinger.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
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; // 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定义屏幕分辨率以对应资源文件夹的位置为
vendor\mediatek\proprietary\bootable\bootloader\lk\project\xxxx.mk 没有则看下面的
device\mediateksample\xxxx\projectconfig.mk
mk 中的 boot_logo = wxga
对应的资源文件位置在 vendor/mediatek/proprietary/bootable/bootloader/lk/dev/logo/wxga
可以看到 wxga 中都是竖屏的图片,而 wxganl 中已经是横屏的图片
则我们将 boot_logo 修改为 wxganl 即可
接下来还需要继续修改显示的角度,依旧改成 270,不然会出现花屏的现象
开机第一张图片 uboot 对应显示
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 对应显示
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 中位置参数
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
frameworks\base\services\core\java\com\android\server\policy\phonewindowmanager.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 的布局显示
vendor\mediatek\proprietary\packages\apps\systemui\src\com\android\systemui\statusbar\phone\navigationbarview.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 键区域太大的问题
vendor\mediatek\proprietary\packages\apps\systemui\src\com\android\systemui\statusbar\phone\navigationbarinflaterview.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); } ...
frameworks\base\core\res\res\values\dimens.xml
<!-- height of the bottom navigation / system bar. --> <!--cczheng change 48dp to 30dp--> <dimen name="navigation_bar_height">30dp</dimen>
ok,这样就大功告成了,完美的横屏适配
上一篇: Linux 命令之 chmod