1/*
2* Copyright (c) 2015 - 2017, 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
53namespace sdm {
54
55uint32_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
61int 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
84void 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
91HWCColorManager *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
138HWCColorManager::~HWCColorManager() {
139}
140
141void 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
151int 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
169bool 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
199bool 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
236int 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
301void 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
317int 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
338int 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->GetPanelResolution(&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      buffer_info.buffer_config.format = kFormatRGBA1010102;
352    } else {
353      DLOGE("Pixel-format: %d NOT support.", frame_capture_data->input_params.out_pix_format);
354      return -EFAULT;
355    }
356
357    buffer_info.buffer_config.buffer_count = 1;
358    buffer_info.alloc_buffer_info.fd = -1;
359    buffer_info.alloc_buffer_info.stride = 0;
360    buffer_info.alloc_buffer_info.size = 0;
361
362    buffer_allocator_ = new HWCBufferAllocator();
363    if (buffer_allocator_ == NULL) {
364      DLOGE("Memory allocation for buffer_allocator_ FAILED");
365      return -ENOMEM;
366    }
367
368    ret = buffer_allocator_->AllocateBuffer(&buffer_info);
369    if (ret != 0) {
370      DLOGE("Buffer allocation failed. ret: %d", ret);
371      delete buffer_allocator_;
372      buffer_allocator_ = NULL;
373      return -ENOMEM;
374    } else {
375      void *buffer = mmap(NULL, buffer_info.alloc_buffer_info.size,
376                          PROT_READ|PROT_WRITE,
377                          MAP_SHARED, buffer_info.alloc_buffer_info.fd, 0);
378
379      if (buffer == MAP_FAILED) {
380        DLOGE("mmap failed. err = %d", errno);
381        frame_capture_data->buffer = NULL;
382        ret = buffer_allocator_->FreeBuffer(&buffer_info);
383        delete buffer_allocator_;
384        buffer_allocator_ = NULL;
385        return -EFAULT;
386      } else {
387        frame_capture_data->buffer = reinterpret_cast<uint8_t *>(buffer);
388        frame_capture_data->buffer_stride = buffer_info.alloc_buffer_info.aligned_width;
389        frame_capture_data->buffer_size = buffer_info.alloc_buffer_info.size;
390      }
391      ret = hwc_display->FrameCaptureAsync(buffer_info, 1);
392      if (ret < 0) {
393        DLOGE("FrameCaptureAsync failed. ret = %d", ret);
394      }
395    }
396  } else {
397    ret = hwc_display->GetFrameCaptureStatus();
398    if (!ret) {
399      if (frame_capture_data->buffer != NULL) {
400        if (munmap(frame_capture_data->buffer, buffer_info.alloc_buffer_info.size) != 0) {
401          DLOGE("munmap failed. err = %d", errno);
402        }
403      }
404      if (buffer_allocator_ != NULL) {
405        std::memset(frame_capture_data, 0x00, sizeof(PPFrameCaptureData));
406        ret = buffer_allocator_->FreeBuffer(&buffer_info);
407        if (ret != 0) {
408          DLOGE("FreeBuffer failed. ret = %d", ret);
409        }
410        delete buffer_allocator_;
411        buffer_allocator_ = NULL;
412      }
413    } else {
414      DLOGE("GetFrameCaptureStatus failed. ret = %d", ret);
415    }
416  }
417  return ret;
418}
419
420int HWCColorManager::SetHWDetailedEnhancerConfig(void *params, HWCDisplay *hwc_display) {
421  int err = -1;
422  DisplayDetailEnhancerData de_data;
423
424  PPDETuningCfgData *de_tuning_cfg_data = reinterpret_cast<PPDETuningCfgData*>(params);
425  if (de_tuning_cfg_data->cfg_pending == true) {
426    if (!de_tuning_cfg_data->cfg_en) {
427      de_data.enable = 0;
428    } else {
429      de_data.override_flags = kOverrideDEEnable;
430      de_data.enable = 1;
431
432      if (de_tuning_cfg_data->params.flags & kDeTuningFlagSharpFactor) {
433        de_data.override_flags |= kOverrideDESharpen1;
434        de_data.sharp_factor = de_tuning_cfg_data->params.sharp_factor;
435      }
436
437      if (de_tuning_cfg_data->params.flags & kDeTuningFlagClip) {
438        de_data.override_flags |= kOverrideDEClip;
439        de_data.clip = de_tuning_cfg_data->params.clip;
440      }
441
442      if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrQuiet) {
443        de_data.override_flags |= kOverrideDEThrQuiet;
444        de_data.thr_quiet = de_tuning_cfg_data->params.thr_quiet;
445      }
446
447      if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrDieout) {
448        de_data.override_flags |= kOverrideDEThrDieout;
449        de_data.thr_dieout = de_tuning_cfg_data->params.thr_dieout;
450      }
451
452      if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrLow) {
453        de_data.override_flags |= kOverrideDEThrLow;
454        de_data.thr_low = de_tuning_cfg_data->params.thr_low;
455      }
456
457      if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrHigh) {
458        de_data.override_flags |= kOverrideDEThrHigh;
459        de_data.thr_high = de_tuning_cfg_data->params.thr_high;
460      }
461
462      if (de_tuning_cfg_data->params.flags & kDeTuningFlagContentQualLevel) {
463        switch (de_tuning_cfg_data->params.quality) {
464          case kDeContentQualLow:
465            de_data.quality_level = kContentQualityLow;
466            break;
467          case kDeContentQualMedium:
468            de_data.quality_level = kContentQualityMedium;
469            break;
470          case kDeContentQualHigh:
471            de_data.quality_level = kContentQualityHigh;
472            break;
473          case kDeContentQualUnknown:
474          default:
475            de_data.quality_level = kContentQualityUnknown;
476            break;
477        }
478      }
479    }
480    err = hwc_display->SetDetailEnhancerConfig(de_data);
481    if (err) {
482      DLOGW("SetDetailEnhancerConfig failed. err = %d", err);
483    }
484    de_tuning_cfg_data->cfg_pending = false;
485  }
486  return err;
487}
488
489void HWCColorManager::SetColorModeDetailEnhancer(HWCDisplay *hwc_display) {
490  SCOPE_LOCK(locker_);
491  int err = -1;
492  PPPendingParams pending_action;
493  PPDisplayAPIPayload req_payload;
494
495  pending_action.action = kGetDetailedEnhancerData;
496  pending_action.params = NULL;
497
498  if (hwc_display) {
499    err = hwc_display->ColorSVCRequestRoute(req_payload, NULL, &pending_action);
500    if (!err && pending_action.action == kConfigureDetailedEnhancer) {
501      err = SetHWDetailedEnhancerConfig(pending_action.params, hwc_display);
502    }
503  }
504  return;
505}
506
507int HWCColorManager::SetDetailedEnhancer(void *params, HWCDisplay *hwc_display) {
508  SCOPE_LOCK(locker_);
509  int err = -1;
510  err = SetHWDetailedEnhancerConfig(params, hwc_display);
511  return err;
512}
513
514const HWCQDCMModeManager::ActiveFeatureCMD HWCQDCMModeManager::kActiveFeatureCMD[] = {
515    HWCQDCMModeManager::ActiveFeatureCMD("cabl:on", "cabl:off", "cabl:status", "running"),
516    HWCQDCMModeManager::ActiveFeatureCMD("ad:on", "ad:off", "ad:query:status", "running"),
517    HWCQDCMModeManager::ActiveFeatureCMD("svi:on", "svi:off", "svi:status", "running"),
518};
519
520const char *const HWCQDCMModeManager::kSocketName = "pps";
521const char *const HWCQDCMModeManager::kTagName = "surfaceflinger";
522const char *const HWCQDCMModeManager::kPackageName = "colormanager";
523
524HWCQDCMModeManager *HWCQDCMModeManager::CreateQDCMModeMgr() {
525  HWCQDCMModeManager *mode_mgr = new HWCQDCMModeManager();
526
527  if (!mode_mgr) {
528    DLOGW("No memory to create HWCQDCMModeManager.");
529    return NULL;
530  } else {
531    mode_mgr->socket_fd_ =
532        ::socket_local_client(kSocketName, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
533    if (mode_mgr->socket_fd_ < 0) {
534      // it should not be disastrous and we still can grab wakelock in QDCM mode.
535      DLOGW("Unable to connect to dpps socket!");
536    }
537
538    // retrieve system GPU idle timeout value for later to recover.
539    mode_mgr->entry_timeout_ = UINT32(HWCDebugHandler::GetIdleTimeoutMs());
540
541    // acquire the binder handle to Android system PowerManager for later use.
542    android::sp<android::IBinder> binder =
543        android::defaultServiceManager()->checkService(android::String16("power"));
544    if (binder == NULL) {
545      DLOGW("Application can't connect to  power manager service");
546      delete mode_mgr;
547      mode_mgr = NULL;
548    } else {
549      mode_mgr->power_mgr_ = android::interface_cast<android::IPowerManager>(binder);
550    }
551  }
552
553  return mode_mgr;
554}
555
556HWCQDCMModeManager::~HWCQDCMModeManager() {
557  if (socket_fd_ >= 0)
558    ::close(socket_fd_);
559}
560
561int HWCQDCMModeManager::AcquireAndroidWakeLock(bool enable) {
562  int ret = 0;
563
564  if (enable) {
565    if (wakelock_token_ == NULL) {
566      android::sp<android::IBinder> binder = new android::BBinder();
567      android::status_t status = power_mgr_->acquireWakeLock(
568          (kFullWakeLock | kAcquireCauseWakeup | kONAfterRelease), binder,
569          android::String16(kTagName), android::String16(kPackageName));
570      if (status == android::NO_ERROR) {
571        wakelock_token_ = binder;
572      }
573    }
574  } else {
575    if (wakelock_token_ != NULL && power_mgr_ != NULL) {
576      power_mgr_->releaseWakeLock(wakelock_token_, 0);
577      wakelock_token_.clear();
578      wakelock_token_ = NULL;
579    }
580  }
581
582  return ret;
583}
584
585int HWCQDCMModeManager::EnableActiveFeatures(bool enable,
586                                             const HWCQDCMModeManager::ActiveFeatureCMD &cmds,
587                                             bool *was_running) {
588  int ret = 0;
589  ssize_t size = 0;
590  char response[kSocketCMDMaxLength] = {
591      0,
592  };
593
594  if (socket_fd_ < 0) {
595    DLOGW("No socket connection available!");
596    return -EFAULT;
597  }
598
599  if (!enable) {  // if client requesting to disable it.
600    // query CABL status, if off, no action. keep the status.
601    size = ::write(socket_fd_, cmds.cmd_query_status, strlen(cmds.cmd_query_status));
602    if (size < 0) {
603      DLOGW("Unable to send data over socket %s", ::strerror(errno));
604      ret = -EFAULT;
605    } else {
606      size = ::read(socket_fd_, response, kSocketCMDMaxLength);
607      if (size < 0) {
608        DLOGW("Unable to read data over socket %s", ::strerror(errno));
609        ret = -EFAULT;
610      } else if (!strncmp(response, cmds.running, strlen(cmds.running))) {
611        *was_running = true;
612      }
613    }
614
615    if (*was_running) {  // if was running, it's requested to disable it.
616      size = ::write(socket_fd_, cmds.cmd_off, strlen(cmds.cmd_off));
617      if (size < 0) {
618        DLOGW("Unable to send data over socket %s", ::strerror(errno));
619        ret = -EFAULT;
620      }
621    }
622  } else {  // if was running, need enable it back.
623    if (*was_running) {
624      size = ::write(socket_fd_, cmds.cmd_on, strlen(cmds.cmd_on));
625      if (size < 0) {
626        DLOGW("Unable to send data over socket %s", ::strerror(errno));
627        ret = -EFAULT;
628      }
629    }
630  }
631
632  return ret;
633}
634
635int HWCQDCMModeManager::EnableQDCMMode(bool enable, HWCDisplay *hwc_display) {
636  int ret = 0;
637
638  ret = EnableActiveFeatures((enable ? false : true), kActiveFeatureCMD[kCABLFeature],
639                             &cabl_was_running_);
640  ret = AcquireAndroidWakeLock(enable);
641
642  // if enter QDCM mode, disable GPU fallback idle timeout.
643  if (hwc_display) {
644    uint32_t timeout = enable ? 0 : entry_timeout_;
645    hwc_display->SetIdleTimeoutMs(timeout);
646  }
647
648  return ret;
649}
650
651}  // namespace sdm
652