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
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index f18ad36..5a1b047 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -40,6 +40,8 @@
#include <hwc_qdcm.h>
#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 @@
// ----------------------------------------------------------------------------
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 @@
return NO_ERROR;
}
+/* register/unregister camera service */
+static bool setCameraDeathNotifier(
+ android::sp<QClient::CamDeathNotifier> camDeathNotifier, bool on) {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> 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<QClient::CamDeathNotifier> 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<IBinder>& 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 @@
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 d955377..c1371f5 100644
--- a/libhwcomposer/hwc_qclient.h
+++ b/libhwcomposer/hwc_qclient.h
@@ -33,6 +33,7 @@
#include <utils/Errors.h>
#include <sys/types.h>
#include <cutils/log.h>
+#include <utils/RefBase.h>
#include <binder/IServiceManager.h>
#include <media/IMediaDeathNotifier.h>
#include <IQClient.h>
@@ -51,6 +52,13 @@
const android::Parcel* inParcel,
android::Parcel* outParcel);
+ //Notifies camera service death
+ class CamDeathNotifier : public IBinder::DeathRecipient {
+ public:
+ CamDeathNotifier(){}
+ virtual void binderDied(const android::wp<IBinder>& who);
+ };
+
private:
//Notifies of Media Player death
class MPDeathNotifier : public android::IMediaDeathNotifier {
@@ -62,6 +70,7 @@
hwc_context_t *mHwcContext;
const android::sp<android::IMediaDeathNotifier> mMPDeathNotifier;
+ const android::sp<QClient::CamDeathNotifier> mCamDeathNotifier;
};
}; // namespace qClient
#endif // ANDROID_QCLIENT_H
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 5054578..0f69d40 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -69,6 +69,7 @@
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 71277e8..62ee0d1 100644
--- a/libqservice/QServiceUtils.h
+++ b/libqservice/QServiceUtils.h
@@ -91,4 +91,8 @@
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 */