status_t StagefrightRecorder::setParameters(const String8 ¶ms) { 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; }
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; }
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); }
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; } }
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; }
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; }