RK3568的HDMI分辨率传递流程

1、packages/apps/Settings/src/com/android/settings/display/DrmDisplaySetting.java

 public static void updateDisplayModesInfo(DisplayInfo displayInfo) {
        RkDisplayOutputManager manager = new RkDisplayOutputManager();
        String[] orginModes = manager.getModeList(display, type);
        orginModes = filterOrginModes(orginModes);
}
//返回分辨率数组
 private static String[] filterOrginModes(String[] modes) {  
        for (int i = 0; i < modes.length; ++i) {
              filterModeList.add(modes[i]);
        }
        return filterModeList.toArray(new String[0]);
}

这里用到了RkDisplayOutputManager 类,最终被应用程序调用的函数是 updateDisplayModesInfo(),用于更新分辨率

2、frameworks/base/core/java/android/os/RkDisplayOutputManager.java

 public String[] getModeList(int display, int type) {
        String iface = typetoface(type);
        try {
            return mService.getModelist(display, iface);
        } catch (Exception e) {
            Log.e(TAG, "Error get list mode :" + e);
            return null;
        }
}

这里使用到了mService的getModelist方法,而mService是进程间通信,如下:

IBinder b = ServiceManager.getService("drm_device_management");
mService = IRkDisplayDeviceManagementService.Stub.asInterface(b);

3、对应的aidl文件在:frameworks/base/core/java/android/os/IRkDisplayDeviceManagementService.aidl

4、实现类在:frameworks/base/services/core/java/com/android/server/RkDisplayDeviceManagementService.java

class RkDisplayDeviceManagementService extends IRkDisplayDeviceManagementService.Stub {
    
    public RkDisplayDeviceManagementService(Context context) {
        mContext = context;
        mdrmModes = new RkDisplayModes();
        mdrmModes.init();
        IntentFilter hdmiFilter = new IntentFilter();
        hdmiFilter.addAction(ACTION_PLUGGED);
        mHdmiReceiver = new HdmiReceiver(mdrmModes);
        mContext.registerReceiver(mHdmiReceiver,hdmiFilter);
    }

    public String[] getModelist(int display, String iface){
        List<String> hdmiResoList = mdrmModes.getModeList(display);
        return hdmiResoList.toArray(new String[hdmiResoList.size()]);
    }
}

5、这里有出现一个新的类RkDisplayModes.java并且调佣了该类的getModeList方法

frameworks/base/services/core/java/com/android/server/rkdisplay/RkDisplayModes.java

public  List<String> getModeList(int dpy){
        List<String> modeList = new ArrayList<>();
        Log.e(TAG, "getModeList =========== dpy " + dpy);
        //readModeWhiteList(RESOLUTION_XML_PATH);
        mDisplayInfos = getDisplayConfigs(dpy);
        if (dpy == 0)
            mMainDisplayInfos = mDisplayInfos;
        else
            mAuxDisplayInfos = mDisplayInfos;

        if (mDisplayInfos != null) {
            modeList.add("Auto");
            for (int i = 0; i < mDisplayInfos.length; i++){
                boolean found=false;
                RkDisplayModes.RkPhysicalDisplayInfo info = mDisplayInfos[i];
                StringBuilder builder = new StringBuilder();
                builder.append(info.width).append("x").append(info.height);
                if (info.interlaceFlag == true) {
                    builder.append("i");
                    builder.append(String.format("%.2f", info.refreshRate));
                } else {
                    builder.append("p");
                    builder.append(String.format("%.2f", info.refreshRate));
                }
                //builder.append("@");
                builder.append("-").append(info.idx);

                boolean existingMode = false;
                if (resolutions == null || IsResolutionNeedFilter(dpy)) {
                    modeList.add(builder.toString());
                } else {
                    for (int j = 0; j < resolutions.size(); j++) {
                        if (resolutions.get(j).hasMatchingMode(info)) {
                            existingMode = true;
                            break;
                        }
                    }
                    if (existingMode) {
                        modeList.add(builder.toString());
                    }
                }
            }
        } else {
            modeList = null;
        }

        return modeList;
    }

从改方法我们可以看到,点击HDMI分辨率设置显示出来的第一个Auto就是在这里添加的,还有其它分辨率也是这里的getDisplayConfigs(dpy);获取到的,继续跟踪getDisplayConfigs函数

public static RkDisplayModes.RkPhysicalDisplayInfo[] getDisplayConfigs(int dpy) {
       return nativeGetDisplayConfigs(dpy);
}

这下芭比Q了,到native去了,又是一顿猛找,终于发现对应的native方法在frameworks/base/services/core/jni/com_android_server_rkdisplay_RkDisplayModes.cpp

static jobjectArray nativeGetDisplayConfigs(JNIEnv* env, jclass clazz,jint dpy) {
    hidl_vec<RkDrmMode> mModes;
    if (mComposer != nullptr)
    {
        mComposer->getDisplayModes(dpy,
                [&](const auto& tmpResult, const auto& tmpModes)
                {
                    if (tmpResult == Result::OK) {
                        mModes = tmpModes;
                    }
                });
    }

    jobjectArray configArray = env->NewObjectArray(mModes.size(),
            gRkPhysicalDisplayInfoClassInfo.clazz, NULL);

    for (size_t c=0;c<mModes.size();c++) {
        RkDrmMode tmpMode = mModes[c];
        jobject infoObj = env->NewObject(gRkPhysicalDisplayInfoClassInfo.clazz,
                gRkPhysicalDisplayInfoClassInfo.ctor);
        env->SetIntField(infoObj, gRkPhysicalDisplayInfoClassInfo.width, tmpMode.width);
        env->SetIntField(infoObj, gRkPhysicalDisplayInfoClassInfo.height, tmpMode.height);
        env->SetFloatField(infoObj, gRkPhysicalDisplayInfoClassInfo.refreshRate, tmpMode.refreshRate);//1000 * 1000 * 1000 /
        env->SetIntField(infoObj, gRkPhysicalDisplayInfoClassInfo.clock, tmpMode.clock);
        env->SetIntField(infoObj, gRkPhysicalDisplayInfoClassInfo.flags, tmpMode.flags);
        env->SetBooleanField(infoObj, gRkPhysicalDisplayInfoClassInfo.interlaceFlag,
                             tmpMode.interlaceFlag>0?1:0);
        env->SetBooleanField(infoObj, gRkPhysicalDisplayInfoClassInfo.yuvFlag, tmpMode.yuvFlag>0?1:0);
        env->SetIntField(infoObj, gRkPhysicalDisplayInfoClassInfo.connectorId, tmpMode.connectorId);//mode_type
        env->SetIntField(infoObj, gRkPhysicalDisplayInfoClassInfo.mode_type, tmpMode.mode_type);
        env->SetIntField(infoObj, gRkPhysicalDisplayInfoClassInfo.idx, tmpMode.idx);
        env->SetIntField(infoObj, gRkPhysicalDisplayInfoClassInfo.hsync_start, tmpMode.hsync_start);
        env->SetIntField(infoObj, gRkPhysicalDisplayInfoClassInfo.hsync_end, tmpMode.hsync_end);
        env->SetIntField(infoObj, gRkPhysicalDisplayInfoClassInfo.htotal, tmpMode.htotal);
        env->SetIntField(infoObj, gRkPhysicalDisplayInfoClassInfo.hskew, tmpMode.hskew);
        env->SetIntField(infoObj, gRkPhysicalDisplayInfoClassInfo.vsync_start, tmpMode.vsync_start);
        env->SetIntField(infoObj, gRkPhysicalDisplayInfoClassInfo.vsync_end, tmpMode.vsync_end);
        env->SetIntField(infoObj, gRkPhysicalDisplayInfoClassInfo.vtotal, tmpMode.vtotal);
        env->SetIntField(infoObj, gRkPhysicalDisplayInfoClassInfo.vscan, tmpMode.vscan);

        env->SetObjectArrayElement(configArray, static_cast<jsize>(c), infoObj);
        env->DeleteLocalRef(infoObj);
    }
    return configArray;
}

这里的关键代码为:mComposer->getDisplayModes,

sp<IRkOutputManager> mComposer = nullptr;
mComposer = IRkOutputManager::getService();

继续跟踪getService

找了好久没找到,有知道的大佬请告知

上面的调用流程我会继续跟踪,先提一下在系统启动之后的设置界面选择HDMI分辨率的问题。

显示出来给用户选择的分辨率是在kernel/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c的dw_hdmi_default_modes数组里面添加的,添加完成之后到Android层还需要经过过滤,过滤函数在frameworks/base/services/core/java/com/android/server/rkdisplay/RkDisplayModes.java

public  List<String> getModeList(int dpy){

     boolean existingMode = false;
     if (resolutions == null || IsResolutionNeedFilter(dpy)) {
         modeList.add(builder.toString());
      } else {
           for (int j = 0; j < resolutions.size(); j++) {
                  if (resolutions.get(j).hasMatchingMode(info)) {
                       existingMode = true;
                        break;
                     }
               }
               if (existingMode) {
                   modeList.add(builder.toString());
                }
       }
}

在上面这个函数里,首先判断resolutions是否有值,就是是否存在resolution_white.xml白名单列表文件,如果存在就使用白名单里面的分辨率,所以如果要屏蔽过滤修改这里就可以了

而变量resolutions又是在readModeWhiteList函数里面被赋值的

private static List<ResolutionParser.RkResolutionInfo> resolutions=null;

private  static boolean readModeWhiteList(String pathname) {
        InputStream is;
        try {
            is = new FileInputStream(RESOLUTION_XML_PATH);
        } catch (FileNotFoundException e) {
            Log.e(TAG, "Couldn't find " + RESOLUTION_XML_PATH + ".");
            return false;
        }
        resolutions=null;
        try {
            resolutions = mParser.parse(is);
            is.close();
        } catch (Exception e) {
            Log.e(TAG, "Couldn't get resolutions path  " + RESOLUTION_XML_PATH + ".");
            return false;
        }
        //logd("readStrListFromFile - " + fileStrings.toString());
        return true;
    }

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

笑三少_Creat

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值