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