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