114d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania/* 214d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania * Copyright (C) 2009 The Android Open Source Project 314d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania * 414d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania * Licensed under the Apache License, Version 2.0 (the "License"); 514d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania * you may not use this file except in compliance with the License. 614d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania * You may obtain a copy of the License at 714d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania * 814d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania * http://www.apache.org/licenses/LICENSE-2.0 914d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania * 1014d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania * Unless required by applicable law or agreed to in writing, software 1114d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania * distributed under the License is distributed on an "AS IS" BASIS, 1214d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1314d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania * See the License for the specific language governing permissions and 1414d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania * limitations under the License. 1514d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania */ 1614d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 1714d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania//#define LOG_NDEBUG 0 1814d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania#define LOG_TAG "TestPlayerStub" 1914d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania#include "utils/Log.h" 2014d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 2114d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania#include "TestPlayerStub.h" 2214d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 2314d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania#include <dlfcn.h> // for dlopen/dlclose 2414d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania#include <stdlib.h> 2514d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania#include <string.h> 2614d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania#include <cutils/properties.h> 2714d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania#include <utils/Errors.h> // for status_t 2814d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 2914d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania#include "media/MediaPlayerInterface.h" 3014d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 3114d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 3214d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catanianamespace { 3314d2747c7e54037e267bcff78b29e65b2181f0faNicolas Cataniausing android::status_t; 3414d2747c7e54037e267bcff78b29e65b2181f0faNicolas Cataniausing android::MediaPlayerBase; 3514d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 3614d2747c7e54037e267bcff78b29e65b2181f0faNicolas Cataniaconst char *kTestUrlScheme = "test:"; 3714d2747c7e54037e267bcff78b29e65b2181f0faNicolas Cataniaconst char *kUrlParam = "url="; 3814d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 3914d2747c7e54037e267bcff78b29e65b2181f0faNicolas Cataniaconst char *kBuildTypePropName = "ro.build.type"; 4014d2747c7e54037e267bcff78b29e65b2181f0faNicolas Cataniaconst char *kEngBuild = "eng"; 4114d2747c7e54037e267bcff78b29e65b2181f0faNicolas Cataniaconst char *kTestBuild = "test"; 4214d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 4314d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania// @return true if the current build is 'eng' or 'test'. 4414d2747c7e54037e267bcff78b29e65b2181f0faNicolas Cataniabool isTestBuild() 4514d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania{ 4614d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania char prop[PROPERTY_VALUE_MAX] = { '\0', }; 4714d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 482d0ac425564ff9882ebaac5267d1a04d4af67d00Bernhard Rosenkränzer property_get(kBuildTypePropName, prop, "\0"); 4914d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania return strcmp(prop, kEngBuild) == 0 || strcmp(prop, kTestBuild) == 0; 5014d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania} 5114d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 5214d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania// @return true if the url scheme is 'test:' 5314d2747c7e54037e267bcff78b29e65b2181f0faNicolas Cataniabool isTestUrl(const char *url) 5414d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania{ 5514d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania return url && strncmp(url, kTestUrlScheme, strlen(kTestUrlScheme)) == 0; 5614d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania} 5714d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 5814d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania} // anonymous namespace 5914d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 6014d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catanianamespace android { 6114d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 6214d2747c7e54037e267bcff78b29e65b2181f0faNicolas CataniaTestPlayerStub::TestPlayerStub() 6314d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania :mUrl(NULL), mFilename(NULL), mContentUrl(NULL), 6414d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania mHandle(NULL), mNewPlayer(NULL), mDeletePlayer(NULL), 6514d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania mPlayer(NULL) { } 6614d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 6714d2747c7e54037e267bcff78b29e65b2181f0faNicolas CataniaTestPlayerStub::~TestPlayerStub() 6814d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania{ 6914d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania resetInternal(); 7014d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania} 7114d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 7214d2747c7e54037e267bcff78b29e65b2181f0faNicolas Cataniastatus_t TestPlayerStub::initCheck() 7314d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania{ 7414d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania return isTestBuild() ? OK : INVALID_OPERATION; 7514d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania} 7614d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 7714d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania// Parse mUrl to get: 7814d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania// * The library to be dlopened. 7914d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania// * The url to be passed to the real setDataSource impl. 8014d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania// 8114d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania// mUrl is expected to be in following format: 8214d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania// 8314d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania// test:<name of the .so>?url=<url for setDataSource> 8414d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania// 8514d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania// The value of the url parameter is treated as a string (no 8614d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania// unescaping of illegal charaters). 8714d2747c7e54037e267bcff78b29e65b2181f0faNicolas Cataniastatus_t TestPlayerStub::parseUrl() 8814d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania{ 8914d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania if (strlen(mUrl) < strlen(kTestUrlScheme)) { 9014d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania resetInternal(); 9114d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania return BAD_VALUE; 9214d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania } 9314d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 9414d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania char *i = mUrl + strlen(kTestUrlScheme); 9514d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 9614d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania mFilename = i; 9714d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 9814d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania while (*i != '\0' && *i != '?') { 9914d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania ++i; 10014d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania } 10114d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 10214d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania if (*i == '\0' || strncmp(i + 1, kUrlParam, strlen(kUrlParam)) != 0) { 10314d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania resetInternal(); 10414d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania return BAD_VALUE; 10514d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania } 10614d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania *i = '\0'; // replace '?' to nul-terminate mFilename 10714d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 10814d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania mContentUrl = i + 1 + strlen(kUrlParam); 10914d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania return OK; 11014d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania} 11114d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 11214d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania// Load the dynamic library. 11314d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania// Create the test player. 11414d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania// Call setDataSource on the test player with the url in param. 1152db8455d8f4468a637109d31f319ce02d9d743ecAndreas Huberstatus_t TestPlayerStub::setDataSource( 1161b86fe063badb5f28c467ade39be0f4008688947Andreas Huber const sp<IMediaHTTPService> &httpService, 1171b86fe063badb5f28c467ade39be0f4008688947Andreas Huber const char *url, 1181b86fe063badb5f28c467ade39be0f4008688947Andreas Huber const KeyedVector<String8, String8> *headers) { 11914d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania if (!isTestUrl(url) || NULL != mHandle) { 12014d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania return INVALID_OPERATION; 12114d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania } 12214d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 12314d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania mUrl = strdup(url); 12414d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 12514d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania status_t status = parseUrl(); 12614d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 12714d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania if (OK != status) { 12814d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania resetInternal(); 12914d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania return status; 13014d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania } 13114d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 13214d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania ::dlerror(); // Clears any pending error. 13314d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 13414d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania // Load the test player from the url. dlopen will fail if the lib 13514d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania // is not there. dls are under /system/lib 13614d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania // None of the entry points should be NULL. 13714d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania mHandle = ::dlopen(mFilename, RTLD_NOW | RTLD_GLOBAL); 13814d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania if (!mHandle) { 13929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("dlopen failed: %s", ::dlerror()); 14014d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania resetInternal(); 14114d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania return UNKNOWN_ERROR; 14214d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania } 14314d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 14414d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania // Load the 2 entry points to create and delete instances. 14514d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania const char *err; 14614d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania mNewPlayer = reinterpret_cast<NEW_PLAYER>(dlsym(mHandle, 14714d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania "newPlayer")); 14814d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania err = ::dlerror(); 14914d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania if (err || mNewPlayer == NULL) { 15014d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania // if err is NULL the string <null> is inserted in the logs => 15114d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania // mNewPlayer was NULL. 15229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("dlsym for newPlayer failed %s", err); 15314d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania resetInternal(); 15414d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania return UNKNOWN_ERROR; 15514d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania } 15614d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 15714d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania mDeletePlayer = reinterpret_cast<DELETE_PLAYER>(dlsym(mHandle, 15814d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania "deletePlayer")); 15914d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania err = ::dlerror(); 16014d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania if (err || mDeletePlayer == NULL) { 16129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("dlsym for deletePlayer failed %s", err); 16214d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania resetInternal(); 16314d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania return UNKNOWN_ERROR; 16414d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania } 16514d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 16614d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania mPlayer = (*mNewPlayer)(); 1671b86fe063badb5f28c467ade39be0f4008688947Andreas Huber return mPlayer->setDataSource(httpService, mContentUrl, headers); 16814d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania} 16914d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 17014d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania// Internal cleanup. 17114d2747c7e54037e267bcff78b29e65b2181f0faNicolas Cataniastatus_t TestPlayerStub::resetInternal() 17214d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania{ 17314d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania if(mUrl) { 17414d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania free(mUrl); 17514d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania mUrl = NULL; 17614d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania } 17714d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania mFilename = NULL; 17814d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania mContentUrl = NULL; 17914d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 18014d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania if (mPlayer) { 181c1dc1cb1d1eaf84e88669f1a5f22579a0d9237c2Steve Block ALOG_ASSERT(mDeletePlayer != NULL, "mDeletePlayer is null"); 18214d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania (*mDeletePlayer)(mPlayer); 18314d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania mPlayer = NULL; 18414d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania } 18514d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 18614d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania if (mHandle) { 18714d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania ::dlclose(mHandle); 18814d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania mHandle = NULL; 18914d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania } 19014d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania return OK; 19114d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania} 19214d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 19314d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania/* static */ bool TestPlayerStub::canBeUsed(const char *url) 19414d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania{ 19514d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania return isTestBuild() && isTestUrl(url); 19614d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania} 19714d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania 19814d2747c7e54037e267bcff78b29e65b2181f0faNicolas Catania} // namespace android 199