Home | History | Annotate | Download | only in libhwcomposer
      1 /*
      2  *  Copyright (c) 2013-14, 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 CLIENTS; 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 <hwc_qclient.h>
     31 #include <IQService.h>
     32 #include <hwc_utils.h>
     33 #include <mdp_version.h>
     34 #include <hwc_mdpcomp.h>
     35 
     36 #define QCLIENT_DEBUG 0
     37 
     38 using namespace android;
     39 using namespace qService;
     40 using namespace qhwc;
     41 
     42 namespace qClient {
     43 
     44 // ----------------------------------------------------------------------------
     45 QClient::QClient(hwc_context_t *ctx) : mHwcContext(ctx),
     46         mMPDeathNotifier(new MPDeathNotifier(ctx))
     47 {
     48     ALOGD_IF(QCLIENT_DEBUG, "QClient Constructor invoked");
     49 }
     50 
     51 QClient::~QClient()
     52 {
     53     ALOGD_IF(QCLIENT_DEBUG,"QClient Destructor invoked");
     54 }
     55 
     56 static void securing(hwc_context_t *ctx, uint32_t startEnd) {
     57     Locker::Autolock _sl(ctx->mDrawLock);
     58     //The only way to make this class in this process subscribe to media
     59     //player's death.
     60     IMediaDeathNotifier::getMediaPlayerService();
     61 
     62     ctx->mSecuring = startEnd;
     63     //We're done securing
     64     if(startEnd == IQService::END)
     65         ctx->mSecureMode = true;
     66     if(ctx->proc)
     67         ctx->proc->invalidate(ctx->proc);
     68 }
     69 
     70 static void unsecuring(hwc_context_t *ctx, uint32_t startEnd) {
     71     Locker::Autolock _sl(ctx->mDrawLock);
     72     ctx->mSecuring = startEnd;
     73     //We're done unsecuring
     74     if(startEnd == IQService::END)
     75         ctx->mSecureMode = false;
     76     if(ctx->proc)
     77         ctx->proc->invalidate(ctx->proc);
     78 }
     79 
     80 void QClient::MPDeathNotifier::died() {
     81     Locker::Autolock _sl(mHwcContext->mDrawLock);
     82     ALOGD_IF(QCLIENT_DEBUG, "Media Player died");
     83     mHwcContext->mSecuring = false;
     84     mHwcContext->mSecureMode = false;
     85     if(mHwcContext->proc)
     86         mHwcContext->proc->invalidate(mHwcContext->proc);
     87 }
     88 
     89 static android::status_t screenRefresh(hwc_context_t *ctx) {
     90     status_t result = NO_INIT;
     91     if(ctx->proc) {
     92         ctx->proc->invalidate(ctx->proc);
     93         result = NO_ERROR;
     94     }
     95     return result;
     96 }
     97 
     98 static void setExtOrientation(hwc_context_t *ctx, uint32_t orientation) {
     99     ctx->mExtOrientation = orientation;
    100 }
    101 
    102 static void isExternalConnected(hwc_context_t* ctx, Parcel* outParcel) {
    103     int connected;
    104     connected = ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected ? 1 : 0;
    105     outParcel->writeInt32(connected);
    106 }
    107 
    108 static void getDisplayAttributes(hwc_context_t* ctx, const Parcel* inParcel,
    109         Parcel* outParcel) {
    110     int dpy = inParcel->readInt32();
    111     outParcel->writeInt32(ctx->dpyAttr[dpy].vsync_period);
    112     if (ctx->dpyAttr[dpy].customFBSize) {
    113         outParcel->writeInt32(ctx->dpyAttr[dpy].xres_new);
    114         outParcel->writeInt32(ctx->dpyAttr[dpy].yres_new);
    115     } else {
    116         outParcel->writeInt32(ctx->dpyAttr[dpy].xres);
    117         outParcel->writeInt32(ctx->dpyAttr[dpy].yres);
    118     }
    119     outParcel->writeFloat(ctx->dpyAttr[dpy].xdpi);
    120     outParcel->writeFloat(ctx->dpyAttr[dpy].ydpi);
    121     //XXX: Need to check what to return for HDMI
    122     outParcel->writeInt32(ctx->mMDP.panel);
    123 }
    124 static void setHSIC(const Parcel* inParcel) {
    125     int dpy = inParcel->readInt32();
    126     ALOGD_IF(0, "In %s: dpy = %d", __FUNCTION__, dpy);
    127     HSICData_t hsic_data;
    128     hsic_data.hue = inParcel->readInt32();
    129     hsic_data.saturation = inParcel->readFloat();
    130     hsic_data.intensity = inParcel->readInt32();
    131     hsic_data.contrast = inParcel->readFloat();
    132     //XXX: Actually set the HSIC data through ABL lib
    133 }
    134 
    135 
    136 static void setBufferMirrorMode(hwc_context_t *ctx, uint32_t enable) {
    137     ctx->mBufferMirrorMode = enable;
    138 }
    139 
    140 static status_t getDisplayVisibleRegion(hwc_context_t* ctx, int dpy,
    141                                 Parcel* outParcel) {
    142     // Get the info only if the dpy is valid
    143     if(dpy >= HWC_DISPLAY_PRIMARY && dpy <= HWC_DISPLAY_VIRTUAL) {
    144         Locker::Autolock _sl(ctx->mDrawLock);
    145         if(dpy && (ctx->mExtOrientation || ctx->mBufferMirrorMode)) {
    146             // Return the destRect on external, if external orienation
    147             // is enabled
    148             outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.left);
    149             outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.top);
    150             outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.right);
    151             outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.bottom);
    152         } else {
    153             outParcel->writeInt32(ctx->mViewFrame[dpy].left);
    154             outParcel->writeInt32(ctx->mViewFrame[dpy].top);
    155             outParcel->writeInt32(ctx->mViewFrame[dpy].right);
    156             outParcel->writeInt32(ctx->mViewFrame[dpy].bottom);
    157         }
    158         return NO_ERROR;
    159     } else {
    160         ALOGE("In %s: invalid dpy index %d", __FUNCTION__, dpy);
    161         return BAD_VALUE;
    162     }
    163 }
    164 
    165 static void pauseWFD(hwc_context_t *ctx, uint32_t pause) {
    166     /* TODO: Will remove pauseWFD once all the clients start using
    167      * setWfdStatus to indicate the status of WFD display
    168      */
    169     int dpy = HWC_DISPLAY_VIRTUAL;
    170     if(pause) {
    171         //WFD Pause
    172         handle_pause(ctx, dpy);
    173     } else {
    174         //WFD Resume
    175         handle_resume(ctx, dpy);
    176     }
    177 }
    178 
    179 static void setWfdStatus(hwc_context_t *ctx, uint32_t wfdStatus) {
    180 
    181     ALOGD_IF(HWC_WFDDISPSYNC_LOG,
    182              "%s: Received a binder call that WFD state is %s",
    183              __FUNCTION__,getExternalDisplayState(wfdStatus));
    184     int dpy = HWC_DISPLAY_VIRTUAL;
    185 
    186     if(wfdStatus == EXTERNAL_OFFLINE) {
    187         ctx->mWfdSyncLock.lock();
    188         ctx->mWfdSyncLock.signal();
    189         ctx->mWfdSyncLock.unlock();
    190     } else if(wfdStatus == EXTERNAL_PAUSE) {
    191         handle_pause(ctx, dpy);
    192     } else if(wfdStatus == EXTERNAL_RESUME) {
    193         handle_resume(ctx, dpy);
    194     }
    195 }
    196 
    197 
    198 static status_t setViewFrame(hwc_context_t* ctx, const Parcel* inParcel) {
    199     int dpy = inParcel->readInt32();
    200     if(dpy >= HWC_DISPLAY_PRIMARY && dpy <= HWC_DISPLAY_VIRTUAL) {
    201         Locker::Autolock _sl(ctx->mDrawLock);
    202         ctx->mViewFrame[dpy].left   = inParcel->readInt32();
    203         ctx->mViewFrame[dpy].top    = inParcel->readInt32();
    204         ctx->mViewFrame[dpy].right  = inParcel->readInt32();
    205         ctx->mViewFrame[dpy].bottom = inParcel->readInt32();
    206         ALOGD_IF(QCLIENT_DEBUG, "%s: mViewFrame[%d] = [%d %d %d %d]",
    207             __FUNCTION__, dpy,
    208             ctx->mViewFrame[dpy].left, ctx->mViewFrame[dpy].top,
    209             ctx->mViewFrame[dpy].right, ctx->mViewFrame[dpy].bottom);
    210         return NO_ERROR;
    211     } else {
    212         ALOGE("In %s: invalid dpy index %d", __FUNCTION__, dpy);
    213         return BAD_VALUE;
    214     }
    215 }
    216 
    217 static void toggleDynamicDebug(hwc_context_t* ctx, const Parcel* inParcel) {
    218     int debug_type = inParcel->readInt32();
    219     bool enable = !!inParcel->readInt32();
    220     ALOGD("%s: debug_type: %d enable:%d",
    221             __FUNCTION__, debug_type, enable);
    222     Locker::Autolock _sl(ctx->mDrawLock);
    223     switch (debug_type) {
    224         //break is ignored for DEBUG_ALL to toggle all of them at once
    225         case IQService::DEBUG_ALL:
    226         case IQService::DEBUG_MDPCOMP:
    227             qhwc::MDPComp::dynamicDebug(enable);
    228             if (debug_type != IQService::DEBUG_ALL)
    229                 break;
    230         case IQService::DEBUG_VSYNC:
    231             ctx->vstate.debug = enable;
    232             if (debug_type != IQService::DEBUG_ALL)
    233                 break;
    234     }
    235 }
    236 
    237 status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
    238         Parcel* outParcel) {
    239     status_t ret = NO_ERROR;
    240 
    241     switch(command) {
    242         case IQService::SECURING:
    243             securing(mHwcContext, inParcel->readInt32());
    244             break;
    245         case IQService::UNSECURING:
    246             unsecuring(mHwcContext, inParcel->readInt32());
    247             break;
    248         case IQService::SCREEN_REFRESH:
    249             return screenRefresh(mHwcContext);
    250             break;
    251         case IQService::EXTERNAL_ORIENTATION:
    252             setExtOrientation(mHwcContext, inParcel->readInt32());
    253             break;
    254         case IQService::BUFFER_MIRRORMODE:
    255             setBufferMirrorMode(mHwcContext, inParcel->readInt32());
    256             break;
    257         case IQService::GET_DISPLAY_VISIBLE_REGION:
    258             ret = getDisplayVisibleRegion(mHwcContext, inParcel->readInt32(),
    259                                     outParcel);
    260             break;
    261         case IQService::CHECK_EXTERNAL_STATUS:
    262             isExternalConnected(mHwcContext, outParcel);
    263             break;
    264         case IQService::GET_DISPLAY_ATTRIBUTES:
    265             getDisplayAttributes(mHwcContext, inParcel, outParcel);
    266             break;
    267         case IQService::SET_HSIC_DATA:
    268             setHSIC(inParcel);
    269             break;
    270         case IQService::PAUSE_WFD:
    271             pauseWFD(mHwcContext, inParcel->readInt32());
    272             break;
    273         case IQService::SET_WFD_STATUS:
    274             setWfdStatus(mHwcContext,inParcel->readInt32());
    275             break;
    276         case IQService::SET_VIEW_FRAME:
    277             setViewFrame(mHwcContext, inParcel);
    278             break;
    279         case IQService::DYNAMIC_DEBUG:
    280             toggleDynamicDebug(mHwcContext, inParcel);
    281             break;
    282         default:
    283             ret = NO_ERROR;
    284     }
    285     return ret;
    286 }
    287 
    288 }
    289