热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

AndroidTV切换系统输出分辨率的一些思考

Android12后的一些思考:是否可以使用原生的某些接口实现切换系统分辨率呢? 参考文章:https:blog.csdn.netu014535072articledetails1

Android 12 后的一些思考:是否可以使用原生的某些接口实现切换系统分辨率呢?

 

参考文章:

https://blog.csdn.net/u014535072/article/details/108692559

 

从源码中看到的可能相关的内容:

 /frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java

中的方法:

@Override
public void setDisplayProperties(int displayId, boolean hasContent,
float requestedRefreshRate, int requestedMode, float requestedMinRefreshRate,
float requestedMaxRefreshRate, boolean requestedMinimalPostProcessing,
boolean inTraversal) {
setDisplayPropertiesInternal(displayId, hasContent, requestedRefreshRate,
requestedMode, requestedMinRefreshRate, requestedMaxRefreshRate,
requestedMinimalPostProcessing, inTraversal);
}

 

获取支持的Display mode:

 

获取Display info的参看

/packages/apps/Launcher3/src/com/android/launcher3/util/DisplayController.java

private final DisplayManager mDM;
mDM = context.getSystemService(DisplayManager.class);
Display display = mDM.getDisplay(DEFAULT_DISPLAY);

基础的Display类

/frameworks/base/core/java/android/view/Display.java

/**
* Returns the active mode of the display.
*/
public Mode getMode() {
synchronized (mLock) {
updateDisplayInfoLocked();
return mDisplayInfo.getMode();
}
}
/**
* Gets the supported modes of this display.
*/
public Mode[] getSupportedModes() {
synchronized (mLock) {
updateDisplayInfoLocked();
final Display.Mode[] modes = mDisplayInfo.supportedModes;
return Arrays.copyOf(modes, modes.length);
}
}

 

Display::Mode的定义:

http://aospxref.com/android-12.0.0_r3/xref/frameworks/base/core/java/android/view/Display.java#1696

 

一个例子demo

http://aospxref.com/android-12.0.0_r3/xref/cts/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/ModeSwitchingTestActivity.java#66

DisplayManager displayManager = getSystemService(DisplayManager.class);
Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
List modeList = findTestModes(display);
Display.Mode lastMode = display.getMode();

private List findTestModes(Display display) {
Display.Mode activeMode = display.getMode();
List modeList = new ArrayList<>();
// Find a mode to test refresh rate switch - the mode with smallest refresh rate and
// the same resolution as the active mode
Arrays.stream(display.getSupportedModes())
.filter(mode -> !mode.equals(activeMode))
.filter(mode -> isResolutionEqual(mode, activeMode))
.min(Comparator.comparingDouble(Display.Mode::getRefreshRate))
.ifPresent(modeList::add);
// Find a mode to test seamless mode switch.
if (modeList.size() > 0 && !DisplayUtil.isModeSwitchSeamless(activeMode, modeList.get(0))
&& activeMode.getAlternativeRefreshRates().length > 0) {
Arrays.stream(display.getSupportedModes())
.filter(mode -> !mode.equals(activeMode))
.filter(mode -> DisplayUtil.isModeSwitchSeamless(activeMode, mode))
.findFirst()
.ifPresent(modeList::add);
}
// Find a mode to test resolution switch - the first 16:9 mode with resolution less
// than the active mode.
Arrays.stream(display.getSupportedModes())
.filter(mode -> !mode.equals(activeMode))
.filter(mode -> !isResolutionEqual(mode, activeMode))
.filter(this::is16to9)
.max(Comparator.comparing(Display.Mode::getPhysicalHeight))
.ifPresent(modeList::add);
return modeList;
}

 

我目前遇到的问题是不是可以直接在apk中加上这一个来通知到 WM 、SurfaceFLinger呢?

private Display.Mode mNextMode;
@Override
public void runTest() {
Window window = mContext.getWindow();
WindowManager.LayoutParams params = window.getAttributes();
params.preferredDisplayModeId = mNextMode.getModeId();
window.setAttributes(params);
}

 

 

 

另一个可能的途径:

 /frameworks/base/core/java/android/view/SurfaceControl.java

/**
* @hide
*/
public static boolean setDesiredDisplayModeSpecs(IBinder displayToken,
DesiredDisplayModeSpecs desiredDisplayModeSpecs) {
if (displayToken == null) {
throw new IllegalArgumentException("displayToken must not be null");
}
if (desiredDisplayModeSpecs == null) {
throw new IllegalArgumentException("desiredDisplayModeSpecs must not be null");
}
if (desiredDisplayModeSpecs.defaultMode <0) {
throw new IllegalArgumentException("defaultMode must be non-negative");
}
return nativeSetDesiredDisplayModeSpecs(displayToken, desiredDisplayModeSpecs);
}

// Verify that this will reapply the desired modes.
verify(mSurfaceControlProxy).setDesiredDisplayModeSpecs(display.token,
new SurfaceControl.DesiredDisplayModeSpecs(
/* baseModeId */ 2,
/* allowGroupSwitching */ false,
/* primaryRange */ 60f, 60f,
/* appRange */ 60f, 60f
));

 

 

 

 

SurfaceFlinger

void SurfaceFlinger::loadDisplayModes(PhysicalDisplayId displayId, DisplayModes& outModes,
DisplayModePtr& outActiveMode) const {

activeModeHwcId = getHwComposer().getActiveMode(displayId);
}

只有这里去HWC 获取 getActiveMode

 

 

 

 

 

/frameworks/base/core/java/android/view/SurfaceControl.java

通知到SurfaceFlinger???

setDisplaySize
--> DisplayState::eDisplaySizeChanged
--> eDisplayTransactionNeeded
--> processDisplayHotplugEventsLocked
--> loadDisplayModes
--> getHwComposer().getActiveMode(displayId);

 

 

获取displayToken

private Bitmap captureScreenshot(Rect crop) {
int width = crop.width();
int height = crop.height();
Bitmap screenshot = null;
final Display display = getDefaultDisplay();
final DisplayAddress address = display.getAddress();
if (!(address instanceof DisplayAddress.Physical)) {
Log.e(TAG, "Skipping Screenshot - Default display does not have a physical address: "
+ display);
} else {
final DisplayAddress.Physical physicalAddress = (DisplayAddress.Physical) address;
final IBinder displayToken = SurfaceControl.getPhysicalDisplayToken(
physicalAddress.getPhysicalDisplayId());
final SurfaceControl.DisplayCaptureArgs captureArgs =
new SurfaceControl.DisplayCaptureArgs.Builder(displayToken)
.setSourceCrop(crop)
.setSize(width, height)
.build();
final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
SurfaceControl.captureDisplay(captureArgs);
screenshot = screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
}
return screenshot;
}

 

心有猛虎,细嗅蔷薇,生活就该无惧无悔



 

作者:二的次方 出处:https://www.cnblogs.com/roger-yu/p/15997843.html 本文版权归作者和博客园共有,转载必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利



推荐阅读
  • 心理学经典:《思考致富》
    《思考致富》是由美国著名成功学大师拿破仑·希尔撰写的一部重要著作,该书基于希尔长达20年的深入研究和访谈,探讨了个人成功的核心要素。书中不仅揭示了成功的关键,还提供了一系列实用的方法和策略。 ... [详细]
  • 深入解析WebP图片格式及其应用
    随着互联网技术的发展,无论是PC端还是移动端,图片数据流量占据了很大比重。尤其在高分辨率屏幕普及的背景下,如何在保证图片质量的同时减少文件大小,成为了亟待解决的问题。本文将详细介绍Google推出的WebP图片格式,探讨其在实际项目中的应用及优化策略。 ... [详细]
  • 本文将详细介绍如何在二进制和十六进制之间进行准确的转换,并提供实际的代码示例来帮助理解这一过程。 ... [详细]
  • 在尝试使用 Android 发送 SOAP 请求时遇到错误,服务器返回 '无法处理请求' 的信息,并指出某个值不能为 null。本文探讨了可能的原因及解决方案。 ... [详细]
  • 新浪微博热搜暂停更新;即刻APP回归;Android 11 Beta版发布 | 科技新闻速递
    为您带来最新的科技资讯,涵盖社交媒体动态、软件更新及行业重大事件。CSDN携手您共同关注科技前沿。 ... [详细]
  • 菜鸟物流用户增长部现正大规模招聘P6及以上级别的JAVA工程师,提供年后入职选项。 ... [详细]
  • 本题要求计算一组正整数的最小公倍数(LCM)。输入包括多组测试数据,每组数据首先给出一个正整数n,随后是n个正整数。 ... [详细]
  • PyCharm 安装与首个 Python 程序实践
    本文将指导您如何安装 PyCharm,并通过创建一个简单的 'Hello, World' 程序来初步体验这一强大的 Python 集成开发环境。 ... [详细]
  • 本文提供了详细的JDK下载和安装步骤,包括多个可靠的下载源、环境配置以及如何验证安装成功。同时,文章还涉及版权问题处理和个人见解分享。 ... [详细]
  • 本文详细介绍了如何在 Vue CLI 3.0 和 2.0 中配置 proxy 来解决开发环境下的跨域问题,包括具体的配置项和使用场景。 ... [详细]
  • 下半年学期如期而至,课程安排密集,每周需完成18学时的学习任务,涉及软件工程、客户关系管理和C程序设计等多门课程。除了繁重的教学任务,时隔八年再次担任班主任的角色,旨在更深入地了解和支持学生们。 ... [详细]
  • 深入理解Java SE 8新特性:Lambda表达式与函数式编程
    本文作为‘Java SE 8新特性概览’系列的一部分,将详细探讨Lambda表达式。通过多种示例,我们将展示Lambda表达式的不同应用场景,并解释编译器如何处理这些表达式。 ... [详细]
  • 流处理中的计数挑战与解决方案
    本文探讨了在流处理中进行计数的各种技术和挑战,并基于作者在2016年圣何塞举行的Hadoop World大会上的演讲进行了深入分析。文章不仅介绍了传统批处理和Lambda架构的局限性,还详细探讨了流处理架构的优势及其在现代大数据应用中的重要作用。 ... [详细]
  • 本文详细介绍了如何在Windows操作系统中配置和使用Lex(Flex)与Yacc(Bison),包括软件的下载、安装以及通过示例验证其正确性的步骤。 ... [详细]
  • 在现代前端开发中,组件化已成为不可或缺的技术,尤其在 React 和 Vue 生态中。然而,组件的管理和测试一直是开发者面临的挑战。本文将介绍如何使用 Storybook 来简化这一过程,提高开发效率。 ... [详细]
author-avatar
博客百度2
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有