/* 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 #include #include #include "utils/Log.h" #include "gui/mediatek/MTKFrameBudgetIndicator.h" #include #include 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(func); if (fpNotifyQueue == NULL) { ALOGE("xgfNotifyQueue error: %s", dlerror()); goto err_fbcInit; } func = dlsym(handle, "xgfNotifyDequeue"); fpNotifyDequeue = reinterpret_cast(func); if (fpNotifyDequeue == NULL) { ALOGE("xgfNotifyDequeue error: %s", dlerror()); goto err_fbcInit; } func = dlsym(handle, "xgfNotifyConnect"); fpNotifyConnect = reinterpret_cast(func); if (fpNotifyConnect == NULL) { ALOGE("xgfNotifyConnect error: %s", dlerror()); goto err_fbcInit; } func = dlsym(handle, "xgfNotifyBqid"); fpNotifyBqid = reinterpret_cast(func); if (fpNotifyBqid == NULL) { ALOGE("xgfNotifyBqid error: %s", dlerror()); goto err_fbcInit; } func = dlsym(handle, "xgfNotifyAcquire"); fpNotifyAcquire = reinterpret_cast(func); if (fpNotifyAcquire == NULL) { ALOGE("xgfNotifyAcquire error: %s", dlerror()); } func = dlsym(handle, "xgfNotifyBufferQuota"); fpNotifyBufferQuota = reinterpret_cast(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(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; }