安卓11中从设置-显示设置hdmi分辨率流程:framework层通过jni控制底层驱动实现,标准驱动模型
packages\apps\Settings\src\com\android\settings\display\HdmiSettings.java
private void updateResolution(final ITEM_CONTROL control, final int index) {
showWaitingDialog(R.string.dialog_update_resolution);
mEnableDisplayListener = false;
new Thread() {
@Override
public void run() {
if (ITEM_CONTROL.CHANGE_RESOLUTION == control) {
synchronized (mLock) {
int display = mSelectDisplayInfo.getDisplayNo();
DrmDisplaySetting.updateDisplayInfos();
DrmDisplaySetting.updateDisplayModesInfo(mSelectDisplayInfo);
int status = DrmDisplaySetting.getCurrentDpyConnState(display);
mSelectDisplayInfo.setStatus(status);
String[] modes = mSelectDisplayInfo.getOrginModes();
Log.v(TAG, "display " + display + ", status=" + status + ", modes=" + modes);
if (DPY_STATUS_CONNECTED == status && null != modes && modes.length > 0) {
DrmDisplaySetting.setDisplayModeTemp(mSelectDisplayInfo, index);
// String mode = Arrays.asList(modes).get(index);
// DrmDisplaySetting.setMode(display, mode);
if (USED_OFFON_RESOLUTION) {
sendSwitchDeviceOffOnMsg(control, SWITCH_STATUS_OFF_ON);
} else {
Message message = new Message();
message.what = MSG_SHOW_CONFIRM_DIALOG;
message.obj = control;
mHandler.sendMessageDelayed(message, 300);
}
} else {
Message message = new Message();
message.what = MSG_UPDATE_STATUS_UI;
message.obj = ITEM_CONTROL.REFRESH_DISPLAY_STATUS_INFO;
mHandler.sendMessage(message);
}
}
}
}
}.start();
}
packages/apps/Settings/src/com/android/settings/display/DrmDisplaySetting.java
public static void setDisplayModeTemp(DisplayInfo di, int index) {
String mode = Arrays.asList(di.getOrginModes()).get(index);
setMode(di.getDisplayNo(), mode);
tmpSetMode = mode;
}
public static void setDisplayModeTemp(DisplayInfo di, int index) {
String mode = Arrays.asList(di.getOrginModes()).get(index);
setMode(di.getDisplayNo(), mode);
tmpSetMode = mode;
}
public static void setMode(int display, String mode) {
RkDisplayOutputManager manager = new RkDisplayOutputManager();
int result = manager.updateDisplayInfos();
int type = manager.getCurrentInterface(display);
logd("setMode display=" + display + ", type=" + type + ", mode=" + mode);
manager.setMode(display, type, mode);
}
frameworks$ vim ./base/core/java/android/os/RkDisplayOutputManager.java
public void setMode(int display, int type, String mode) {
String iface = typetoface(type);
try {
mService.setMode(display, iface, mode);
}catch (Exception e) {
Log.e(TAG, "Error set mode :" + e);
return;
}
}
public RkDisplayOutputManager() {
IBinder b = ServiceManager.getService("drm_device_management");
if(b == null) {
Log.e(TAG, "Unable to connect to display device management service! - is it running yet?");
return;
}
mService = IRkDisplayDeviceManagementService.Stub.asInterface(b);
int mMainState = getCurrentDpyConnState(MAIN_DISPLAY);
try {
// Get main display interface
String[] display_iface = mService.listInterfaces(MAIN_DISPLAY);
if(DBG) Log.d(TAG, "main display iface num is " + display_iface.length);
if(display_iface != null && display_iface.length > 0 && mMainState==DRM_MODE_CONNECTED) {
m_main_iface = new int[display_iface.length];
for(int i = 0; i < m_main_iface.length; i++) {
if(DBG) Log.d(TAG, display_iface[i]);
m_main_iface[i] = ifacetotype(display_iface[i]);
}
}
./base/services/core/java/com/android/server/RkDisplayDeviceManagementService.java
public void setMode(int display, String iface, String mode) {
boolean isSameProperty = false;
String lastMode;
mdrmModes.setMode(display, iface, mode);
}
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);
}
./base/services/core/java/com/android/server/rkdisplay/RkDisplayModes.java
public void setMode(int display, String iface, String mode){
int ifaceType = ifacetotype(iface);
String[] mode_str;
int idx=0;
RkDisplayModes.RkPhysicalDisplayInfo info;
Log.w(TAG, "setMode " + mode + " display " + display);
if (mode.contains("Auto")) {
nativeSetMode(display, ifaceType, mode);//通过本地方法实现
} else {
mode_str = mode.split("-");
for (String mval: mode_str){
Log.e(TAG, "setMode split: " + mval);
}
if (mode_str.length != 2){
return;
}
idx = Integer.parseInt(mode_str[1]);
if (mMainDisplayInfos!=null && idx >= mMainDisplayInfos.length && display==0)
idx=0;
else if (mAuxDisplayInfos!=null && idx >= mAuxDisplayInfos.length && display==1)
idx=0;
if (display == 0)
info = mMainDisplayInfos[idx];
else
info = mAuxDisplayInfos[idx];
StringBuilder builder = new StringBuilder();
builder.append(info.width).append("x").append(info.height);
/*
if (info.interlaceFlag == true)
builder.append("i");
else
builder.append("p");
*/
builder.append("@");
builder.append(String.format(Locale.ENGLISH, "%.2f", info.refreshRate));
builder.append("-");
builder.append(info.hsync_start);
builder.append("-");
builder.append(info.hsync_end);
builder.append("-");
builder.append(info.htotal);
builder.append("-");
builder.append(info.vsync_start)
.append("-").append(info.vsync_end).append("-").append(info.vtotal).append("-").append(String.format(Locale.ENGLISH, "%x", info.flags)).append("-").append(info.clock);
nativeSetMode(display, ifaceType, builder.toString());
}
}
base/services/core/jni/com_android_server_rkdisplay_RkDisplayModes.cpp
#include <rockchip/hardware/outputmanager/1.0/IRkOutputManager.h>
static void nativeSetMode(JNIEnv* env, jobject obj, jint dpy, jint iface_type, jstring mode)
{
const char* mMode = env->GetStringUTFChars(mode, NULL);
if (mComposer != nullptr)
mComposer->setMode(dpy, mMode); //这里又调用了hal层的方法
env->ReleaseStringUTFChars(mode, mMode);
}
static void nativeInit(JNIEnv* env, jobject obj) {
mComposer = IRkOutputManager::getService();//通过IRkOutputManager实现hdmi分辨率写入的
if (mComposer != nullptr) {
mComposer->initial();
} else {
ALOGD("nativeInit failed to get IRkOutputManager");
}
}
./vendor/rockchip/hardware/interfaces/outputmanager/1.0/default/RkOutputManager.cpp
Return<Result> RkOutputManager::setMode(Display display, const hidl_string& mode)
{
std::string modeStd(mode.c_str());
mHwOutput->setMode(mHwOutput, display, modeStd.c_str()); //找到设备写入的地方
return Result::OK;
}
IRkOutputManager* HIDL_FETCH_IRkOutputManager(const char* /* name */) {
struct hw_output_device* mHwOutput;
const hw_module_t* hw_module = nullptr;
int ret = hw_get_module(HW_OUTPUT_HARDWARE_MODULE_ID, &hw_module);//找到这个设备,获取设备,设备的具体实现在hw_output.cpp
if (ret == 0) {
ret = hw_output_open(hw_module, &mHwOutput);
if (ret == 0) {
return new RkOutputManager(mHwOutput);
} else {
LOG(ERROR) << "Passthrough failed to load legacy HAL.";
return nullptr;
}
}
else {
LOG(ERROR) << "hw_get_module " << HWC_HARDWARE_MODULE_ID
<< " failed: " << ret;
return nullptr;
}
}
hardware/libhardware/modules/hw_output/hw_output.cpp
static int hw_output_device_open(const struct hw_module_t* module,
const char* name, struct hw_device_t** device)
{
int status = -EINVAL;
if (!strcmp(name, HW_OUTPUT_DEFAULT_DEVICE)) {
hw_output_private_t* dev = (hw_output_private_t*)malloc(sizeof(*dev));
/* initialize our state here */
//memset(dev, 0, sizeof(*dev));
/* initialize the procs */
dev->device.common.tag = HARDWARE_DEVICE_TAG;
dev->device.common.version = HW_OUTPUT_DEVICE_API_VERSION_0_1;
dev->device.common.module = const_cast<hw_module_t*>(module);
dev->device.common.close = hw_output_device_close;
dev->device.initialize = hw_output_initialize;
dev->device.setMode = hw_output_set_mode; //这里传递一个函数指针,具体设置分辨率的地方
..........
static int hw_output_set_mode(struct hw_output_device* dev, int dpy, const char* mode)
{
hw_output_private_t* priv = (hw_output_private_t*)dev;
DrmConnector* conn = getValidDrmConnector(priv, dpy);
BaseParameter* mBaseParameter = priv->mBaseParmeter;
char property[PROPERTY_VALUE_MAX];
std::string propertyStr;
propertyStr = getPropertySuffix(priv, "persist.vendor.resolution.", dpy);
ALOGD("nativeSetMode %s display %d", mode, dpy);
if (strcmp(mode, property) !=0) {
property_set(propertyStr.c_str(), mode);
updateTimeline();
struct disp_info info;
float vfresh=0.0f;
int slot = 0;
mBaseParameter->get_disp_info(conn->get_type(), conn->connector_id(), &info);
slot = findSuitableInfoSlot(&info, conn->get_type(), conn->connector_id());
info.screen_info[slot].type = conn->get_type();
info.screen_info[slot].id = conn->connector_id();
if (strncmp(mode, "Auto", 4) != 0 && strncmp(mode, "0x0p0-0", 7) !=0) {
sscanf(mode,"%dx%d@%f-%d-%d-%d-%d-%d-%d-%x-%d",
&info.screen_info[slot].resolution.hdisplay, &info.screen_info[slot].resolution.vdisplay,
&vfresh, &info.screen_info[slot].resolution.hsync_start,&info.screen_info[slot].resolution.hsync_end,
&info.screen_info[slot].resolution.htotal,&info.screen_info[slot].resolution.vsync_start,
&info.screen_info[slot].resolution.vsync_end, &info.screen_info[slot].resolution.vtotal,
&info.screen_info[slot].resolution.flags, &info.screen_info[slot].resolution.clock);
info.screen_info[slot].resolution.vrefresh = (int)vfresh;
} else {
info.screen_info[slot].feature|= RESOLUTION_AUTO;
memset(&info.screen_info[slot].resolution, 0, sizeof(info.screen_info[slot].resolution));
}
mBaseParameter->set_disp_info(conn->get_type(), conn->connector_id(), &info);
}
return 0;
}