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