1 /*
2 * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
3 * Not a Contribution.
4 *
5 * Copyright 2015 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 #include <core/buffer_allocator.h>
21 #include <private/color_params.h>
22 #include <utils/constants.h>
23 #include <utils/String16.h>
24 #include <cutils/properties.h>
25 #include <hardware_legacy/uevent.h>
26 #include <sys/resource.h>
27 #include <sys/prctl.h>
28 #include <binder/Parcel.h>
29 #include <QService.h>
30 #include <display_config.h>
31 #include <utils/debug.h>
32 #include <sync/sync.h>
33 #include <profiler.h>
34 #include <algorithm>
35 #include <string>
36 #include <bitset>
37 #include <thread>
38 #include <memory>
39
40 #include "hwc_buffer_allocator.h"
41 #include "hwc_buffer_sync_handler.h"
42 #include "hwc_session.h"
43 #include "hwc_debugger.h"
44 #include "hwc_display_primary.h"
45 #include "hwc_display_virtual.h"
46 #include "hwc_display_external_test.h"
47 #include "qd_utils.h"
48
49 #define __CLASS__ "HWCSession"
50
51 #define HWC_UEVENT_SWITCH_HDMI "change@/devices/virtual/switch/hdmi"
52 #define HWC_UEVENT_GRAPHICS_FB0 "change@/devices/virtual/graphics/fb0"
53
54 static sdm::HWCSession::HWCModuleMethods g_hwc_module_methods;
55
56 hwc_module_t HAL_MODULE_INFO_SYM = {
57 .common = {
58 .tag = HARDWARE_MODULE_TAG,
59 .version_major = 3,
60 .version_minor = 0,
61 .id = HWC_HARDWARE_MODULE_ID,
62 .name = "QTI Hardware Composer Module",
63 .author = "CodeAurora Forum",
64 .methods = &g_hwc_module_methods,
65 .dso = 0,
66 .reserved = {0},
67 }
68 };
69
70 namespace sdm {
71
72 static HWCUEvent g_hwc_uevent_;
73 Locker HWCSession::locker_[HWC_NUM_DISPLAY_TYPES];
74 bool HWCSession::disable_skip_validate_ = false;
75
UEventThread(HWCUEvent * hwc_uevent)76 void HWCUEvent::UEventThread(HWCUEvent *hwc_uevent) {
77 const char *uevent_thread_name = "HWC_UeventThread";
78
79 prctl(PR_SET_NAME, uevent_thread_name, 0, 0, 0);
80 setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
81
82 int status = uevent_init();
83 if (!status) {
84 std::unique_lock<std::mutex> caller_lock(hwc_uevent->mutex_);
85 hwc_uevent->caller_cv_.notify_one();
86 DLOGE("Failed to init uevent with err %d", status);
87 return;
88 }
89
90 {
91 // Signal caller thread that worker thread is ready to listen to events.
92 std::unique_lock<std::mutex> caller_lock(hwc_uevent->mutex_);
93 hwc_uevent->init_done_ = true;
94 hwc_uevent->caller_cv_.notify_one();
95 }
96
97 while (1) {
98 char uevent_data[PAGE_SIZE] = {};
99
100 // keep last 2 zeroes to ensure double 0 termination
101 int length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2);
102
103 // scope of lock to this block only, so that caller is free to set event handler to nullptr;
104 {
105 std::lock_guard<std::mutex> guard(hwc_uevent->mutex_);
106 if (hwc_uevent->uevent_listener_) {
107 hwc_uevent->uevent_listener_->UEventHandler(uevent_data, length);
108 } else {
109 DLOGW("UEvent dropped. No uevent listener.");
110 }
111 }
112 }
113 }
114
HWCUEvent()115 HWCUEvent::HWCUEvent() {
116 std::unique_lock<std::mutex> caller_lock(mutex_);
117 std::thread thread(HWCUEvent::UEventThread, this);
118 thread.detach();
119 caller_cv_.wait(caller_lock);
120 }
121
Register(HWCUEventListener * uevent_listener)122 void HWCUEvent::Register(HWCUEventListener *uevent_listener) {
123 DLOGI("Set uevent listener = %p", uevent_listener);
124
125 std::lock_guard<std::mutex> obj(mutex_);
126 uevent_listener_ = uevent_listener;
127 }
128
HWCSession(const hw_module_t * module)129 HWCSession::HWCSession(const hw_module_t *module) {
130 hwc2_device_t::common.tag = HARDWARE_DEVICE_TAG;
131 hwc2_device_t::common.version = HWC_DEVICE_API_VERSION_2_0;
132 hwc2_device_t::common.module = const_cast<hw_module_t *>(module);
133 hwc2_device_t::common.close = Close;
134 hwc2_device_t::getCapabilities = GetCapabilities;
135 hwc2_device_t::getFunction = GetFunction;
136 }
137
Init()138 int HWCSession::Init() {
139 SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
140
141 int status = -EINVAL;
142 const char *qservice_name = "display.qservice";
143
144 if (!g_hwc_uevent_.InitDone()) {
145 return status;
146 }
147
148 // Start QService and connect to it.
149 qService::QService::init();
150 android::sp<qService::IQService> iqservice = android::interface_cast<qService::IQService>(
151 android::defaultServiceManager()->getService(android::String16(qservice_name)));
152
153 if (iqservice.get()) {
154 iqservice->connect(android::sp<qClient::IQClient>(this));
155 qservice_ = reinterpret_cast<qService::QService *>(iqservice.get());
156 } else {
157 ALOGE("%s::%s: Failed to acquire %s", __CLASS__, __FUNCTION__, qservice_name);
158 return -EINVAL;
159 }
160
161 StartServices();
162
163 DisplayError error = buffer_allocator_.Init();
164 if (error != kErrorNone) {
165 ALOGE("%s::%s: Buffer allocaor initialization failed. Error = %d",
166 __CLASS__, __FUNCTION__, error);
167 return -EINVAL;
168 }
169
170 error = CoreInterface::CreateCore(HWCDebugHandler::Get(), &buffer_allocator_,
171 &buffer_sync_handler_, &socket_handler_, &core_intf_);
172 if (error != kErrorNone) {
173 buffer_allocator_.Deinit();
174 ALOGE("%s::%s: Display core initialization failed. Error = %d", __CLASS__, __FUNCTION__, error);
175 return -EINVAL;
176 }
177
178 g_hwc_uevent_.Register(this);
179
180 // If HDMI display is primary display, defer display creation until hotplug event is received.
181 HWDisplayInterfaceInfo hw_disp_info = {};
182 error = core_intf_->GetFirstDisplayInterfaceType(&hw_disp_info);
183 if (error != kErrorNone) {
184 g_hwc_uevent_.Register(nullptr);
185 CoreInterface::DestroyCore();
186 buffer_allocator_.Deinit();
187 DLOGE("Primary display type not recognized. Error = %d", error);
188 return -EINVAL;
189 }
190
191 if (hw_disp_info.type == kHDMI) {
192 status = 0;
193 hdmi_is_primary_ = true;
194 // Create display if it is connected, else wait for hotplug connect event.
195 if (hw_disp_info.is_connected) {
196 status = CreateExternalDisplay(HWC_DISPLAY_PRIMARY);
197 }
198 } else {
199 // Create and power on primary display
200 status = HWCDisplayPrimary::Create(core_intf_, &buffer_allocator_, &callbacks_, qservice_,
201 &hwc_display_[HWC_DISPLAY_PRIMARY]);
202 color_mgr_ = HWCColorManager::CreateColorManager(&buffer_allocator_);
203 if (!color_mgr_) {
204 DLOGW("Failed to load HWCColorManager.");
205 }
206 }
207
208 if (status) {
209 g_hwc_uevent_.Register(nullptr);
210 CoreInterface::DestroyCore();
211 buffer_allocator_.Deinit();
212 return status;
213 }
214
215 return 0;
216 }
217
Deinit()218 int HWCSession::Deinit() {
219 Locker::SequenceCancelScopeLock lock_v(locker_[HWC_DISPLAY_VIRTUAL]);
220 Locker::SequenceCancelScopeLock lock_e(locker_[HWC_DISPLAY_EXTERNAL]);
221 Locker::SequenceCancelScopeLock lock_p(locker_[HWC_DISPLAY_PRIMARY]);
222
223 HWCDisplay *primary_display = hwc_display_[HWC_DISPLAY_PRIMARY];
224 if (primary_display) {
225 if (hdmi_is_primary_) {
226 HWCDisplayExternal::Destroy(primary_display);
227 } else {
228 HWCDisplayPrimary::Destroy(primary_display);
229 }
230 }
231 hwc_display_[HWC_DISPLAY_PRIMARY] = nullptr;
232
233 if (color_mgr_) {
234 color_mgr_->DestroyColorManager();
235 }
236
237 g_hwc_uevent_.Register(nullptr);
238
239 DisplayError error = CoreInterface::DestroyCore();
240 if (error != kErrorNone) {
241 ALOGE("Display core de-initialization failed. Error = %d", error);
242 }
243
244 return 0;
245 }
246
Open(const hw_module_t * module,const char * name,hw_device_t ** device)247 int HWCSession::Open(const hw_module_t *module, const char *name, hw_device_t **device) {
248 if (!module || !name || !device) {
249 ALOGE("%s::%s: Invalid parameters.", __CLASS__, __FUNCTION__);
250 return -EINVAL;
251 }
252
253 if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
254 HWCSession *hwc_session = new HWCSession(module);
255 if (!hwc_session) {
256 return -ENOMEM;
257 }
258
259 int status = hwc_session->Init();
260 if (status != 0) {
261 return status;
262 }
263
264 hwc2_device_t *composer_device = hwc_session;
265 *device = reinterpret_cast<hw_device_t *>(composer_device);
266 }
267
268 return 0;
269 }
270
Close(hw_device_t * device)271 int HWCSession::Close(hw_device_t *device) {
272 if (!device) {
273 return -EINVAL;
274 }
275
276 hwc2_device_t *composer_device = reinterpret_cast<hwc2_device_t *>(device);
277 HWCSession *hwc_session = static_cast<HWCSession *>(composer_device);
278
279 hwc_session->Deinit();
280
281 return 0;
282 }
283
GetCapabilities(struct hwc2_device * device,uint32_t * outCount,int32_t * outCapabilities)284 void HWCSession::GetCapabilities(struct hwc2_device *device, uint32_t *outCount,
285 int32_t *outCapabilities) {
286 if (!outCount) {
287 return;
288 }
289
290 int value = 0;
291 uint32_t count = 0;
292 HWCSession *hwc_session = static_cast<HWCSession *>(device);
293 bool color_transform_supported = hwc_session->core_intf_->IsColorTransformSupported();
294
295 if (Debug::Get()->GetProperty(DISABLE_SKIP_VALIDATE_PROP, &value) == kErrorNone) {
296 disable_skip_validate_ = (value == 1);
297 }
298
299 count += (color_transform_supported) ? 1 : 0;
300 count += (!disable_skip_validate_) ? 1 : 0;
301
302 if (outCapabilities != nullptr && (*outCount >= count)) {
303 int i = 0;
304 if (color_transform_supported) {
305 outCapabilities[i++] = HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
306 }
307 if (!disable_skip_validate_) {
308 outCapabilities[i++] = HWC2_CAPABILITY_SKIP_VALIDATE;
309 }
310 }
311 *outCount = count;
312 }
313
314 template <typename PFN, typename T>
AsFP(T function)315 static hwc2_function_pointer_t AsFP(T function) {
316 static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer");
317 return reinterpret_cast<hwc2_function_pointer_t>(function);
318 }
319
320 // HWC2 functions returned in GetFunction
321 // Defined in the same order as in the HWC2 header
322
AcceptDisplayChanges(hwc2_device_t * device,hwc2_display_t display)323 int32_t HWCSession::AcceptDisplayChanges(hwc2_device_t *device, hwc2_display_t display) {
324 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::AcceptDisplayChanges);
325 }
326
CreateLayer(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t * out_layer_id)327 int32_t HWCSession::CreateLayer(hwc2_device_t *device, hwc2_display_t display,
328 hwc2_layer_t *out_layer_id) {
329 if (!out_layer_id) {
330 return HWC2_ERROR_BAD_PARAMETER;
331 }
332
333 return CallDisplayFunction(device, display, &HWCDisplay::CreateLayer, out_layer_id);
334 }
335
CreateVirtualDisplay(hwc2_device_t * device,uint32_t width,uint32_t height,int32_t * format,hwc2_display_t * out_display_id)336 int32_t HWCSession::CreateVirtualDisplay(hwc2_device_t *device, uint32_t width, uint32_t height,
337 int32_t *format, hwc2_display_t *out_display_id) {
338 // TODO(user): Handle concurrency with HDMI
339 SCOPE_LOCK(locker_[HWC_DISPLAY_VIRTUAL]);
340 if (!device) {
341 return HWC2_ERROR_BAD_DISPLAY;
342 }
343
344 if (!out_display_id || !width || !height || !format) {
345 return HWC2_ERROR_BAD_PARAMETER;
346 }
347
348 HWCSession *hwc_session = static_cast<HWCSession *>(device);
349 auto status = hwc_session->CreateVirtualDisplayObject(width, height, format);
350 if (status == HWC2::Error::None) {
351 *out_display_id = HWC_DISPLAY_VIRTUAL;
352 DLOGI("Created virtual display id:% " PRIu64 " with res: %dx%d",
353 *out_display_id, width, height);
354 } else {
355 DLOGE("Failed to create virtual display: %s", to_string(status).c_str());
356 }
357 return INT32(status);
358 }
359
DestroyLayer(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer)360 int32_t HWCSession::DestroyLayer(hwc2_device_t *device, hwc2_display_t display,
361 hwc2_layer_t layer) {
362 return CallDisplayFunction(device, display, &HWCDisplay::DestroyLayer, layer);
363 }
364
DestroyVirtualDisplay(hwc2_device_t * device,hwc2_display_t display)365 int32_t HWCSession::DestroyVirtualDisplay(hwc2_device_t *device, hwc2_display_t display) {
366 if (!device || display != HWC_DISPLAY_VIRTUAL) {
367 return HWC2_ERROR_BAD_DISPLAY;
368 }
369
370 SCOPE_LOCK(locker_[display]);
371 DLOGI("Destroying virtual display id:%" PRIu64, display);
372 auto *hwc_session = static_cast<HWCSession *>(device);
373
374 if (hwc_session->hwc_display_[display]) {
375 HWCDisplayVirtual::Destroy(hwc_session->hwc_display_[display]);
376 hwc_session->hwc_display_[display] = nullptr;
377 return HWC2_ERROR_NONE;
378 } else {
379 return HWC2_ERROR_BAD_DISPLAY;
380 }
381 }
382
Dump(hwc2_device_t * device,uint32_t * out_size,char * out_buffer)383 void HWCSession::Dump(hwc2_device_t *device, uint32_t *out_size, char *out_buffer) {
384 if (!device || !out_size) {
385 return;
386 }
387
388 auto *hwc_session = static_cast<HWCSession *>(device);
389 const size_t max_dump_size = 8192;
390
391 if (out_buffer == nullptr) {
392 *out_size = max_dump_size;
393 } else {
394 std::string s {};
395 for (int id = HWC_DISPLAY_PRIMARY; id <= HWC_DISPLAY_VIRTUAL; id++) {
396 SCOPE_LOCK(locker_[id]);
397 if (hwc_session->hwc_display_[id]) {
398 s += hwc_session->hwc_display_[id]->Dump();
399 }
400 }
401 auto copied = s.copy(out_buffer, std::min(s.size(), max_dump_size), 0);
402 *out_size = UINT32(copied);
403 }
404 }
405
GetActiveConfig(hwc2_device_t * device,hwc2_display_t display,hwc2_config_t * out_config)406 static int32_t GetActiveConfig(hwc2_device_t *device, hwc2_display_t display,
407 hwc2_config_t *out_config) {
408 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetActiveConfig, out_config);
409 }
410
GetChangedCompositionTypes(hwc2_device_t * device,hwc2_display_t display,uint32_t * out_num_elements,hwc2_layer_t * out_layers,int32_t * out_types)411 static int32_t GetChangedCompositionTypes(hwc2_device_t *device, hwc2_display_t display,
412 uint32_t *out_num_elements, hwc2_layer_t *out_layers,
413 int32_t *out_types) {
414 // null_ptr check only for out_num_elements, as out_layers and out_types can be null.
415 if (!out_num_elements) {
416 return HWC2_ERROR_BAD_PARAMETER;
417 }
418 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetChangedCompositionTypes,
419 out_num_elements, out_layers, out_types);
420 }
421
GetClientTargetSupport(hwc2_device_t * device,hwc2_display_t display,uint32_t width,uint32_t height,int32_t format,int32_t dataspace)422 static int32_t GetClientTargetSupport(hwc2_device_t *device, hwc2_display_t display, uint32_t width,
423 uint32_t height, int32_t format, int32_t dataspace) {
424 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetClientTargetSupport,
425 width, height, format, dataspace);
426 }
427
GetColorModes(hwc2_device_t * device,hwc2_display_t display,uint32_t * out_num_modes,int32_t * int_out_modes)428 static int32_t GetColorModes(hwc2_device_t *device, hwc2_display_t display, uint32_t *out_num_modes,
429 int32_t /*android_color_mode_t*/ *int_out_modes) {
430 auto out_modes = reinterpret_cast<android_color_mode_t *>(int_out_modes);
431 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetColorModes, out_num_modes,
432 out_modes);
433 }
434
GetDisplayAttribute(hwc2_device_t * device,hwc2_display_t display,hwc2_config_t config,int32_t int_attribute,int32_t * out_value)435 static int32_t GetDisplayAttribute(hwc2_device_t *device, hwc2_display_t display,
436 hwc2_config_t config, int32_t int_attribute,
437 int32_t *out_value) {
438 auto attribute = static_cast<HWC2::Attribute>(int_attribute);
439 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayAttribute, config,
440 attribute, out_value);
441 }
442
GetDisplayConfigs(hwc2_device_t * device,hwc2_display_t display,uint32_t * out_num_configs,hwc2_config_t * out_configs)443 static int32_t GetDisplayConfigs(hwc2_device_t *device, hwc2_display_t display,
444 uint32_t *out_num_configs, hwc2_config_t *out_configs) {
445 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayConfigs,
446 out_num_configs, out_configs);
447 }
448
GetDisplayName(hwc2_device_t * device,hwc2_display_t display,uint32_t * out_size,char * out_name)449 static int32_t GetDisplayName(hwc2_device_t *device, hwc2_display_t display, uint32_t *out_size,
450 char *out_name) {
451 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayName, out_size,
452 out_name);
453 }
454
GetDisplayRequests(hwc2_device_t * device,hwc2_display_t display,int32_t * out_display_requests,uint32_t * out_num_elements,hwc2_layer_t * out_layers,int32_t * out_layer_requests)455 static int32_t GetDisplayRequests(hwc2_device_t *device, hwc2_display_t display,
456 int32_t *out_display_requests, uint32_t *out_num_elements,
457 hwc2_layer_t *out_layers, int32_t *out_layer_requests) {
458 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayRequests,
459 out_display_requests, out_num_elements, out_layers,
460 out_layer_requests);
461 }
462
GetDisplayType(hwc2_device_t * device,hwc2_display_t display,int32_t * out_type)463 static int32_t GetDisplayType(hwc2_device_t *device, hwc2_display_t display, int32_t *out_type) {
464 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayType, out_type);
465 }
466
GetDozeSupport(hwc2_device_t * device,hwc2_display_t display,int32_t * out_support)467 static int32_t GetDozeSupport(hwc2_device_t *device, hwc2_display_t display, int32_t *out_support) {
468 if (display == HWC_DISPLAY_PRIMARY) {
469 *out_support = 1;
470 } else {
471 // TODO(user): Port over connect_display_ from HWC1
472 // Return no error for connected displays
473 *out_support = 0;
474 return HWC2_ERROR_BAD_DISPLAY;
475 }
476 return HWC2_ERROR_NONE;
477 }
478
GetHdrCapabilities(hwc2_device_t * device,hwc2_display_t display,uint32_t * out_num_types,int32_t * out_types,float * out_max_luminance,float * out_max_average_luminance,float * out_min_luminance)479 static int32_t GetHdrCapabilities(hwc2_device_t* device, hwc2_display_t display,
480 uint32_t* out_num_types, int32_t* out_types,
481 float* out_max_luminance, float* out_max_average_luminance,
482 float* out_min_luminance) {
483 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetHdrCapabilities,
484 out_num_types, out_types, out_max_luminance,
485 out_max_average_luminance, out_min_luminance);
486 }
487
GetMaxVirtualDisplayCount(hwc2_device_t * device)488 static uint32_t GetMaxVirtualDisplayCount(hwc2_device_t *device) {
489 char property[PROPERTY_VALUE_MAX];
490 property_get(WRITEBACK_SUPPORTED, property, "1");
491 return (uint32_t) atoi(property);
492 }
493
GetReleaseFences(hwc2_device_t * device,hwc2_display_t display,uint32_t * out_num_elements,hwc2_layer_t * out_layers,int32_t * out_fences)494 static int32_t GetReleaseFences(hwc2_device_t *device, hwc2_display_t display,
495 uint32_t *out_num_elements, hwc2_layer_t *out_layers,
496 int32_t *out_fences) {
497 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetReleaseFences,
498 out_num_elements, out_layers, out_fences);
499 }
500
PresentDisplay(hwc2_device_t * device,hwc2_display_t display,int32_t * out_retire_fence)501 int32_t HWCSession::PresentDisplay(hwc2_device_t *device, hwc2_display_t display,
502 int32_t *out_retire_fence) {
503 HWCSession *hwc_session = static_cast<HWCSession *>(device);
504 bool notify_hotplug = false;
505 auto status = HWC2::Error::BadDisplay;
506 DTRACE_SCOPED();
507
508 if (display >= HWC_NUM_DISPLAY_TYPES) {
509 return HWC2_ERROR_BAD_DISPLAY;
510 }
511
512 {
513 SEQUENCE_EXIT_SCOPE_LOCK(locker_[display]);
514 if (!device) {
515 return HWC2_ERROR_BAD_DISPLAY;
516 }
517
518 // TODO(user): Handle virtual display/HDMI concurrency
519 if (hwc_session->hwc_display_[display]) {
520 status = hwc_session->hwc_display_[display]->Present(out_retire_fence);
521 // This is only indicative of how many times SurfaceFlinger posts
522 // frames to the display.
523 CALC_FPS();
524 }
525 }
526
527 if (status != HWC2::Error::None && status != HWC2::Error::NotValidated) {
528 SEQUENCE_CANCEL_SCOPE_LOCK(locker_[display]);
529 }
530
531 // Handle Pending external display connection
532 if (hwc_session->external_pending_connect_ && (display == HWC_DISPLAY_PRIMARY)) {
533 Locker::ScopeLock lock_e(locker_[HWC_DISPLAY_EXTERNAL]);
534 Locker::ScopeLock lock_v(locker_[HWC_DISPLAY_VIRTUAL]);
535
536 if (!hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]) {
537 DLOGD("Process pending external display connection");
538 hwc_session->ConnectDisplay(HWC_DISPLAY_EXTERNAL);
539 hwc_session->external_pending_connect_ = false;
540 notify_hotplug = true;
541 }
542 }
543
544 if (notify_hotplug) {
545 hwc_session->HotPlug(HWC_DISPLAY_EXTERNAL, HWC2::Connection::Connected);
546 }
547
548 return INT32(status);
549 }
550
RegisterCallback(hwc2_device_t * device,int32_t descriptor,hwc2_callback_data_t callback_data,hwc2_function_pointer_t pointer)551 int32_t HWCSession::RegisterCallback(hwc2_device_t *device, int32_t descriptor,
552 hwc2_callback_data_t callback_data,
553 hwc2_function_pointer_t pointer) {
554 if (!device) {
555 return HWC2_ERROR_BAD_PARAMETER;
556 }
557 HWCSession *hwc_session = static_cast<HWCSession *>(device);
558 auto error = HWC2::Error::BadDisplay;
559 {
560 SCOPE_LOCK(hwc_session->callbacks_lock_);
561 auto desc = static_cast<HWC2::Callback>(descriptor);
562 error = hwc_session->callbacks_.Register(desc, callback_data, pointer);
563 hwc_session->callbacks_lock_.Broadcast();
564 DLOGD("%s callback: %s", pointer ? "Registering" : "Deregistering", to_string(desc).c_str());
565 }
566 if (descriptor == HWC2_CALLBACK_HOTPLUG) {
567 if (hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY]) {
568 hwc_session->callbacks_.Hotplug(HWC_DISPLAY_PRIMARY, HWC2::Connection::Connected);
569 }
570 }
571 hwc_session->need_invalidate_ = false;
572 return INT32(error);
573 }
574
SetActiveConfig(hwc2_device_t * device,hwc2_display_t display,hwc2_config_t config)575 static int32_t SetActiveConfig(hwc2_device_t *device, hwc2_display_t display,
576 hwc2_config_t config) {
577 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetActiveConfig, config);
578 }
579
SetClientTarget(hwc2_device_t * device,hwc2_display_t display,buffer_handle_t target,int32_t acquire_fence,int32_t dataspace,hwc_region_t damage)580 static int32_t SetClientTarget(hwc2_device_t *device, hwc2_display_t display,
581 buffer_handle_t target, int32_t acquire_fence,
582 int32_t dataspace, hwc_region_t damage) {
583 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetClientTarget, target,
584 acquire_fence, dataspace, damage);
585 }
586
SetColorMode(hwc2_device_t * device,hwc2_display_t display,int32_t int_mode)587 int32_t HWCSession::SetColorMode(hwc2_device_t *device, hwc2_display_t display,
588 int32_t /*android_color_mode_t*/ int_mode) {
589 if (int_mode < HAL_COLOR_MODE_NATIVE || int_mode > HAL_COLOR_MODE_DISPLAY_P3) {
590 return HWC2_ERROR_BAD_PARAMETER;
591 }
592 auto mode = static_cast<android_color_mode_t>(int_mode);
593 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorMode, mode);
594 }
595
SetColorTransform(hwc2_device_t * device,hwc2_display_t display,const float * matrix,int32_t hint)596 int32_t HWCSession::SetColorTransform(hwc2_device_t *device, hwc2_display_t display,
597 const float *matrix,
598 int32_t /*android_color_transform_t*/ hint) {
599 if (!matrix || hint < HAL_COLOR_TRANSFORM_IDENTITY ||
600 hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA) {
601 return HWC2_ERROR_BAD_PARAMETER;
602 }
603 android_color_transform_t transform_hint = static_cast<android_color_transform_t>(hint);
604 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorTransform, matrix,
605 transform_hint);
606 }
607
SetCursorPosition(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,int32_t x,int32_t y)608 static int32_t SetCursorPosition(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
609 int32_t x, int32_t y) {
610 auto status = INT32(HWC2::Error::None);
611 status = HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetCursorPosition,
612 layer, x, y);
613 if (status == INT32(HWC2::Error::None)) {
614 // Update cursor position
615 HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetCursorPosition, x, y);
616 }
617 return status;
618 }
619
SetLayerBlendMode(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,int32_t int_mode)620 static int32_t SetLayerBlendMode(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
621 int32_t int_mode) {
622 if (int_mode < HWC2_BLEND_MODE_INVALID || int_mode > HWC2_BLEND_MODE_COVERAGE) {
623 return HWC2_ERROR_BAD_PARAMETER;
624 }
625 auto mode = static_cast<HWC2::BlendMode>(int_mode);
626 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerBlendMode, mode);
627 }
628
SetLayerBuffer(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,buffer_handle_t buffer,int32_t acquire_fence)629 static int32_t SetLayerBuffer(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
630 buffer_handle_t buffer, int32_t acquire_fence) {
631 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerBuffer, buffer,
632 acquire_fence);
633 }
634
SetLayerColor(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,hwc_color_t color)635 static int32_t SetLayerColor(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
636 hwc_color_t color) {
637 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerColor, color);
638 }
639
SetLayerCompositionType(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,int32_t int_type)640 static int32_t SetLayerCompositionType(hwc2_device_t *device, hwc2_display_t display,
641 hwc2_layer_t layer, int32_t int_type) {
642 auto type = static_cast<HWC2::Composition>(int_type);
643 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerCompositionType,
644 type);
645 }
646
SetLayerDataspace(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,int32_t dataspace)647 static int32_t SetLayerDataspace(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
648 int32_t dataspace) {
649 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerDataspace,
650 dataspace);
651 }
652
SetLayerDisplayFrame(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,hwc_rect_t frame)653 static int32_t SetLayerDisplayFrame(hwc2_device_t *device, hwc2_display_t display,
654 hwc2_layer_t layer, hwc_rect_t frame) {
655 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerDisplayFrame,
656 frame);
657 }
658
SetLayerPlaneAlpha(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,float alpha)659 static int32_t SetLayerPlaneAlpha(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
660 float alpha) {
661 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerPlaneAlpha,
662 alpha);
663 }
664
SetLayerSourceCrop(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,hwc_frect_t crop)665 static int32_t SetLayerSourceCrop(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
666 hwc_frect_t crop) {
667 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerSourceCrop, crop);
668 }
669
SetLayerSurfaceDamage(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,hwc_region_t damage)670 static int32_t SetLayerSurfaceDamage(hwc2_device_t *device, hwc2_display_t display,
671 hwc2_layer_t layer, hwc_region_t damage) {
672 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerSurfaceDamage,
673 damage);
674 }
675
SetLayerTransform(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,int32_t int_transform)676 static int32_t SetLayerTransform(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
677 int32_t int_transform) {
678 auto transform = static_cast<HWC2::Transform>(int_transform);
679 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerTransform,
680 transform);
681 }
682
SetLayerVisibleRegion(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,hwc_region_t visible)683 static int32_t SetLayerVisibleRegion(hwc2_device_t *device, hwc2_display_t display,
684 hwc2_layer_t layer, hwc_region_t visible) {
685 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerVisibleRegion,
686 visible);
687 }
688
SetLayerZOrder(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,uint32_t z)689 static int32_t SetLayerZOrder(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
690 uint32_t z) {
691 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetLayerZOrder, layer, z);
692 }
693
SetOutputBuffer(hwc2_device_t * device,hwc2_display_t display,buffer_handle_t buffer,int32_t releaseFence)694 int32_t HWCSession::SetOutputBuffer(hwc2_device_t *device, hwc2_display_t display,
695 buffer_handle_t buffer, int32_t releaseFence) {
696 if (!device) {
697 return HWC2_ERROR_BAD_DISPLAY;
698 }
699
700 if (display != HWC_DISPLAY_VIRTUAL) {
701 return HWC2_ERROR_UNSUPPORTED;
702 }
703
704 SCOPE_LOCK(locker_[display]);
705 auto *hwc_session = static_cast<HWCSession *>(device);
706 if (hwc_session->hwc_display_[display]) {
707 auto vds = reinterpret_cast<HWCDisplayVirtual *>(hwc_session->hwc_display_[display]);
708 auto status = vds->SetOutputBuffer(buffer, releaseFence);
709 return INT32(status);
710 } else {
711 return HWC2_ERROR_BAD_DISPLAY;
712 }
713 }
714
SetPowerMode(hwc2_device_t * device,hwc2_display_t display,int32_t int_mode)715 int32_t HWCSession::SetPowerMode(hwc2_device_t *device, hwc2_display_t display, int32_t int_mode) {
716 auto mode = static_cast<HWC2::PowerMode>(int_mode);
717 return CallDisplayFunction(device, display, &HWCDisplay::SetPowerMode, mode);
718 }
719
SetVsyncEnabled(hwc2_device_t * device,hwc2_display_t display,int32_t int_enabled)720 static int32_t SetVsyncEnabled(hwc2_device_t *device, hwc2_display_t display, int32_t int_enabled) {
721 auto enabled = static_cast<HWC2::Vsync>(int_enabled);
722 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetVsyncEnabled, enabled);
723 }
724
ValidateDisplay(hwc2_device_t * device,hwc2_display_t display,uint32_t * out_num_types,uint32_t * out_num_requests)725 int32_t HWCSession::ValidateDisplay(hwc2_device_t *device, hwc2_display_t display,
726 uint32_t *out_num_types, uint32_t *out_num_requests) {
727 DTRACE_SCOPED();
728 HWCSession *hwc_session = static_cast<HWCSession *>(device);
729 if (!device) {
730 return HWC2_ERROR_BAD_DISPLAY;
731 }
732
733 // TODO(user): Handle secure session, handle QDCM solid fill
734 // Handle external_pending_connect_ in CreateVirtualDisplay
735 auto status = HWC2::Error::BadDisplay;
736 {
737 SEQUENCE_ENTRY_SCOPE_LOCK(locker_[display]);
738 if (hwc_session->hwc_display_[display]) {
739 if (display == HWC_DISPLAY_PRIMARY) {
740 // TODO(user): This can be moved to HWCDisplayPrimary
741 if (hwc_session->reset_panel_) {
742 DLOGW("panel is in bad state, resetting the panel");
743 hwc_session->ResetPanel();
744 }
745
746 if (hwc_session->need_invalidate_) {
747 hwc_session->Refresh(display);
748 hwc_session->need_invalidate_ = false;
749 }
750
751 if (hwc_session->color_mgr_) {
752 hwc_session->color_mgr_->SetColorModeDetailEnhancer(hwc_session->hwc_display_[display]);
753 }
754 }
755
756 status = hwc_session->hwc_display_[display]->Validate(out_num_types, out_num_requests);
757 }
758 }
759
760 // Sequence locking currently begins on Validate, so cancel the sequence lock on failures
761 if (status != HWC2::Error::None && status != HWC2::Error::HasChanges) {
762 SEQUENCE_CANCEL_SCOPE_LOCK(locker_[display]);
763 }
764
765 return INT32(status);
766 }
767
GetFunction(struct hwc2_device * device,int32_t int_descriptor)768 hwc2_function_pointer_t HWCSession::GetFunction(struct hwc2_device *device,
769 int32_t int_descriptor) {
770 auto descriptor = static_cast<HWC2::FunctionDescriptor>(int_descriptor);
771
772 switch (descriptor) {
773 case HWC2::FunctionDescriptor::AcceptDisplayChanges:
774 return AsFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(HWCSession::AcceptDisplayChanges);
775 case HWC2::FunctionDescriptor::CreateLayer:
776 return AsFP<HWC2_PFN_CREATE_LAYER>(CreateLayer);
777 case HWC2::FunctionDescriptor::CreateVirtualDisplay:
778 return AsFP<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(HWCSession::CreateVirtualDisplay);
779 case HWC2::FunctionDescriptor::DestroyLayer:
780 return AsFP<HWC2_PFN_DESTROY_LAYER>(DestroyLayer);
781 case HWC2::FunctionDescriptor::DestroyVirtualDisplay:
782 return AsFP<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(HWCSession::DestroyVirtualDisplay);
783 case HWC2::FunctionDescriptor::Dump:
784 return AsFP<HWC2_PFN_DUMP>(HWCSession::Dump);
785 case HWC2::FunctionDescriptor::GetActiveConfig:
786 return AsFP<HWC2_PFN_GET_ACTIVE_CONFIG>(GetActiveConfig);
787 case HWC2::FunctionDescriptor::GetChangedCompositionTypes:
788 return AsFP<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(GetChangedCompositionTypes);
789 case HWC2::FunctionDescriptor::GetClientTargetSupport:
790 return AsFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(GetClientTargetSupport);
791 case HWC2::FunctionDescriptor::GetColorModes:
792 return AsFP<HWC2_PFN_GET_COLOR_MODES>(GetColorModes);
793 case HWC2::FunctionDescriptor::GetDisplayAttribute:
794 return AsFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(GetDisplayAttribute);
795 case HWC2::FunctionDescriptor::GetDisplayConfigs:
796 return AsFP<HWC2_PFN_GET_DISPLAY_CONFIGS>(GetDisplayConfigs);
797 case HWC2::FunctionDescriptor::GetDisplayName:
798 return AsFP<HWC2_PFN_GET_DISPLAY_NAME>(GetDisplayName);
799 case HWC2::FunctionDescriptor::GetDisplayRequests:
800 return AsFP<HWC2_PFN_GET_DISPLAY_REQUESTS>(GetDisplayRequests);
801 case HWC2::FunctionDescriptor::GetDisplayType:
802 return AsFP<HWC2_PFN_GET_DISPLAY_TYPE>(GetDisplayType);
803 case HWC2::FunctionDescriptor::GetHdrCapabilities:
804 return AsFP<HWC2_PFN_GET_HDR_CAPABILITIES>(GetHdrCapabilities);
805 case HWC2::FunctionDescriptor::GetDozeSupport:
806 return AsFP<HWC2_PFN_GET_DOZE_SUPPORT>(GetDozeSupport);
807 case HWC2::FunctionDescriptor::GetMaxVirtualDisplayCount:
808 return AsFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(GetMaxVirtualDisplayCount);
809 case HWC2::FunctionDescriptor::GetReleaseFences:
810 return AsFP<HWC2_PFN_GET_RELEASE_FENCES>(GetReleaseFences);
811 case HWC2::FunctionDescriptor::PresentDisplay:
812 return AsFP<HWC2_PFN_PRESENT_DISPLAY>(PresentDisplay);
813 case HWC2::FunctionDescriptor::RegisterCallback:
814 return AsFP<HWC2_PFN_REGISTER_CALLBACK>(RegisterCallback);
815 case HWC2::FunctionDescriptor::SetActiveConfig:
816 return AsFP<HWC2_PFN_SET_ACTIVE_CONFIG>(SetActiveConfig);
817 case HWC2::FunctionDescriptor::SetClientTarget:
818 return AsFP<HWC2_PFN_SET_CLIENT_TARGET>(SetClientTarget);
819 case HWC2::FunctionDescriptor::SetColorMode:
820 return AsFP<HWC2_PFN_SET_COLOR_MODE>(SetColorMode);
821 case HWC2::FunctionDescriptor::SetColorTransform:
822 return AsFP<HWC2_PFN_SET_COLOR_TRANSFORM>(SetColorTransform);
823 case HWC2::FunctionDescriptor::SetCursorPosition:
824 return AsFP<HWC2_PFN_SET_CURSOR_POSITION>(SetCursorPosition);
825 case HWC2::FunctionDescriptor::SetLayerBlendMode:
826 return AsFP<HWC2_PFN_SET_LAYER_BLEND_MODE>(SetLayerBlendMode);
827 case HWC2::FunctionDescriptor::SetLayerBuffer:
828 return AsFP<HWC2_PFN_SET_LAYER_BUFFER>(SetLayerBuffer);
829 case HWC2::FunctionDescriptor::SetLayerColor:
830 return AsFP<HWC2_PFN_SET_LAYER_COLOR>(SetLayerColor);
831 case HWC2::FunctionDescriptor::SetLayerCompositionType:
832 return AsFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(SetLayerCompositionType);
833 case HWC2::FunctionDescriptor::SetLayerDataspace:
834 return AsFP<HWC2_PFN_SET_LAYER_DATASPACE>(SetLayerDataspace);
835 case HWC2::FunctionDescriptor::SetLayerDisplayFrame:
836 return AsFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(SetLayerDisplayFrame);
837 case HWC2::FunctionDescriptor::SetLayerPlaneAlpha:
838 return AsFP<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(SetLayerPlaneAlpha);
839 // Sideband stream is not supported
840 // case HWC2::FunctionDescriptor::SetLayerSidebandStream:
841 case HWC2::FunctionDescriptor::SetLayerSourceCrop:
842 return AsFP<HWC2_PFN_SET_LAYER_SOURCE_CROP>(SetLayerSourceCrop);
843 case HWC2::FunctionDescriptor::SetLayerSurfaceDamage:
844 return AsFP<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(SetLayerSurfaceDamage);
845 case HWC2::FunctionDescriptor::SetLayerTransform:
846 return AsFP<HWC2_PFN_SET_LAYER_TRANSFORM>(SetLayerTransform);
847 case HWC2::FunctionDescriptor::SetLayerVisibleRegion:
848 return AsFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(SetLayerVisibleRegion);
849 case HWC2::FunctionDescriptor::SetLayerZOrder:
850 return AsFP<HWC2_PFN_SET_LAYER_Z_ORDER>(SetLayerZOrder);
851 case HWC2::FunctionDescriptor::SetOutputBuffer:
852 return AsFP<HWC2_PFN_SET_OUTPUT_BUFFER>(SetOutputBuffer);
853 case HWC2::FunctionDescriptor::SetPowerMode:
854 return AsFP<HWC2_PFN_SET_POWER_MODE>(SetPowerMode);
855 case HWC2::FunctionDescriptor::SetVsyncEnabled:
856 return AsFP<HWC2_PFN_SET_VSYNC_ENABLED>(SetVsyncEnabled);
857 case HWC2::FunctionDescriptor::ValidateDisplay:
858 return AsFP<HWC2_PFN_VALIDATE_DISPLAY>(HWCSession::ValidateDisplay);
859 default:
860 DLOGD("Unknown/Unimplemented function descriptor: %d (%s)", int_descriptor,
861 to_string(descriptor).c_str());
862 return nullptr;
863 }
864 return nullptr;
865 }
866
867 // TODO(user): handle locking
868
CreateVirtualDisplayObject(uint32_t width,uint32_t height,int32_t * format)869 HWC2::Error HWCSession::CreateVirtualDisplayObject(uint32_t width, uint32_t height,
870 int32_t *format) {
871 if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
872 return HWC2::Error::NoResources;
873 }
874 auto status = HWCDisplayVirtual::Create(core_intf_, &buffer_allocator_, &callbacks_, width,
875 height, format, &hwc_display_[HWC_DISPLAY_VIRTUAL]);
876 // TODO(user): validate width and height support
877 if (status)
878 return HWC2::Error::Unsupported;
879
880 return HWC2::Error::None;
881 }
882
ConnectDisplay(int disp)883 int32_t HWCSession::ConnectDisplay(int disp) {
884 DLOGI("Display = %d", disp);
885
886 int status = 0;
887 uint32_t primary_width = 0;
888 uint32_t primary_height = 0;
889
890 hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
891
892 if (disp == HWC_DISPLAY_EXTERNAL) {
893 status = CreateExternalDisplay(disp, primary_width, primary_height);
894 } else {
895 DLOGE("Invalid display type");
896 return -1;
897 }
898
899 if (!status) {
900 hwc_display_[disp]->SetSecureDisplay(secure_display_active_);
901 }
902
903 return status;
904 }
905
DisconnectDisplay(int disp)906 int HWCSession::DisconnectDisplay(int disp) {
907 DLOGI("Display = %d", disp);
908
909 if (disp == HWC_DISPLAY_EXTERNAL) {
910 HWCDisplayExternal::Destroy(hwc_display_[disp]);
911 } else if (disp == HWC_DISPLAY_VIRTUAL) {
912 HWCDisplayVirtual::Destroy(hwc_display_[disp]);
913 } else {
914 DLOGE("Invalid display type");
915 return -1;
916 }
917
918 hwc_display_[disp] = NULL;
919
920 return 0;
921 }
922
923 // Qclient methods
notifyCallback(uint32_t command,const android::Parcel * input_parcel,android::Parcel * output_parcel)924 android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
925 android::Parcel *output_parcel) {
926 android::status_t status = 0;
927
928 switch (command) {
929 case qService::IQService::DYNAMIC_DEBUG:
930 DynamicDebug(input_parcel);
931 break;
932
933 case qService::IQService::SCREEN_REFRESH:
934 refreshScreen();
935 break;
936
937 case qService::IQService::SET_IDLE_TIMEOUT:
938 setIdleTimeout(UINT32(input_parcel->readInt32()));
939 break;
940
941 case qService::IQService::SET_FRAME_DUMP_CONFIG:
942 SetFrameDumpConfig(input_parcel);
943 break;
944
945 case qService::IQService::SET_MAX_PIPES_PER_MIXER:
946 status = SetMaxMixerStages(input_parcel);
947 break;
948
949 case qService::IQService::SET_DISPLAY_MODE:
950 status = SetDisplayMode(input_parcel);
951 break;
952
953 case qService::IQService::SET_SECONDARY_DISPLAY_STATUS: {
954 int disp_id = INT(input_parcel->readInt32());
955 HWCDisplay::DisplayStatus disp_status =
956 static_cast<HWCDisplay::DisplayStatus>(input_parcel->readInt32());
957 status = SetSecondaryDisplayStatus(disp_id, disp_status);
958 output_parcel->writeInt32(status);
959 }
960 break;
961
962 case qService::IQService::CONFIGURE_DYN_REFRESH_RATE:
963 status = ConfigureRefreshRate(input_parcel);
964 break;
965
966 case qService::IQService::SET_VIEW_FRAME:
967 break;
968
969 case qService::IQService::TOGGLE_SCREEN_UPDATES: {
970 int32_t input = input_parcel->readInt32();
971 status = toggleScreenUpdate(input == 1);
972 output_parcel->writeInt32(status);
973 }
974 break;
975
976 case qService::IQService::QDCM_SVC_CMDS:
977 status = QdcmCMDHandler(input_parcel, output_parcel);
978 break;
979
980 case qService::IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED: {
981 int disp_id = input_parcel->readInt32();
982 uint32_t min_enc_level = UINT32(input_parcel->readInt32());
983 status = MinHdcpEncryptionLevelChanged(disp_id, min_enc_level);
984 output_parcel->writeInt32(status);
985 }
986 break;
987
988 case qService::IQService::CONTROL_PARTIAL_UPDATE: {
989 int disp_id = input_parcel->readInt32();
990 uint32_t enable = UINT32(input_parcel->readInt32());
991 status = ControlPartialUpdate(disp_id, enable == 1);
992 output_parcel->writeInt32(status);
993 }
994 break;
995
996 case qService::IQService::SET_ACTIVE_CONFIG: {
997 uint32_t config = UINT32(input_parcel->readInt32());
998 int disp_id = input_parcel->readInt32();
999 status = SetActiveConfigIndex(disp_id, config);
1000 }
1001 break;
1002
1003 case qService::IQService::GET_ACTIVE_CONFIG: {
1004 int disp_id = input_parcel->readInt32();
1005 uint32_t config = 0;
1006 status = GetActiveConfigIndex(disp_id, &config);
1007 output_parcel->writeInt32(INT(config));
1008 }
1009 break;
1010
1011 case qService::IQService::GET_CONFIG_COUNT: {
1012 int disp_id = input_parcel->readInt32();
1013 uint32_t count = 0;
1014 status = GetConfigCount(disp_id, &count);
1015 output_parcel->writeInt32(INT(count));
1016 }
1017 break;
1018
1019 case qService::IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG:
1020 status = HandleGetDisplayAttributesForConfig(input_parcel, output_parcel);
1021 break;
1022
1023 case qService::IQService::GET_PANEL_BRIGHTNESS: {
1024 int level = 0;
1025 status = GetPanelBrightness(&level);
1026 output_parcel->writeInt32(level);
1027 }
1028 break;
1029
1030 case qService::IQService::SET_PANEL_BRIGHTNESS: {
1031 uint32_t level = UINT32(input_parcel->readInt32());
1032 status = setPanelBrightness(level);
1033 output_parcel->writeInt32(status);
1034 }
1035 break;
1036
1037 case qService::IQService::GET_DISPLAY_VISIBLE_REGION:
1038 status = GetVisibleDisplayRect(input_parcel, output_parcel);
1039 break;
1040
1041 case qService::IQService::SET_CAMERA_STATUS: {
1042 uint32_t camera_status = UINT32(input_parcel->readInt32());
1043 status = setCameraLaunchStatus(camera_status);
1044 }
1045 break;
1046
1047 case qService::IQService::GET_BW_TRANSACTION_STATUS: {
1048 bool state = true;
1049 status = DisplayBWTransactionPending(&state);
1050 output_parcel->writeInt32(state);
1051 }
1052 break;
1053
1054 case qService::IQService::SET_LAYER_MIXER_RESOLUTION:
1055 status = SetMixerResolution(input_parcel);
1056 break;
1057
1058 case qService::IQService::SET_COLOR_MODE:
1059 status = SetColorModeOverride(input_parcel);
1060 break;
1061
1062 default:
1063 DLOGW("QService command = %d is not supported", command);
1064 return -EINVAL;
1065 }
1066
1067 return status;
1068 }
1069
HandleGetDisplayAttributesForConfig(const android::Parcel * input_parcel,android::Parcel * output_parcel)1070 android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android::Parcel
1071 *input_parcel,
1072 android::Parcel *output_parcel) {
1073 int config = input_parcel->readInt32();
1074 int dpy = input_parcel->readInt32();
1075 int error = android::BAD_VALUE;
1076 DisplayConfigVariableInfo display_attributes;
1077
1078 if (dpy < HWC_DISPLAY_PRIMARY || dpy >= HWC_NUM_DISPLAY_TYPES || config < 0) {
1079 return android::BAD_VALUE;
1080 }
1081
1082 SEQUENCE_WAIT_SCOPE_LOCK(locker_[dpy]);
1083 if (hwc_display_[dpy]) {
1084 error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &display_attributes);
1085 if (error == 0) {
1086 output_parcel->writeInt32(INT(display_attributes.vsync_period_ns));
1087 output_parcel->writeInt32(INT(display_attributes.x_pixels));
1088 output_parcel->writeInt32(INT(display_attributes.y_pixels));
1089 output_parcel->writeFloat(display_attributes.x_dpi);
1090 output_parcel->writeFloat(display_attributes.y_dpi);
1091 output_parcel->writeInt32(0); // Panel type, unsupported.
1092 }
1093 }
1094
1095 return error;
1096 }
1097
ConfigureRefreshRate(const android::Parcel * input_parcel)1098 android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) {
1099 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
1100
1101 uint32_t operation = UINT32(input_parcel->readInt32());
1102 HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
1103
1104 switch (operation) {
1105 case qdutils::DISABLE_METADATA_DYN_REFRESH_RATE:
1106 return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false);
1107
1108 case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE:
1109 return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true);
1110
1111 case qdutils::SET_BINDER_DYN_REFRESH_RATE: {
1112 uint32_t refresh_rate = UINT32(input_parcel->readInt32());
1113 return hwc_display->Perform(HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE, refresh_rate);
1114 }
1115
1116 default:
1117 DLOGW("Invalid operation %d", operation);
1118 return -EINVAL;
1119 }
1120
1121 return 0;
1122 }
1123
SetDisplayMode(const android::Parcel * input_parcel)1124 android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
1125 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
1126
1127 uint32_t mode = UINT32(input_parcel->readInt32());
1128 return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayPrimary::SET_DISPLAY_MODE, mode);
1129 }
1130
SetMaxMixerStages(const android::Parcel * input_parcel)1131 android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
1132 DisplayError error = kErrorNone;
1133 std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
1134 uint32_t max_mixer_stages = UINT32(input_parcel->readInt32());
1135
1136 if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
1137 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
1138 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
1139 error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMaxMixerStages(max_mixer_stages);
1140 if (error != kErrorNone) {
1141 return -EINVAL;
1142 }
1143 }
1144 }
1145
1146 if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
1147 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
1148 if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
1149 error = hwc_display_[HWC_DISPLAY_EXTERNAL]->SetMaxMixerStages(max_mixer_stages);
1150 if (error != kErrorNone) {
1151 return -EINVAL;
1152 }
1153 }
1154 }
1155
1156 if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
1157 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_VIRTUAL]);
1158 if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
1159 error = hwc_display_[HWC_DISPLAY_VIRTUAL]->SetMaxMixerStages(max_mixer_stages);
1160 if (error != kErrorNone) {
1161 return -EINVAL;
1162 }
1163 }
1164 }
1165
1166 return 0;
1167 }
1168
SetFrameDumpConfig(const android::Parcel * input_parcel)1169 void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
1170 uint32_t frame_dump_count = UINT32(input_parcel->readInt32());
1171 std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
1172 uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
1173
1174 if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
1175 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
1176 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
1177 hwc_display_[HWC_DISPLAY_PRIMARY]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
1178 }
1179 }
1180
1181 if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
1182 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
1183 if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
1184 hwc_display_[HWC_DISPLAY_EXTERNAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
1185 }
1186 }
1187
1188 if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
1189 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_VIRTUAL]);
1190 if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
1191 hwc_display_[HWC_DISPLAY_VIRTUAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
1192 }
1193 }
1194 }
1195
SetMixerResolution(const android::Parcel * input_parcel)1196 android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_parcel) {
1197 DisplayError error = kErrorNone;
1198 uint32_t dpy = UINT32(input_parcel->readInt32());
1199
1200 if (dpy != HWC_DISPLAY_PRIMARY) {
1201 DLOGI("Resoulution change not supported for this display %d", dpy);
1202 return -EINVAL;
1203 }
1204
1205 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
1206 if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
1207 DLOGI("Primary display is not initialized");
1208 return -EINVAL;
1209 }
1210
1211 uint32_t width = UINT32(input_parcel->readInt32());
1212 uint32_t height = UINT32(input_parcel->readInt32());
1213
1214 error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMixerResolution(width, height);
1215 if (error != kErrorNone) {
1216 return -EINVAL;
1217 }
1218
1219 return 0;
1220 }
1221
SetColorModeOverride(const android::Parcel * input_parcel)1222 android::status_t HWCSession::SetColorModeOverride(const android::Parcel *input_parcel) {
1223 auto display = static_cast<hwc2_display_t >(input_parcel->readInt32());
1224 auto mode = static_cast<android_color_mode_t>(input_parcel->readInt32());
1225 auto device = static_cast<hwc2_device_t *>(this);
1226
1227 if (display >= HWC_NUM_DISPLAY_TYPES) {
1228 return -EINVAL;
1229 }
1230 auto err = CallDisplayFunction(device, display, &HWCDisplay::SetColorMode, mode);
1231 if (err != HWC2_ERROR_NONE)
1232 return -EINVAL;
1233
1234 return 0;
1235 }
1236
DynamicDebug(const android::Parcel * input_parcel)1237 void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
1238 // TODO(user): Do we really need a lock here?
1239
1240 int type = input_parcel->readInt32();
1241 bool enable = (input_parcel->readInt32() > 0);
1242 DLOGI("type = %d enable = %d", type, enable);
1243 int verbose_level = input_parcel->readInt32();
1244
1245 switch (type) {
1246 case qService::IQService::DEBUG_ALL:
1247 HWCDebugHandler::DebugAll(enable, verbose_level);
1248 break;
1249
1250 case qService::IQService::DEBUG_MDPCOMP:
1251 HWCDebugHandler::DebugStrategy(enable, verbose_level);
1252 HWCDebugHandler::DebugCompManager(enable, verbose_level);
1253 break;
1254
1255 case qService::IQService::DEBUG_PIPE_LIFECYCLE:
1256 HWCDebugHandler::DebugResources(enable, verbose_level);
1257 break;
1258
1259 case qService::IQService::DEBUG_DRIVER_CONFIG:
1260 HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
1261 break;
1262
1263 case qService::IQService::DEBUG_ROTATOR:
1264 HWCDebugHandler::DebugResources(enable, verbose_level);
1265 HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
1266 HWCDebugHandler::DebugRotator(enable, verbose_level);
1267 break;
1268
1269 case qService::IQService::DEBUG_QDCM:
1270 HWCDebugHandler::DebugQdcm(enable, verbose_level);
1271 break;
1272
1273 case qService::IQService::DEBUG_SCALAR:
1274 HWCDebugHandler::DebugScalar(enable, verbose_level);
1275 break;
1276
1277 case qService::IQService::DEBUG_CLIENT:
1278 HWCDebugHandler::DebugClient(enable, verbose_level);
1279 break;
1280
1281 case qService::IQService::DEBUG_DISPLAY:
1282 HWCDebugHandler::DebugDisplay(enable, verbose_level);
1283 break;
1284
1285 default:
1286 DLOGW("type = %d is not supported", type);
1287 }
1288 }
1289
QdcmCMDHandler(const android::Parcel * input_parcel,android::Parcel * output_parcel)1290 android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel,
1291 android::Parcel *output_parcel) {
1292 int ret = 0;
1293 int32_t *brightness_value = NULL;
1294 uint32_t display_id(0);
1295 PPPendingParams pending_action;
1296 PPDisplayAPIPayload resp_payload, req_payload;
1297
1298 if (!color_mgr_) {
1299 return -1;
1300 }
1301
1302 pending_action.action = kNoAction;
1303 pending_action.params = NULL;
1304
1305 // Read display_id, payload_size and payload from in_parcel.
1306 ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload);
1307 if (!ret) {
1308 if (HWC_DISPLAY_PRIMARY == display_id && hwc_display_[HWC_DISPLAY_PRIMARY])
1309 ret = hwc_display_[HWC_DISPLAY_PRIMARY]->ColorSVCRequestRoute(req_payload, &resp_payload,
1310 &pending_action);
1311
1312 if (HWC_DISPLAY_EXTERNAL == display_id && hwc_display_[HWC_DISPLAY_EXTERNAL])
1313 ret = hwc_display_[HWC_DISPLAY_EXTERNAL]->ColorSVCRequestRoute(req_payload, &resp_payload,
1314 &pending_action);
1315 }
1316
1317 if (ret || pending_action.action == kNoAction) {
1318 output_parcel->writeInt32(ret); // first field in out parcel indicates return code.
1319 if (pending_action.action == kNoAction) {
1320 HWCColorManager::MarshallStructIntoParcel(resp_payload, output_parcel);
1321 }
1322 req_payload.DestroyPayload();
1323 resp_payload.DestroyPayload();
1324 return ret;
1325 }
1326
1327
1328 int32_t action = pending_action.action;
1329 int count = -1;
1330 bool reset_validate = true;
1331 while (action > 0) {
1332 count++;
1333 int32_t bit = (action & 1);
1334 action = action >> 1;
1335
1336 if (!bit)
1337 continue;
1338
1339 DLOGV_IF(kTagQDCM, "pending action = %d", BITMAP(count));
1340 switch (BITMAP(count)) {
1341 case kInvalidating:
1342 Refresh(HWC_DISPLAY_PRIMARY);
1343 reset_validate = !disable_skip_validate_;
1344 break;
1345 case kEnterQDCMMode:
1346 ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]);
1347 break;
1348 case kExitQDCMMode:
1349 ret = color_mgr_->EnableQDCMMode(false, hwc_display_[HWC_DISPLAY_PRIMARY]);
1350 break;
1351 case kApplySolidFill:
1352 ret = color_mgr_->SetSolidFill(pending_action.params,
1353 true, hwc_display_[HWC_DISPLAY_PRIMARY]);
1354 Refresh(HWC_DISPLAY_PRIMARY);
1355 break;
1356 case kDisableSolidFill:
1357 ret = color_mgr_->SetSolidFill(pending_action.params,
1358 false, hwc_display_[HWC_DISPLAY_PRIMARY]);
1359 Refresh(HWC_DISPLAY_PRIMARY);
1360 break;
1361 case kSetPanelBrightness:
1362 brightness_value = reinterpret_cast<int32_t *>(resp_payload.payload);
1363 if (brightness_value == NULL) {
1364 DLOGE("Brightness value is Null");
1365 return -EINVAL;
1366 }
1367 if (HWC_DISPLAY_PRIMARY == display_id)
1368 ret = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(*brightness_value);
1369 break;
1370 case kEnableFrameCapture:
1371 ret = color_mgr_->SetFrameCapture(pending_action.params, true,
1372 hwc_display_[HWC_DISPLAY_PRIMARY]);
1373 Refresh(HWC_DISPLAY_PRIMARY);
1374 break;
1375 case kDisableFrameCapture:
1376 ret = color_mgr_->SetFrameCapture(pending_action.params, false,
1377 hwc_display_[HWC_DISPLAY_PRIMARY]);
1378 break;
1379 case kConfigureDetailedEnhancer:
1380 ret = color_mgr_->SetDetailedEnhancer(pending_action.params,
1381 hwc_display_[HWC_DISPLAY_PRIMARY]);
1382 Refresh(HWC_DISPLAY_PRIMARY);
1383 break;
1384 case kModeSet:
1385 ret = static_cast<int>
1386 (hwc_display_[HWC_DISPLAY_PRIMARY]->RestoreColorTransform());
1387 Refresh(HWC_DISPLAY_PRIMARY);
1388 break;
1389 case kNoAction:
1390 break;
1391 default:
1392 DLOGW("Invalid pending action = %d!", pending_action.action);
1393 break;
1394 }
1395 }
1396 // for display API getter case, marshall returned params into out_parcel.
1397 output_parcel->writeInt32(ret);
1398 HWCColorManager::MarshallStructIntoParcel(resp_payload, output_parcel);
1399 req_payload.DestroyPayload();
1400 resp_payload.DestroyPayload();
1401 if (reset_validate) {
1402 hwc_display_[display_id]->ResetValidation();
1403 }
1404
1405 return (ret ? -EINVAL : 0);
1406 }
1407
UEventHandler(const char * uevent_data,int length)1408 void HWCSession::UEventHandler(const char *uevent_data, int length) {
1409 if (!strcasecmp(uevent_data, HWC_UEVENT_SWITCH_HDMI)) {
1410 DLOGI("Uevent HDMI = %s", uevent_data);
1411 int connected = GetEventValue(uevent_data, length, "SWITCH_STATE=");
1412 if (connected >= 0) {
1413 DLOGI("HDMI = %s", connected ? "connected" : "disconnected");
1414 if (HotPlugHandler(connected) == -1) {
1415 DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected");
1416 }
1417 }
1418 } else if (!strcasecmp(uevent_data, HWC_UEVENT_GRAPHICS_FB0)) {
1419 DLOGI("Uevent FB0 = %s", uevent_data);
1420 int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE=");
1421 if (panel_reset == 0) {
1422 Refresh(0);
1423 reset_panel_ = true;
1424 }
1425 }
1426 }
1427
GetEventValue(const char * uevent_data,int length,const char * event_info)1428 int HWCSession::GetEventValue(const char *uevent_data, int length, const char *event_info) {
1429 const char *iterator_str = uevent_data;
1430 while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
1431 const char *pstr = strstr(iterator_str, event_info);
1432 if (pstr != NULL) {
1433 return (atoi(iterator_str + strlen(event_info)));
1434 }
1435 iterator_str += strlen(iterator_str) + 1;
1436 }
1437
1438 return -1;
1439 }
1440
ResetPanel()1441 void HWCSession::ResetPanel() {
1442 HWC2::Error status;
1443
1444 DLOGI("Powering off primary");
1445 status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC2::PowerMode::Off);
1446 if (status != HWC2::Error::None) {
1447 DLOGE("power-off on primary failed with error = %d", status);
1448 }
1449
1450 DLOGI("Restoring power mode on primary");
1451 HWC2::PowerMode mode = hwc_display_[HWC_DISPLAY_PRIMARY]->GetLastPowerMode();
1452 status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(mode);
1453 if (status != HWC2::Error::None) {
1454 DLOGE("Setting power mode = %d on primary failed with error = %d", mode, status);
1455 }
1456
1457 status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetVsyncEnabled(HWC2::Vsync::Enable);
1458 if (status != HWC2::Error::None) {
1459 DLOGE("enabling vsync failed for primary with error = %d", status);
1460 }
1461
1462 reset_panel_ = false;
1463 }
1464
HotPlugHandler(bool connected)1465 int HWCSession::HotPlugHandler(bool connected) {
1466 int status = 0;
1467 bool notify_hotplug = false;
1468
1469 // To prevent sending events to client while a lock is held, acquire scope locks only within
1470 // below scope so that those get automatically unlocked after the scope ends.
1471 do {
1472 // If HDMI is primary but not created yet (first time), create it and notify surfaceflinger.
1473 // if it is already created, but got disconnected/connected again,
1474 // just toggle display status and do not notify surfaceflinger.
1475 // If HDMI is not primary, create/destroy external display normally.
1476 if (hdmi_is_primary_) {
1477 SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
1478 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
1479 status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetState(connected);
1480 } else {
1481 status = CreateExternalDisplay(HWC_DISPLAY_PRIMARY);
1482 notify_hotplug = true;
1483 }
1484
1485 break;
1486 }
1487
1488 {
1489 SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
1490 // Primary display must be connected for HDMI as secondary cases.
1491 if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
1492 DLOGE("Primary display is not connected.");
1493 return -1;
1494 }
1495 }
1496
1497 if (connected) {
1498 SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
1499 Locker::ScopeLock lock_v(locker_[HWC_DISPLAY_VIRTUAL]);
1500 // Connect external display if virtual display is not connected.
1501 // Else, defer external display connection and process it when virtual display
1502 // tears down; Do not notify SurfaceFlinger since connection is deferred now.
1503 if (!hwc_display_[HWC_DISPLAY_VIRTUAL]) {
1504 status = ConnectDisplay(HWC_DISPLAY_EXTERNAL);
1505 if (status) {
1506 return status;
1507 }
1508 notify_hotplug = true;
1509 } else {
1510 DLOGI("Virtual display is connected, pending connection");
1511 external_pending_connect_ = true;
1512 }
1513 } else {
1514 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
1515 // Do not return error if external display is not in connected status.
1516 // Due to virtual display concurrency, external display connection might be still pending
1517 // but hdmi got disconnected before pending connection could be processed.
1518 if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
1519 status = DisconnectDisplay(HWC_DISPLAY_EXTERNAL);
1520 notify_hotplug = true;
1521 }
1522 external_pending_connect_ = false;
1523 }
1524 } while (0);
1525
1526 if (connected) {
1527 Refresh(0);
1528
1529 if (!hdmi_is_primary_) {
1530 // wait for sufficient time to ensure sufficient resources are available to process new
1531 // new display connection.
1532 uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY));
1533 usleep(vsync_period * 2 / 1000);
1534 }
1535 }
1536
1537 // notify client
1538 if (notify_hotplug) {
1539 HotPlug(hdmi_is_primary_ ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL,
1540 connected ? HWC2::Connection::Connected : HWC2::Connection::Disconnected);
1541 }
1542
1543 qservice_->onHdmiHotplug(INT(connected));
1544
1545 return 0;
1546 }
1547
GetVsyncPeriod(int disp)1548 int HWCSession::GetVsyncPeriod(int disp) {
1549 SCOPE_LOCK(locker_[disp]);
1550 // default value
1551 int32_t vsync_period = 1000000000l / 60;
1552 auto attribute = HWC2::Attribute::VsyncPeriod;
1553
1554 if (hwc_display_[disp]) {
1555 hwc_display_[disp]->GetDisplayAttribute(0, attribute, &vsync_period);
1556 }
1557
1558 return vsync_period;
1559 }
1560
GetVisibleDisplayRect(const android::Parcel * input_parcel,android::Parcel * output_parcel)1561 android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel,
1562 android::Parcel *output_parcel) {
1563 int dpy = input_parcel->readInt32();
1564 if (dpy < HWC_DISPLAY_PRIMARY || dpy >= HWC_NUM_DISPLAY_TYPES) {
1565 return android::BAD_VALUE;
1566 }
1567
1568 SEQUENCE_WAIT_SCOPE_LOCK(locker_[dpy]);
1569 if (!hwc_display_[dpy]) {
1570 return android::NO_INIT;
1571 }
1572
1573 hwc_rect_t visible_rect = {0, 0, 0, 0};
1574 int error = hwc_display_[dpy]->GetVisibleDisplayRect(&visible_rect);
1575 if (error < 0) {
1576 return error;
1577 }
1578
1579 output_parcel->writeInt32(visible_rect.left);
1580 output_parcel->writeInt32(visible_rect.top);
1581 output_parcel->writeInt32(visible_rect.right);
1582 output_parcel->writeInt32(visible_rect.bottom);
1583
1584 return android::NO_ERROR;
1585 }
1586
Refresh(hwc2_display_t display)1587 void HWCSession::Refresh(hwc2_display_t display) {
1588 SCOPE_LOCK(callbacks_lock_);
1589 callbacks_.Refresh(display);
1590 }
1591
HotPlug(hwc2_display_t display,HWC2::Connection state)1592 void HWCSession::HotPlug(hwc2_display_t display, HWC2::Connection state) {
1593 SCOPE_LOCK(callbacks_lock_);
1594 HWC2::Error err = callbacks_.Hotplug(display, state);
1595 while (err != HWC2::Error::None) {
1596 callbacks_lock_.Wait();
1597 err = callbacks_.Hotplug(display, state);
1598 }
1599 }
1600
CreateExternalDisplay(int disp,uint32_t primary_width,uint32_t primary_height,bool use_primary_res)1601 int HWCSession::CreateExternalDisplay(int disp, uint32_t primary_width,
1602 uint32_t primary_height, bool use_primary_res) {
1603 uint32_t panel_bpp = 0;
1604 uint32_t pattern_type = 0;
1605 if (qdutils::isDPConnected()) {
1606 qdutils::getDPTestConfig(&panel_bpp, &pattern_type);
1607 }
1608 if (panel_bpp && pattern_type) {
1609 return HWCDisplayExternalTest::Create(core_intf_, &buffer_allocator_, &callbacks_,
1610 qservice_, panel_bpp,
1611 pattern_type, &hwc_display_[disp]);
1612 }
1613 if (use_primary_res) {
1614 return HWCDisplayExternal::Create(core_intf_, &buffer_allocator_, &callbacks_,
1615 primary_width, primary_height, qservice_,
1616 use_primary_res, &hwc_display_[disp]);
1617 } else {
1618 return HWCDisplayExternal::Create(core_intf_, &buffer_allocator_, &callbacks_,
1619 qservice_, &hwc_display_[disp]);
1620 }
1621 }
1622
1623 } // namespace sdm
1624