From db274fa42ad251b0ddc8466f37e40997e7feedaf Mon Sep 17 00:00:00 2001 From: Prabhanjan Kandula Date: Mon, 30 Mar 2015 22:35:09 +0530 Subject: [PATCH] hwc : Set bw limit on mdss when camera is on. -Expose qservice API to get notified when Camera is on or off. -Set bandwidth hint to mdss based on camera launch status by writing into fb0/mdp/bw_mode_bitmap. -Implement camera service death notifier to recover display bw. Change-Id: I532f44281b5d7de1d638f1cef250114a3cc952ae --- libhwcomposer/hwc_qclient.cpp | 87 ++++++++++++++++++++++++++++++++++- libhwcomposer/hwc_qclient.h | 9 ++++ libqservice/IQService.h | 1 + libqservice/QServiceUtils.h | 4 ++ 4 files changed, 100 insertions(+), 1 deletion(-) diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp index f18ad366..5a1b047e 100644 --- a/libhwcomposer/hwc_qclient.cpp +++ b/libhwcomposer/hwc_qclient.cpp @@ -40,6 +40,8 @@ #include #define QCLIENT_DEBUG 0 +#define FILE_MAX_MDSSBW_FLAG \ + "/sys/devices/virtual/graphics/fb0/mdp/bw_mode_bitmap" using namespace android; using namespace qService; @@ -52,7 +54,8 @@ namespace qClient { // ---------------------------------------------------------------------------- QClient::QClient(hwc_context_t *ctx) : mHwcContext(ctx), - mMPDeathNotifier(new MPDeathNotifier(ctx)) + mMPDeathNotifier(new MPDeathNotifier(ctx)), + mCamDeathNotifier(new CamDeathNotifier()) { ALOGD_IF(QCLIENT_DEBUG, "QClient Constructor invoked"); } @@ -481,6 +484,84 @@ static status_t getDisplayAttributesForConfig(hwc_context_t* ctx, return NO_ERROR; } +/* register/unregister camera service */ +static bool setCameraDeathNotifier( + android::sp camDeathNotifier, bool on) { + sp sm = defaultServiceManager(); + sp binder = sm->getService(String16("media.camera")); + if (binder == 0) { + ALOGW("%s: CameraService not published or dead...", __FUNCTION__); + return false; + } + if(on) { + binder->linkToDeath(camDeathNotifier); + } else { + binder->unlinkToDeath(camDeathNotifier); + } + return true; +} + +static bool updateDisplayBWCapForCam(bool on) { + char sysfsPath[255]; + char bw[64]; + int bw_flag = 0; // to reset to default. + + memset(sysfsPath, 0, sizeof(sysfsPath)); + snprintf(sysfsPath , sizeof(sysfsPath), FILE_MAX_MDSSBW_FLAG); + int sysfsFd = open(sysfsPath, O_RDWR); + if(sysfsFd < 0 ) { + ALOGE("%s: Status: %d Error in opening %s: %s", + __FUNCTION__, on, sysfsPath, strerror(errno)); + return false; + } + + if(on) { + bw_flag = MDSS_MAX_BW_LIMIT_CAMERA; + } + snprintf(bw, sizeof(bw), "%d", bw_flag); + ssize_t bytes = pwrite(sysfsFd, bw, strlen(bw), 0); + if(bytes < 0) { + ALOGE ("%s: Unable to write into %s node %s", + __FUNCTION__, sysfsPath, strerror(errno)); + close(sysfsFd); + return false; + } + close(sysfsFd); + return true; +} + +static void setCameraStatus(hwc_context_t* ctx, + android::sp camDeathNotifier, uint32_t on) { + + //Currently we need this only for 8952. + if(!MDPVersion::getInstance().is8x52()) { + ALOGI("%s Not 8952?? return", __FUNCTION__); + return; + } + + if(!setCameraDeathNotifier(camDeathNotifier, on)) { + ALOGE("%s failed in updateCameraStatus", __FUNCTION__); + return; + } + + if(!updateDisplayBWCapForCam(on)) { + ALOGE("%s failed in updateDisplayBWCap", __FUNCTION__); + return; + } + + // Trigger a screen update so that our BW setting will reflect + // atleast by next vsync. + screenRefresh(ctx); +} + +void QClient::CamDeathNotifier::binderDied(const wp& who) { + //If Cameraservice abruptly gone, reset mdss bw caps + //This new cap will be applicable from next frame onwards + if(!updateDisplayBWCapForCam(false)) { + ALOGE("%s failed in updateDisplayBWCap", __FUNCTION__); + } +} + status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel, Parcel* outParcel) { status_t ret = NO_ERROR; @@ -559,6 +640,10 @@ status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel, case IQService::QDCM_SVC_CMDS: qdcmCmdsHandler(mHwcContext, inParcel, outParcel); break; + case IQService::SET_CAMERA_STATUS: + setCameraStatus(mHwcContext, + mCamDeathNotifier, inParcel->readInt32()); + break; default: ret = NO_ERROR; } diff --git a/libhwcomposer/hwc_qclient.h b/libhwcomposer/hwc_qclient.h index d9553773..c1371f5c 100644 --- a/libhwcomposer/hwc_qclient.h +++ b/libhwcomposer/hwc_qclient.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,13 @@ public: const android::Parcel* inParcel, android::Parcel* outParcel); + //Notifies camera service death + class CamDeathNotifier : public IBinder::DeathRecipient { + public: + CamDeathNotifier(){} + virtual void binderDied(const android::wp& who); + }; + private: //Notifies of Media Player death class MPDeathNotifier : public android::IMediaDeathNotifier { @@ -62,6 +70,7 @@ private: hwc_context_t *mHwcContext; const android::sp mMPDeathNotifier; + const android::sp mCamDeathNotifier; }; }; // namespace qClient #endif // ANDROID_QCLIENT_H diff --git a/libqservice/IQService.h b/libqservice/IQService.h index 50545781..0f69d40e 100644 --- a/libqservice/IQService.h +++ b/libqservice/IQService.h @@ -69,6 +69,7 @@ public: GET_CONFIG_COUNT = 27, //Get the number of supported display configs GET_DISPLAY_ATTRIBUTES_FOR_CONFIG = 28, //Get attr for specified config SET_DISPLAY_MODE = 29, // Set display mode to command or video mode + SET_CAMERA_STATUS = 30, // To notify display when camera is on and off COMMAND_LIST_END = 400, }; diff --git a/libqservice/QServiceUtils.h b/libqservice/QServiceUtils.h index 71277e8b..62ee0d11 100644 --- a/libqservice/QServiceUtils.h +++ b/libqservice/QServiceUtils.h @@ -91,4 +91,8 @@ inline android::status_t setBufferMirrorMode(uint32_t enable) { return sendSingleParam(qService::IQService::BUFFER_MIRRORMODE, enable); } +inline android::status_t setCameraLaunchStatus(uint32_t on) { + return sendSingleParam(qService::IQService::SET_CAMERA_STATUS, on); +} + #endif /* end of include guard: QSERVICEUTILS_H */