• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (c) 2015 - 2016, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *     * Redistributions of source code must retain the above copyright
8 *       notice, this list of conditions and the following disclaimer.
9 *     * Redistributions in binary form must reproduce the above
10 *       copyright notice, this list of conditions and the following
11 *       disclaimer in the documentation and/or other materials provided
12 *       with the distribution.
13 *     * Neither the name of The Linux Foundation nor the names of its
14 *       contributors may be used to endorse or promote products derived
15 *       from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 
30 #include <dlfcn.h>
31 #include <powermanager/IPowerManager.h>
32 #include <cutils/sockets.h>
33 #include <cutils/native_handle.h>
34 #include <utils/String16.h>
35 #include <binder/Parcel.h>
36 #include <gralloc_priv.h>
37 #include <hardware/hwcomposer.h>
38 #include <hardware/hwcomposer_defs.h>
39 #include <QService.h>
40 
41 #include <core/dump_interface.h>
42 #include <utils/constants.h>
43 #include <utils/debug.h>
44 #include <core/buffer_allocator.h>
45 #include <private/color_params.h>
46 #include "hwc_buffer_allocator.h"
47 #include "hwc_buffer_sync_handler.h"
48 #include "hwc_session.h"
49 #include "hwc_debugger.h"
50 
51 #define __CLASS__ "HWCColorManager"
52 
53 namespace sdm {
54 
Get8BitsARGBColorValue(const PPColorFillParams & params)55 uint32_t HWCColorManager::Get8BitsARGBColorValue(const PPColorFillParams &params) {
56   uint32_t argb_color = ((params.color.r << 16) & 0xff0000) | ((params.color.g << 8) & 0xff00) |
57                         ((params.color.b) & 0xff);
58   return argb_color;
59 }
60 
CreatePayloadFromParcel(const android::Parcel & in,uint32_t * disp_id,PPDisplayAPIPayload * sink)61 int HWCColorManager::CreatePayloadFromParcel(const android::Parcel &in, uint32_t *disp_id,
62                                              PPDisplayAPIPayload *sink) {
63   int ret = 0;
64   uint32_t id(0);
65   uint32_t size(0);
66 
67   id = UINT32(in.readInt32());
68   size = UINT32(in.readInt32());
69   if (size > 0 && size == in.dataAvail()) {
70     const void *data = in.readInplace(size);
71     const uint8_t *temp = reinterpret_cast<const uint8_t *>(data);
72 
73     sink->size = size;
74     sink->payload = const_cast<uint8_t *>(temp);
75     *disp_id = id;
76   } else {
77     DLOGW("Failing size checking, size = %d", size);
78     ret = -EINVAL;
79   }
80 
81   return ret;
82 }
83 
MarshallStructIntoParcel(const PPDisplayAPIPayload & data,android::Parcel * out_parcel)84 void HWCColorManager::MarshallStructIntoParcel(const PPDisplayAPIPayload &data,
85                                                android::Parcel *out_parcel) {
86   out_parcel->writeInt32(INT32(data.size));
87   if (data.payload)
88     out_parcel->write(data.payload, data.size);
89 }
90 
CreateColorManager()91 HWCColorManager *HWCColorManager::CreateColorManager() {
92   HWCColorManager *color_mgr = new HWCColorManager();
93 
94   if (color_mgr) {
95     // Load display API interface library. And retrieve color API function tables.
96     DynLib &color_apis_lib = color_mgr->color_apis_lib_;
97     if (color_apis_lib.Open(DISPLAY_API_INTERFACE_LIBRARY_NAME)) {
98       if (!color_apis_lib.Sym(DISPLAY_API_FUNC_TABLES, &color_mgr->color_apis_)) {
99         DLOGE("Fail to retrieve = %s from %s", DISPLAY_API_FUNC_TABLES,
100               DISPLAY_API_INTERFACE_LIBRARY_NAME);
101         delete color_mgr;
102         return NULL;
103       }
104     } else {
105       DLOGW("Unable to load = %s", DISPLAY_API_INTERFACE_LIBRARY_NAME);
106       delete color_mgr;
107       return NULL;
108     }
109     DLOGI("Successfully loaded %s", DISPLAY_API_INTERFACE_LIBRARY_NAME);
110 
111     // Load diagclient library and invokes its entry point to pass in display APIs.
112     DynLib &diag_client_lib = color_mgr->diag_client_lib_;
113     if (diag_client_lib.Open(QDCM_DIAG_CLIENT_LIBRARY_NAME)) {
114       if (!diag_client_lib.Sym(INIT_QDCM_DIAG_CLIENT_NAME,
115                                reinterpret_cast<void **>(&color_mgr->qdcm_diag_init_)) ||
116         !diag_client_lib.Sym(DEINIT_QDCM_DIAG_CLIENT_NAME,
117                                reinterpret_cast<void **>(&color_mgr->qdcm_diag_deinit_))) {
118         DLOGE("Fail to retrieve = %s from %s", INIT_QDCM_DIAG_CLIENT_NAME,
119               QDCM_DIAG_CLIENT_LIBRARY_NAME);
120       } else {
121         // invoke Diag Client entry point to initialize.
122         color_mgr->qdcm_diag_init_(color_mgr->color_apis_);
123         DLOGI("Successfully loaded %s and %s and diag_init'ed", DISPLAY_API_INTERFACE_LIBRARY_NAME,
124               QDCM_DIAG_CLIENT_LIBRARY_NAME);
125       }
126     } else {
127       DLOGW("Unable to load = %s", QDCM_DIAG_CLIENT_LIBRARY_NAME);
128       // only QDCM Diag client failed to be loaded and system still should function.
129     }
130   } else {
131     DLOGE("Unable to create HWCColorManager");
132     return NULL;
133   }
134 
135   return color_mgr;
136 }
137 
~HWCColorManager()138 HWCColorManager::~HWCColorManager() {
139 }
140 
DestroyColorManager()141 void HWCColorManager::DestroyColorManager() {
142   if (qdcm_mode_mgr_) {
143     delete qdcm_mode_mgr_;
144   }
145   if (qdcm_diag_deinit_) {
146     qdcm_diag_deinit_();
147   }
148   delete this;
149 }
150 
EnableQDCMMode(bool enable,HWCDisplay * hwc_display)151 int HWCColorManager::EnableQDCMMode(bool enable, HWCDisplay *hwc_display) {
152   int ret = 0;
153 
154   if (!qdcm_mode_mgr_) {
155     qdcm_mode_mgr_ = HWCQDCMModeManager::CreateQDCMModeMgr();
156     if (!qdcm_mode_mgr_) {
157       DLOGE("Unable to create QDCM operating mode manager.");
158       ret = -EFAULT;
159     }
160   }
161 
162   if (qdcm_mode_mgr_) {
163     ret = qdcm_mode_mgr_->EnableQDCMMode(enable, hwc_display);
164   }
165 
166   return ret;
167 }
168 
SolidFillLayersPrepare(hwc_display_contents_1_t ** displays,HWCDisplay * hwc_display)169 bool HWCColorManager::SolidFillLayersPrepare(hwc_display_contents_1_t **displays,
170                                              HWCDisplay *hwc_display) {
171   SCOPE_LOCK(locker_);
172 
173   // Query HWCColorManager if QDCM tool requesting SOLID_FILL mode.
174   uint32_t solid_fill_color = Get8BitsARGBColorValue(solid_fill_params_);
175   hwc_display_contents_1_t *layer_list = displays[HWC_DISPLAY_PRIMARY];
176 
177   if (solid_fill_enable_ && solid_fill_layers_ && layer_list) {
178     // 1. shallow copy HWC_FRAMEBUFFER_TARGET layer info solid fill layer list.
179     solid_fill_layers_->hwLayers[1] = layer_list->hwLayers[layer_list->numHwLayers - 1];
180 
181     // 2. continue the prepare<> on solid_fill_layers.
182     hwc_display->Perform(HWCDisplayPrimary::SET_QDCM_SOLID_FILL_INFO, solid_fill_color);
183     hwc_display->Prepare(solid_fill_layers_);  // RECT info included.
184 
185     // 3. Set HWC_OVERLAY to all SF layers before returning to framework.
186     for (size_t i = 0; i < (layer_list->numHwLayers - 1); i++) {
187       hwc_layer_1_t *layer = &layer_list->hwLayers[i];
188       layer->compositionType = HWC_OVERLAY;
189     }
190 
191     return true;
192   } else if (!solid_fill_enable_) {
193     hwc_display->Perform(HWCDisplayPrimary::UNSET_QDCM_SOLID_FILL_INFO, 0);
194   }
195 
196   return false;
197 }
198 
SolidFillLayersSet(hwc_display_contents_1_t ** displays,HWCDisplay * hwc_display)199 bool HWCColorManager::SolidFillLayersSet(hwc_display_contents_1_t **displays,
200                                          HWCDisplay *hwc_display) {
201   // Query HWCColorManager if QDCM tool requesting SOLID_FILL mode.
202   SCOPE_LOCK(locker_);
203   hwc_display_contents_1_t *layer_list = displays[HWC_DISPLAY_PRIMARY];
204   if (solid_fill_enable_ && solid_fill_layers_ && layer_list) {
205     hwc_display->Commit(solid_fill_layers_);
206 
207     // SurfaceFlinger layer stack is dropped in solid fill case and replaced with local layer stack
208     // Close acquire fence fds associated with SF layer stack
209     // Close release/retire fence fds returned along with local layer stack
210     for (size_t i = 0; i < (layer_list->numHwLayers - 1); i++) {
211       int &fence_fd = layer_list->hwLayers[i].acquireFenceFd;
212       if (fence_fd >= 0) {
213         close(fence_fd);
214         fence_fd = -1;
215       }
216     }
217 
218     for (size_t i = 0; i < (solid_fill_layers_->numHwLayers - 1); i++) {
219       int &fence_fd = solid_fill_layers_->hwLayers[i].releaseFenceFd;
220       if (fence_fd >= 0) {
221         close(fence_fd);
222         fence_fd = -1;
223       }
224     }
225     if (solid_fill_layers_->retireFenceFd >= 0) {
226       close(solid_fill_layers_->retireFenceFd);
227       solid_fill_layers_->retireFenceFd = -1;
228     }
229 
230     return true;
231   }
232 
233   return false;
234 }
235 
CreateSolidFillLayers(HWCDisplay * hwc_display)236 int HWCColorManager::CreateSolidFillLayers(HWCDisplay *hwc_display) {
237   int ret = 0;
238 
239   if (!solid_fill_layers_) {
240     uint32_t size = sizeof(hwc_display_contents_1) + kNumSolidFillLayers * sizeof(hwc_layer_1_t);
241     uint32_t primary_width = 0;
242     uint32_t primary_height = 0;
243 
244     hwc_display->GetMixerResolution(&primary_width, &primary_height);
245     uint8_t *buf = new uint8_t[size]();
246     // handle for solid fill layer with fd = -1.
247     private_handle_t *handle =
248         new private_handle_t(-1, 0, private_handle_t::PRIV_FLAGS_FRAMEBUFFER, BUFFER_TYPE_UI,
249                              HAL_PIXEL_FORMAT_RGBA_8888, INT32(primary_width),
250                              INT32(primary_height));
251 
252     if (!buf || !handle) {
253       DLOGE("Failed to allocate memory.");
254       if (buf)
255         delete[] buf;
256       if (handle)
257         delete handle;
258 
259       return -ENOMEM;
260     }
261 
262     solid_fill_layers_ = reinterpret_cast<hwc_display_contents_1 *>(buf);
263     hwc_layer_1_t &layer = solid_fill_layers_->hwLayers[0];
264     layer.handle = handle;
265   }
266 
267   solid_fill_layers_->flags = HWC_GEOMETRY_CHANGED;
268   solid_fill_layers_->numHwLayers = kNumSolidFillLayers;
269   solid_fill_layers_->retireFenceFd = -1;
270   solid_fill_layers_->outbuf = NULL;
271   solid_fill_layers_->outbufAcquireFenceFd = -1;
272 
273   hwc_layer_1_t &layer = solid_fill_layers_->hwLayers[0];
274   hwc_rect_t solid_fill_rect = {
275       INT(solid_fill_params_.rect.x),
276       INT(solid_fill_params_.rect.y),
277       solid_fill_params_.rect.x + INT(solid_fill_params_.rect.width),
278       solid_fill_params_.rect.y + INT(solid_fill_params_.rect.height),
279   };
280 
281   layer.compositionType = HWC_FRAMEBUFFER;
282   layer.blending = HWC_BLENDING_PREMULT;
283   layer.sourceCropf.left = solid_fill_params_.rect.x;
284   layer.sourceCropf.top = solid_fill_params_.rect.y;
285   layer.sourceCropf.right = UINT32(solid_fill_params_.rect.x) + solid_fill_params_.rect.width;
286   layer.sourceCropf.bottom = UINT32(solid_fill_params_.rect.y) + solid_fill_params_.rect.height;
287   layer.acquireFenceFd = -1;
288   layer.releaseFenceFd = -1;
289   layer.flags = 0;
290   layer.transform = 0;
291   layer.hints = 0;
292   layer.planeAlpha = 0xff;
293   layer.displayFrame = solid_fill_rect;
294   layer.visibleRegionScreen.numRects = 1;
295   layer.visibleRegionScreen.rects = &layer.displayFrame;
296   layer.surfaceDamage.numRects = 0;
297 
298   return ret;
299 }
300 
DestroySolidFillLayers()301 void HWCColorManager::DestroySolidFillLayers() {
302   if (solid_fill_layers_) {
303     hwc_layer_1_t &layer = solid_fill_layers_->hwLayers[0];
304     uint8_t *buf = reinterpret_cast<uint8_t *>(solid_fill_layers_);
305     private_handle_t const *hnd = reinterpret_cast<private_handle_t const *>(layer.handle);
306 
307     if (hnd)
308         delete hnd;
309 
310     if (buf)
311         delete[] buf;
312 
313     solid_fill_layers_ = NULL;
314   }
315 }
316 
SetSolidFill(const void * params,bool enable,HWCDisplay * hwc_display)317 int HWCColorManager::SetSolidFill(const void *params, bool enable, HWCDisplay *hwc_display) {
318   SCOPE_LOCK(locker_);
319   int ret = 0;
320 
321   if (params) {
322     solid_fill_params_ = *reinterpret_cast<const PPColorFillParams *>(params);
323   } else {
324     solid_fill_params_ = PPColorFillParams();
325   }
326 
327   if (enable) {
328     // will create solid fill layers for rendering if not present.
329     ret = CreateSolidFillLayers(hwc_display);
330   } else {
331     DestroySolidFillLayers();
332   }
333   solid_fill_enable_ = enable;
334 
335   return ret;
336 }
337 
SetFrameCapture(void * params,bool enable,HWCDisplay * hwc_display)338 int HWCColorManager::SetFrameCapture(void *params, bool enable, HWCDisplay *hwc_display) {
339   SCOPE_LOCK(locker_);
340   int ret = 0;
341 
342   PPFrameCaptureData *frame_capture_data = reinterpret_cast<PPFrameCaptureData*>(params);
343 
344   if (enable) {
345     std::memset(&buffer_info, 0x00, sizeof(buffer_info));
346     hwc_display->GetFrameBufferResolution(&buffer_info.buffer_config.width,
347                                           &buffer_info.buffer_config.height);
348     if (frame_capture_data->input_params.out_pix_format == PP_PIXEL_FORMAT_RGB_888) {
349       buffer_info.buffer_config.format = kFormatRGB888;
350     } else if (frame_capture_data->input_params.out_pix_format == PP_PIXEL_FORMAT_RGB_2101010) {
351       // TODO(user): Complete the implementation
352       DLOGE("RGB 10-bit format NOT supported");
353       return -EFAULT;
354     } else {
355       DLOGE("Pixel-format: %d NOT support.", frame_capture_data->input_params.out_pix_format);
356       return -EFAULT;
357     }
358 
359     buffer_info.buffer_config.buffer_count = 1;
360     buffer_info.alloc_buffer_info.fd = -1;
361     buffer_info.alloc_buffer_info.stride = 0;
362     buffer_info.alloc_buffer_info.size = 0;
363 
364     buffer_allocator_ = new HWCBufferAllocator();
365     if (buffer_allocator_ == NULL) {
366       DLOGE("Memory allocation for buffer_allocator_ FAILED");
367       return -ENOMEM;
368     }
369 
370     ret = buffer_allocator_->AllocateBuffer(&buffer_info);
371     if (ret != 0) {
372       DLOGE("Buffer allocation failed. ret: %d", ret);
373       delete[] buffer_allocator_;
374       buffer_allocator_ = NULL;
375       return -ENOMEM;
376     } else {
377       void *buffer = mmap(NULL, buffer_info.alloc_buffer_info.size,
378                           PROT_READ|PROT_WRITE,
379                           MAP_SHARED, buffer_info.alloc_buffer_info.fd, 0);
380 
381       if (buffer == MAP_FAILED) {
382         DLOGE("mmap failed. err = %d", errno);
383         frame_capture_data->buffer = NULL;
384         ret = buffer_allocator_->FreeBuffer(&buffer_info);
385         delete[] buffer_allocator_;
386         buffer_allocator_ = NULL;
387         return -EFAULT;
388       } else {
389         frame_capture_data->buffer = reinterpret_cast<uint8_t *>(buffer);
390         frame_capture_data->buffer_stride = buffer_info.alloc_buffer_info.stride;
391         frame_capture_data->buffer_size = buffer_info.alloc_buffer_info.size;
392       }
393       // TODO(user): Call HWC interface to provide the buffer and rectangle information
394     }
395   } else {
396     if (frame_capture_data->buffer != NULL) {
397       if (munmap(frame_capture_data->buffer, buffer_info.alloc_buffer_info.size) != 0) {
398         DLOGE("munmap failed. err = %d", errno);
399       }
400     }
401     if (buffer_allocator_ != NULL) {
402       std::memset(frame_capture_data, 0x00, sizeof(PPFrameCaptureData));
403       ret = buffer_allocator_->FreeBuffer(&buffer_info);
404       if (ret != 0) {
405         DLOGE("FreeBuffer failed. ret = %d", ret);
406       }
407       delete[] buffer_allocator_;
408       buffer_allocator_ = NULL;
409     }
410   }
411   return ret;
412 }
413 
414 const HWCQDCMModeManager::ActiveFeatureCMD HWCQDCMModeManager::kActiveFeatureCMD[] = {
415     HWCQDCMModeManager::ActiveFeatureCMD("cabl:on", "cabl:off", "cabl:status", "running"),
416     HWCQDCMModeManager::ActiveFeatureCMD("ad:on", "ad:off", "ad:query:status", "running"),
417     HWCQDCMModeManager::ActiveFeatureCMD("svi:on", "svi:off", "svi:status", "running"),
418 };
419 
420 const char *const HWCQDCMModeManager::kSocketName = "pps";
421 const char *const HWCQDCMModeManager::kTagName = "surfaceflinger";
422 const char *const HWCQDCMModeManager::kPackageName = "colormanager";
423 
CreateQDCMModeMgr()424 HWCQDCMModeManager *HWCQDCMModeManager::CreateQDCMModeMgr() {
425   HWCQDCMModeManager *mode_mgr = new HWCQDCMModeManager();
426 
427   if (!mode_mgr) {
428     DLOGW("No memory to create HWCQDCMModeManager.");
429     return NULL;
430   } else {
431     mode_mgr->socket_fd_ =
432         ::socket_local_client(kSocketName, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
433     if (mode_mgr->socket_fd_ < 0) {
434       // it should not be disastrous and we still can grab wakelock in QDCM mode.
435       DLOGW("Unable to connect to dpps socket!");
436     }
437 
438     // retrieve system GPU idle timeout value for later to recover.
439     mode_mgr->entry_timeout_ = UINT32(HWCDebugHandler::GetIdleTimeoutMs());
440 
441     // acquire the binder handle to Android system PowerManager for later use.
442     android::sp<android::IBinder> binder =
443         android::defaultServiceManager()->checkService(android::String16("power"));
444     if (binder == NULL) {
445       DLOGW("Application can't connect to  power manager service");
446       delete mode_mgr;
447       mode_mgr = NULL;
448     } else {
449       mode_mgr->power_mgr_ = android::interface_cast<android::IPowerManager>(binder);
450     }
451   }
452 
453   return mode_mgr;
454 }
455 
~HWCQDCMModeManager()456 HWCQDCMModeManager::~HWCQDCMModeManager() {
457   if (socket_fd_ >= 0)
458     ::close(socket_fd_);
459 }
460 
AcquireAndroidWakeLock(bool enable)461 int HWCQDCMModeManager::AcquireAndroidWakeLock(bool enable) {
462   int ret = 0;
463 
464   if (enable) {
465     if (wakelock_token_ == NULL) {
466       android::sp<android::IBinder> binder = new android::BBinder();
467       android::status_t status = power_mgr_->acquireWakeLock(
468           (kFullWakeLock | kAcquireCauseWakeup | kONAfterRelease), binder,
469           android::String16(kTagName), android::String16(kPackageName));
470       if (status == android::NO_ERROR) {
471         wakelock_token_ = binder;
472       }
473     }
474   } else {
475     if (wakelock_token_ != NULL && power_mgr_ != NULL) {
476       power_mgr_->releaseWakeLock(wakelock_token_, 0);
477       wakelock_token_.clear();
478       wakelock_token_ = NULL;
479     }
480   }
481 
482   return ret;
483 }
484 
EnableActiveFeatures(bool enable,const HWCQDCMModeManager::ActiveFeatureCMD & cmds,bool * was_running)485 int HWCQDCMModeManager::EnableActiveFeatures(bool enable,
486                                              const HWCQDCMModeManager::ActiveFeatureCMD &cmds,
487                                              bool *was_running) {
488   int ret = 0;
489   ssize_t size = 0;
490   char response[kSocketCMDMaxLength] = {
491       0,
492   };
493 
494   if (socket_fd_ < 0) {
495     DLOGW("No socket connection available!");
496     return -EFAULT;
497   }
498 
499   if (!enable) {  // if client requesting to disable it.
500     // query CABL status, if off, no action. keep the status.
501     size = ::write(socket_fd_, cmds.cmd_query_status, strlen(cmds.cmd_query_status));
502     if (size < 0) {
503       DLOGW("Unable to send data over socket %s", ::strerror(errno));
504       ret = -EFAULT;
505     } else {
506       size = ::read(socket_fd_, response, kSocketCMDMaxLength);
507       if (size < 0) {
508         DLOGW("Unable to read data over socket %s", ::strerror(errno));
509         ret = -EFAULT;
510       } else if (!strncmp(response, cmds.running, strlen(cmds.running))) {
511         *was_running = true;
512       }
513     }
514 
515     if (*was_running) {  // if was running, it's requested to disable it.
516       size = ::write(socket_fd_, cmds.cmd_off, strlen(cmds.cmd_off));
517       if (size < 0) {
518         DLOGW("Unable to send data over socket %s", ::strerror(errno));
519         ret = -EFAULT;
520       }
521     }
522   } else {  // if was running, need enable it back.
523     if (*was_running) {
524       size = ::write(socket_fd_, cmds.cmd_on, strlen(cmds.cmd_on));
525       if (size < 0) {
526         DLOGW("Unable to send data over socket %s", ::strerror(errno));
527         ret = -EFAULT;
528       }
529     }
530   }
531 
532   return ret;
533 }
534 
EnableQDCMMode(bool enable,HWCDisplay * hwc_display)535 int HWCQDCMModeManager::EnableQDCMMode(bool enable, HWCDisplay *hwc_display) {
536   int ret = 0;
537 
538   ret = EnableActiveFeatures((enable ? false : true), kActiveFeatureCMD[kCABLFeature],
539                              &cabl_was_running_);
540   ret = AcquireAndroidWakeLock(enable);
541 
542   // if enter QDCM mode, disable GPU fallback idle timeout.
543   if (hwc_display) {
544     uint32_t timeout = enable ? 0 : entry_timeout_;
545     hwc_display->SetIdleTimeoutMs(timeout);
546   }
547 
548   return ret;
549 }
550 
551 }  // namespace sdm
552