Example #1
0
void TextureTracker::update(int textureId, bool ghost, String8 name) {
    Mutex::Autolock _l(mLock);
    TextureEntry entry(textureId);
    ssize_t index = mMemoryList.indexOf(entry);

    if (index >= 0) {
        TextureEntry& item = mMemoryList.editItemAt(index);
        TTLOGD("[TT]update before %s %d %d %d %d %d\n", item.mName.string(), item.mId, item.mWidth, item.mHeight,
               item.mMemory, item.mGhost);

        item.mGhost = ghost;

        if (name.isEmpty()) {
            if (!ghost) {
                item.mName = mViews.top();
            }
        } else {
            item.mName = name;
        }


        entry = mMemoryList.itemAt(index);
        TTLOGD("[TT]update after %s %d %d %d %d %d\n", entry.mName.string(), entry.mId, entry.mWidth, entry.mHeight,
               entry.mMemory, entry.mGhost);
    } else {
        TTLOGD("[TT]update not found %d", textureId);
    }

}
Example #2
0
bool
ParamsManager::
splitInt(String8 const& s8Input, Vector<int>& rOutput)
{
    rOutput.clear();
    //
    if  ( s8Input.isEmpty() )
    {
        MY_LOGW("empty string");
        return  false;
    }
    //
    char const*start = s8Input.string();
    char *end = NULL;
    do {
        int value = ::strtol(start, &end, 10);
        if  ( start == end ) {
            MY_LOGW_IF(0, "no digits in str:%s", s8Input.string());
            return  false;
        }
        rOutput.push_back(value);
        MY_LOGD_IF(0, "%d", value);
        start = end + 1;
    } while ( end && *end );
    //
    return  (rOutput.size() > 0);
}
Example #3
0
/******************************************************************************
*   Splits a comma delimited string to a List of int Vector.
*   Example string: "(10000,26623),(10000,30000)"
*******************************************************************************/
bool
ParamsManager::
splitRange(String8 const& s8Input, List< Vector<int> >& rOutput)
{
    rOutput.clear();
    //
    if  ( s8Input.isEmpty() )
    {
        MY_LOGW("empty string");
        return  false;
    }
    //
    int endIndex, fromIndex = 1;
    int endIndex_input = s8Input.length()-1;
    if  ( s8Input[0] != '(' || s8Input[endIndex_input] != ')' )
    {
        MY_LOGW("Invalid range list string=%s", s8Input.string());
        return  false;
    }
    //
    do  {
        endIndex = s8Input.find("),(", fromIndex);
        if (endIndex == -1) endIndex = endIndex_input;
        //
        Vector<int> vOut;
        String8 const s8SubString(s8Input.string()+fromIndex, endIndex-fromIndex);
        if  ( splitInt(s8SubString, vOut) ) {
            rOutput.push_back(vOut);
        }
        //
        fromIndex = endIndex + 3;
    } while (endIndex != endIndex_input);
    //
    return  (rOutput.size() > 0);
}
// static
sp<DataSource> DataSource::CreateFromURI(
        const char *uri, const KeyedVector<String8, String8> *headers) {
    bool isWidevine = !strncasecmp("widevine://", uri, 11);

    sp<DataSource> source;
    if (!strncasecmp("file://", uri, 7)) {
        source = new FileSource(uri + 7);
    } else if (!strncasecmp("http://", uri, 7)
            || !strncasecmp("https://", uri, 8)
            || isWidevine) {
        sp<HTTPBase> httpSource = HTTPBase::Create();

        String8 tmp;
        if (isWidevine) {
            tmp = String8("http://");
            tmp.append(uri + 11);

            uri = tmp.string();
        }

        if (httpSource->connect(uri, headers) != OK) {
            return NULL;
        }

        if (!isWidevine) {
            String8 cacheConfig;
            bool disconnectAtHighwatermark;
            if (headers != NULL) {
                KeyedVector<String8, String8> copy = *headers;
                NuCachedSource2::RemoveCacheSpecificHeaders(
                        &copy, &cacheConfig, &disconnectAtHighwatermark);
            }

            source = new NuCachedSource2(
                    httpSource,
                    cacheConfig.isEmpty() ? NULL : cacheConfig.string());
        } else {
            // We do not want that prefetching, caching, datasource wrapper
            // in the widevine:// case.
            source = httpSource;
        }

# if CHROMIUM_AVAILABLE
    } else if (!strncasecmp("data:", uri, 5)) {
        source = createDataUriSource(uri);
#endif
    } else {
        // Assume it's a filename.
        source = new FileSource(uri);
    }

    if (source == NULL || source->initCheck() != OK) {
        return NULL;
    }

    return source;
}
    status_t PropertyMap::Parser::parse() {
        while (!mTokenizer->isEof()) {
#if DEBUG_PARSER
            ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(),
                    mTokenizer->peekRemainderOfLine().string());
#endif

            mTokenizer->skipDelimiters(WHITESPACE);

            if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
                String8 keyToken = mTokenizer->nextToken(WHITESPACE_OR_PROPERTY_DELIMITER);
                if (keyToken.isEmpty()) {
                    ALOGE("%s: Expected non-empty property key.",
                          mTokenizer->getLocation().string());
                    return BAD_VALUE;
                }

                mTokenizer->skipDelimiters(WHITESPACE);

                if (mTokenizer->nextChar() != '=') {
                    ALOGE("%s: Expected '=' between property key and value.",
                          mTokenizer->getLocation().string());
                    return BAD_VALUE;
                }

                mTokenizer->skipDelimiters(WHITESPACE);

                String8 valueToken = mTokenizer->nextToken(WHITESPACE);
                if (valueToken.find("\\", 0) >= 0 || valueToken.find("\"", 0) >= 0) {
                    ALOGE("%s: Found reserved character '\\' or '\"' in property value.",
                          mTokenizer->getLocation().string());
                    return BAD_VALUE;
                }

                mTokenizer->skipDelimiters(WHITESPACE);
                if (!mTokenizer->isEol()) {
                    ALOGE("%s: Expected end of line, got '%s'.",
                          mTokenizer->getLocation().string(),
                          mTokenizer->peekRemainderOfLine().string());
                    return BAD_VALUE;
                }

                if (mMap->hasProperty(keyToken)) {
                    ALOGE("%s: Duplicate property value for key '%s'.",
                          mTokenizer->getLocation().string(), keyToken.string());
                    return BAD_VALUE;
                }

                mMap->addProperty(keyToken, valueToken);
            }

            mTokenizer->nextLine();
        }
        return NO_ERROR;
    }
static int readFromFile(const String8& path, char* buf, size_t size)
{
    if (path.isEmpty())
        return -1;
    int fd = open(path.string(), O_RDONLY, 0);
    if (fd == -1) {
        ALOGE("Could not open '%s'", path.string());
        return -1;
    }
    
    ssize_t count = read(fd, buf, size);
    if (count > 0) {
        while (count > 0 && buf[count-1] == '\n')
            count--;
        buf[count] = '\0';
    } else {
        buf[0] = '\0';
    } 

    close(fd);
    return count;
}
int BatteryMonitor::readFromFile(const String8& path, char* buf, size_t size) {
    char *cp = NULL;

    if (path.isEmpty())
        return -1;
    int fd = open(path.string(), O_RDONLY, 0);
    if (fd == -1) {
        KLOG_ERROR(LOG_TAG, "Could not open '%s'\n", path.string());
        return -1;
    }

    ssize_t count = TEMP_FAILURE_RETRY(read(fd, buf, size));
    if (count > 0)
        cp = (char *)memrchr(buf, '\n', count);

    if (cp)
        *cp = '\0';
    else
        buf[0] = '\0';

    close(fd);
    return count;
}
void DisplayDevice::setDisplayName(const String8& displayName) {
    if (!displayName.isEmpty()) {
        // never override the name with an empty name
        mDisplayName = displayName;
    }
}
status_t
CamAdapter::
setParameters()
{
    MY_LOGD("+");
    status_t ret = OK;
    //
    //(1) must set to mpPreviewCmdQueThread earlier than to 3A
    if ( mpPreviewCmdQueThread != 0 )
    {
        if ( ! mpPreviewCmdQueThread->setParameters() )
        {
            MY_LOGE("mpPreviewCmdQueThread->setParameters fail");
        }
    }
    else
    {
        MY_LOGE("mpPreviewCmdQueThread is NULL");
    }

    // (2) get Param from 3A
    NS3A::Param_T cam3aParam;
    Hal3ABase* p3AHal = Hal3ABase::createInstance(DevMetaInfo::queryHalSensorDev(getOpenId()));
    if ( ! p3AHal )
    {
        MY_LOGE("p3AHal == NULL");
        return INVALID_OPERATION;
    }
    //
    if ( ! p3AHal->getParams(cam3aParam) )
    {
        MY_LOGE("getParams fail");
        ret = INVALID_OPERATION;
        goto lbExit;
    }

    //(3) set Param to 3A
#define UPDATE_PARAMS(param, eMapXXX, key) \
    do { \
        String8 const s = mpParamsMgr->getStr(key); \
        if  ( ! s.isEmpty() ) { \
            param = PARAMSMANAGER_MAP_INST(eMapXXX)->valueFor(s); \
        } \
    } while (0)

    // DEFAULT DEFINITION CATEGORY
    cam3aParam.i4MinFps   = 5000;
    cam3aParam.i4MaxFps   = 60000;
    //
    UPDATE_PARAMS(cam3aParam.u4AfMode, eMapFocusMode, CameraParameters::KEY_FOCUS_MODE);
    UPDATE_PARAMS(cam3aParam.u4AwbMode, eMapWhiteBalance, CameraParameters::KEY_WHITE_BALANCE);
    UPDATE_PARAMS(cam3aParam.u4SceneMode, eMapScene, CameraParameters::KEY_SCENE_MODE);
    UPDATE_PARAMS(cam3aParam.u4StrobeMode, eMapFlashMode, CameraParameters::KEY_FLASH_MODE);
    UPDATE_PARAMS(cam3aParam.u4EffectMode, eMapEffect, CameraParameters::KEY_EFFECT);
    UPDATE_PARAMS(cam3aParam.u4AntiBandingMode, eMapAntiBanding, CameraParameters::KEY_ANTIBANDING); 
    //
    cam3aParam.i4ExpIndex = mpParamsMgr->getInt(CameraParameters::KEY_EXPOSURE_COMPENSATION);
    cam3aParam.fExpCompStep = mpParamsMgr->getFloat(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP);
    //
    // AE lock 
    {
        String8 const s = mpParamsMgr->getStr(CameraParameters::KEY_AUTO_EXPOSURE_LOCK);
        cam3aParam.bIsAELock = ( ! s.isEmpty() && s == CameraParameters::TRUE ) ? 1 : 0; 
    }
    // AWB lock 
    {
        String8 const s = mpParamsMgr->getStr(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK);
        cam3aParam.bIsAWBLock = ( ! s.isEmpty() && s == CameraParameters::TRUE ) ? 1 : 0;
    }
    // AF Focus Areas 
    {
        String8 const s8Area = mpParamsMgr->getStr(CameraParameters::KEY_FOCUS_AREAS);
        if  ( ! s8Area.isEmpty() )
        {
            MY_LOGD("Focus Areas:%s", s8Area.string());
            const int maxNumFocusAreas = mpParamsMgr->getInt(CameraParameters::KEY_MAX_NUM_FOCUS_AREAS);
            List <camera_area_t> focusAreas;
            mpParamsMgr->parseCamAreas(s8Area.string(), focusAreas, maxNumFocusAreas);
            int index = 0;
            for (List<camera_area_t>::iterator it = focusAreas.begin(); it != focusAreas.end(); it++) {
                cam3aParam.rFocusAreas.rAreas[index].i4Left = it->left;
                cam3aParam.rFocusAreas.rAreas[index].i4Top = it->top;
                cam3aParam.rFocusAreas.rAreas[index].i4Right = it->right;
                cam3aParam.rFocusAreas.rAreas[index].i4Bottom = it->bottom;
                cam3aParam.rFocusAreas.rAreas[index].i4Weight = it->weight;
                index++;
            }
            cam3aParam.rFocusAreas.u4Count = focusAreas.size();
        }
    }
    // AE Metering Areas 
    {
        String8 const s8Area = mpParamsMgr->getStr(CameraParameters::KEY_METERING_AREAS);
        if  ( ! s8Area.isEmpty() )
        {
            MY_LOGD("Metering Areas:%s", s8Area.string());
            const int maxNumMeteringAreas = mpParamsMgr->getInt(CameraParameters::KEY_MAX_NUM_METERING_AREAS);
            List <camera_area_t> meterAreas;
            mpParamsMgr->parseCamAreas(s8Area.string(), meterAreas, maxNumMeteringAreas);
            int index = 0;
            for (List<camera_area_t>::iterator it = meterAreas.begin(); it != meterAreas.end(); it++) {
                cam3aParam.rMeteringAreas.rAreas[index].i4Left = it->left;
                cam3aParam.rMeteringAreas.rAreas[index].i4Top = it->top;
                cam3aParam.rMeteringAreas.rAreas[index].i4Right = it->right;
                cam3aParam.rMeteringAreas.rAreas[index].i4Bottom = it->bottom;
                cam3aParam.rMeteringAreas.rAreas[index].i4Weight = it->weight;
                index++;
            }
            cam3aParam.rMeteringAreas.u4Count = meterAreas.size();
        }
    }

    // MTK DEFINITION CATEGORY
    UPDATE_PARAMS(cam3aParam.u4AeMode, eMapExpMode, MtkCameraParameters::KEY_SCENE_MODE);
    UPDATE_PARAMS(cam3aParam.u4IsoSpeedMode, eMapIso, MtkCameraParameters::KEY_ISO_SPEED);
    UPDATE_PARAMS(cam3aParam.u4AfLampMode, eMapFocusLamp, MtkCameraParameters::KEY_AF_LAMP_MODE);
    //
    UPDATE_PARAMS(cam3aParam.u4BrightnessMode, eMapLevel, MtkCameraParameters::KEY_BRIGHTNESS);
    UPDATE_PARAMS(cam3aParam.u4SaturationMode, eMapLevel, MtkCameraParameters::KEY_SATURATION);
    UPDATE_PARAMS(cam3aParam.u4ContrastMode, eMapLevel, MtkCameraParameters::KEY_CONTRAST);
    UPDATE_PARAMS(cam3aParam.u4EdgeMode, eMapLevel, MtkCameraParameters::KEY_EDGE);
    UPDATE_PARAMS(cam3aParam.u4HueMode, eMapLevel, MtkCameraParameters::KEY_HUE);
    //
    cam3aParam.u4ShotMode   = mpParamsMgr->getShotMode();
    cam3aParam.u4CamMode    = mpParamsMgr->getHalAppMode();    
    cam3aParam.i4RotateDegree = mpParamsMgr->getInt(MtkCameraParameters::KEY_ROTATION);    
    //
    if ( ! p3AHal->setParams(cam3aParam) )
    {
        MY_LOGE("setParams fail");
        ret = INVALID_OPERATION;
        goto lbExit;
    }

lbExit:
    p3AHal->destroyInstance();
    MY_LOGD("-");
    
    return ret;
}
static void CameraMetadata_dump(JNIEnv *env, jobject thiz) {
    ALOGV("%s", __FUNCTION__);
    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
    if (metadata == NULL) {
        return;
    }

    /*
     * Create a socket pair for local streaming read/writes.
     *
     * The metadata will be dumped into the write side,
     * and then read back out (and logged) via the read side.
     */

    int writeFd, readFd;
    {

        int sv[2];
        if (socketpair(AF_LOCAL, SOCK_STREAM, /*protocol*/0, &sv[0]) < 0) {
            jniThrowExceptionFmt(env, "java/io/IOException",
                    "Failed to create socketpair (errno = %#x, message = '%s')",
                    errno, strerror(errno));
            return;
        }
        writeFd = sv[0];
        readFd = sv[1];
    }

    /*
     * Create a thread for doing the writing.
     *
     * The reading and writing must be concurrent, otherwise
     * the write will block forever once it exhausts the capped
     * buffer size (from getsockopt).
     */
    pthread_t writeThread;
    DumpMetadataParams params = {
        writeFd,
        metadata
    };

    {
        int threadRet = pthread_create(&writeThread, /*attr*/NULL,
                CameraMetadata_writeMetadataThread, (void*)&params);

        if (threadRet != 0) {
            close(writeFd);

            jniThrowExceptionFmt(env, "java/io/IOException",
                    "Failed to create thread for writing (errno = %#x, message = '%s')",
                    threadRet, strerror(threadRet));
        }
    }

    /*
     * Read out a byte until stream is complete. Write completed lines
     * to ALOG.
     */
    {
        char out[] = {'\0', '\0'}; // large enough to append as a string
        String8 logLine;

        // Read one byte at a time! Very slow but avoids complicated \n scanning.
        ssize_t res;
        while ((res = TEMP_FAILURE_RETRY(read(readFd, &out[0], /*count*/1))) > 0) {
            if (out[0] == '\n') {
                ALOGD("%s", logLine.string());
                logLine.clear();
            } else {
                logLine.append(out);
            }
        }

        if (res < 0) {
            jniThrowExceptionFmt(env, "java/io/IOException",
                    "Failed to read from fd (errno = %#x, message = '%s')",
                    errno, strerror(errno));
            //return;
        } else if (!logLine.isEmpty()) {
            ALOGD("%s", logLine.string());
        }
    }

    int res;

    // Join until thread finishes. Ensures params/metadata is valid until then.
    if ((res = pthread_join(writeThread, /*retval*/NULL)) != 0) {
        ALOGE("%s: Failed to join thread (errno = %#x, message = '%s')",
                __FUNCTION__, res, strerror(res));
    }
}
String8 KeyMap::getPath(const InputDeviceIdentifier& deviceIdentifier,
        const String8& name, InputDeviceConfigurationFileType type) {
    return name.isEmpty()
            ? getInputDeviceConfigurationFilePathByDeviceIdentifier(deviceIdentifier, type)
            : getInputDeviceConfigurationFilePathByName(name, type);
}
int doDump(Bundle* bundle)
{
    status_t result = UNKNOWN_ERROR;

    if (bundle->getFileSpecCount() < 1) {
        fprintf(stderr, "ERROR: no dump option specified\n");
        return 1;
    }

    if (bundle->getFileSpecCount() < 2) {
        fprintf(stderr, "ERROR: no dump file specified\n");
        return 1;
    }

    const char* option = bundle->getFileSpecEntry(0);
    const char* filename = bundle->getFileSpecEntry(1);

    AssetManager assets;
    int32_t assetsCookie;
    if (!assets.addAssetPath(String8(filename), &assetsCookie)) {
        fprintf(stderr, "ERROR: dump failed because assets could not be loaded\n");
        return 1;
    }

    // Make a dummy config for retrieving resources...  we need to supply
    // non-default values for some configs so that we can retrieve resources
    // in the app that don't have a default.  The most important of these is
    // the API version because key resources like icons will have an implicit
    // version if they are using newer config types like density.
    ResTable_config config;
    memset(&config, 0, sizeof(ResTable_config));
    config.language[0] = 'e';
    config.language[1] = 'n';
    config.country[0] = 'U';
    config.country[1] = 'S';
    config.orientation = ResTable_config::ORIENTATION_PORT;
    config.density = ResTable_config::DENSITY_MEDIUM;
    config.sdkVersion = 10000; // Very high.
    config.screenWidthDp = 320;
    config.screenHeightDp = 480;
    config.smallestScreenWidthDp = 320;
    config.screenLayout |= ResTable_config::SCREENSIZE_NORMAL;
    assets.setConfiguration(config);

    const ResTable& res = assets.getResources(false);
    if (res.getError() != NO_ERROR) {
        fprintf(stderr, "ERROR: dump failed because the resource table is invalid/corrupt.\n");
        return 1;
    }

    // The dynamicRefTable can be null if there are no resources for this asset cookie.
    // This fine.
    const DynamicRefTable* dynamicRefTable = res.getDynamicRefTableForCookie(assetsCookie);

    Asset* asset = NULL;

    if (strcmp("resources", option) == 0) {
#ifndef __ANDROID__
        res.print(bundle->getValues());
#endif

    } else if (strcmp("strings", option) == 0) {
        const ResStringPool* pool = res.getTableStringBlock(0);
        printStringPool(pool);

    } else if (strcmp("xmltree", option) == 0) {
        if (bundle->getFileSpecCount() < 3) {
            fprintf(stderr, "ERROR: no dump xmltree resource file specified\n");
            goto bail;
        }

        for (int i=2; i<bundle->getFileSpecCount(); i++) {
            const char* resname = bundle->getFileSpecEntry(i);
            ResXMLTree tree(dynamicRefTable);
            asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER);
            if (asset == NULL) {
                fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
                goto bail;
            }

            if (tree.setTo(asset->getBuffer(true),
                           asset->getLength()) != NO_ERROR) {
                fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname);
                goto bail;
            }
            tree.restart();
            printXMLBlock(&tree);
            tree.uninit();
            delete asset;
            asset = NULL;
        }

    } else if (strcmp("xmlstrings", option) == 0) {
        if (bundle->getFileSpecCount() < 3) {
            fprintf(stderr, "ERROR: no dump xmltree resource file specified\n");
            goto bail;
        }

        for (int i=2; i<bundle->getFileSpecCount(); i++) {
            const char* resname = bundle->getFileSpecEntry(i);
            asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER);
            if (asset == NULL) {
                fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
                goto bail;
            }

            ResXMLTree tree(dynamicRefTable);
            if (tree.setTo(asset->getBuffer(true),
                           asset->getLength()) != NO_ERROR) {
                fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname);
                goto bail;
            }
            printStringPool(&tree.getStrings());
            delete asset;
            asset = NULL;
        }

    } else {
        asset = assets.openNonAsset(assetsCookie, "AndroidManifest.xml", Asset::ACCESS_BUFFER);
        if (asset == NULL) {
            fprintf(stderr, "ERROR: dump failed because no AndroidManifest.xml found\n");
            goto bail;
        }

        ResXMLTree tree(dynamicRefTable);
        if (tree.setTo(asset->getBuffer(true),
                       asset->getLength()) != NO_ERROR) {
            fprintf(stderr, "ERROR: AndroidManifest.xml is corrupt\n");
            goto bail;
        }
        tree.restart();

        if (strcmp("permissions", option) == 0) {
            size_t len;
            ResXMLTree::event_code_t code;
            int depth = 0;
            while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
                if (code == ResXMLTree::END_TAG) {
                    depth--;
                    continue;
                }
                if (code != ResXMLTree::START_TAG) {
                    continue;
                }
                depth++;
                const char16_t* ctag16 = tree.getElementName(&len);
                if (ctag16 == NULL) {
                    fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n");
                    goto bail;
                }
                String8 tag(ctag16);
                //printf("Depth %d tag %s\n", depth, tag.string());
                if (depth == 1) {
                    if (tag != "manifest") {
                        fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
                        goto bail;
                    }
                    String8 pkg = AaptXml::getAttribute(tree, NULL, "package", NULL);
                    printf("package: %s\n", ResTable::normalizeForOutput(pkg.string()).string());
                } else if (depth == 2 && tag == "permission") {
                    String8 error;
                    String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
                    if (error != "") {
                        fprintf(stderr, "ERROR: %s\n", error.string());
                        goto bail;
                    }
                    printf("permission: %s\n",
                            ResTable::normalizeForOutput(name.string()).string());
                } else if (depth == 2 && tag == "uses-permission") {
                    String8 error;
                    String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
                    if (error != "") {
                        fprintf(stderr, "ERROR: %s\n", error.string());
                        goto bail;
                    }
                    printUsesPermission(name,
                            AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0,
                            AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR));
                }
            }
        } else if (strcmp("badging", option) == 0) {
            Vector<String8> locales;
            res.getLocales(&locales);

            Vector<ResTable_config> configs;
            res.getConfigurations(&configs);
            SortedVector<int> densities;
            const size_t NC = configs.size();
            for (size_t i=0; i<NC; i++) {
                int dens = configs[i].density;
                if (dens == 0) {
                    dens = 160;
                }
                densities.add(dens);
            }

            size_t len;
            ResXMLTree::event_code_t code;
            int depth = 0;
            String8 error;
            bool withinActivity = false;
            bool isMainActivity = false;
            bool isLauncherActivity = false;
            bool isLeanbackLauncherActivity = false;
            bool isSearchable = false;
            bool withinApplication = false;
            bool withinSupportsInput = false;
            bool withinFeatureGroup = false;
            bool withinReceiver = false;
            bool withinService = false;
            bool withinProvider = false;
            bool withinIntentFilter = false;
            bool hasMainActivity = false;
            bool hasOtherActivities = false;
            bool hasOtherReceivers = false;
            bool hasOtherServices = false;
            bool hasIntentFilter = false;

            bool hasWallpaperService = false;
            bool hasImeService = false;
            bool hasAccessibilityService = false;
            bool hasPrintService = false;
            bool hasWidgetReceivers = false;
            bool hasDeviceAdminReceiver = false;
            bool hasPaymentService = false;
            bool hasDocumentsProvider = false;
            bool hasCameraActivity = false;
            bool hasCameraSecureActivity = false;
            bool hasLauncher = false;
            bool hasNotificationListenerService = false;
            bool hasDreamService = false;

            bool actMainActivity = false;
            bool actWidgetReceivers = false;
            bool actDeviceAdminEnabled = false;
            bool actImeService = false;
            bool actWallpaperService = false;
            bool actAccessibilityService = false;
            bool actPrintService = false;
            bool actHostApduService = false;
            bool actOffHostApduService = false;
            bool actDocumentsProvider = false;
            bool actNotificationListenerService = false;
            bool actDreamService = false;
            bool actCamera = false;
            bool actCameraSecure = false;
            bool catLauncher = false;
            bool hasMetaHostPaymentCategory = false;
            bool hasMetaOffHostPaymentCategory = false;

            // These permissions are required by services implementing services
            // the system binds to (IME, Accessibility, PrintServices, etc.)
            bool hasBindDeviceAdminPermission = false;
            bool hasBindInputMethodPermission = false;
            bool hasBindAccessibilityServicePermission = false;
            bool hasBindPrintServicePermission = false;
            bool hasBindNfcServicePermission = false;
            bool hasRequiredSafAttributes = false;
            bool hasBindNotificationListenerServicePermission = false;
            bool hasBindDreamServicePermission = false;

            // These two implement the implicit permissions that are granted
            // to pre-1.6 applications.
            bool hasWriteExternalStoragePermission = false;
            bool hasReadPhoneStatePermission = false;

            // If an app requests write storage, they will also get read storage.
            bool hasReadExternalStoragePermission = false;

            // Implement transition to read and write call log.
            bool hasReadContactsPermission = false;
            bool hasWriteContactsPermission = false;
            bool hasReadCallLogPermission = false;
            bool hasWriteCallLogPermission = false;

            // If an app declares itself as multiArch, we report the
            // native libraries differently.
            bool hasMultiArch = false;

            // This next group of variables is used to implement a group of
            // backward-compatibility heuristics necessitated by the addition of
            // some new uses-feature constants in 2.1 and 2.2. In most cases, the
            // heuristic is "if an app requests a permission but doesn't explicitly
            // request the corresponding <uses-feature>, presume it's there anyway".

            // 2.2 also added some other features that apps can request, but that
            // have no corresponding permission, so we cannot implement any
            // back-compatibility heuristic for them. The below are thus unnecessary
            // (but are retained here for documentary purposes.)
            //bool specCompassFeature = false;
            //bool specAccelerometerFeature = false;
            //bool specProximityFeature = false;
            //bool specAmbientLightFeature = false;
            //bool specLiveWallpaperFeature = false;

            int targetSdk = 0;
            int smallScreen = 1;
            int normalScreen = 1;
            int largeScreen = 1;
            int xlargeScreen = 1;
            int anyDensity = 1;
            int requiresSmallestWidthDp = 0;
            int compatibleWidthLimitDp = 0;
            int largestWidthLimitDp = 0;
            String8 pkg;
            String8 activityName;
            String8 activityLabel;
            String8 activityIcon;
            String8 activityBanner;
            String8 receiverName;
            String8 serviceName;
            Vector<String8> supportedInput;

            FeatureGroup commonFeatures;
            Vector<FeatureGroup> featureGroups;
            KeyedVector<String8, ImpliedFeature> impliedFeatures;

            while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
                if (code == ResXMLTree::END_TAG) {
                    depth--;
                    if (depth < 2) {
                        if (withinSupportsInput && !supportedInput.isEmpty()) {
                            printf("supports-input: '");
                            const size_t N = supportedInput.size();
                            for (size_t i=0; i<N; i++) {
                                printf("%s", ResTable::normalizeForOutput(
                                        supportedInput[i].string()).string());
                                if (i != N - 1) {
                                    printf("' '");
                                } else {
                                    printf("'\n");
                                }
                            }
                            supportedInput.clear();
                        }
                        withinApplication = false;
                        withinSupportsInput = false;
                        withinFeatureGroup = false;
                    } else if (depth < 3) {
                        if (withinActivity && isMainActivity) {
                            String8 aName(getComponentName(pkg, activityName));
                            if (isLauncherActivity) {
                                printf("launchable-activity:");
                                if (aName.length() > 0) {
                                    printf(" name='%s' ",
                                            ResTable::normalizeForOutput(aName.string()).string());
                                }
                                printf(" label='%s' icon='%s'\n",
                                        ResTable::normalizeForOutput(activityLabel.string()).string(),
                                        ResTable::normalizeForOutput(activityIcon.string()).string());
                            }
                            if (isLeanbackLauncherActivity) {
                                printf("leanback-launchable-activity:");
                                if (aName.length() > 0) {
                                    printf(" name='%s' ",
                                            ResTable::normalizeForOutput(aName.string()).string());
                                }
                                printf(" label='%s' icon='%s' banner='%s'\n",
                                        ResTable::normalizeForOutput(activityLabel.string()).string(),
                                        ResTable::normalizeForOutput(activityIcon.string()).string(),
                                        ResTable::normalizeForOutput(activityBanner.string()).string());
                            }
                        }
                        if (!hasIntentFilter) {
                            hasOtherActivities |= withinActivity;
                            hasOtherReceivers |= withinReceiver;
                            hasOtherServices |= withinService;
                        } else {
                            if (withinService) {
                                hasPaymentService |= (actHostApduService && hasMetaHostPaymentCategory &&
                                        hasBindNfcServicePermission);
                                hasPaymentService |= (actOffHostApduService && hasMetaOffHostPaymentCategory &&
                                        hasBindNfcServicePermission);
                            }
                        }
                        withinActivity = false;
                        withinService = false;
                        withinReceiver = false;
                        withinProvider = false;
                        hasIntentFilter = false;
                        isMainActivity = isLauncherActivity = isLeanbackLauncherActivity = false;
                    } else if (depth < 4) {
                        if (withinIntentFilter) {
                            if (withinActivity) {
                                hasMainActivity |= actMainActivity;
                                hasLauncher |= catLauncher;
                                hasCameraActivity |= actCamera;
                                hasCameraSecureActivity |= actCameraSecure;
                                hasOtherActivities |= !actMainActivity && !actCamera && !actCameraSecure;
                            } else if (withinReceiver) {
                                hasWidgetReceivers |= actWidgetReceivers;
                                hasDeviceAdminReceiver |= (actDeviceAdminEnabled &&
                                        hasBindDeviceAdminPermission);
                                hasOtherReceivers |= (!actWidgetReceivers && !actDeviceAdminEnabled);
                            } else if (withinService) {
                                hasImeService |= actImeService;
                                hasWallpaperService |= actWallpaperService;
                                hasAccessibilityService |= (actAccessibilityService &&
                                        hasBindAccessibilityServicePermission);
                                hasPrintService |= (actPrintService && hasBindPrintServicePermission);
                                hasNotificationListenerService |= actNotificationListenerService &&
                                        hasBindNotificationListenerServicePermission;
                                hasDreamService |= actDreamService && hasBindDreamServicePermission;
                                hasOtherServices |= (!actImeService && !actWallpaperService &&
                                        !actAccessibilityService && !actPrintService &&
                                        !actHostApduService && !actOffHostApduService &&
                                        !actNotificationListenerService);
                            } else if (withinProvider) {
                                hasDocumentsProvider |= actDocumentsProvider && hasRequiredSafAttributes;
                            }
                        }
                        withinIntentFilter = false;
                    }
                    continue;
                }
                if (code != ResXMLTree::START_TAG) {
                    continue;
                }
                depth++;

                const char16_t* ctag16 = tree.getElementName(&len);
                if (ctag16 == NULL) {
                    fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n");
                    goto bail;
                }
                String8 tag(ctag16);
                //printf("Depth %d,  %s\n", depth, tag.string());
                if (depth == 1) {
                    if (tag != "manifest") {
                        fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
                        goto bail;
                    }
                    pkg = AaptXml::getAttribute(tree, NULL, "package", NULL);
                    printf("package: name='%s' ",
                            ResTable::normalizeForOutput(pkg.string()).string());
                    int32_t versionCode = AaptXml::getIntegerAttribute(tree, VERSION_CODE_ATTR,
                            &error);
                    if (error != "") {
                        fprintf(stderr, "ERROR getting 'android:versionCode' attribute: %s\n",
                                error.string());
                        goto bail;
                    }
                    if (versionCode > 0) {
                        printf("versionCode='%d' ", versionCode);
                    } else {
                        printf("versionCode='' ");
                    }
                    String8 versionName = AaptXml::getResolvedAttribute(res, tree,
                            VERSION_NAME_ATTR, &error);
                    if (error != "") {
                        fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n",
                                error.string());
                        goto bail;
                    }
                    printf("versionName='%s'",
                            ResTable::normalizeForOutput(versionName.string()).string());

                    String8 splitName = AaptXml::getAttribute(tree, NULL, "split");
                    if (!splitName.isEmpty()) {
                        printf(" split='%s'", ResTable::normalizeForOutput(
                                    splitName.string()).string());
                    }

                    String8 platformVersionName = AaptXml::getAttribute(tree, NULL,
                            "platformBuildVersionName");
                    printf(" platformBuildVersionName='%s'", platformVersionName.string());
                    printf("\n");

                    int32_t installLocation = AaptXml::getResolvedIntegerAttribute(res, tree,
                            INSTALL_LOCATION_ATTR, &error);
                    if (error != "") {
                        fprintf(stderr, "ERROR getting 'android:installLocation' attribute: %s\n",
                                error.string());
                        goto bail;
                    }

                    if (installLocation >= 0) {
                        printf("install-location:'");
                        switch (installLocation) {
                            case 0:
                                printf("auto");
                                break;
                            case 1:
                                printf("internalOnly");
                                break;
                            case 2:
                                printf("preferExternal");
                                break;
                            default:
                                fprintf(stderr, "Invalid installLocation %d\n", installLocation);
                                goto bail;
                        }
                        printf("'\n");
                    }
                } else if (depth == 2) {
                    withinApplication = false;
                    if (tag == "application") {
int main(int argc, char* const argv[])
{
    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
        LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));
    }

    if (!LOG_NDEBUG) {
      String8 argv_String;
      for (int i = 0; i < argc; ++i) {
        argv_String.append("\"");
        argv_String.append(argv[i]);
        argv_String.append("\" ");
      }
      ALOGV("app_process main with argv: %s", argv_String.string());
    }

    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    // Process command line arguments
    // ignore argv[0]
    argc--;
    argv++;

    // Everything up to '--' or first non '-' arg goes to the vm.
    //
    // The first argument after the VM args is the "parent dir", which
    // is currently unused.
    //
    // After the parent dir, we expect one or more the following internal
    // arguments :
    //
    // --zygote : Start in zygote mode
    // --start-system-server : Start the system server.
    // --application : Start in application (stand alone, non zygote) mode.
    // --nice-name : The nice name for this process.
    //
    // For non zygote starts, these arguments will be followed by
    // the main class name. All remaining arguments are passed to
    // the main method of this class.
    //
    // For zygote starts, all remaining arguments are passed to the zygote.
    // main function.
    //
    // Note that we must copy argument string values since we will rewrite the
    // entire argument block when we apply the nice name to argv0.
    //
    // As an exception to the above rule, anything in "spaced commands"
    // goes to the vm even though it has a space in it.
    const char* spaced_commands[] = { "-cp", "-classpath" };
    // Allow "spaced commands" to be succeeded by exactly 1 argument (regardless of -s).
    bool known_command = false;

    int i;
    for (i = 0; i < argc; i++) {
        if (known_command == true) {
          runtime.addOption(strdup(argv[i]));
          ALOGV("app_process main add known option '%s'", argv[i]);
          known_command = false;
          continue;
        }

        for (int j = 0;
             j < static_cast<int>(sizeof(spaced_commands) / sizeof(spaced_commands[0]));
             ++j) {
          if (strcmp(argv[i], spaced_commands[j]) == 0) {
            known_command = true;
            ALOGV("app_process main found known command '%s'", argv[i]);
          }
        }

        if (argv[i][0] != '-') {
            break;
        }
        if (argv[i][1] == '-' && argv[i][2] == 0) {
            ++i; // Skip --.
            break;
        }

        runtime.addOption(strdup(argv[i]));
        ALOGV("app_process main add option '%s'", argv[i]);
    }

    // Parse runtime arguments.  Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }

    Vector<String8> args;
    if (!className.isEmpty()) {
        // We're not in zygote mode, the only argument we need to pass
        // to RuntimeInit is the application argument.
        //
        // The Remainder of args get passed to startup class main(). Make
        // copies of them before we overwrite them with the process name.
        args.add(application ? String8("application") : String8("tool"));
        runtime.setClassNameAndArgs(className, argc - i, argv + i);

        if (!LOG_NDEBUG) {
          String8 restOfArgs;
          char* const* argv_new = argv + i;
          int argc_new = argc - i;
          for (int k = 0; k < argc_new; ++k) {
            restOfArgs.append("\"");
            restOfArgs.append(argv_new[k]);
            restOfArgs.append("\" ");
          }
          ALOGV("Class name = %s, args = %s", className.string(), restOfArgs.string());
        }
    } else {
        // We're in zygote mode.
        maybeCreateDalvikCache();

        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }

        char prop[PROP_VALUE_MAX];
        if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
            LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
                ABI_LIST_PROPERTY);
            return 11;
        }

        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);
        args.add(abiFlag);

        // In zygote mode, pass all remaining arguments to the zygote
        // main() method.
        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }

    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string(), true /* setProcName */);
    }

    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    }
}
Example #14
0
void *Loader::load_driver(const char* kind,
        egl_connection_t* cnx, uint32_t mask)
{
    class MatchFile {
    public:
        static String8 find(const char* kind) {
            String8 result;
            String8 pattern;
            pattern.appendFormat("lib%s", kind);
            const char* const searchPaths[] = {
#if defined(__LP64__)
                    "/vendor/lib64/egl",
                    "/system/lib64/egl"
#else
                    "/vendor/lib/egl",
                    "/system/lib/egl"
#endif
            };

            // first, we search for the exact name of the GLES userspace
            // driver in both locations.
            // i.e.:
            //      libGLES.so, or:
            //      libEGL.so, libGLESv1_CM.so, libGLESv2.so

            for (size_t i=0 ; i<NELEM(searchPaths) ; i++) {
                if (find(result, pattern, searchPaths[i], true)) {
                    return result;
                }
            }

            // for compatibility with the old "egl.cfg" naming convention
            // we look for files that match:
            //      libGLES_*.so, or:
            //      libEGL_*.so, libGLESv1_CM_*.so, libGLESv2_*.so

            pattern.append("_");
            for (size_t i=0 ; i<NELEM(searchPaths) ; i++) {
                if (find(result, pattern, searchPaths[i], false)) {
                    return result;
                }
            }

            // we didn't find the driver. gah.
            result.clear();
            return result;
        }

    private:
        static bool find(String8& result,
                const String8& pattern, const char* const search, bool exact) {

            // in the emulator case, we just return the hardcoded name
            // of the software renderer.
            if (checkGlesEmulationStatus() == 0) {
                ALOGD("Emulator without GPU support detected. "
                      "Fallback to software renderer.");
#if defined(__LP64__)
                result.setTo("/system/lib64/egl/libGLES_android.so");
#else
                result.setTo("/system/lib/egl/libGLES_android.so");
#endif
                return true;
            }

            if (exact) {
                String8 absolutePath;
                absolutePath.appendFormat("%s/%s.so", search, pattern.string());
                if (!access(absolutePath.string(), R_OK)) {
                    result = absolutePath;
                    return true;
                }
                return false;
            }

            DIR* d = opendir(search);
            if (d != NULL) {
                struct dirent cur;
                struct dirent* e;
                while (readdir_r(d, &cur, &e) == 0 && e) {
                    if (e->d_type == DT_DIR) {
                        continue;
                    }
                    if (!strcmp(e->d_name, "libGLES_android.so")) {
                        // always skip the software renderer
                        continue;
                    }
                    if (strstr(e->d_name, pattern.string()) == e->d_name) {
                        if (!strcmp(e->d_name + strlen(e->d_name) - 3, ".so")) {
                            result.clear();
                            result.appendFormat("%s/%s", search, e->d_name);
                            closedir(d);
                            return true;
                        }
                    }
                }
                closedir(d);
            }
            return false;
        }
    };


    String8 absolutePath = MatchFile::find(kind);
    if (absolutePath.isEmpty()) {
        // this happens often, we don't want to log an error
        return 0;
    }
    const char* const driver_absolute_path = absolutePath.string();

    void* dso = dlopen(driver_absolute_path, RTLD_NOW | RTLD_LOCAL);
    if (dso == 0) {
        const char* err = dlerror();
        ALOGE("load_driver(%s): %s", driver_absolute_path, err?err:"unknown");
        return 0;
    }

    ALOGD("loaded %s", driver_absolute_path);

    if (mask & EGL) {
        getProcAddress = (getProcAddressType)dlsym(dso, "eglGetProcAddress");

        ALOGE_IF(!getProcAddress,
                "can't find eglGetProcAddress() in %s", driver_absolute_path);

        egl_t* egl = &cnx->egl;
        __eglMustCastToProperFunctionPointerType* curr =
            (__eglMustCastToProperFunctionPointerType*)egl;
        char const * const * api = egl_names;
        while (*api) {
            char const * name = *api;
            __eglMustCastToProperFunctionPointerType f =
                (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
            if (f == NULL) {
                // couldn't find the entry-point, use eglGetProcAddress()
                f = getProcAddress(name);
                if (f == NULL) {
                    f = (__eglMustCastToProperFunctionPointerType)0;
                }
            }
            *curr++ = f;
            api++;
        }
    }

    if (mask & GLESv1_CM) {
        init_api(dso, gl_names,
            (__eglMustCastToProperFunctionPointerType*)
                &cnx->hooks[egl_connection_t::GLESv1_INDEX]->gl,
            getProcAddress);
    }

    if (mask & GLESv2) {
      init_api(dso, gl_names,
            (__eglMustCastToProperFunctionPointerType*)
                &cnx->hooks[egl_connection_t::GLESv2_INDEX]->gl,
            getProcAddress);
    }

    return dso;
}
status_t VendorTagDescriptor::createFromParcel(const Parcel* parcel,
            /*out*/
            sp<VendorTagDescriptor>& descriptor) {
    status_t res = OK;
    if (parcel == NULL) {
        ALOGE("%s: parcel argument was NULL.", __FUNCTION__);
        return BAD_VALUE;
    }

    int32_t tagCount = 0;
    if ((res = parcel->readInt32(&tagCount)) != OK) {
        ALOGE("%s: could not read tag count from parcel", __FUNCTION__);
        return res;
    }

    if (tagCount < 0 || tagCount > INT32_MAX) {
        ALOGE("%s: tag count %d from vendor ops is invalid.", __FUNCTION__, tagCount);
        return BAD_VALUE;
    }

    sp<VendorTagDescriptor> desc = new VendorTagDescriptor();
    desc->mTagCount = tagCount;

    uint32_t tag, sectionIndex;
    uint32_t maxSectionIndex = 0;
    int32_t tagType;
    Vector<uint32_t> allTags;
    for (int32_t i = 0; i < tagCount; ++i) {
        if ((res = parcel->readInt32(reinterpret_cast<int32_t*>(&tag))) != OK) {
            ALOGE("%s: could not read tag id from parcel for index %d", __FUNCTION__, i);
            break;
        }
        if (tag < CAMERA_METADATA_VENDOR_TAG_BOUNDARY) {
            ALOGE("%s: vendor tag %d not in vendor tag section.", __FUNCTION__, tag);
            res = BAD_VALUE;
            break;
        }
        if ((res = parcel->readInt32(&tagType)) != OK) {
            ALOGE("%s: could not read tag type from parcel for tag %d", __FUNCTION__, tag);
            break;
        }
        if (tagType < 0 || tagType >= NUM_TYPES) {
            ALOGE("%s: tag type %d from vendor ops does not exist.", __FUNCTION__, tagType);
            res = BAD_VALUE;
            break;
        }
        String8 tagName = parcel->readString8();
        if (tagName.isEmpty()) {
            ALOGE("%s: parcel tag name was NULL for tag %d.", __FUNCTION__, tag);
            res = NOT_ENOUGH_DATA;
            break;
        }

        if ((res = parcel->readInt32(reinterpret_cast<int32_t*>(&sectionIndex))) != OK) {
            ALOGE("%s: could not read section index for tag %d.", __FUNCTION__, tag);
            break;
        }

        maxSectionIndex = (maxSectionIndex >= sectionIndex) ? maxSectionIndex : sectionIndex;

        allTags.add(tag);
        desc->mTagToNameMap.add(tag, tagName);
        desc->mTagToSectionMap.add(tag, sectionIndex);
        desc->mTagToTypeMap.add(tag, tagType);
    }

    if (res != OK) {
        return res;
    }

    size_t sectionCount;
    if (tagCount > 0) {
        if ((res = parcel->readInt32(reinterpret_cast<int32_t*>(&sectionCount))) != OK) {
            ALOGE("%s: could not read section count for.", __FUNCTION__);
            return res;
        }
        if (sectionCount < (maxSectionIndex + 1)) {
            ALOGE("%s: Incorrect number of sections defined, received %zu, needs %d.",
                    __FUNCTION__, sectionCount, (maxSectionIndex + 1));
            return BAD_VALUE;
        }
        LOG_ALWAYS_FATAL_IF(desc->mSections.setCapacity(sectionCount) <= 0,
                "Vector capacity must be positive");
        for (size_t i = 0; i < sectionCount; ++i) {
            String8 sectionName = parcel->readString8();
            if (sectionName.isEmpty()) {
                ALOGE("%s: parcel section name was NULL for section %zu.",
                      __FUNCTION__, i);
                return NOT_ENOUGH_DATA;
            }
            desc->mSections.add(sectionName);
        }
    }

    LOG_ALWAYS_FATAL_IF(static_cast<size_t>(tagCount) != allTags.size(),
                        "tagCount must be the same as allTags size");
    // Set up reverse mapping
    for (size_t i = 0; i < static_cast<size_t>(tagCount); ++i) {
        uint32_t tag = allTags[i];
        String8 sectionString = desc->mSections[desc->mTagToSectionMap.valueFor(tag)];

        ssize_t reverseIndex = -1;
        if ((reverseIndex = desc->mReverseMapping.indexOfKey(sectionString)) < 0) {
            KeyedVector<String8, uint32_t>* nameMapper = new KeyedVector<String8, uint32_t>();
            reverseIndex = desc->mReverseMapping.add(sectionString, nameMapper);
        }
        desc->mReverseMapping[reverseIndex]->add(desc->mTagToNameMap.valueFor(tag), tag);
    }

    descriptor = desc;
    return res;
}
void StagefrightMetadataRetriever::parseMetaData() {
    sp<MetaData> meta = mExtractor->getMetaData();

    if (meta == NULL) {
        ALOGV("extractor doesn't publish metadata, failed to initialize?");
        return;
    }

    struct Map {
        int from;
        int to;
    };
    static const Map kMap[] = {
        { kKeyMIMEType, METADATA_KEY_MIMETYPE },
        { kKeyCDTrackNumber, METADATA_KEY_CD_TRACK_NUMBER },
        { kKeyDiscNumber, METADATA_KEY_DISC_NUMBER },
        { kKeyAlbum, METADATA_KEY_ALBUM },
        { kKeyArtist, METADATA_KEY_ARTIST },
        { kKeyAlbumArtist, METADATA_KEY_ALBUMARTIST },
        { kKeyAuthor, METADATA_KEY_AUTHOR },
        { kKeyComposer, METADATA_KEY_COMPOSER },
        { kKeyDate, METADATA_KEY_DATE },
        { kKeyGenre, METADATA_KEY_GENRE },
        { kKeyTitle, METADATA_KEY_TITLE },
        { kKeyYear, METADATA_KEY_YEAR },
        { kKeyWriter, METADATA_KEY_WRITER },
        { kKeyCompilation, METADATA_KEY_COMPILATION },
        { kKeyLocation, METADATA_KEY_LOCATION },
    };
    static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);

    for (size_t i = 0; i < kNumMapEntries; ++i) {
        const char *value;
        if (meta->findCString(kMap[i].from, &value)) {
            mMetaData.add(kMap[i].to, String8(value));
        }
    }

    const void *data;
    uint32_t type;
    size_t dataSize;
    if (meta->findData(kKeyAlbumArt, &type, &data, &dataSize)
            && mAlbumArt == NULL) {
        mAlbumArt = new MediaAlbumArt;
        mAlbumArt->mSize = dataSize;
        mAlbumArt->mData = new uint8_t[dataSize];
        memcpy(mAlbumArt->mData, data, dataSize);
    }

    size_t numTracks = mExtractor->countTracks();

    char tmp[32];
    sprintf(tmp, "%d", numTracks);

    mMetaData.add(METADATA_KEY_NUM_TRACKS, String8(tmp));

    bool hasAudio = false;
    bool hasVideo = false;
    int32_t videoWidth = -1;
    int32_t videoHeight = -1;
    int32_t audioBitrate = -1;
    int32_t rotationAngle = -1;

    // The overall duration is the duration of the longest track.
    int64_t maxDurationUs = 0;
    String8 timedTextLang;
    for (size_t i = 0; i < numTracks; ++i) {
        sp<MetaData> trackMeta = mExtractor->getTrackMetaData(i);

        int64_t durationUs;
        if (trackMeta->findInt64(kKeyDuration, &durationUs)) {
            if (durationUs > maxDurationUs) {
                maxDurationUs = durationUs;
            }
        }

        const char *mime;
        if (trackMeta->findCString(kKeyMIMEType, &mime)) {
            if (!hasAudio && !strncasecmp("audio/", mime, 6)) {
                hasAudio = true;

                if (!trackMeta->findInt32(kKeyBitRate, &audioBitrate)) {
                    audioBitrate = -1;
                }
            } else if (!hasVideo && !strncasecmp("video/", mime, 6)) {
                hasVideo = true;

                CHECK(trackMeta->findInt32(kKeyWidth, &videoWidth));
                CHECK(trackMeta->findInt32(kKeyHeight, &videoHeight));
                if (!trackMeta->findInt32(kKeyRotation, &rotationAngle)) {
                    rotationAngle = 0;
                }
            } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
                const char *lang;
                bool success = trackMeta->findCString(kKeyMediaLanguage, &lang);
                if (success) {
                    timedTextLang.append(String8(lang));
                    timedTextLang.append(String8(":"));
                } else {
                    ALOGE("No language found for timed text");
                }
            }
        }
    }

    // To save the language codes for all timed text tracks
    // If multiple text tracks present, the format will look
    // like "eng:chi"
    if (!timedTextLang.isEmpty()) {
        mMetaData.add(METADATA_KEY_TIMED_TEXT_LANGUAGES, timedTextLang);
    }

    // The duration value is a string representing the duration in ms.
    sprintf(tmp, "%lld", (maxDurationUs + 500) / 1000);
    mMetaData.add(METADATA_KEY_DURATION, String8(tmp));

    if (hasAudio) {
        mMetaData.add(METADATA_KEY_HAS_AUDIO, String8("yes"));
    }

    if (hasVideo) {
        mMetaData.add(METADATA_KEY_HAS_VIDEO, String8("yes"));

        sprintf(tmp, "%d", videoWidth);
        mMetaData.add(METADATA_KEY_VIDEO_WIDTH, String8(tmp));

        sprintf(tmp, "%d", videoHeight);
        mMetaData.add(METADATA_KEY_VIDEO_HEIGHT, String8(tmp));

        sprintf(tmp, "%d", rotationAngle);
        mMetaData.add(METADATA_KEY_VIDEO_ROTATION, String8(tmp));
    }

    if (numTracks == 1 && hasAudio && audioBitrate >= 0) {
        sprintf(tmp, "%d", audioBitrate);
        mMetaData.add(METADATA_KEY_BITRATE, String8(tmp));
    } else {
        off64_t sourceSize;
        if (mSource->getSize(&sourceSize) == OK) {
            int64_t avgBitRate = (int64_t)(sourceSize * 8E6 / maxDurationUs);

            sprintf(tmp, "%lld", avgBitRate);
            mMetaData.add(METADATA_KEY_BITRATE, String8(tmp));
        }
    }

    if (numTracks == 1) {
        const char *fileMIME;
        CHECK(meta->findCString(kKeyMIMEType, &fileMIME));

        if (!strcasecmp(fileMIME, "video/x-matroska")) {
            sp<MetaData> trackMeta = mExtractor->getTrackMetaData(0);
            const char *trackMIME;
            CHECK(trackMeta->findCString(kKeyMIMEType, &trackMIME));

            if (!strncasecmp("audio/", trackMIME, 6)) {
                // The matroska file only contains a single audio track,
                // rewrite its mime type.
                mMetaData.add(
                        METADATA_KEY_MIMETYPE, String8("audio/x-matroska"));
            }
        }
    }

    // To check whether the media file is drm-protected
    if (mExtractor->getDrmFlag()) {
        mMetaData.add(METADATA_KEY_IS_DRM, String8("1"));
    }
}
bool isWVM(const char* url,
           const KeyedVector<String8, String8> *headers) {
    sp<DataSource> dataSource;
    String8 mUri;
    KeyedVector<String8, String8> mUriHeaders;
    sp<HTTPBase> mConnectingDataSource;
    sp<NuCachedSource2> mCachedSource;
    uint32_t mFlags;

    mUri = url;

    void *VendorLibHandle = NULL;
    if (VendorLibHandle == NULL) {
        VendorLibHandle = dlopen("libwvm.so", RTLD_NOW);
    }

    if (!VendorLibHandle) {
        return false;
    }

    if (headers) {
        mUriHeaders = *headers;

        ssize_t index = mUriHeaders.indexOfKey(String8("x-hide-urls-from-log"));
        if (index >= 0) {
            // Browser is in "incognito" mode, suppress logging URLs.

            // This isn't something that should be passed to the server.
            mUriHeaders.removeItemsAt(index);

            mFlags |= INCOGNITO;
        }
    }

    if (!strncasecmp("http://", mUri.string(), 7)
            || !strncasecmp("https://", mUri.string(), 8)) {
        mConnectingDataSource = HTTPBase::Create(
                (mFlags & INCOGNITO)
                    ? HTTPBase::kFlagIncognito
                    : 0);

        String8 cacheConfig;
        bool disconnectAtHighwatermark;
        NuCachedSource2::RemoveCacheSpecificHeaders(
                &mUriHeaders, &cacheConfig, &disconnectAtHighwatermark);

        status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);

        if (err != OK) {
            mConnectingDataSource.clear();

            ALOGI("mConnectingDataSource->connect() returned %d", err);
            return false;
        }

        // The widevine extractor does its own caching.
        mCachedSource = new NuCachedSource2(
                mConnectingDataSource,
                cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
                disconnectAtHighwatermark);

        dataSource = mCachedSource;

        mConnectingDataSource.clear();

        // Removed prefill as we can't abort it.
        //
        // We're going to prefill the cache before trying to instantiate
        // the extractor below, as the latter is an operation that otherwise
        // could block on the datasource for a significant amount of time.
        // During that time we'd be unable to abort the preparation phase
        // without this prefill.

    } else {
        dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
    }

    if (dataSource == NULL) {
        return false;
    }

    typedef WVMLoadableExtractor *(*SnifferFunc)(const sp<DataSource>&);
    SnifferFunc snifferFunc =
        (SnifferFunc) dlsym(VendorLibHandle,
                "_ZN7android15IsWidevineMediaERKNS_2spINS_10DataSourceEEE");

    if (snifferFunc) {
        if ((*snifferFunc)(dataSource)) {
            return true;
        }
    }

    return false;
}
Example #18
0
int main(int argc, char* const argv[])
{
    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
        // Older kernels don't understand PR_SET_NO_NEW_PRIVS and return
        // EINVAL. Don't die on such kernels.
        if (errno != EINVAL) {
            LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));
            return 12;
        }
    }

    if (xposed::handleOptions(argc, argv))
            return 0;

    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    // Process command line arguments
    // ignore argv[0]
    argc--;
    argv++;

    // Everything up to '--' or first non '-' arg goes to the vm.
    //
    // The first argument after the VM args is the "parent dir", which
    // is currently unused.
    //
    // After the parent dir, we expect one or more the following internal
    // arguments :
    //
    // --zygote : Start in zygote mode
    // --start-system-server : Start the system server.
    // --application : Start in application (stand alone, non zygote) mode.
    // --nice-name : The nice name for this process.
    //
    // For non zygote starts, these arguments will be followed by
    // the main class name. All remaining arguments are passed to
    // the main method of this class.
    //
    // For zygote starts, all remaining arguments are passed to the zygote.
    // main function.
    //
    // Note that we must copy argument string values since we will rewrite the
    // entire argument block when we apply the nice name to argv0.

    int i;
    for (i = 0; i < argc; i++) {
        if (argv[i][0] != '-') {
            break;
        }
        if (argv[i][1] == '-' && argv[i][2] == 0) {
            ++i; // Skip --.
            break;
        }
        runtime.addOption(strdup(argv[i]));
    }

    // Parse runtime arguments.  Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }

    Vector<String8> args;
    if (!className.isEmpty()) {
        // We're not in zygote mode, the only argument we need to pass
        // to RuntimeInit is the application argument.
        //
        // The Remainder of args get passed to startup class main(). Make
        // copies of them before we overwrite them with the process name.
        args.add(application ? String8("application") : String8("tool"));
        runtime.setClassNameAndArgs(className, argc - i, argv + i);
    } else {
        // We're in zygote mode.
        maybeCreateDalvikCache();

        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }

        char prop[PROP_VALUE_MAX];
        if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
            LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
                ABI_LIST_PROPERTY);
            return 11;
        }

        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);
        args.add(abiFlag);

        // In zygote mode, pass all remaining arguments to the zygote
        // main() method.
        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }

    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string());
        set_process_name(niceName.string());
    }

    isXposedLoaded = xposed::initialize(zygote, startSystemServer, className, argc, argv);
    if (zygote) {
        runtimeStart(runtime, isXposedLoaded ? XPOSED_CLASS_DOTS_ZYGOTE : "com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtimeStart(runtime, isXposedLoaded ? XPOSED_CLASS_DOTS_TOOLS : "com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
        return 10;
    }
}
Example #19
0
// static
sp<DataSource> DataSource::CreateFromURI(
        const sp<IMediaHTTPService> &httpService,
        const char *uri,
        const KeyedVector<String8, String8> *headers,
        String8 *contentType,
        HTTPBase *httpSource) {
    if (contentType != NULL) {
        *contentType = "";
    }

    bool isWidevine = !strncasecmp("widevine://", uri, 11);

    sp<DataSource> source;
    if (!strncasecmp("file://", uri, 7)) {
        source = new FileSource(uri + 7);
    } else if (!strncasecmp("http://", uri, 7)
            || !strncasecmp("https://", uri, 8)
            || isWidevine) {
        if (httpService == NULL) {
            ALOGE("Invalid http service!");
            return NULL;
        }

        if (httpSource == NULL) {
            sp<IMediaHTTPConnection> conn = httpService->makeHTTPConnection();
            if (conn == NULL) {
                ALOGE("Failed to make http connection from http service!");
                return NULL;
            }
            httpSource = new MediaHTTP(conn);
        }

        String8 tmp;
        if (isWidevine) {
            tmp = String8("http://");
            tmp.append(uri + 11);

            uri = tmp.string();
        }

        String8 cacheConfig;
        bool disconnectAtHighwatermark;
        KeyedVector<String8, String8> nonCacheSpecificHeaders;
        if (headers != NULL) {
            nonCacheSpecificHeaders = *headers;
            NuCachedSource2::RemoveCacheSpecificHeaders(
                    &nonCacheSpecificHeaders,
                    &cacheConfig,
                    &disconnectAtHighwatermark);
        }

        if (httpSource->connect(uri, &nonCacheSpecificHeaders) != OK) {
            ALOGE("Failed to connect http source!");
            return NULL;
        }

        if (!isWidevine) {
            if (contentType != NULL) {
                *contentType = httpSource->getMIMEType();
            }

            source = new NuCachedSource2(
                    httpSource,
                    cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
                    disconnectAtHighwatermark);
        } else {
            // We do not want that prefetching, caching, datasource wrapper
            // in the widevine:// case.
            source = httpSource;
        }
    } else if (!strncasecmp("data:", uri, 5)) {
        source = DataURISource::Create(uri);
    } else {
        // Assume it's a filename.
        source = new FileSource(uri);
    }

    if (source == NULL || source->initCheck() != OK) {
        return NULL;
    }

    return source;
}