blob: f49b826f876e1c5a5a1f5409aed22bd4097af3e7
1 | //#define LOG_NDEBUG 0 |
2 | #include <HwcTrace.h> |
3 | #include <binder/IServiceManager.h> |
4 | #include <utils/Tokenizer.h> |
5 | #include <thread> |
6 | #include <gui/SurfaceComposerClient.h> |
7 | #include <gui/ISurfaceComposer.h> |
8 | #include "DisplayHdmi.h" |
9 | |
10 | namespace android { |
11 | namespace amlogic { |
12 | |
13 | DisplayHdmi::DisplayHdmi(hwc2_display_t id) { |
14 | mDisplayId = id; |
15 | |
16 | sp<IServiceManager> sm = defaultServiceManager(); |
17 | if (sm == NULL) |
18 | { |
19 | ETRACE("Couldn't get default ServiceManager\n"); |
20 | return ; |
21 | } |
22 | |
23 | mSystemControlService = interface_cast<ISystemControlService>(sm->getService(String16("system_control"))); |
24 | if (mSystemControlService == NULL) |
25 | { |
26 | ETRACE("Couldn't get connection to SystemControlService\n"); |
27 | return ; |
28 | } |
29 | |
30 | initModes(); |
31 | } |
32 | |
33 | DisplayHdmi::~DisplayHdmi() { |
34 | mAllModes.clear(); |
35 | } |
36 | |
37 | void DisplayHdmi::initialize() { |
38 | reset(); |
39 | } |
40 | |
41 | void DisplayHdmi::deinitialize() { |
42 | reset(); |
43 | } |
44 | |
45 | void DisplayHdmi::reset() { |
46 | mConnected = false; |
47 | mActiveDisplayConfigItem = 0; |
48 | mActiveRefreshRate = 60; |
49 | memset(mActiveDisplaymode, 0, HWC_DISPLAY_MODE_LENGTH); |
50 | mSupportDispModes.clear(); |
51 | for (size_t i = 0; i < mDisplayConfigs.size(); i++) { |
52 | DisplayConfig *config = mDisplayConfigs[i]; |
53 | if (config) |
54 | delete config; |
55 | } |
56 | mDisplayConfigs.clear(); |
57 | } |
58 | |
59 | bool DisplayHdmi::updateHotplug(bool connected, |
60 | framebuffer_info_t * framebufferInfo, |
61 | private_handle_t* framebufferHnd) { |
62 | bool ret = true; |
63 | int32_t rate; |
64 | |
65 | mConnected = connected; |
66 | |
67 | if (!isConnected()) { |
68 | ETRACE("disp: %d disconnect", (int32_t)mDisplayId); |
69 | return true; |
70 | } |
71 | |
72 | mFramebufferInfo = framebufferInfo; |
73 | mFramebufferHnd = framebufferHnd; |
74 | |
75 | if (-1 == updateDisplayModeList()) { |
76 | //hdmi plug out when system is starting up |
77 | std::string dispMode; |
78 | int width, height; |
79 | mSystemControlService->getActiveDispMode(&dispMode); |
80 | ret = calcMode2Config(dispMode.c_str(), &rate, &width, &height); |
81 | if (!ret) { |
82 | dispMode = std::string("1080p60hz"); |
83 | rate = 60; |
84 | } |
85 | ETRACE("only init one display config: %s", dispMode.c_str()); |
86 | strcpy(mActiveDisplaymode, dispMode.c_str()); |
87 | |
88 | // reset display configs |
89 | for (size_t i = 0; i < mDisplayConfigs.size(); i++) { |
90 | DisplayConfig *config = mDisplayConfigs[i]; |
91 | if (config) |
92 | delete config; |
93 | } |
94 | mDisplayConfigs.clear(); |
95 | |
96 | // use active fb dimension as config width/height |
97 | DisplayConfig *config = new DisplayConfig(mActiveDisplaymode, |
98 | rate, |
99 | mFramebufferInfo->info.xres, |
100 | mFramebufferInfo->info.yres, |
101 | mFramebufferInfo->xdpi, |
102 | mFramebufferInfo->ydpi); |
103 | // add it to the front of other configs |
104 | mDisplayConfigs.push_back(config); |
105 | |
106 | // init the active display config |
107 | mActiveDisplayConfigItem = 0; |
108 | mActiveRefreshRate = rate; |
109 | //ETRACE("Active display mode %s, refresh rate: %d", mActiveDisplaymode, rate); |
110 | } else { |
111 | //hdmi plug in when system is starting up |
112 | updateActiveDisplayMode(); |
113 | updateDisplayConfigures(); |
114 | updateActiveDisplayConfigure(); |
115 | |
116 | ALOGD("updateHotplug setDisplayMode to %s", mActiveDisplaymode); |
117 | std::string strmode(mActiveDisplaymode); |
118 | mSystemControlService->setActiveDispMode(strmode); |
119 | } |
120 | |
121 | std::thread t1(&DisplayHdmi::setSurfaceFlingerActiveMode, this); |
122 | t1.detach(); |
123 | |
124 | return true; |
125 | } |
126 | |
127 | int DisplayHdmi::updateDisplayModeList() { |
128 | // clear display modes |
129 | mSupportDispModes.clear(); |
130 | |
131 | bool fullActiveMode = Utils::get_bool_prop("ro.sf.full_activemode"); |
132 | bool isConfiged = readConfigFile("/system/etc/displayModeList.cfg", &mSupportDispModes); |
133 | if (isConfiged) { |
134 | return 0; |
135 | } |
136 | |
137 | if (!fullActiveMode) { |
138 | ALOGD("Simple Active Mode!!!"); |
139 | return -1; |
140 | } |
141 | |
142 | std::vector<std::string> getSupportDispModes; |
143 | std::string::size_type pos; |
144 | mSystemControlService->getSupportDispModeList(&getSupportDispModes); |
145 | if (getSupportDispModes.size() == 0) { |
146 | ALOGD("SupportDispModeList null!!!"); |
147 | return -1; |
148 | } |
149 | |
150 | for (size_t i = 0; i < getSupportDispModes.size(); i++) { |
151 | //ALOGD("get support display mode:%s", getSupportDispModes[i].c_str()); |
152 | while (!getSupportDispModes[i].empty()) { |
153 | pos = getSupportDispModes[i].find('*'); |
154 | if (pos != std::string::npos) { |
155 | getSupportDispModes[i].erase(pos, 1); |
156 | //ALOGD("modify support display mode:%s", getSupportDispModes[i].c_str()); |
157 | } else { |
158 | break; |
159 | } |
160 | } |
161 | } |
162 | |
163 | |
164 | for (size_t k = 0; k < mAllModes.size(); k++) { |
165 | for (size_t j = 0; j < getSupportDispModes.size(); j++) { |
166 | if (!getSupportDispModes[j].empty()) { |
167 | if (mAllModes[k] == getSupportDispModes[j]) { |
168 | mSupportDispModes.push_back(getSupportDispModes[j]); |
169 | ALOGD("support display mode:%s", getSupportDispModes[j].c_str()); |
170 | } |
171 | } |
172 | } |
173 | } |
174 | |
175 | return 0; |
176 | } |
177 | |
178 | int DisplayHdmi::updateActiveDisplayMode() { |
179 | std::string dispMode; |
180 | mSystemControlService->getActiveDispMode(&dispMode); |
181 | strcpy(mActiveDisplaymode, dispMode.c_str()); |
182 | |
183 | int refreshRate = 60; |
184 | if (strstr(mActiveDisplaymode, "60hz") != NULL) { |
185 | refreshRate = 60; |
186 | } else if (strstr(mActiveDisplaymode, "50hz") != NULL) { |
187 | refreshRate = 50; |
188 | } else if (strstr(mActiveDisplaymode, "30hz") != NULL) { |
189 | refreshRate = 30; |
190 | } else if (strstr(mActiveDisplaymode, "25hz") != NULL) { |
191 | refreshRate = 25; |
192 | } else if ((strstr(mActiveDisplaymode, "24hz") != NULL) |
193 | || (strstr(mActiveDisplaymode, "smpte") != NULL)) { |
194 | refreshRate = 24; |
195 | } else |
196 | ETRACE("displaymode (%s) doesn't specify HZ", mActiveDisplaymode); |
197 | |
198 | ALOGD("Active display mode: (%s), refresh rate: (%d)", mActiveDisplaymode, refreshRate); |
199 | |
200 | mActiveRefreshRate = refreshRate; |
201 | |
202 | return 0; |
203 | } |
204 | |
205 | int DisplayHdmi::setDisplayMode(const char* displaymode) { |
206 | ALOGD("setDisplayMode to %s", displaymode); |
207 | |
208 | std::string strmode(displaymode); |
209 | mSystemControlService->setActiveDispMode(strmode); |
210 | |
211 | updateActiveDisplayMode(); |
212 | |
213 | return 0; |
214 | } |
215 | |
216 | int DisplayHdmi::updateDisplayConfigures() { |
217 | size_t i; |
218 | |
219 | std::string dispMode; |
220 | int refreshRate, width, height; |
221 | |
222 | // reset display configs |
223 | for (i = 0; i < mDisplayConfigs.size(); i++) { |
224 | DisplayConfig *config = mDisplayConfigs[i]; |
225 | if (config) |
226 | delete config; |
227 | } |
228 | mDisplayConfigs.clear(); |
229 | |
230 | for (i =0; i < mSupportDispModes.size(); i ++) { |
231 | dispMode = mSupportDispModes[i]; |
232 | calcMode2Config(dispMode.c_str(), &refreshRate, &width, &height); |
233 | |
234 | // init dimension as config width/height, set xdpi/ydpi after |
235 | DisplayConfig *config = new DisplayConfig(dispMode.c_str(), |
236 | refreshRate, width, height, |
237 | mFramebufferInfo->xdpi, |
238 | mFramebufferInfo->ydpi); |
239 | // add it to the front of other configs |
240 | mDisplayConfigs.push_back(config); |
241 | } |
242 | return 0; |
243 | } |
244 | |
245 | int DisplayHdmi::updateActiveDisplayConfigure() { |
246 | size_t i; |
247 | |
248 | DisplayConfig *dispConfig = NULL; |
249 | for (i = 0; i < mDisplayConfigs.size(); i++) { |
250 | dispConfig = mDisplayConfigs[i]; |
251 | if (!dispConfig) { |
252 | continue; |
253 | } |
254 | if (0 == strncmp(mActiveDisplaymode, dispConfig->getDisplayMode(), |
255 | HWC_DISPLAY_MODE_LENGTH-1)) { |
256 | mActiveDisplayConfigItem = i; |
257 | ALOGD("updateActiveDisplayConfigure to config(%d)", mActiveDisplayConfigItem); |
258 | dispConfig->setDpi(mFramebufferInfo->xdpi, mFramebufferInfo->ydpi); |
259 | break; |
260 | } |
261 | } |
262 | return 0; |
263 | } |
264 | |
265 | int DisplayHdmi::getDisplayConfigs(uint32_t* outNumConfigs, |
266 | hwc2_config_t* outConfigs) { |
267 | size_t i; |
268 | |
269 | if (!isConnected()) { |
270 | //ETRACE("display %d is not connected.", (int32_t)mDisplayId); |
271 | } |
272 | |
273 | for (i = 0; i < mDisplayConfigs.size(); i++) { |
274 | if (NULL != outConfigs) |
275 | outConfigs[i] = i; |
276 | } |
277 | |
278 | *outNumConfigs = i; |
279 | |
280 | return HWC2_ERROR_NONE; |
281 | } |
282 | |
283 | int DisplayHdmi::getDisplayAttribute(hwc2_config_t config, |
284 | int32_t /*hwc2_attribute_t*/ attribute, |
285 | int32_t* outValue) { |
286 | |
287 | if (!isConnected()) { |
288 | //ETRACE("display %d is not connected.", (int32_t)mDisplayId); |
289 | } |
290 | |
291 | DisplayConfig *configChosen = mDisplayConfigs[config]; |
292 | if (!configChosen) { |
293 | ETRACE("failed to get display config: %d", config); |
294 | return HWC2_ERROR_NONE; |
295 | } |
296 | |
297 | switch (attribute) { |
298 | case HWC2_ATTRIBUTE_VSYNC_PERIOD: |
299 | if (configChosen->getRefreshRate()) { |
300 | *outValue = 1e9 / configChosen->getRefreshRate(); |
301 | } |
302 | break; |
303 | case HWC2_ATTRIBUTE_WIDTH: |
304 | *outValue = configChosen->getWidth(); |
305 | break; |
306 | case HWC2_ATTRIBUTE_HEIGHT: |
307 | *outValue = configChosen->getHeight(); |
308 | break; |
309 | case HWC2_ATTRIBUTE_DPI_X: |
310 | *outValue = configChosen->getDpiX() * 1000.0f; |
311 | break; |
312 | case HWC2_ATTRIBUTE_DPI_Y: |
313 | *outValue = configChosen->getDpiY() * 1000.0f; |
314 | break; |
315 | default: |
316 | ETRACE("unknown display attribute %u", attribute); |
317 | *outValue = -1; |
318 | break; |
319 | } |
320 | |
321 | return HWC2_ERROR_NONE; |
322 | } |
323 | |
324 | int DisplayHdmi::getActiveConfig(hwc2_config_t* outConfig) { |
325 | if (!isConnected()) { |
326 | //ETRACE("display %d is not connected.", (int32_t)mDisplayId); |
327 | } |
328 | //ALOGD("getActiveConfig to config(%d).", mActiveDisplayConfigItem); |
329 | *outConfig = mActiveDisplayConfigItem; |
330 | |
331 | return HWC2_ERROR_NONE; |
332 | } |
333 | |
334 | int DisplayHdmi::setActiveConfig(int id) { |
335 | DisplayConfig *dispConfig = NULL; |
336 | char *dispMode = NULL; |
337 | |
338 | if (!isConnected()) { |
339 | //ETRACE("display %d is not connected.", (int32_t)mDisplayId); |
340 | } |
341 | |
342 | ALOGD("setActiveConfig to config(%d).", id); |
343 | mActiveDisplayConfigItem = id; |
344 | dispConfig = mDisplayConfigs[id]; |
345 | if (!dispConfig) { |
346 | ETRACE("failed to get display config: %d", id); |
347 | return HWC2_ERROR_BAD_CONFIG; |
348 | } |
349 | |
350 | dispConfig->setDpi(mFramebufferInfo->xdpi, |
351 | mFramebufferInfo->ydpi); |
352 | |
353 | dispMode = dispConfig->getDisplayMode(); |
354 | if (!dispMode) { |
355 | ETRACE("failed to get display mode by config: %d", id); |
356 | return HWC2_ERROR_BAD_CONFIG; |
357 | } |
358 | |
359 | setDisplayMode(dispMode); |
360 | |
361 | return HWC2_ERROR_NONE; |
362 | } |
363 | |
364 | bool DisplayHdmi::calcMode2Config(const char *dispMode, int* refreshRate, |
365 | int* width, int* height) { |
366 | |
367 | if (NULL == dispMode) { |
368 | ETRACE("dispMode is NULL"); |
369 | return false; |
370 | } |
371 | |
372 | if (strstr(dispMode, "60hz") != NULL) { |
373 | *refreshRate = 60; |
374 | } else if (strstr(dispMode, "50hz") != NULL) { |
375 | *refreshRate = 50; |
376 | } else if (strstr(dispMode, "30hz") != NULL) { |
377 | *refreshRate = 30; |
378 | } else if (strstr(dispMode, "25hz") != NULL) { |
379 | *refreshRate = 25; |
380 | } else if ((strstr(dispMode, "24hz") != NULL) |
381 | || (strstr(dispMode, "smpte") != NULL)) { |
382 | *refreshRate = 24; |
383 | } else { |
384 | ETRACE("displaymode (%s) doesn't specify HZ", dispMode); |
385 | return false; |
386 | } |
387 | |
388 | if (strstr(dispMode, "2160") != NULL) { |
389 | *width = 3840; |
390 | *height = 2160; |
391 | } else if (strstr(dispMode, "1080") != NULL) { |
392 | *width = 1920; |
393 | *height = 1080; |
394 | } else if (strstr(dispMode, "720") != NULL) { |
395 | *width = 1280; |
396 | *height = 720; |
397 | } else if (strstr(dispMode, "576") != NULL) { |
398 | *width = 720; |
399 | *height = 576; |
400 | } else if (strstr(dispMode, "480") != NULL) { |
401 | *width = 640; |
402 | *height = 480; |
403 | } else { |
404 | // smpte and panle imcomplete!!!!! |
405 | ETRACE("calcMode2Config displaymode (%s) doesn't specify HZ", dispMode); |
406 | return false; |
407 | } |
408 | |
409 | //DTRACE("calcMode2Config (%s) refreshRate(%d), (%dx%d)", dispMode, *refreshRate, *width, *height); |
410 | return true; |
411 | } |
412 | |
413 | bool DisplayHdmi::readConfigFile(const char* configPath, std::vector<std::string>* supportDispModes) { |
414 | const char* WHITESPACE = " \t\r"; |
415 | |
416 | Tokenizer* tokenizer; |
417 | status_t status = Tokenizer::open(String8(configPath), &tokenizer); |
418 | |
419 | if (status) { |
420 | DTRACE("Error %d opening display config file %s.", status, configPath); |
421 | return false; |
422 | } else { |
423 | while (!tokenizer->isEof()) { |
424 | tokenizer->skipDelimiters(WHITESPACE); |
425 | if (!tokenizer->isEol() && tokenizer->peekChar() != '#') { |
426 | String8 token = tokenizer->nextToken(WHITESPACE); |
427 | const char* dispMode = token.string(); |
428 | if (strstr(dispMode, "hz")) { |
429 | ETRACE("dispMode %s.", dispMode); |
430 | (*supportDispModes).push_back(std::string(dispMode)); |
431 | } |
432 | } |
433 | |
434 | tokenizer->nextLine(); |
435 | } |
436 | delete tokenizer; |
437 | } |
438 | |
439 | size_t num = (*supportDispModes).size(); |
440 | |
441 | if (num <= 0) { |
442 | return false; |
443 | } else { |
444 | return true; |
445 | } |
446 | } |
447 | |
448 | void DisplayHdmi::setSurfaceFlingerActiveMode() { |
449 | sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay( |
450 | ISurfaceComposer::eDisplayIdMain)); |
451 | |
452 | SurfaceComposerClient::setActiveConfig(dtoken, mDisplayConfigs.size()-mActiveDisplayConfigItem-1); |
453 | |
454 | return; |
455 | } |
456 | |
457 | void DisplayHdmi::initModes() { |
458 | //mAllModes.push_back("480p60hz"); |
459 | //mAllModes.push_back("576p50hz"); |
460 | //mAllModes.push_back("720p50hz"); |
461 | //mAllModes.push_back("720p60hz"); |
462 | mAllModes.push_back("1080p60hz"); |
463 | mAllModes.push_back("1080p50hz"); |
464 | mAllModes.push_back("1080p30hz"); |
465 | mAllModes.push_back("1080p25hz"); |
466 | mAllModes.push_back("1080p24hz"); |
467 | //mAllModes.push_back("2160p24hz"); |
468 | //mAllModes.push_back("2160p25hz"); |
469 | //mAllModes.push_back("2160p30hz"); |
470 | //mAllModes.push_back("2160p50hz"); |
471 | //mAllModes.push_back("2160p60hz"); |
472 | } |
473 | |
474 | void DisplayHdmi::dump(Dump& d) { |
475 | d.append(" CONFIG | VSYNC_PERIOD | WIDTH | HEIGHT |" |
476 | " DPI_X | DPI_Y \n"); |
477 | d.append("------------+------------------+-----------+------------+" |
478 | "-----------+-----------\n"); |
479 | for (size_t i = 0; i < mDisplayConfigs.size(); i++) { |
480 | DisplayConfig *config = mDisplayConfigs[i]; |
481 | if (config) { |
482 | d.append("%s %2d | %4d | %5d | %4d |" |
483 | " %3d | %3d \n", |
484 | (i == (size_t)mActiveDisplayConfigItem) ? "* " : " ", |
485 | i, |
486 | config->getRefreshRate(), |
487 | config->getWidth(), |
488 | config->getHeight(), |
489 | config->getDpiX(), |
490 | config->getDpiY()); |
491 | } |
492 | } |
493 | } |
494 | |
495 | } // namespace amlogic |
496 | } // namespace android |
497 | |
498 | |
499 | |
500 |