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) & 0xff)
57                         | ((params.color.b << 8) & 0xff00);
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     void *&color_lib = color_mgr->color_apis_lib_;
96     // Load display API interface library. And retrieve color API function tables.
97     color_lib = ::dlopen(DISPLAY_API_INTERFACE_LIBRARY_NAME, RTLD_NOW);
98     if (color_lib) {
99       color_mgr->color_apis_ = ::dlsym(color_lib, DISPLAY_API_FUNC_TABLES);
100       if (!color_mgr->color_apis_) {
101         DLOGE("Fail to retrieve = %s from %s", DISPLAY_API_FUNC_TABLES,
102               DISPLAY_API_INTERFACE_LIBRARY_NAME);
103         ::dlclose(color_lib);
104         delete color_mgr;
105         return NULL;
106       }
107     } else {
108       DLOGW("Unable to load = %s", DISPLAY_API_INTERFACE_LIBRARY_NAME);
109       delete color_mgr;
110       return NULL;
111     }
112     DLOGI("Successfully loaded %s", DISPLAY_API_INTERFACE_LIBRARY_NAME);
113 
114     // Load diagclient library and invokes its entry point to pass in display APIs.
115     void *&diag_lib = color_mgr->diag_client_lib_;
116     diag_lib = ::dlopen(QDCM_DIAG_CLIENT_LIBRARY_NAME, RTLD_NOW);
117     if (diag_lib) {
118       *(reinterpret_cast<void **>(&color_mgr->qdcm_diag_init_)) =
119           ::dlsym(diag_lib, INIT_QDCM_DIAG_CLIENT_NAME);
120       *(reinterpret_cast<void **>(&color_mgr->qdcm_diag_deinit_)) =
121           ::dlsym(diag_lib, DEINIT_QDCM_DIAG_CLIENT_NAME);
122 
123       if (!color_mgr->qdcm_diag_init_ || !color_mgr->qdcm_diag_deinit_) {
124         DLOGE("Fail to retrieve = %s from %s", INIT_QDCM_DIAG_CLIENT_NAME,
125               QDCM_DIAG_CLIENT_LIBRARY_NAME);
126         ::dlclose(diag_lib);
127       } else {
128         // invoke Diag Client entry point to initialize.
129         color_mgr->qdcm_diag_init_(color_mgr->color_apis_);
130         DLOGI("Successfully loaded %s and %s and diag_init'ed", DISPLAY_API_INTERFACE_LIBRARY_NAME,
131               QDCM_DIAG_CLIENT_LIBRARY_NAME);
132       }
133     } else {
134       DLOGW("Unable to load = %s", QDCM_DIAG_CLIENT_LIBRARY_NAME);
135       // only QDCM Diag client failed to be loaded and system still should function.
136     }
137   } else {
138     DLOGE("Unable to create HWCColorManager");
139     return NULL;
140   }
141 
142   return color_mgr;
143 }
144 
~HWCColorManager()145 HWCColorManager::~HWCColorManager() {
146 }
147 
DestroyColorManager()148 void HWCColorManager::DestroyColorManager() {
149   if (qdcm_mode_mgr_) {
150     delete qdcm_mode_mgr_;
151   }
152   if (qdcm_diag_deinit_) {
153     qdcm_diag_deinit_();
154   }
155   if (diag_client_lib_) {
156     ::dlclose(diag_client_lib_);
157   }
158   if (color_apis_lib_) {
159     ::dlclose(color_apis_lib_);
160   }
161   delete this;
162 }
163 
EnableQDCMMode(bool enable,HWCDisplay * hwc_display)164 int HWCColorManager::EnableQDCMMode(bool enable, HWCDisplay *hwc_display) {
165   int ret = 0;
166 
167   if (!qdcm_mode_mgr_) {
168     qdcm_mode_mgr_ = HWCQDCMModeManager::CreateQDCMModeMgr();
169     if (!qdcm_mode_mgr_) {
170       DLOGE("Unable to create QDCM operating mode manager.");
171       ret = -EFAULT;
172     }
173   }
174 
175   if (qdcm_mode_mgr_) {
176     ret = qdcm_mode_mgr_->EnableQDCMMode(enable, hwc_display);
177   }
178 
179   return ret;
180 }
181 
SolidFillLayersPrepare(hwc_display_contents_1_t ** displays,HWCDisplay * hwc_display)182 bool HWCColorManager::SolidFillLayersPrepare(hwc_display_contents_1_t **displays,
183                                              HWCDisplay *hwc_display) {
184   SCOPE_LOCK(locker_);
185 
186   // Query HWCColorManager if QDCM tool requesting SOLID_FILL mode.
187   uint32_t solid_fill_color = Get8BitsARGBColorValue(solid_fill_params_);
188   hwc_display_contents_1_t *layer_list = displays[HWC_DISPLAY_PRIMARY];
189 
190   if (solid_fill_enable_ && solid_fill_layers_ && layer_list) {
191     // 1. shallow copy HWC_FRAMEBUFFER_TARGET layer info solid fill layer list.
192     solid_fill_layers_->hwLayers[1] = layer_list->hwLayers[layer_list->numHwLayers - 1];
193 
194     // 2. continue the prepare<> on solid_fill_layers.
195     hwc_display->Perform(HWCDisplayPrimary::SET_QDCM_SOLID_FILL_INFO, solid_fill_color);
196     hwc_display->Prepare(solid_fill_layers_);  // RECT info included.
197 
198     // 3. Set HWC_OVERLAY to all SF layers before returning to framework.
199     for (size_t i = 0; i < (layer_list->numHwLayers - 1); i++) {
200       hwc_layer_1_t *layer = &layer_list->hwLayers[i];
201       layer->compositionType = HWC_OVERLAY;
202     }
203 
204     return true;
205   } else if (!solid_fill_enable_) {
206     hwc_display->Perform(HWCDisplayPrimary::UNSET_QDCM_SOLID_FILL_INFO, 0);
207   }
208 
209   return false;
210 }
211 
SolidFillLayersSet(hwc_display_contents_1_t ** displays,HWCDisplay * hwc_display)212 bool HWCColorManager::SolidFillLayersSet(hwc_display_contents_1_t **displays,
213                                          HWCDisplay *hwc_display) {
214   // Query HWCColorManager if QDCM tool requesting SOLID_FILL mode.
215   SCOPE_LOCK(locker_);
216   hwc_display_contents_1_t *layer_list = displays[HWC_DISPLAY_PRIMARY];
217   if (solid_fill_enable_ && solid_fill_layers_ && layer_list) {
218     hwc_display->Commit(solid_fill_layers_);
219 
220     // SurfaceFlinger layer stack is dropped in solid fill case and replaced with local layer stack
221     // Close acquire fence fds associated with SF layer stack
222     // Close release/retire fence fds returned along with local layer stack
223     for (size_t i = 0; i < (layer_list->numHwLayers - 1); i++) {
224       int &fence_fd = layer_list->hwLayers[i].acquireFenceFd;
225       if (fence_fd >= 0) {
226         close(fence_fd);
227         fence_fd = -1;
228       }
229     }
230 
231     for (size_t i = 0; i < (solid_fill_layers_->numHwLayers - 1); i++) {
232       int &fence_fd = solid_fill_layers_->hwLayers[i].releaseFenceFd;
233       if (fence_fd >= 0) {
234         close(fence_fd);
235         fence_fd = -1;
236       }
237     }
238     if (solid_fill_layers_->retireFenceFd >= 0) {
239       close(solid_fill_layers_->retireFenceFd);
240       solid_fill_layers_->retireFenceFd = -1;
241     }
242 
243     return true;
244   }
245 
246   return false;
247 }
248 
CreateSolidFillLayers(HWCDisplay * hwc_display)249 int HWCColorManager::CreateSolidFillLayers(HWCDisplay *hwc_display) {
250   int ret = 0;
251 
252   if (!solid_fill_layers_) {
253     uint32_t size = sizeof(hwc_display_contents_1) + kNumSolidFillLayers * sizeof(hwc_layer_1_t);
254     uint32_t primary_width = 0;
255     uint32_t primary_height = 0;
256 
257     hwc_display->GetPanelResolution(&primary_width, &primary_height);
258     uint8_t *buf = new uint8_t[size]();
259     // handle for solid fill layer with fd = -1.
260     private_handle_t *handle =
261         new private_handle_t(-1, 0, private_handle_t::PRIV_FLAGS_FRAMEBUFFER, BUFFER_TYPE_UI,
262                              HAL_PIXEL_FORMAT_RGBA_8888, INT32(primary_width),
263                              INT32(primary_height));
264 
265     if (!buf || !handle) {
266       DLOGE("Failed to allocate memory.");
267       if (buf)
268         delete[] buf;
269       if (handle)
270         delete handle;
271 
272       return -ENOMEM;
273     }
274 
275     solid_fill_layers_ = reinterpret_cast<hwc_display_contents_1 *>(buf);
276     hwc_layer_1_t &layer = solid_fill_layers_->hwLayers[0];
277     layer.handle = handle;
278   }
279 
280   solid_fill_layers_->flags = HWC_GEOMETRY_CHANGED;
281   solid_fill_layers_->numHwLayers = kNumSolidFillLayers;
282   solid_fill_layers_->retireFenceFd = -1;
283   solid_fill_layers_->outbuf = NULL;
284   solid_fill_layers_->outbufAcquireFenceFd = -1;
285 
286   hwc_layer_1_t &layer = solid_fill_layers_->hwLayers[0];
287   hwc_rect_t solid_fill_rect = {
288       INT(solid_fill_params_.rect.x),
289       INT(solid_fill_params_.rect.y),
290       solid_fill_params_.rect.x + INT(solid_fill_params_.rect.width),
291       solid_fill_params_.rect.y + INT(solid_fill_params_.rect.height),
292   };
293 
294   layer.compositionType = HWC_FRAMEBUFFER;
295   layer.blending = HWC_BLENDING_PREMULT;
296   layer.sourceCropf.left = solid_fill_params_.rect.x;
297   layer.sourceCropf.top = solid_fill_params_.rect.y;
298   layer.sourceCropf.right = UINT32(solid_fill_params_.rect.x) + solid_fill_params_.rect.width;
299   layer.sourceCropf.bottom = UINT32(solid_fill_params_.rect.y) + solid_fill_params_.rect.height;
300   layer.acquireFenceFd = -1;
301   layer.releaseFenceFd = -1;
302   layer.flags = 0;
303   layer.transform = 0;
304   layer.hints = 0;
305   layer.planeAlpha = 0xff;
306   layer.displayFrame = solid_fill_rect;
307   layer.visibleRegionScreen.numRects = 1;
308   layer.visibleRegionScreen.rects = &layer.displayFrame;
309   layer.surfaceDamage.numRects = 0;
310 
311   return ret;
312 }
313 
DestroySolidFillLayers()314 void HWCColorManager::DestroySolidFillLayers() {
315   if (solid_fill_layers_) {
316     hwc_layer_1_t &layer = solid_fill_layers_->hwLayers[0];
317     uint8_t *buf = reinterpret_cast<uint8_t *>(solid_fill_layers_);
318     private_handle_t const *hnd = reinterpret_cast<private_handle_t const *>(layer.handle);
319 
320     if (hnd)
321         delete hnd;
322 
323     if (buf)
324         delete[] buf;
325 
326     solid_fill_layers_ = NULL;
327   }
328 }
329 
SetSolidFill(const void * params,bool enable,HWCDisplay * hwc_display)330 int HWCColorManager::SetSolidFill(const void *params, bool enable, HWCDisplay *hwc_display) {
331   SCOPE_LOCK(locker_);
332   int ret = 0;
333 
334   if (params) {
335     solid_fill_params_ = *reinterpret_cast<const PPColorFillParams *>(params);
336   } else {
337     solid_fill_params_ = PPColorFillParams();
338   }
339 
340   if (enable) {
341     // will create solid fill layers for rendering if not present.
342     ret = CreateSolidFillLayers(hwc_display);
343   } else {
344     DestroySolidFillLayers();
345   }
346   solid_fill_enable_ = enable;
347 
348   return ret;
349 }
350 
351 const HWCQDCMModeManager::ActiveFeatureCMD HWCQDCMModeManager::kActiveFeatureCMD[] = {
352     HWCQDCMModeManager::ActiveFeatureCMD("cabl:on", "cabl:off", "cabl:status", "running"),
353     HWCQDCMModeManager::ActiveFeatureCMD("ad:on", "ad:off", "ad:query:status", "running"),
354     HWCQDCMModeManager::ActiveFeatureCMD("svi:on", "svi:off", "svi:status", "running"),
355 };
356 
357 const char *const HWCQDCMModeManager::kSocketName = "pps";
358 const char *const HWCQDCMModeManager::kTagName = "surfaceflinger";
359 const char *const HWCQDCMModeManager::kPackageName = "colormanager";
360 
CreateQDCMModeMgr()361 HWCQDCMModeManager *HWCQDCMModeManager::CreateQDCMModeMgr() {
362   HWCQDCMModeManager *mode_mgr = new HWCQDCMModeManager();
363 
364   if (!mode_mgr) {
365     DLOGW("No memory to create HWCQDCMModeManager.");
366     return NULL;
367   } else {
368     mode_mgr->socket_fd_ =
369         ::socket_local_client(kSocketName, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
370     if (mode_mgr->socket_fd_ < 0) {
371       // it should not be disastrous and we still can grab wakelock in QDCM mode.
372       DLOGW("Unable to connect to dpps socket!");
373     }
374 
375     // retrieve system GPU idle timeout value for later to recover.
376     mode_mgr->entry_timeout_ = UINT32(HWCDebugHandler::GetIdleTimeoutMs());
377 
378     // acquire the binder handle to Android system PowerManager for later use.
379     android::sp<android::IBinder> binder =
380         android::defaultServiceManager()->checkService(android::String16("power"));
381     if (binder == NULL) {
382       DLOGW("Application can't connect to  power manager service");
383       delete mode_mgr;
384       mode_mgr = NULL;
385     } else {
386       mode_mgr->power_mgr_ = android::interface_cast<android::IPowerManager>(binder);
387     }
388   }
389 
390   return mode_mgr;
391 }
392 
~HWCQDCMModeManager()393 HWCQDCMModeManager::~HWCQDCMModeManager() {
394   if (socket_fd_ >= 0)
395     ::close(socket_fd_);
396 }
397 
AcquireAndroidWakeLock(bool enable)398 int HWCQDCMModeManager::AcquireAndroidWakeLock(bool enable) {
399   int ret = 0;
400 
401   if (enable) {
402     if (wakelock_token_ == NULL) {
403       android::sp<android::IBinder> binder = new android::BBinder();
404       android::status_t status = power_mgr_->acquireWakeLock(
405           (kFullWakeLock | kAcquireCauseWakeup | kONAfterRelease), binder,
406           android::String16(kTagName), android::String16(kPackageName));
407       if (status == android::NO_ERROR) {
408         wakelock_token_ = binder;
409       }
410     }
411   } else {
412     if (wakelock_token_ != NULL && power_mgr_ != NULL) {
413       power_mgr_->releaseWakeLock(wakelock_token_, 0);
414       wakelock_token_.clear();
415       wakelock_token_ = NULL;
416     }
417   }
418 
419   return ret;
420 }
421 
EnableActiveFeatures(bool enable,const HWCQDCMModeManager::ActiveFeatureCMD & cmds,bool * was_running)422 int HWCQDCMModeManager::EnableActiveFeatures(bool enable,
423                                              const HWCQDCMModeManager::ActiveFeatureCMD &cmds,
424                                              bool *was_running) {
425   int ret = 0;
426   ssize_t size = 0;
427   char response[kSocketCMDMaxLength] = {
428       0,
429   };
430 
431   if (socket_fd_ < 0) {
432     DLOGW("No socket connection available!");
433     return -EFAULT;
434   }
435 
436   if (!enable) {  // if client requesting to disable it.
437     // query CABL status, if off, no action. keep the status.
438     size = ::write(socket_fd_, cmds.cmd_query_status, strlen(cmds.cmd_query_status));
439     if (size < 0) {
440       DLOGW("Unable to send data over socket %s", ::strerror(errno));
441       ret = -EFAULT;
442     } else {
443       size = ::read(socket_fd_, response, kSocketCMDMaxLength);
444       if (size < 0) {
445         DLOGW("Unable to read data over socket %s", ::strerror(errno));
446         ret = -EFAULT;
447       } else if (!strncmp(response, cmds.running, strlen(cmds.running))) {
448         *was_running = true;
449       }
450     }
451 
452     if (*was_running) {  // if was running, it's requested to disable it.
453       size = ::write(socket_fd_, cmds.cmd_off, strlen(cmds.cmd_off));
454       if (size < 0) {
455         DLOGW("Unable to send data over socket %s", ::strerror(errno));
456         ret = -EFAULT;
457       }
458     }
459   } else {  // if was running, need enable it back.
460     if (*was_running) {
461       size = ::write(socket_fd_, cmds.cmd_on, strlen(cmds.cmd_on));
462       if (size < 0) {
463         DLOGW("Unable to send data over socket %s", ::strerror(errno));
464         ret = -EFAULT;
465       }
466     }
467   }
468 
469   return ret;
470 }
471 
EnableQDCMMode(bool enable,HWCDisplay * hwc_display)472 int HWCQDCMModeManager::EnableQDCMMode(bool enable, HWCDisplay *hwc_display) {
473   int ret = 0;
474 
475   ret = EnableActiveFeatures((enable ? false : true), kActiveFeatureCMD[kCABLFeature],
476                              &cabl_was_running_);
477   ret = AcquireAndroidWakeLock(enable);
478 
479   // if enter QDCM mode, disable GPU fallback idle timeout.
480   if (hwc_display) {
481     uint32_t timeout = enable ? 0 : entry_timeout_;
482     hwc_display->SetIdleTimeoutMs(timeout);
483   }
484 
485   return ret;
486 }
487 
488 }  // namespace sdm
489