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 // ----------------------------------------------------------------------------
QClient(hwc_context_t * ctx)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 
~QClient()50 QClient::~QClient()
51 {
52     ALOGD_IF(QCLIENT_DEBUG,"QClient Destructor invoked");
53 }
54 
securing(hwc_context_t * ctx,uint32_t startEnd)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 
unsecuring(hwc_context_t * ctx,uint32_t startEnd)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 
died()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 
screenRefresh(hwc_context_t * ctx)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 
setExtOrientation(hwc_context_t * ctx,uint32_t orientation)97 static void setExtOrientation(hwc_context_t *ctx, uint32_t orientation) {
98     ctx->mExtOrientation = orientation;
99 }
100 
isExternalConnected(hwc_context_t * ctx,Parcel * outParcel)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 
getDisplayAttributes(hwc_context_t * ctx,const Parcel * inParcel,Parcel * outParcel)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 }
setHSIC(const Parcel * inParcel)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 
setBufferMirrorMode(hwc_context_t * ctx,uint32_t enable)130 static void setBufferMirrorMode(hwc_context_t *ctx, uint32_t enable) {
131     ctx->mBufferMirrorMode = enable;
132 }
133 
getDisplayVisibleRegion(hwc_context_t * ctx,int dpy,Parcel * outParcel)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 
pauseWFD(hwc_context_t * ctx,uint32_t pause)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 
setWfdStatus(hwc_context_t * ctx,uint32_t wfdStatus)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 
notifyCallback(uint32_t command,const Parcel * inParcel,Parcel * outParcel)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