status_t StagefrightRecorder::setParameters(const String8 &params) {
    LOGV("setParameters: %s", params.string());
    const char *cparams = params.string();
    const char *key_start = cparams;
    for (;;) {
        const char *equal_pos = strchr(key_start, '=');
        if (equal_pos == NULL) {
            LOGE("Parameters %s miss a value", cparams);
            return BAD_VALUE;
        }
        String8 key(key_start, equal_pos - key_start);
        TrimString(&key);
        if (key.length() == 0) {
            LOGE("Parameters %s contains an empty key", cparams);
            return BAD_VALUE;
        }
        const char *value_start = equal_pos + 1;
        const char *semicolon_pos = strchr(value_start, ';');
        String8 value;
        if (semicolon_pos == NULL) {
            value.setTo(value_start);
        } else {
            value.setTo(value_start, semicolon_pos - value_start);
        }
        if (setParameter(key, value) != OK) {
            return BAD_VALUE;
        }
        if (semicolon_pos == NULL) {
            break;  // Reaches the end
        }
        key_start = semicolon_pos + 1;
    }
    return OK;
}
Example #2
0
        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;
        }
status_t ASessionDescription::getSessionUrl(String8& uri) const{
    AString line;
    if(findAttribute(0, "a=control", &line)) {
        // rtsp without aggregation control url will be considered as pure RTP
        if (!line.startsWith("rtsp://"))
            return ERROR_UNSUPPORTED;

        uri.setTo(line.c_str());
    } else {
        // assume as rtp streaming
        uri.setTo("rtp://0.0.0.0");
    }
    return OK;
}
Example #4
0
String8 getInputDeviceConfigurationFilePathByName(
        const String8& name, InputDeviceConfigurationFileType type) {
    // Search system repository.
    String8 path;

    // Treblized input device config files will be located /odm/usr or /vendor/usr.
    const char *rootsForPartition[] {"/odm", "/vendor", getenv("ANDROID_ROOT")};
    for (size_t i = 0; i < size(rootsForPartition); i++) {
        path.setTo(rootsForPartition[i]);
        path.append("/usr/");
        appendInputDeviceConfigurationFileRelativePath(path, name, type);
#if DEBUG_PROBE
        ALOGD("Probing for system provided input device configuration file: path='%s'",
              path.string());
#endif
        if (!access(path.string(), R_OK)) {
#if DEBUG_PROBE
            ALOGD("Found");
#endif
            return path;
        }
    }

    // Search user repository.
    // TODO Should only look here if not in safe mode.
    path.setTo(getenv("ANDROID_DATA"));
    path.append("/system/devices/");
    appendInputDeviceConfigurationFileRelativePath(path, name, type);
#if DEBUG_PROBE
    ALOGD("Probing for system user input device configuration file: path='%s'", path.string());
#endif
    if (!access(path.string(), R_OK)) {
#if DEBUG_PROBE
        ALOGD("Found");
#endif
        return path;
    }

    // Not found.
#if DEBUG_PROBE
    ALOGD("Probe failed to find input device configuration file: name='%s', type=%d",
            name.string(), type);
#endif
    return String8();
}
String8 getInputDeviceConfigurationFilePathByName(
        const String8& name, InputDeviceConfigurationFileType type) {
    // Search system repository.
    String8 path;
    path.setTo(getenv("ANDROID_ROOT"));
    path.append("/usr/");
    appendInputDeviceConfigurationFileRelativePath(path, name, type);
#if DEBUG_PROBE
    ALOGD("Probing for system provided input device configuration file: path='%s'", path.string());
#endif
    if (!access(path.string(), R_OK)) {
#if DEBUG_PROBE
        ALOGD("Found");
#endif
        return path;
    }

    // Search user repository.
    // TODO Should only look here if not in safe mode.
    path.setTo(getenv("ANDROID_DATA"));
    path.append("/system/devices/");
    appendInputDeviceConfigurationFileRelativePath(path, name, type);
#if DEBUG_PROBE
    ALOGD("Probing for system user input device configuration file: path='%s'", path.string());
#endif
    if (!access(path.string(), R_OK)) {
#if DEBUG_PROBE
        ALOGD("Found");
#endif
        return path;
    }

    // Not found.
#if DEBUG_PROBE
    ALOGD("Probe failed to find input device configuration file: name='%s', type=%d",
            name.string(), type);
#endif
    return String8();
}
static jint nativeCreate(JNIEnv* env, jclass clazz, jstring nameObj, jint cursorWindowSize) {
    String8 name;
    if (nameObj) {
        const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
        name.setTo(nameStr);
        env->ReleaseStringUTFChars(nameObj, nameStr);
    }
    if (name.size() == 0) {
        name.setTo("<unnamed>");
    }

    CursorWindow* window;
    status_t status = CursorWindow::create(name, cursorWindowSize, &window);
    if (status || !window) {
        LOGE("Could not allocate CursorWindow '%s' of size %d due to error %d.",
                name.string(), cursorWindowSize, status);
        return 0;
    }

    LOG_WINDOW("nativeInitializeEmpty: window = %p", window);
    return reinterpret_cast<jint>(window);
}
bool BootAnimation::readFile(const char* name, String8& outString)
{
    ZipEntryRO entry = mZip->findEntryByName(name);
    ALOGE_IF(!entry, "couldn't find %s", name);
    if (!entry) {
        return false;
    }

    FileMap* entryMap = mZip->createEntryFileMap(entry);
    mZip->releaseEntry(entry);
    ALOGE_IF(!entryMap, "entryMap is null");
    if (!entryMap) {
        return false;
    }

    outString.setTo((char const*)entryMap->getDataPtr(), entryMap->getDataLength());
    entryMap->release();
    return true;
}
//[BUGFIX]-Add-BEGIN by TCTNB.Ruili.Liu,04/08/2014,PR629105,
//Can not display Chinese SSID by GBK  normal
void parseSsid(String16& str, const char *reply)
{
    unsigned int lineBeg = 0, lineEnd = 0;
    size_t  replyLen = strlen(reply);
    char    *pos = NULL;
    char    ssid[BUF_SIZE] = {0};
    char    ssid_utf8[BUF_SIZE] = {0};
    char    ssid_txt[BUF_SIZE] ={0};
    bool    isUTF8 = false, isCh = false;
    char    buf[BUF_SIZE] = {0};
    String8 line;

    UConverterType conType = UCNV_UTF8;
    char dest[CONVERT_LINE_LEN] = {0};
    UErrorCode err = U_ZERO_ERROR;
    UConverter* pConverter = ucnv_open(CHARSET_CN, &err);
    if (U_FAILURE(err)) {
        ALOGE("ucnv_open error");
        return;
    }
    /* Parse every line of the reply to construct accessPointObjectItem list */
    for (lineBeg = 0, lineEnd = 0; lineEnd <= replyLen; ++lineEnd) {
        if (lineEnd == replyLen || ' ' == reply[lineEnd]) {
            line.setTo(reply + lineBeg, lineEnd - lineBeg + 1);
            if (DBG)
                ALOGD("%s, line=%s ", __FUNCTION__, line.string());
            if (strncmp(line.string(), "SSID=", 5) == 0) {
                sscanf(line.string() + 5, "%[^\n]", ssid);
                ssid_decode(buf,BUF_SIZE,ssid);
                isUTF8 = isUTF8String(buf,sizeof(buf));
                isCh = false;
                for (pos = buf; '\0' != *pos; pos++) {
                    if (0x80 == (*pos & 0x80)) {
                        isCh = true;
                        break;
                    }
                }
                if (DBG)
                    ALOGD("%s, ssid = %s, buf = %s,isUTF8= %d, isCh = %d",
                        __FUNCTION__, ssid, buf ,isUTF8, isCh);
                if (!isUTF8 && isCh) {
                    ucnv_toAlgorithmic(conType, pConverter, dest, CONVERT_LINE_LEN,
                                buf, strlen(buf), &err);
                    if (U_FAILURE(err)) {
                        ALOGE("ucnv_toUChars error");
                        goto EXIT;
                    }
                    ssid_encode(ssid_txt, BUF_SIZE, dest, strlen(dest));
                    if (DBG)
                        ALOGD("%s, ssid_txt = %s", __FUNCTION__,ssid_txt);
                    str += String16("SSID=");
                    str += String16(ssid_txt);
                    str += String16("\n");
                    strncpy(ssid_utf8, dest, strlen(dest));
                    memset(dest, 0, CONVERT_LINE_LEN);
                    memset(ssid_txt, 0, BUF_SIZE);
                } else {
                    memset(buf, 0, BUF_SIZE);
                    str += String16(line.string());
                }
            }
            if (strncmp(line.string(), "SSID=", 5) != 0)
                str += String16(line.string());
            lineBeg = lineEnd + 1;
        }
    }
EXIT:
    ucnv_close(pConverter);
}
Example #9
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 #10
0
void
AudioManager::HandleBluetoothStatusChanged(nsISupports* aSubject,
                                           const char* aTopic,
                                           const nsCString aAddress)
{
#ifdef MOZ_B2G_BT
  bool status;
  if (!strcmp(aTopic, BLUETOOTH_SCO_STATUS_CHANGED_ID)) {
    BluetoothHfpManagerBase* hfp =
      static_cast<BluetoothHfpManagerBase*>(aSubject);
    status = hfp->IsScoConnected();
  } else {
    BluetoothProfileManagerBase* profile =
      static_cast<BluetoothProfileManagerBase*>(aSubject);
    status = profile->IsConnected();
  }

  audio_policy_dev_state_t audioState = status ?
    AUDIO_POLICY_DEVICE_STATE_AVAILABLE :
    AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;

  if (!strcmp(aTopic, BLUETOOTH_SCO_STATUS_CHANGED_ID)) {
    if (audioState == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
      String8 cmd;
      cmd.appendFormat("bt_samplerate=%d", kBtSampleRate);
      AudioSystem::setParameters(0, cmd);
      SetForceForUse(nsIAudioManager::USE_COMMUNICATION, nsIAudioManager::FORCE_BT_SCO);
      SwitchProfileData(DEVICE_BLUETOOTH, true);
    } else {
      int32_t force;
      GetForceForUse(nsIAudioManager::USE_COMMUNICATION, &force);
      if (force == nsIAudioManager::FORCE_BT_SCO) {
        SetForceForUse(nsIAudioManager::USE_COMMUNICATION, nsIAudioManager::FORCE_NONE);
      }
      SwitchProfileData(DEVICE_BLUETOOTH, false);
    }
  } else if (!strcmp(aTopic, BLUETOOTH_A2DP_STATUS_CHANGED_ID)) {
    if (audioState == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE && sA2dpSwitchDone) {
      MessageLoop::current()->PostDelayedTask(
        FROM_HERE, NewRunnableFunction(&ProcessDelayedA2dpRoute, audioState, aAddress), 1000);
      sA2dpSwitchDone = false;
      SwitchProfileData(DEVICE_BLUETOOTH, false);
    } else {
      AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
                                            audioState, aAddress.get());
      String8 cmd("bluetooth_enabled=true");
      AudioSystem::setParameters(0, cmd);
      cmd.setTo("A2dpSuspended=false");
      AudioSystem::setParameters(0, cmd);
      sA2dpSwitchDone = true;
      SwitchProfileData(DEVICE_BLUETOOTH, true);
#if ANDROID_VERSION >= 17
      if (AudioSystem::getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) == AUDIO_POLICY_FORCE_NO_BT_A2DP) {
        SetForceForUse(AUDIO_POLICY_FORCE_FOR_MEDIA, AUDIO_POLICY_FORCE_NONE);
      }
#endif
    }
    sBluetoothA2dpEnabled = audioState == AUDIO_POLICY_DEVICE_STATE_AVAILABLE;
  } else if (!strcmp(aTopic, BLUETOOTH_HFP_STATUS_CHANGED_ID)) {
    AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
                                          audioState, aAddress.get());
    AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
                                          audioState, aAddress.get());
  } else if (!strcmp(aTopic, BLUETOOTH_HFP_NREC_STATUS_CHANGED_ID)) {
      String8 cmd;
      BluetoothHfpManagerBase* hfp =
          static_cast<BluetoothHfpManagerBase*>(aSubject);
      if (hfp->IsNrecEnabled()) {
          cmd.setTo("bt_headset_name=<unknown>;bt_headset_nrec=on");
          AudioSystem::setParameters(0, cmd);
      } else {
          cmd.setTo("bt_headset_name=<unknown>;bt_headset_nrec=off");
          AudioSystem::setParameters(0, cmd);
      }
  }
#endif
}
MediaScanResult StagefrightMediaScanner::processFileInternal(
        const char *path, const char *mimeType,
        MediaScannerClient &client) {
    const char *extension = strrchr(path, '.');

    if (!extension) {
        return MEDIA_SCAN_RESULT_SKIPPED;
    }

    if (!FileHasAcceptableExtension(extension)) {
        return MEDIA_SCAN_RESULT_SKIPPED;
    }

#ifndef ANDROID_DEFAULT_CODE
#ifdef MTK_DRM_APP
    // add dcf meta data for dcf file
    // check extension first
    LOGV("processFileInternal() : the extension: %s", extension);
    bool isOMADrmDcf = false;
    if (0 == strcasecmp(extension, ".dcf")) {
        String8 tmp(path);
        DrmManagerClient* drmManagerClient = new DrmManagerClient();
        DrmMetadata* dcfMetadata = drmManagerClient->getMetadata(&tmp);

        if (dcfMetadata == NULL) {
            LOGW("scan: OMA DRM v1: failed to get drm metadata, not scanned into db.");
            delete drmManagerClient;
            client.setMimeType("bad mime type");
            return MEDIA_SCAN_RESULT_SKIPPED;
        }

        struct Map {
            const char* from;
            int to;
        };
        static const Map kMap[] = {
            {DrmMetaKey::META_KEY_IS_DRM,
                METADATA_KEY_IS_DRM}, // "is_drm"
            {DrmMetaKey::META_KEY_CONTENT_URI, 
                METADATA_KEY_DRM_CONTENT_URI},
            {DrmMetaKey::META_KEY_OFFSET,
                METADATA_KEY_DRM_OFFSET},
            {DrmMetaKey::META_KEY_DATALEN,
                METADATA_KEY_DRM_DATALEN},
            {DrmMetaKey::META_KEY_RIGHTS_ISSUER,
                METADATA_KEY_DRM_RIGHTS_ISSUER},
            {DrmMetaKey::META_KEY_CONTENT_NAME,
                METADATA_KEY_DRM_CONTENT_NAME},
            {DrmMetaKey::META_KEY_CONTENT_DESCRIPTION,
                METADATA_KEY_DRM_CONTENT_DES},
            {DrmMetaKey::META_KEY_CONTENT_VENDOR,
                METADATA_KEY_DRM_CONTENT_VENDOR},
            {DrmMetaKey::META_KEY_ICON_URI,
                METADATA_KEY_DRM_ICON_URI} ,
            {DrmMetaKey::META_KEY_METHOD,
                METADATA_KEY_DRM_METHOD},
            {DrmMetaKey::META_KEY_MIME,
                METADATA_KEY_DRM_MIME}
        };
        static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);

        int action = Action::PLAY;
        String8 type;
        for (size_t i = 0; i < kNumMapEntries; ++i) {
            String8 value = dcfMetadata->get(String8(kMap[i].from));
            if (value.length() != 0)
            {
                if (kMap[i].to == METADATA_KEY_DRM_MIME) {
                    value = DrmMtkUtil::toCommonMime(value.string());
                    // not audio/video/image -> not scan into db
                    type.setTo(value.string(), 6);
                    if (0 != strcasecmp(type.string(), "audio/")
                        && 0 != strcasecmp(type.string(), "video/")
                        && 0 != strcasecmp(type.string(), "image/")) {
                        LOGW("scan: OMA DRM v1: invalid drm media file mime type[%s], not added into db.",
                                value.string());
                        delete dcfMetadata;
                        delete drmManagerClient;
                        client.setMimeType("bad mime type");
                        return MEDIA_SCAN_RESULT_SKIPPED;
                    }

                    client.setMimeType(value.string());
                    LOGD("scan: OMA DRM v1: drm original mime type[%s].",
                            value.string());

                    // determine the Action it shall used.
                    if ((0 == strcasecmp(type.string(), "audio/"))
                        || (0 == strcasecmp(type.string(), "video/"))) {
                        action = Action::PLAY;
                    } else if ((0 == strcasecmp(type.string(), "image/"))) {
                        action = Action::DISPLAY;
                    }
                }

                if (kMap[i].to == METADATA_KEY_IS_DRM) {
                    isOMADrmDcf = (value == String8("1"));
                }

                client.addStringTag(kMap[i].from, value.string());
                LOGD("scan: OMA DRM v1: client.addString tag[%s] value[%s].",
                        kMap[i].from, value.string());
            }
        }

        // if there's no valid rights for this file currently, just return OK
        // to make sure it can be scanned into db.
        if (isOMADrmDcf
            && RightsStatus::RIGHTS_VALID != drmManagerClient->checkRightsStatus(tmp, action)) {
            LOGD("scan: OMA DRM v1: current no valid rights, return OK so that it can be added into db.");
            delete dcfMetadata;
            delete drmManagerClient;
            return MEDIA_SCAN_RESULT_OK;
        }

        // when there's valid rights, should contine to add extra metadata
        LOGD("scan: OMA DRM v1: current valid rights, continue to add extra info.");
        delete dcfMetadata; dcfMetadata = NULL;
        delete drmManagerClient; drmManagerClient = NULL;

        // if picture then we need not to scan with extractors.
        if (isOMADrmDcf && 0 == strcasecmp(type.string(), "image/")) {
            LOGD("scan: OMA DRM v1: for DRM image we do not sniff with extractors.");
            return MEDIA_SCAN_RESULT_OK;
        }
    }
#endif
#endif

    if (!strcasecmp(extension, ".mid")
            || !strcasecmp(extension, ".smf")
            || !strcasecmp(extension, ".imy")
            || !strcasecmp(extension, ".midi")
            || !strcasecmp(extension, ".xmf")
            || !strcasecmp(extension, ".rtttl")
            || !strcasecmp(extension, ".rtx")
            || !strcasecmp(extension, ".ota")
            || !strcasecmp(extension, ".mxmf")) {
        return HandleMIDI(path, &client);
    }

    sp<MediaMetadataRetriever> mRetriever(new MediaMetadataRetriever);

    status_t status = mRetriever->setDataSource(path);
    if (status) {
#ifndef ANDROID_DEFAULT_CODE
         //if this still need on ICS
        // set mime type to "bad mime type" for unsupported format, otherwise the file will be included in Gallery/Music
        LOGE("processFile '%s' - not supported", path);
        client.setMimeType("bad mime type");
        return MEDIA_SCAN_RESULT_SKIPPED;
#else
        return MEDIA_SCAN_RESULT_ERROR;
#endif
    }

    const char *value;
    if ((value = mRetriever->extractMetadata(
                    METADATA_KEY_MIMETYPE)) != NULL) {
        status = client.setMimeType(value);
        if (status) {
            return MEDIA_SCAN_RESULT_ERROR;
        }
    }

    struct KeyMap {
        const char *tag;
        int key;
    };
    static const KeyMap kKeyMap[] = {
        { "tracknumber", METADATA_KEY_CD_TRACK_NUMBER },
        { "discnumber", METADATA_KEY_DISC_NUMBER },
        { "album", METADATA_KEY_ALBUM },
        { "artist", METADATA_KEY_ARTIST },
        { "albumartist", METADATA_KEY_ALBUMARTIST },
        { "composer", METADATA_KEY_COMPOSER },
        { "genre", METADATA_KEY_GENRE },
        { "title", METADATA_KEY_TITLE },
        { "year", METADATA_KEY_YEAR },
        { "duration", METADATA_KEY_DURATION },
        { "writer", METADATA_KEY_WRITER },
        { "compilation", METADATA_KEY_COMPILATION },
        { "isdrm", METADATA_KEY_IS_DRM }, // "isdrm"
#ifdef MTK_S3D_SUPPORT
        {"stereotype",METADATA_KEY_STEREO_3D}, //stereo 3d info
#endif
    };
    static const size_t kNumEntries = sizeof(kKeyMap) / sizeof(kKeyMap[0]);

    for (size_t i = 0; i < kNumEntries; ++i) {
        const char *value;
        if ((value = mRetriever->extractMetadata(kKeyMap[i].key)) != NULL) {
#ifndef ANDROID_DEFAULT_CODE
#ifdef MTK_DRM_APP
            if (kKeyMap[i].key == METADATA_KEY_IS_DRM) {
                if (isOMADrmDcf) {
                    LOGD("set METADATA_KEY_IS_DRM to 1 for OMA DRM v1.");
                    value = "1";
                }
            }
#endif
#endif
            status = client.addStringTag(kKeyMap[i].tag, value);
            LOGD("processFileInternal() : client.addString tag[%s] value[%s]",
                        kKeyMap[i].tag, value);
            if (status != OK) {
                return MEDIA_SCAN_RESULT_ERROR;
            }
#ifndef ANDROID_DEFAULT_CODE
            if (kKeyMap[i].key == METADATA_KEY_DURATION) {
                if (!strcasecmp(extension, ".mp3")
                        || !strcasecmp(extension, ".aac")
                        || !strcasecmp(extension, ".amr")
                        || !strcasecmp(extension, ".awb")) {
                    client.addStringTag("isAccurateDuration", "0");
                } else if (!strcasecmp(extension, ".wav")
                        || !strcasecmp(extension, ".ogg")
                        || !strcasecmp(extension, ".oga")) {
                    client.addStringTag("isAccurateDuration", "1");
                }
            }
#endif // ANDROID_DEFAULT_CODE
        }
    }
#ifndef ANDROID_DEFAULT_CODE
	LOGD("processFileInternal '%s' - return OK", path);
#endif
    return MEDIA_SCAN_RESULT_OK;
}
int main(int argc, char **argv) {
    android::ProcessState::self()->startThreadPool();

    bool audioOnly = false;
    bool listComponents = false;
    bool dumpProfiles = false;
    bool extractThumbnail = false;
    bool seekTest = false;
    bool useSurfaceAlloc = false;
    bool useSurfaceTexAlloc = false;
    bool dumpStream = false;
    bool dumpPCMStream = false;
    String8 dumpStreamFilename;
    gNumRepetitions = 1;
    gMaxNumFrames = 0;
    gReproduceBug = -1;
    gPreferSoftwareCodec = false;
    gForceToUseHardwareCodec = false;
    gPlaybackAudio = false;
    gWriteMP4 = false;
    gDisplayHistogram = false;

    sp<ALooper> looper;
    sp<LiveSession> liveSession;

    int res;
    while ((res = getopt(argc, argv, "han:lm:b:ptsrow:kxSTd:D:")) >= 0) {
        switch (res) {
            case 'a':
            {
                audioOnly = true;
                break;
            }

            case 'd':
            {
                dumpStream = true;
                dumpStreamFilename.setTo(optarg);
                break;
            }

            case 'D':
            {
                dumpPCMStream = true;
                audioOnly = true;
                dumpStreamFilename.setTo(optarg);
                break;
            }

            case 'l':
            {
                listComponents = true;
                break;
            }

            case 'm':
            case 'n':
            case 'b':
            {
                char *end;
                long x = strtol(optarg, &end, 10);

                if (*end != '\0' || end == optarg || x <= 0) {
                    x = 1;
                }

                if (res == 'n') {
                    gNumRepetitions = x;
                } else if (res == 'm') {
                    gMaxNumFrames = x;
                } else {
                    CHECK_EQ(res, 'b');
                    gReproduceBug = x;
                }
                break;
            }

            case 'w':
            {
                gWriteMP4 = true;
                gWriteMP4Filename.setTo(optarg);
                break;
            }

            case 'p':
            {
                dumpProfiles = true;
                break;
            }

            case 't':
            {
                extractThumbnail = true;
                break;
            }

            case 's':
            {
                gPreferSoftwareCodec = true;
                break;
            }

            case 'r':
            {
                gForceToUseHardwareCodec = true;
                break;
            }

            case 'o':
            {
                gPlaybackAudio = true;
                break;
            }

            case 'k':
            {
                seekTest = true;
                break;
            }

            case 'x':
            {
                gDisplayHistogram = true;
                break;
            }

            case 'S':
            {
                useSurfaceAlloc = true;
                break;
            }

            case 'T':
            {
                useSurfaceTexAlloc = true;
                break;
            }

            case '?':
            case 'h':
            default:
            {
                usage(argv[0]);
                exit(1);
                break;
            }
        }
    }

    if (gPlaybackAudio && !audioOnly) {
        // This doesn't make any sense if we're decoding the video track.
        gPlaybackAudio = false;
    }

    argc -= optind;
    argv += optind;

    if (extractThumbnail) {
        sp<IServiceManager> sm = defaultServiceManager();
        sp<IBinder> binder = sm->getService(String16("media.player"));
        sp<IMediaPlayerService> service =
            interface_cast<IMediaPlayerService>(binder);

        CHECK(service.get() != NULL);

        sp<IMediaMetadataRetriever> retriever =
            service->createMetadataRetriever();

        CHECK(retriever != NULL);

        for (int k = 0; k < argc; ++k) {
            const char *filename = argv[k];

            bool failed = true;

            int fd = open(filename, O_RDONLY | O_LARGEFILE);
            CHECK_GE(fd, 0);

            off64_t fileSize = lseek64(fd, 0, SEEK_END);
            CHECK_GE(fileSize, 0ll);

            CHECK_EQ(retriever->setDataSource(fd, 0, fileSize), (status_t)OK);

            close(fd);
            fd = -1;

            sp<IMemory> mem =
                    retriever->getFrameAtTime(-1,
                                    MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);

            if (mem != NULL) {
                failed = false;
                printf("getFrameAtTime(%s) => OK\n", filename);

                VideoFrame *frame = (VideoFrame *)mem->pointer();

                CHECK_EQ(writeJpegFile("/sdcard/out.jpg",
                            (uint8_t *)frame + sizeof(VideoFrame),
                            frame->mWidth, frame->mHeight), 0);
            }

            {
                mem = retriever->extractAlbumArt();

                if (mem != NULL) {
                    failed = false;
                    printf("extractAlbumArt(%s) => OK\n", filename);
                }
            }

            if (failed) {
                printf("both getFrameAtTime and extractAlbumArt "
                    "failed on file '%s'.\n", filename);
            }
        }

        return 0;
    }

    if (dumpProfiles) {
        sp<IServiceManager> sm = defaultServiceManager();
        sp<IBinder> binder = sm->getService(String16("media.player"));
        sp<IMediaPlayerService> service =
            interface_cast<IMediaPlayerService>(binder);

        CHECK(service.get() != NULL);

        sp<IOMX> omx = service->getOMX();
        CHECK(omx.get() != NULL);
        dumpCodecProfiles(omx, true /* queryDecoders */);
        dumpCodecProfiles(omx, false /* queryDecoders */);
    }

    if (listComponents) {
        sp<IServiceManager> sm = defaultServiceManager();
        sp<IBinder> binder = sm->getService(String16("media.player"));
        sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);

        CHECK(service.get() != NULL);

        sp<IOMX> omx = service->getOMX();
        CHECK(omx.get() != NULL);

        List<IOMX::ComponentInfo> list;
        omx->listNodes(&list);

        for (List<IOMX::ComponentInfo>::iterator it = list.begin();
             it != list.end(); ++it) {
            printf("%s\t Roles: ", (*it).mName.string());
            for (List<String8>::iterator itRoles = (*it).mRoles.begin() ;
                    itRoles != (*it).mRoles.end() ; ++itRoles) {
                printf("%s\t", (*itRoles).string());
            }
            printf("\n");
        }
    }

    sp<SurfaceComposerClient> composerClient;
    sp<SurfaceControl> control;

    if ((useSurfaceAlloc || useSurfaceTexAlloc) && !audioOnly) {
        if (useSurfaceAlloc) {
            composerClient = new SurfaceComposerClient;
            CHECK_EQ(composerClient->initCheck(), (status_t)OK);

            control = composerClient->createSurface(
                    String8("A Surface"),
                    1280,
                    800,
                    PIXEL_FORMAT_RGB_565,
                    0);

            CHECK(control != NULL);
            CHECK(control->isValid());

            SurfaceComposerClient::openGlobalTransaction();
            CHECK_EQ(control->setLayer(INT_MAX), (status_t)OK);
            CHECK_EQ(control->show(), (status_t)OK);
            SurfaceComposerClient::closeGlobalTransaction();

            gSurface = control->getSurface();
            CHECK(gSurface != NULL);
        } else {
            CHECK(useSurfaceTexAlloc);

            sp<GLConsumer> texture = new GLConsumer(0 /* tex */);
            gSurface = new Surface(texture->getBufferQueue());
        }

        CHECK_EQ((status_t)OK,
                 native_window_api_connect(
                     gSurface.get(), NATIVE_WINDOW_API_MEDIA));
    }

    DataSource::RegisterDefaultSniffers();

    OMXClient client;
    status_t err = client.connect();

    for (int k = 0; k < argc; ++k) {
        bool syncInfoPresent = true;

        const char *filename = argv[k];

        sp<DataSource> dataSource = DataSource::CreateFromURI(filename);

        if (strncasecmp(filename, "sine:", 5)
                && strncasecmp(filename, "httplive://", 11)
                && dataSource == NULL) {
            fprintf(stderr, "Unable to create data source.\n");
            return 1;
        }

        bool isJPEG = false;

        size_t len = strlen(filename);
        if (len >= 4 && !strcasecmp(filename + len - 4, ".jpg")) {
            isJPEG = true;
        }

        Vector<sp<MediaSource> > mediaSources;
        sp<MediaSource> mediaSource;

        if (isJPEG) {
            mediaSource = new JPEGSource(dataSource);
            if (gWriteMP4) {
                mediaSources.push(mediaSource);
            }
        } else if (!strncasecmp("sine:", filename, 5)) {
            char *end;
            long sampleRate = strtol(filename + 5, &end, 10);

            if (end == filename + 5) {
                sampleRate = 44100;
            }
            mediaSource = new SineSource(sampleRate, 1);
            if (gWriteMP4) {
                mediaSources.push(mediaSource);
            }
        } else {
            sp<MediaExtractor> extractor;

            if (!strncasecmp("httplive://", filename, 11)) {
                String8 uri("http://");
                uri.append(filename + 11);

                if (looper == NULL) {
                    looper = new ALooper;
                    looper->start();
                }
                liveSession = new LiveSession(NULL /* notify */);
                looper->registerHandler(liveSession);

                liveSession->connect(uri.string());
                dataSource = liveSession->getDataSource();

                extractor =
                    MediaExtractor::Create(
                            dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);

                syncInfoPresent = false;
            } else {
                extractor = MediaExtractor::Create(dataSource);

                if (extractor == NULL) {
                    fprintf(stderr, "could not create extractor.\n");
                    return -1;
                }

                sp<MetaData> meta = extractor->getMetaData();

                if (meta != NULL) {
                    const char *mime;
                    CHECK(meta->findCString(kKeyMIMEType, &mime));

                    if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
                        syncInfoPresent = false;
                    }
                }
            }

            size_t numTracks = extractor->countTracks();

            if (gWriteMP4) {
                bool haveAudio = false;
                bool haveVideo = false;
                for (size_t i = 0; i < numTracks; ++i) {
                    sp<MediaSource> source = extractor->getTrack(i);

                    const char *mime;
                    CHECK(source->getFormat()->findCString(
                                kKeyMIMEType, &mime));

                    bool useTrack = false;
                    if (!haveAudio && !strncasecmp("audio/", mime, 6)) {
                        haveAudio = true;
                        useTrack = true;
                    } else if (!haveVideo && !strncasecmp("video/", mime, 6)) {
                        haveVideo = true;
                        useTrack = true;
                    }

                    if (useTrack) {
                        mediaSources.push(source);

                        if (haveAudio && haveVideo) {
                            break;
                        }
                    }
                }
            } else {
                sp<MetaData> meta;
                size_t i;
                for (i = 0; i < numTracks; ++i) {
                    meta = extractor->getTrackMetaData(
                            i, MediaExtractor::kIncludeExtensiveMetaData);

                    const char *mime;
                    meta->findCString(kKeyMIMEType, &mime);

                    if (audioOnly && !strncasecmp(mime, "audio/", 6)) {
                        break;
                    }

                    if (!audioOnly && !strncasecmp(mime, "video/", 6)) {
                        break;
                    }

                    meta = NULL;
                }

                if (meta == NULL) {
                    fprintf(stderr,
                            "No suitable %s track found. The '-a' option will "
                            "target audio tracks only, the default is to target "
                            "video tracks only.\n",
                            audioOnly ? "audio" : "video");
                    return -1;
                }

                int64_t thumbTimeUs;
                if (meta->findInt64(kKeyThumbnailTime, &thumbTimeUs)) {
                    printf("thumbnailTime: %lld us (%.2f secs)\n",
                           thumbTimeUs, thumbTimeUs / 1E6);
                }

                mediaSource = extractor->getTrack(i);
            }
        }

        if (gWriteMP4) {
            writeSourcesToMP4(mediaSources, syncInfoPresent);
        } else if (dumpStream) {
            dumpSource(mediaSource, dumpStreamFilename);
        } else if (dumpPCMStream) {
            OMXClient client;
            CHECK_EQ(client.connect(), (status_t)OK);

            sp<MediaSource> decSource =
                OMXCodec::Create(
                        client.interface(),
                        mediaSource->getFormat(),
                        false,
                        mediaSource,
                        0,
                        0);

            dumpSource(decSource, dumpStreamFilename);
        } else if (seekTest) {
            performSeekTest(mediaSource);
        } else {
            playSource(&client, mediaSource);
        }
    }

    if ((useSurfaceAlloc || useSurfaceTexAlloc) && !audioOnly) {
        CHECK_EQ((status_t)OK,
                 native_window_api_disconnect(
                     gSurface.get(), NATIVE_WINDOW_API_MEDIA));

        gSurface.clear();

        if (useSurfaceAlloc) {
            composerClient->dispose();
        }
    }

    client.disconnect();

    return 0;
}
static int main(int argc, char** argv) {
    // Skip over the first argument.
    argc--;
    argv++;

    bool generateFlag = false;
    String8 targetConfigStr;
    Vector<String8> splitApkPaths;
    String8 baseApkPath;
    while (argc > 0) {
        const String8 arg(*argv);
        if (arg == "--target") {
            argc--;
            argv++;
            if (argc < 1) {
                fprintf(stderr, "error: missing parameter for --target.\n");
                usage();
                return 1;
            }
            targetConfigStr.setTo(*argv);
        } else if (arg == "--split") {
            argc--;
            argv++;
            if (argc < 1) {
                fprintf(stderr, "error: missing parameter for --split.\n");
                usage();
                return 1;
            }
            splitApkPaths.add(String8(*argv));
        } else if (arg == "--base") {
            argc--;
            argv++;
            if (argc < 1) {
                fprintf(stderr, "error: missing parameter for --base.\n");
                usage();
                return 1;
            }

            if (baseApkPath.size() > 0) {
                fprintf(stderr, "error: multiple --base flags not allowed.\n");
                usage();
                return 1;
            }
            baseApkPath.setTo(*argv);
        } else if (arg == "--generate") {
            generateFlag = true;
        } else if (arg == "--help") {
            help();
            return 0;
        } else {
            fprintf(stderr, "error: unknown argument '%s'.\n", arg.string());
            usage();
            return 1;
        }
        argc--;
        argv++;
    }

    if (!generateFlag && targetConfigStr == "") {
        usage();
        return 1;
    }

    if (baseApkPath.size() == 0) {
        fprintf(stderr, "error: missing --base argument.\n");
        usage();
        return 1;
    }

    // Find out some details about the base APK.
    AppInfo baseAppInfo;
    if (!getAppInfo(baseApkPath, baseAppInfo)) {
        fprintf(stderr, "error: unable to read base APK: '%s'.\n", baseApkPath.string());
        return 1;
    }

    SplitDescription targetSplit;
    if (!generateFlag) {
        if (!SplitDescription::parse(targetConfigStr, &targetSplit)) {
            fprintf(stderr, "error: invalid --target config: '%s'.\n",
                    targetConfigStr.string());
            usage();
            return 1;
        }

        // We don't want to match on things that will change at run-time
        // (orientation, w/h, etc.).
        removeRuntimeQualifiers(&targetSplit.config);
    }

    splitApkPaths.add(baseApkPath);

    KeyedVector<String8, Vector<SplitDescription> > apkPathSplitMap;
    KeyedVector<SplitDescription, String8> splitApkPathMap;
    Vector<SplitDescription> splitConfigs;
    const size_t splitCount = splitApkPaths.size();
    for (size_t i = 0; i < splitCount; i++) {
        Vector<SplitDescription> splits = extractSplitDescriptionsFromApk(splitApkPaths[i]);
        if (splits.isEmpty()) {
            fprintf(stderr, "error: invalid --split path: '%s'. No splits found.\n",
                    splitApkPaths[i].string());
            usage();
            return 1;
        }
        apkPathSplitMap.replaceValueFor(splitApkPaths[i], splits);
        const size_t apkSplitDescriptionCount = splits.size();
        for (size_t j = 0; j < apkSplitDescriptionCount; j++) {
            splitApkPathMap.replaceValueFor(splits[j], splitApkPaths[i]);
        }
        splitConfigs.appendVector(splits);
    }

    if (!generateFlag) {
        Vector<SplitDescription> matchingConfigs = select(targetSplit, splitConfigs);
        const size_t matchingConfigCount = matchingConfigs.size();
        SortedVector<String8> matchingSplitPaths;
        for (size_t i = 0; i < matchingConfigCount; i++) {
            matchingSplitPaths.add(splitApkPathMap.valueFor(matchingConfigs[i]));
        }

        const size_t matchingSplitApkPathCount = matchingSplitPaths.size();
        for (size_t i = 0; i < matchingSplitApkPathCount; i++) {
            if (matchingSplitPaths[i] != baseApkPath) {
                fprintf(stdout, "%s\n", matchingSplitPaths[i].string());
            }
        }
    } else {
        generate(apkPathSplitMap, baseApkPath);
    }
    return 0;
}
Example #14
0
int main(int argc, char **argv) {
    android::ProcessState::self()->startThreadPool();

    bool audioOnly = false;
    bool listComponents = false;
    bool dumpProfiles = false;
    bool extractThumbnail = false;
    bool seekTest = false;
    gNumRepetitions = 1;
    gMaxNumFrames = 0;
    gReproduceBug = -1;
    gPreferSoftwareCodec = false;
    gPlaybackAudio = false;
    gWriteMP4 = false;

    sp<ALooper> looper;
    sp<ARTSPController> rtspController;

    int res;
    while ((res = getopt(argc, argv, "han:lm:b:ptsow:k")) >= 0) {
        switch (res) {
            case 'a':
            {
                audioOnly = true;
                break;
            }

            case 'l':
            {
                listComponents = true;
                break;
            }

            case 'm':
            case 'n':
            case 'b':
            {
                char *end;
                long x = strtol(optarg, &end, 10);

                if (*end != '\0' || end == optarg || x <= 0) {
                    x = 1;
                }

                if (res == 'n') {
                    gNumRepetitions = x;
                } else if (res == 'm') {
                    gMaxNumFrames = x;
                } else {
                    CHECK_EQ(res, 'b');
                    gReproduceBug = x;
                }
                break;
            }

            case 'w':
            {
                gWriteMP4 = true;
                gWriteMP4Filename.setTo(optarg);
                break;
            }

            case 'p':
            {
                dumpProfiles = true;
                break;
            }

            case 't':
            {
                extractThumbnail = true;
                break;
            }

            case 's':
            {
                gPreferSoftwareCodec = true;
                break;
            }

            case 'o':
            {
                gPlaybackAudio = true;
                break;
            }

            case 'k':
            {
                seekTest = true;
                break;
            }

            case '?':
            case 'h':
            default:
            {
                usage(argv[0]);
                exit(1);
                break;
            }
        }
    }

    if (gPlaybackAudio && !audioOnly) {
        // This doesn't make any sense if we're decoding the video track.
        gPlaybackAudio = false;
    }

    argc -= optind;
    argv += optind;

    if (extractThumbnail) {
        sp<IServiceManager> sm = defaultServiceManager();
        sp<IBinder> binder = sm->getService(String16("media.player"));
        sp<IMediaPlayerService> service =
            interface_cast<IMediaPlayerService>(binder);

        CHECK(service.get() != NULL);

        sp<IMediaMetadataRetriever> retriever =
            service->createMetadataRetriever(getpid());

        CHECK(retriever != NULL);

        for (int k = 0; k < argc; ++k) {
            const char *filename = argv[k];

            CHECK_EQ(retriever->setDataSource(filename), (status_t)OK);
            sp<IMemory> mem =
                    retriever->getFrameAtTime(-1,
                                    MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);

            if (mem != NULL) {
                printf("getFrameAtTime(%s) => OK\n", filename);
            } else {
                mem = retriever->extractAlbumArt();

                if (mem != NULL) {
                    printf("extractAlbumArt(%s) => OK\n", filename);
                } else {
                    printf("both getFrameAtTime and extractAlbumArt "
                           "failed on file '%s'.\n", filename);
                }
            }
        }

        return 0;
    }

    if (dumpProfiles) {
        sp<IServiceManager> sm = defaultServiceManager();
        sp<IBinder> binder = sm->getService(String16("media.player"));
        sp<IMediaPlayerService> service =
            interface_cast<IMediaPlayerService>(binder);

        CHECK(service.get() != NULL);

        sp<IOMX> omx = service->getOMX();
        CHECK(omx.get() != NULL);

        const char *kMimeTypes[] = {
            MEDIA_MIMETYPE_VIDEO_AVC, MEDIA_MIMETYPE_VIDEO_MPEG4,
            MEDIA_MIMETYPE_VIDEO_H263, MEDIA_MIMETYPE_AUDIO_AAC,
            MEDIA_MIMETYPE_AUDIO_AMR_NB, MEDIA_MIMETYPE_AUDIO_AMR_WB,
            MEDIA_MIMETYPE_AUDIO_MPEG
        };

        for (size_t k = 0; k < sizeof(kMimeTypes) / sizeof(kMimeTypes[0]);
             ++k) {
            printf("type '%s':\n", kMimeTypes[k]);

            Vector<CodecCapabilities> results;
            CHECK_EQ(QueryCodecs(omx, kMimeTypes[k],
                                 true, // queryDecoders
                                 &results), (status_t)OK);

            for (size_t i = 0; i < results.size(); ++i) {
                printf("  decoder '%s' supports ",
                       results[i].mComponentName.string());

                if (results[i].mProfileLevels.size() == 0) {
                    printf("NOTHING.\n");
                    continue;
                }

                for (size_t j = 0; j < results[i].mProfileLevels.size(); ++j) {
                    const CodecProfileLevel &profileLevel =
                        results[i].mProfileLevels[j];

                    printf("%s%ld/%ld", j > 0 ? ", " : "",
                           profileLevel.mProfile, profileLevel.mLevel);
                }

                printf("\n");
            }
        }
    }

    if (listComponents) {
        sp<IServiceManager> sm = defaultServiceManager();
        sp<IBinder> binder = sm->getService(String16("media.player"));
        sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);

        CHECK(service.get() != NULL);

        sp<IOMX> omx = service->getOMX();
        CHECK(omx.get() != NULL);

        List<IOMX::ComponentInfo> list;
        omx->listNodes(&list);

        for (List<IOMX::ComponentInfo>::iterator it = list.begin();
             it != list.end(); ++it) {
            printf("%s\n", (*it).mName.string());
        }
    }

    DataSource::RegisterDefaultSniffers();

    OMXClient client;
    status_t err = client.connect();

    for (int k = 0; k < argc; ++k) {
        bool syncInfoPresent = true;

        const char *filename = argv[k];

        sp<DataSource> dataSource = DataSource::CreateFromURI(filename);

        if (strncasecmp(filename, "sine:", 5)
                && strncasecmp(filename, "rtsp://", 7)
                && strncasecmp(filename, "httplive://", 11)
                && dataSource == NULL) {
            fprintf(stderr, "Unable to create data source.\n");
            return 1;
        }

        bool isJPEG = false;

        size_t len = strlen(filename);
        if (len >= 4 && !strcasecmp(filename + len - 4, ".jpg")) {
            isJPEG = true;
        }

        Vector<sp<MediaSource> > mediaSources;
        sp<MediaSource> mediaSource;

        if (isJPEG) {
            mediaSource = new JPEGSource(dataSource);
            if (gWriteMP4) {
                mediaSources.push(mediaSource);
            }
        } else if (!strncasecmp("sine:", filename, 5)) {
            char *end;
            long sampleRate = strtol(filename + 5, &end, 10);

            if (end == filename + 5) {
                sampleRate = 44100;
            }
            mediaSource = new SineSource(sampleRate, 1);
            if (gWriteMP4) {
                mediaSources.push(mediaSource);
            }
        } else {
            sp<MediaExtractor> extractor;

            if (!strncasecmp("rtsp://", filename, 7)) {
                if (looper == NULL) {
                    looper = new ALooper;
                    looper->start();
                }

                rtspController = new ARTSPController(looper);
                status_t err = rtspController->connect(filename);
                if (err != OK) {
                    fprintf(stderr, "could not connect to rtsp server.\n");
                    return -1;
                }

                extractor = rtspController.get();

                syncInfoPresent = false;
            } else if (!strncasecmp("httplive://", filename, 11)) {
                String8 uri("http://");
                uri.append(filename + 11);

                dataSource = new LiveSource(uri.string());
                dataSource = new NuCachedSource2(dataSource);

                extractor =
                    MediaExtractor::Create(
                            dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);

                syncInfoPresent = false;
            } else {
                extractor = MediaExtractor::Create(dataSource);
                if (extractor == NULL) {
                    fprintf(stderr, "could not create extractor.\n");
                    return -1;
                }
            }

            size_t numTracks = extractor->countTracks();

            if (gWriteMP4) {
                bool haveAudio = false;
                bool haveVideo = false;
                for (size_t i = 0; i < numTracks; ++i) {
                    sp<MediaSource> source = extractor->getTrack(i);

                    const char *mime;
                    CHECK(source->getFormat()->findCString(
                                kKeyMIMEType, &mime));

                    bool useTrack = false;
                    if (!haveAudio && !strncasecmp("audio/", mime, 6)) {
                        haveAudio = true;
                        useTrack = true;
                    } else if (!haveVideo && !strncasecmp("video/", mime, 6)) {
                        haveVideo = true;
                        useTrack = true;
                    }

                    if (useTrack) {
                        mediaSources.push(source);

                        if (haveAudio && haveVideo) {
                            break;
                        }
                    }
                }
            } else {
                sp<MetaData> meta;
                size_t i;
                for (i = 0; i < numTracks; ++i) {
                    meta = extractor->getTrackMetaData(
                            i, MediaExtractor::kIncludeExtensiveMetaData);

                    const char *mime;
                    meta->findCString(kKeyMIMEType, &mime);

                    if (audioOnly && !strncasecmp(mime, "audio/", 6)) {
                        break;
                    }

                    if (!audioOnly && !strncasecmp(mime, "video/", 6)) {
                        break;
                    }

                    meta = NULL;
                }

                if (meta == NULL) {
                    fprintf(stderr,
                            "No suitable %s track found. The '-a' option will "
                            "target audio tracks only, the default is to target "
                            "video tracks only.\n",
                            audioOnly ? "audio" : "video");
                    return -1;
                }

                int64_t thumbTimeUs;
                if (meta->findInt64(kKeyThumbnailTime, &thumbTimeUs)) {
                    printf("thumbnailTime: %lld us (%.2f secs)\n",
                           thumbTimeUs, thumbTimeUs / 1E6);
                }

                mediaSource = extractor->getTrack(i);
            }
        }

        if (gWriteMP4) {
            writeSourcesToMP4(mediaSources, syncInfoPresent);
        } else if (seekTest) {
            performSeekTest(mediaSource);
        } else {
            playSource(&client, mediaSource);
        }

        if (rtspController != NULL) {
            rtspController->disconnect();
            rtspController.clear();

            sleep(3);
        }
    }

    client.disconnect();

    return 0;
}
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.");
    }
}
        static String8 find(const char* kind) {
            String8 result;
            int emulationStatus = checkGlesEmulationStatus();
            switch (emulationStatus) {
                case 0:
#if defined(__LP64__)
                    result.setTo("/system/lib64/egl/libGLES_android.so");
#else
                    result.setTo("/system/lib/egl/libGLES_android.so");
#endif
                    return result;
                case 1:
                    // Use host-side OpenGL through the "emulation" library
#if defined(__LP64__)
                    result.appendFormat("/system/lib64/egl/lib%s_emulation.so", kind);
#else
                    result.appendFormat("/system/lib/egl/lib%s_emulation.so", kind);
#endif
                    return result;
                default:
                    // Not in emulator, or use other guest-side implementation
                    break;
            }

            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;
        }