18f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania/*
28f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania * Copyright (C) 2009 The Android Open Source Project
38f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania *
48f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania * Licensed under the Apache License, Version 2.0 (the "License");
58f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania * you may not use this file except in compliance with the License.
68f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania * You may obtain a copy of the License at
78f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania *
88f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania *      http://www.apache.org/licenses/LICENSE-2.0
98f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania *
108f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania * Unless required by applicable law or agreed to in writing, software
118f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania * distributed under the License is distributed on an "AS IS" BASIS,
128f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania * See the License for the specific language governing permissions and
148f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania * limitations under the License.
158f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania */
168f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
178f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania//#define LOG_NDEBUG 0
188f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania#define LOG_TAG "TestPlayerStub"
198f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania#include "utils/Log.h"
208f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
218f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania#include "TestPlayerStub.h"
228f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
238f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania#include <dlfcn.h>  // for dlopen/dlclose
248f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania#include <stdlib.h>
258f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania#include <string.h>
268f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania#include <cutils/properties.h>
278f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania#include <utils/Errors.h>  // for status_t
288f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
298f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania#include "media/MediaPlayerInterface.h"
308f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
318f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
328f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catanianamespace {
338f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Cataniausing android::status_t;
348f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Cataniausing android::MediaPlayerBase;
358f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
368f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Cataniaconst char *kTestUrlScheme = "test:";
378f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Cataniaconst char *kUrlParam = "url=";
388f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
398f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Cataniaconst char *kBuildTypePropName = "ro.build.type";
408f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Cataniaconst char *kEngBuild = "eng";
418f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Cataniaconst char *kTestBuild = "test";
428f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
438f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania// @return true if the current build is 'eng' or 'test'.
448f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Cataniabool isTestBuild()
458f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania{
468f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    char prop[PROPERTY_VALUE_MAX] = { '\0', };
478f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
488f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    property_get(kBuildTypePropName, prop, '\0');
498f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    return strcmp(prop, kEngBuild) == 0 || strcmp(prop, kTestBuild) == 0;
508f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania}
518f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
528f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania// @return true if the url scheme is 'test:'
538f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Cataniabool isTestUrl(const char *url)
548f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania{
558f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    return url && strncmp(url, kTestUrlScheme, strlen(kTestUrlScheme)) == 0;
568f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania}
578f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
588f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania}  // anonymous namespace
598f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
608f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catanianamespace android {
618f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
628f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas CataniaTestPlayerStub::TestPlayerStub()
638f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    :mUrl(NULL), mFilename(NULL), mContentUrl(NULL),
648f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania     mHandle(NULL), mNewPlayer(NULL), mDeletePlayer(NULL),
658f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania     mPlayer(NULL) { }
668f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
678f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas CataniaTestPlayerStub::~TestPlayerStub()
688f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania{
698f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    resetInternal();
708f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania}
718f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
728f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Cataniastatus_t TestPlayerStub::initCheck()
738f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania{
748f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    return isTestBuild() ? OK : INVALID_OPERATION;
758f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania}
768f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
778f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania// Parse mUrl to get:
788f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania// * The library to be dlopened.
798f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania// * The url to be passed to the real setDataSource impl.
808f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania//
818f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania// mUrl is expected to be in following format:
828f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania//
838f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania// test:<name of the .so>?url=<url for setDataSource>
848f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania//
858f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania// The value of the url parameter is treated as a string (no
868f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania// unescaping of illegal charaters).
878f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Cataniastatus_t TestPlayerStub::parseUrl()
888f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania{
898f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    if (strlen(mUrl) < strlen(kTestUrlScheme)) {
908f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        resetInternal();
918f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        return BAD_VALUE;
928f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    }
938f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
948f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    char *i = mUrl + strlen(kTestUrlScheme);
958f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
968f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    mFilename = i;
978f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
988f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    while (*i != '\0' && *i != '?') {
998f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        ++i;
1008f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    }
1018f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
1028f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    if (*i == '\0' || strncmp(i + 1, kUrlParam, strlen(kUrlParam)) != 0) {
1038f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        resetInternal();
1048f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        return BAD_VALUE;
1058f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    }
1068f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    *i = '\0';  // replace '?' to nul-terminate mFilename
1078f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
1088f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    mContentUrl = i + 1 + strlen(kUrlParam);
1098f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    return OK;
1108f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania}
1118f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
1128f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania// Load the dynamic library.
1138f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania// Create the test player.
1148f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania// Call setDataSource on the test player with the url in param.
115256430093679e1d62b54fb0c852126e54d162f6fAndreas Huberstatus_t TestPlayerStub::setDataSource(
116256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber        const char *url, const KeyedVector<String8, String8> *headers) {
1178f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    if (!isTestUrl(url) || NULL != mHandle) {
1188f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        return INVALID_OPERATION;
1198f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    }
1208f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
1218f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    mUrl = strdup(url);
1228f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
1238f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    status_t status = parseUrl();
1248f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
1258f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    if (OK != status) {
1268f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        resetInternal();
1278f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        return status;
1288f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    }
1298f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
1308f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    ::dlerror();  // Clears any pending error.
1318f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
1328f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    // Load the test player from the url. dlopen will fail if the lib
1338f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    // is not there. dls are under /system/lib
1348f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    // None of the entry points should be NULL.
1358f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    mHandle = ::dlopen(mFilename, RTLD_NOW | RTLD_GLOBAL);
1368f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    if (!mHandle) {
1378f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        LOGE("dlopen failed: %s", ::dlerror());
1388f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        resetInternal();
1398f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        return UNKNOWN_ERROR;
1408f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    }
1418f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
1428f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    // Load the 2 entry points to create and delete instances.
1438f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    const char *err;
1448f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    mNewPlayer = reinterpret_cast<NEW_PLAYER>(dlsym(mHandle,
1458f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania                                                    "newPlayer"));
1468f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    err = ::dlerror();
1478f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    if (err || mNewPlayer == NULL) {
1488f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        // if err is NULL the string <null> is inserted in the logs =>
1498f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        // mNewPlayer was NULL.
1508f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        LOGE("dlsym for newPlayer failed %s", err);
1518f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        resetInternal();
1528f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        return UNKNOWN_ERROR;
1538f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    }
1548f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
1558f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    mDeletePlayer = reinterpret_cast<DELETE_PLAYER>(dlsym(mHandle,
1568f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania                                                          "deletePlayer"));
1578f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    err = ::dlerror();
1588f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    if (err || mDeletePlayer == NULL) {
1598f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        LOGE("dlsym for deletePlayer failed %s", err);
1608f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        resetInternal();
1618f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        return UNKNOWN_ERROR;
1628f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    }
1638f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
1648f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    mPlayer = (*mNewPlayer)();
165256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber    return mPlayer->setDataSource(mContentUrl, headers);
1668f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania}
1678f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
1688f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania// Internal cleanup.
1698f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Cataniastatus_t TestPlayerStub::resetInternal()
1708f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania{
1718f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    if(mUrl) {
1728f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        free(mUrl);
1738f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        mUrl = NULL;
1748f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    }
1758f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    mFilename = NULL;
1768f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    mContentUrl = NULL;
1778f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
1788f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    if (mPlayer) {
179c5e3d73f92f33b3fffef57f95d017211f4169c49Patrick Scott        LOG_ASSERT(mDeletePlayer != NULL, "mDeletePlayer is null");
1808f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        (*mDeletePlayer)(mPlayer);
1818f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        mPlayer = NULL;
1828f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    }
1838f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
1848f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    if (mHandle) {
1858f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        ::dlclose(mHandle);
1868f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania        mHandle = NULL;
1878f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    }
1888f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    return OK;
1898f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania}
1908f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
1918f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania/* static */ bool TestPlayerStub::canBeUsed(const char *url)
1928f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania{
1938f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania    return isTestBuild() && isTestUrl(url);
1948f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania}
1958f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania
1968f5fcab05f1d6f644a9c30f012b8ff302f24a118Nicolas Catania}  // namespace android
197