You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

292 lines
8.8 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2020. All rights reserved.
* Description: NxMediaPlayerFactory class implement
* Author: NxPlayer software group
* Create: 2019-11-21
*/
#define LOG_NDEBUG 0
#define LOG_TAG "NP_Factory"
#include "NxMediaPlayerFactory.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <utils/KeyedVector.h>
#include <utils/String8.h>
#include <utils/Log.h>
#include <cutils/properties.h>
#include <binder/IPCThreadState.h>
#include "NxMetadataRetriever.h"
#include "NxMediaPlayerManage.h"
using ::android::hardware::hidl_handle;
namespace android {
const std::string PROPERTY_NP_FF_NXPLAYER = "persist.sys.media.np.ff.nxplayer";
const std::string PROPERTY_NP_OUTPUT = "persist.sys.media.np.output";
const int BUF_SIZE = 1024;
const int PROC_FILE_SIZE = 64;
/* NxPlayer not support even in graphics output mode */
std::vector<std::string> NxMediaPlayerFactory::g_accseeAllowedList = {
"cent.qqmusic",
"cts.media",
"cts.mediastress",
"cts.hardware",
"media.cts",
"areinfo.alibaba",
"view.cts",
"false.cts",
"security.cts",
"media.gts",
"drm.cts",
"d.process.media",
"ernalstorageapp"
};
/* NxPlayer in VO output mode */
std::vector<std::string> NxMediaPlayerFactory::g_whiteListOthers = {
"android.youtube",
"android.chrome",
"com.UCMobile",
"cent.qqmusic",
"cts.media",
"cts.mediastress",
"cts.hardware",
"media.cts",
"areinfo.alibaba",
"view.cts",
"false.cts",
"security.cts",
"media.gts",
"drm.cts",
"d.process.media",
"ernalstorageapp",
"ndroid.systemui",
"s.device.statsd", /* com.android.server.cts.device.statsd.AtomTests */
"artext.true.cts", /* android.netsecpolicy.usescleartext.true.cts */
"unspecified.cts", /* android.netsecpolicy.usescleartext.unspecified.cts */
"mediastress.cts", /* android.mediastress.cts */
"id.cts.verifier", /* com.android.cts.verifier */
"roid.camera.cts", /* android.camera.cts */
};
/* MIDI case use default_player */
std::vector<std::string> NxMediaPlayerFactory::g_fileExts = {
".mid",
".midi",
".smf",
".xmf",
".mxmf",
".imy",
".rtttl",
".rtx",
".ota"
};
bool NxMediaPlayerFactory ::IsFileAccess(const int fd) const
{
ALOGD("call %s, fd=%d", __FUNCTION__, fd);
sp<INxMediaPlayerStore_V1_1> playerStore;
playerStore = INxMediaPlayerStore_V1_1::getService();
if (playerStore.get() == nullptr) {
ALOGE("%s, get nxplayer service failed!", NMP_VIP_TAG);
return false;
}
native_handle_t * const nativeHdl = native_handle_create(1, 0);
if (nativeHdl == nullptr) {
return false;
}
nativeHdl->data[0] = fd;
hidl_handle fdHandle;
fdHandle.setTo(nativeHdl, false);
Return<int32_t> transCheckPermissiveForPlayer = playerStore->checkFileAccess(fdHandle);
(void)native_handle_delete(nativeHdl);
if (!transCheckPermissiveForPlayer.isOk() || static_cast<int32_t>(transCheckPermissiveForPlayer) == 0) {
ALOGW("%s, nxplayer can not play it, access fd=%d permission denied", NMP_VIP_TAG, fd);
return false;
}
return true;
}
float NxMediaPlayerFactory ::scoreFactory(const char *url, float curScore)
{
static const float kOurScore = 1.0;
if (curScore >= kOurScore) {
return 0.0;
}
/* unsupport play local stream with url, local stream uses fd to play */
if (url == nullptr || url[0] == '/') {
ALOGW("%s, nxplayer can not play it, url is null or start with '/'", NMP_VIP_TAG);
return 0.0;
}
if (!IsNxPlayerSupport()) {
return 0.0;
}
/* unsupport url MidiFile use MidiFile for MIDI extensions */
unsigned int lenURL = strlen(url);
for (auto it = g_fileExts.begin(); it != g_fileExts.end(); it++) {
unsigned int len = strlen((*it).c_str());
int start = lenURL - len;
if (start <= 0) {
continue;
}
if (strncasecmp(url + start, (*it).c_str(), len) == 0) {
ALOGW("%s, nxplayer can not play it, url extension name=%s", NMP_VIP_TAG, (*it).c_str());
return 0.0;
}
}
ALOGD("call %s uri, kOurScore=%.1f", __FUNCTION__, kOurScore);
return kOurScore;
}
float NxMediaPlayerFactory ::scoreFactory(int fd)
{
static const float kOurScore = 0.7; /* should <= 0.8 due to mid file */
char filePath[PROC_FILE_SIZE] = {0};
char dataSrcPath[BUF_SIZE + 1] = {0};
if (!IsNxPlayerSupport()) {
return 0.0;
}
/* modify for cts testEncodingDetection */
int ret = snprintf_s(filePath, PROC_FILE_SIZE, PROC_FILE_SIZE - 1, "/proc/%d/fd/%d", getpid(), fd);
if (ret < 0) {
ALOGE("[%s:%d] snprintf_s failed!\n", __FUNCTION__, __LINE__);
return 0.0;
}
readlink(filePath, dataSrcPath, BUF_SIZE);
if (strstr(dataSrcPath, "android.media.cts") || strstr(dataSrcPath, "cts.verifier")) {
ALOGW("%s, nxplayer can not play it, dataSrcPath restricted!", NMP_VIP_TAG);
return 0.0;
}
if (!IsFileAccess(fd)) {
return 0.0;
}
unsigned int lenURL = strlen(dataSrcPath);
for (auto it = g_fileExts.begin(); it != g_fileExts.end(); it++) {
unsigned int len = strlen((*it).c_str());
int start = lenURL - len;
if (start <= 0) {
continue;
}
if (strncasecmp(dataSrcPath + start, (*it).c_str(), len) == 0) {
ALOGW("%s, nxplayer can not play it, file extension name=%s", NMP_VIP_TAG, (*it).c_str());
return 0.0;
}
}
/* MIDI case end */
ALOGD("call %s fd, kOurScore=%.1f", __FUNCTION__, kOurScore);
return kOurScore;
}
void NxMediaPlayerFactory ::GetProcessNameByPid(pid_t pid, const char *taskName) const
{
char procPidPath[BUF_SIZE] = {0};
char buf[BUF_SIZE] = {0};
if (taskName == nullptr) {
ALOGE("invalid parameter, taskName is null");
return;
}
int ret = snprintf_s(procPidPath, BUF_SIZE, BUF_SIZE - 1, "/proc/%d/status", pid);
if (ret < 0) {
ALOGE("[%s:%d] snprintf_s failed!", __FUNCTION__, __LINE__);
return;
}
FILE *fp = fopen(procPidPath, "r");
if (fp != nullptr) {
if (fgets(buf, BUF_SIZE - 1, fp) == nullptr) {
fclose(fp);
return;
}
fclose(fp);
ret = sscanf_s(buf, "%*s %s", taskName, BUF_SIZE - 1);
if (ret < 0) {
ALOGE("[%s:%d] sscanf_s failed!", __FUNCTION__, __LINE__);
return;
}
} else {
ALOGW("fopen(/proc/%d/status) to get application process name failed!", pid);
}
}
bool NxMediaPlayerFactory ::IsNxPlayerDisable() const
{
char value[PROPERTY_VALUE_MAX] = {0};
int ret = property_get(PROPERTY_NP_FF_NXPLAYER.c_str(), value, "false");
bool disable = ((ret != 0) && (strcasecmp("false", value) == 0));
return disable;
}
bool NxMediaPlayerFactory ::IsOutPutOverLay() const
{
char value[PROPERTY_VALUE_MAX] = {0};
int ret = property_get(PROPERTY_NP_OUTPUT.c_str(), value, "NULL");
bool overLay = ((ret != 0) && (strcasecmp("overlay", value) == 0));
return overLay;
}
bool NxMediaPlayerFactory ::IsNxPlayerSupport() const
{
pid_t pid = IPCThreadState::self()->getCallingPid();
char strCallerName[BUF_SIZE] = {0};
/* NxPlayer not support when property [persist.sys.media.np.ff.nxplayer]=false */
bool disable = IsNxPlayerDisable();
if (disable) {
ALOGW("%s, property [persist.sys.media.np.ff.nxplayer]=false, nxplayer is disabled", NMP_VIP_TAG);
return false;
}
GetProcessNameByPid(pid, strCallerName);
bool overlay = IsOutPutOverLay();
if (overlay) {
auto index = std::find(g_accseeAllowedList.cbegin(), g_accseeAllowedList.cend(), strCallerName);
if (index != g_accseeAllowedList.end()) {
ALOGW("%s, caller name %s, nxplayer not support it in graphics output mode", NMP_VIP_TAG, strCallerName);
return false;
}
ALOGI("%s, process %s call nxplayer in graphics output mode", NMP_VIP_TAG, strCallerName);
return true;
}
auto index = std::find(g_whiteListOthers.cbegin(), g_whiteListOthers.cend(), strCallerName);
if (index != g_whiteListOthers.end()) {
ALOGW("%s, caller name %s, nxplayer not support it in VO output mode", NMP_VIP_TAG, strCallerName);
return false;
}
ALOGI("%s, process %s call nxplayer in VO output mode", NMP_VIP_TAG, strCallerName);
return true;
}
};
extern "C" android::NxMediaPlayerFactoryInterface *CreateNxMediaPlayerFactoryInterfaceInstance()
{
ALOGI("create NxMediaPlayerFactory");
return new ::android::NxMediaPlayerFactory();
}
extern "C" void DestroyNxMediaPlayerFactoryInterfaceInstance(android::NxMediaPlayerFactoryInterface *factory)
{
ALOGI("destroy NxMediaPlayerFactory");
delete factory;
}