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