unplugged-system/frameworks/native/libs/gui/mediatek/MTKFrameBudgetIndicator.cpp

290 lines
11 KiB
C++

/* Copyright Statement:
*
* This software/firmware and related documentation ("MediaTek Software") are
* protected under relevant copyright laws. The information contained herein is
* confidential and proprietary to MediaTek Inc. and/or its licensors. Without
* the prior written permission of MediaTek inc. and/or its licensors, any
* reproduction, modification, use or disclosure of MediaTek Software, and
* information contained herein, in whole or in part, shall be strictly
* prohibited.
*
* MediaTek Inc. (C) 2010. All rights reserved.
*
* BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
* ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
* RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
* INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
* TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
* RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
* OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
* SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
* RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
* STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
* ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
* RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
* MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
* CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
*
* The following software/firmware and/or related documentation ("MediaTek
* Software") have been modified by MediaTek Inc. All revisions are subject to
* any receiver's applicable license agreements with MediaTek Inc.
*/
#define LOG_TAG "FBI"
#include <dlfcn.h>
#include <stdio.h>
#include <unistd.h>
#include "utils/Log.h"
#include "gui/mediatek/MTKFrameBudgetIndicator.h"
#include <linux/types.h>
#include <pthread.h>
static int (*fpNotifyQueue)(__u32, __u64, __s32, __u64) = nullptr;
static int (*fpNotifyDequeue)(__u32, __u64, __s32, __u64) = nullptr;
static int (*fpNotifyConnect)(__u32, __u64, __u32, __u64) = nullptr;
static int (*fpNotifyBqid)(__u32, __u64, __s32, __u64) = nullptr;
static int (*fpNotifyAcquire)(__u32, __u32, __u32, __u64) = nullptr;
static int (*fpNotifyBufferQuota)(__u32, __s32, __u64) = nullptr;
static void *handle = nullptr, *func = nullptr;
typedef int (*FpNotifyQueue)(__u32, __u64, __s32, __u64);
typedef int (*FpNotifyDequeue)(__u32, __u64, __s32, __u64);
typedef int (*FpNotifyConnect)(__u32, __u64, __u32, __u64);
typedef int (*FpNotifyBqid)(__u32, __u64, __s32, __u64);
typedef int (*FpNotifyAcquire)(__u32, __u32, __u32, __u64);
typedef int (*FpNotifyBufferQuota)(__u32, __s32, __u64);
static void *handle2 = nullptr;
static int (*fpMagtSyncNotify)(__u32, __u64, __s32, __u64) = nullptr;
static bool enableMagtSync = false;
static uid_t uid = 0;
#define LIB_FULL_NAME "libperfctl.so"
#define LIB_MAGT_SYNC_NAME "libmagtsync.so"
void fbcInit() {
static bool inited = false;
static pthread_mutex_t mMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&mMutex);
if (inited) {
pthread_mutex_unlock(&mMutex);
return;
}
/*
* Consider if library or funcion is missing, re-try helps
* nothing but lots of error logs. Thus, just init once no
* matter if anything is well-prepared or not. However,
* entire init flow should be lock-protected.
*/
inited = true;
handle = dlopen(LIB_FULL_NAME, RTLD_NOW);
if (handle == NULL) {
ALOGE("Can't load library: %s", dlerror());
pthread_mutex_unlock(&mMutex);
return;
}
func = dlsym(handle, "xgfNotifyQueue");
fpNotifyQueue = reinterpret_cast<FpNotifyQueue>(func);
if (fpNotifyQueue == NULL) {
ALOGE("xgfNotifyQueue error: %s", dlerror());
goto err_fbcInit;
}
func = dlsym(handle, "xgfNotifyDequeue");
fpNotifyDequeue = reinterpret_cast<FpNotifyDequeue>(func);
if (fpNotifyDequeue == NULL) {
ALOGE("xgfNotifyDequeue error: %s", dlerror());
goto err_fbcInit;
}
func = dlsym(handle, "xgfNotifyConnect");
fpNotifyConnect = reinterpret_cast<FpNotifyConnect>(func);
if (fpNotifyConnect == NULL) {
ALOGE("xgfNotifyConnect error: %s", dlerror());
goto err_fbcInit;
}
func = dlsym(handle, "xgfNotifyBqid");
fpNotifyBqid = reinterpret_cast<FpNotifyBqid>(func);
if (fpNotifyBqid == NULL) {
ALOGE("xgfNotifyBqid error: %s", dlerror());
goto err_fbcInit;
}
func = dlsym(handle, "xgfNotifyAcquire");
fpNotifyAcquire = reinterpret_cast<FpNotifyAcquire>(func);
if (fpNotifyAcquire == NULL) {
ALOGE("xgfNotifyAcquire error: %s", dlerror());
}
func = dlsym(handle, "xgfNotifyBufferQuota");
fpNotifyBufferQuota = reinterpret_cast<FpNotifyBufferQuota>(func);
if (fpNotifyBufferQuota == NULL) {
ALOGE("xgfNotifyBufferQuota is NULL: %s", dlerror());
}
uid = geteuid();
if (uid >= 10000) {
handle2 = dlopen(LIB_MAGT_SYNC_NAME, RTLD_NOW);
if (handle2 == NULL) {
ALOGE("Can't load library: %s", dlerror());
pthread_mutex_unlock(&mMutex);
return;
}
func = dlsym(handle2, "magt_sync_notify");
fpMagtSyncNotify = reinterpret_cast<FpNotifyQueue>(func);
if (fpMagtSyncNotify == NULL) {
ALOGE("magt_sync_notify error: %s", dlerror());
//goto err_fbcInit;
}
else {
enableMagtSync = true;
}
} else {
enableMagtSync = false;
}
pthread_mutex_unlock(&mMutex);
return;
err_fbcInit:
fpNotifyQueue = NULL;
fpNotifyDequeue = NULL;
fpMagtSyncNotify = NULL;
fpNotifyBufferQuota = NULL;
dlclose(handle);
dlclose(handle2);
pthread_mutex_unlock(&mMutex);
}
android::status_t notifyFbc(const int32_t& value, const uint64_t& bufID, const int32_t& param, const uint64_t& id) {
fbcInit();
switch (value) {
case FBC_CNT:
case FBC_DISCNT:
if (fpNotifyConnect) {
const int32_t err = fpNotifyConnect(value == FBC_CNT ? 1 : 0, 0, static_cast<__u32>(param), id);
if (err != android::NO_ERROR) {
ALOGE("notifyConnect(%d %d) err:%d", value, param, err);
return android::INVALID_OPERATION;
}
} else {
ALOGE("notifyConnect load error");
return android::NO_INIT;
}
break;
case FBC_QUEUE_BEG:
case FBC_QUEUE_END:
if (fpNotifyQueue) {
const int32_t err = fpNotifyQueue(value == FBC_QUEUE_BEG ? 1 : 0, 0, 0, id);
if (err != android::NO_ERROR) {
ALOGE("notifyQueue(%d) err:%d", value, err);
return android::INVALID_OPERATION;
}
} else {
ALOGE("notifyQueue load error");
return android::NO_INIT;
}
if (enableMagtSync) {
if (fpMagtSyncNotify) {
const int32_t err = fpMagtSyncNotify(value, 0, value == FBC_QUEUE_BEG ? 1 : 0, id);
if (err != android::NO_ERROR) {
ALOGE("fpMagtSyncNotify(%d) err:%d", value, err);
return android::INVALID_OPERATION;
}
} else {
ALOGE("MAGT sync notify load error");
return android::NO_INIT;
}
}
break;
case FBC_DEQUEUE_BEG:
case FBC_DEQUEUE_END:
if (fpNotifyDequeue) {
const int32_t err = fpNotifyDequeue(value == FBC_DEQUEUE_BEG ? 1 : 0, 0, 0, id);
if (err != android::NO_ERROR) {
ALOGE("notifyDequeue(%d) err:%d", value, err);
return android::INVALID_OPERATION;
}
} else {
ALOGE("notifyDequeue load error");
return android::NO_INIT;
}
if (enableMagtSync) {
if (fpMagtSyncNotify) {
const int32_t err = fpMagtSyncNotify(value, 0, value == FBC_DEQUEUE_BEG ? 1 : 0, id);
if (err != android::NO_ERROR) {
ALOGE("magtSyncNotify(%d) err:%d", value, err);
return android::INVALID_OPERATION;
}
} else {
ALOGE("magtSyncNotify load error");
return android::NO_INIT;
}
}
break;
case FBC_BQID:
case FBC_BQID_DES:
if (fpNotifyBqid) {
const int32_t err = fpNotifyBqid(value == FBC_BQID ? 1 : 0, bufID, param, id);
if (err != android::NO_ERROR) {
ALOGE("notifyIdUsage err:%d", err);
return android::INVALID_OPERATION;
}
} else {
ALOGE("notifyIdUsage load error");
return android::NO_INIT;
}
break;
case FBC_ACQUIRE:
if (fpNotifyAcquire) {
const int32_t err = fpNotifyAcquire(getpid(), static_cast<__u32>(id), static_cast<__u32>(param), bufID);
if (err != android::NO_ERROR) {
ALOGE("notifyAcquireUsage err:%d", err);
return android::INVALID_OPERATION;
}
} else {
ALOGE("notifyAcquireUsage load error");
return android::NO_INIT;
}
break;
case FBC_BUFFER_QUOTA:
if (fpNotifyBufferQuota) {
__u32 buffer_quota = static_cast<__u32>(bufID);
const int32_t err = fpNotifyBufferQuota(buffer_quota, param, id);
if (err != android::NO_ERROR) {
ALOGE("notifyBufferQuota(%d-%d) err:%d", buffer_quota, param, err);
return android::INVALID_OPERATION;
}
} else {
ALOGE("notifyBufferQuota load is NULL.");
return android::NO_INIT;
}
break;
}
return android::NO_ERROR;
}