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