void printStringPool(const ResStringPool* pool) { if (pool->getError() == NO_INIT) { printf("String pool is unitialized.\n"); return; } else if (pool->getError() != NO_ERROR) { printf("String pool is corrupt/invalid.\n"); return; } SortedVector<const void*> uniqueStrings; const size_t N = pool->size(); for (size_t i=0; i<N; i++) { size_t len; if (pool->isUTF8()) { uniqueStrings.add(pool->string8At(i, &len)); } else { uniqueStrings.add(pool->stringAt(i, &len)); } } printf("String pool of " ZD " unique %s %s strings, " ZD " entries and " ZD " styles using " ZD " bytes:\n", (ZD_TYPE)uniqueStrings.size(), pool->isUTF8() ? "UTF-8" : "UTF-16", pool->isSorted() ? "sorted" : "non-sorted", (ZD_TYPE)N, (ZD_TYPE)pool->styleCount(), (ZD_TYPE)pool->bytes()); const size_t NS = pool->size(); for (size_t s=0; s<NS; s++) { String8 str = pool->string8ObjectAt(s); printf("String #" ZD ": %s\n", (ZD_TYPE) s, str.string()); } }
void AudioPort::toAudioPort(struct audio_port *port) const { // TODO: update this function once audio_port structure reflects the new profile definition. // For compatibility reason: flatening the AudioProfile into audio_port structure. SortedVector<audio_format_t> flatenedFormats; SampleRateVector flatenedRates; ChannelsVector flatenedChannels; for (size_t profileIndex = 0; profileIndex < mProfiles.size(); profileIndex++) { if (mProfiles[profileIndex]->isValid()) { audio_format_t formatToExport = mProfiles[profileIndex]->getFormat(); const SampleRateVector &ratesToExport = mProfiles[profileIndex]->getSampleRates(); const ChannelsVector &channelsToExport = mProfiles[profileIndex]->getChannels(); if (flatenedFormats.indexOf(formatToExport) < 0) { flatenedFormats.add(formatToExport); } for (size_t rateIndex = 0; rateIndex < ratesToExport.size(); rateIndex++) { uint32_t rate = ratesToExport[rateIndex]; if (flatenedRates.indexOf(rate) < 0) { flatenedRates.add(rate); } } for (size_t chanIndex = 0; chanIndex < channelsToExport.size(); chanIndex++) { audio_channel_mask_t channels = channelsToExport[chanIndex]; if (flatenedChannels.indexOf(channels) < 0) { flatenedChannels.add(channels); } } if (flatenedRates.size() > AUDIO_PORT_MAX_SAMPLING_RATES || flatenedChannels.size() > AUDIO_PORT_MAX_CHANNEL_MASKS || flatenedFormats.size() > AUDIO_PORT_MAX_FORMATS) { ALOGE("%s: bailing out: cannot export profiles to port config", __FUNCTION__); return; } } } port->role = mRole; port->type = mType; strlcpy(port->name, mName, AUDIO_PORT_MAX_NAME_LEN); port->num_sample_rates = flatenedRates.size(); port->num_channel_masks = flatenedChannels.size(); port->num_formats = flatenedFormats.size(); for (size_t i = 0; i < flatenedRates.size(); i++) { port->sample_rates[i] = flatenedRates[i]; } for (size_t i = 0; i < flatenedChannels.size(); i++) { port->channel_masks[i] = flatenedChannels[i]; } for (size_t i = 0; i < flatenedFormats.size(); i++) { port->formats[i] = flatenedFormats[i]; } ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size()); uint32_t i; for (i = 0; i < mGains.size() && i < AUDIO_PORT_MAX_GAINS; i++) { port->gains[i] = mGains[i]->getGain(); } port->num_gains = i; }
int idmap_scan(const char *target_package_name, const char *target_apk_path, const char *idmap_dir, const android::Vector<const char *> *overlay_dirs) { String8 filename = String8(idmap_dir); filename.appendPath("overlays.list"); if (unlink(filename.string()) != 0 && errno != ENOENT) { return EXIT_FAILURE; } SortedVector<Overlay> overlayVector; const size_t N = overlay_dirs->size(); for (size_t i = 0; i < N; ++i) { const char *overlay_dir = overlay_dirs->itemAt(i); DIR *dir = opendir(overlay_dir); if (dir == NULL) { return EXIT_FAILURE; } struct dirent *dirent; while ((dirent = readdir(dir)) != NULL) { struct stat st; char overlay_apk_path[PATH_MAX + 1]; snprintf(overlay_apk_path, PATH_MAX, "%s/%s", overlay_dir, dirent->d_name); if (stat(overlay_apk_path, &st) < 0) { continue; } if (!S_ISREG(st.st_mode)) { continue; } int priority = parse_apk(overlay_apk_path, target_package_name); if (priority < 0) { continue; } String8 idmap_path(idmap_dir); idmap_path.appendPath(flatten_path(overlay_apk_path + 1)); idmap_path.append("@idmap"); if (idmap_create_path(target_apk_path, overlay_apk_path, idmap_path.string()) != 0) { ALOGE("error: failed to create idmap for target=%s overlay=%s idmap=%s\n", target_apk_path, overlay_apk_path, idmap_path.string()); continue; } Overlay overlay(String8(overlay_apk_path), idmap_path, priority); overlayVector.add(overlay); } closedir(dir); } if (!writePackagesList(filename.string(), overlayVector)) { return EXIT_FAILURE; } return EXIT_SUCCESS; }
DisplayState& Composer::getDisplayStateLocked(const sp<IBinder>& token) { DisplayState s; s.token = token; ssize_t index = mDisplayStates.indexOf(s); if (index < 0) { // we don't have it, add an initialized layer_state to our list s.what = 0; index = mDisplayStates.add(s); } return mDisplayStates.editItemAt(index); }
SortedVector<SurfaceSize> V4L2Camera::getAvailableSizes() const { LOGD("V4L2Camera::getAvailableSizes"); SortedVector<SurfaceSize> ret; // Iterate through the list. All duplicated entries will be removed unsigned int i; for (i = 0; i< m_AllFmts.size() ; i++) { ret.add(m_AllFmts[i].getSize()); } return ret; }
IHalSensor* HalSensorList:: createSensor( char const* szCallerName, MUINT const index ) { Mutex::Autolock _l(mEnumSensorMutex); SortedVector<MUINT> vSensorIndex; vSensorIndex.add(index); mCreateSensorCount++; MY_LOGD("createSensor count = %d, caller =%s",mCreateSensorCount,szCallerName); return openSensor(vSensorIndex, szCallerName); }
void Extensions::findExtensions(const char* extensions, SortedVector<String8>& list) const { const char* current = extensions; const char* head = current; EXT_LOGD("Available extensions:"); do { head = strchr(current, ' '); String8 s(current, head ? head - current : strlen(current)); if (s.length()) { list.add(s); EXT_LOGD(" %s", s.string()); } current = head + 1; } while (head); }
void testSortedVector() { printf("Test Firebird::SortedVector: "); SortedVector<int, 100> v; int i; for (i = 0; i < 100; i++) v.add(99 - i); for (i = 0; i < 50; i++) v.remove(0); bool passed = true; for (i = 50; i < 100; i++) if (v[i - 50] != i) passed = false; printf(passed ? "PASSED\n" : "FAILED\n"); }
layer_state_t* Composer::getLayerStateLocked( const sp<SurfaceComposerClient>& client, SurfaceID id) { ComposerState s; s.client = client->mClient; s.state.surface = id; ssize_t index = mComposerStates.indexOf(s); if (index < 0) { // we don't have it, add an initialized layer_state to our list index = mComposerStates.add(s); } ComposerState* const out = mComposerStates.editArray(); return &(out[index].state); }
IHalSensor* HalSensorList:: createSensor( char const* szCallerName, MUINT const uCountOfIndex, MUINT const*pArrayOfIndex ) { Mutex::Autolock _l(mEnumSensorMutex); MY_LOGF_IF(0==uCountOfIndex||0==pArrayOfIndex, "<%s> Bad uCountOfIndex:%d pArrayOfIndex:%p", szCallerName, uCountOfIndex, pArrayOfIndex); // SortedVector<MUINT> vSensorIndex; for (MUINT i = 0; i < uCountOfIndex; i++) { vSensorIndex.add(pArrayOfIndex[i]); } mCreateSensorCount++; MY_LOGD("createSensor count = %d, caller =%s",mCreateSensorCount,szCallerName); return openSensor(vSensorIndex, szCallerName); }
// ---------------------------------------------------------------------------- static int android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this, jint source, jint sampleRateInHertz, jint channelMask, // Java channel masks map directly to the native definition jint audioFormat, jint buffSizeInBytes, jintArray jSession) { //ALOGV(">> Entering android_media_AudioRecord_setup"); //ALOGV("sampleRate=%d, audioFormat=%d, channel mask=%x, buffSizeInBytes=%d", // sampleRateInHertz, audioFormat, channelMask, buffSizeInBytes); if (!audio_is_input_channel(channelMask)) { ALOGE("Error creating AudioRecord: channel mask %#x is not valid.", channelMask); return AUDIORECORD_ERROR_SETUP_INVALIDCHANNELMASK; } uint32_t nbChannels = popcount(channelMask); // compare the format against the Java constants if ((audioFormat != ENCODING_PCM_16BIT) && (audioFormat != ENCODING_PCM_8BIT) && (audioFormat != ENCODING_AMRNB) && (audioFormat != ENCODING_AMRWB) && (audioFormat != ENCODING_EVRC) && (audioFormat != ENCODING_EVRCB) && (audioFormat != ENCODING_EVRCWB) && (audioFormat != ENCODING_EVRCNW)) { ALOGE("Error creating AudioRecord: unsupported audio format."); return AUDIORECORD_ERROR_SETUP_INVALIDFORMAT; } int bytesPerSample; if(audioFormat == ENCODING_PCM_16BIT) bytesPerSample = 2; else if((audioFormat == ENCODING_AMRWB) && ((uint32_t)source != AUDIO_SOURCE_VOICE_COMMUNICATION)) bytesPerSample = 61; else bytesPerSample = 1; audio_format_t format = (audio_format_t)getformatrec(audioFormat); if (buffSizeInBytes == 0) { ALOGE("Error creating AudioRecord: frameCount is 0."); return AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT; } int frameSize = nbChannels * bytesPerSample; size_t frameCount = buffSizeInBytes / frameSize; if ((uint32_t(source) >= AUDIO_SOURCE_CNT) && (uint32_t(source) != AUDIO_SOURCE_HOTWORD)) { ALOGE("Error creating AudioRecord: unknown source."); return AUDIORECORD_ERROR_SETUP_INVALIDSOURCE; } jclass clazz = env->GetObjectClass(thiz); if (clazz == NULL) { ALOGE("Can't find %s when setting up callback.", kClassPathName); return AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED; } if (jSession == NULL) { ALOGE("Error creating AudioRecord: invalid session ID pointer"); return AUDIORECORD_ERROR; } jint* nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL); if (nSession == NULL) { ALOGE("Error creating AudioRecord: Error retrieving session id pointer"); return AUDIORECORD_ERROR; } int sessionId = nSession[0]; env->ReleasePrimitiveArrayCritical(jSession, nSession, 0); nSession = NULL; // create an uninitialized AudioRecord object sp<AudioRecord> lpRecorder = new AudioRecord(); // create the callback information: // this data will be passed with every AudioRecord callback audiorecord_callback_cookie *lpCallbackData = new audiorecord_callback_cookie; lpCallbackData->audioRecord_class = (jclass)env->NewGlobalRef(clazz); // we use a weak reference so the AudioRecord object can be garbage collected. lpCallbackData->audioRecord_ref = env->NewGlobalRef(weak_this); lpCallbackData->busy = false; lpRecorder->set((audio_source_t) source, sampleRateInHertz, format, // word length, PCM channelMask, frameCount, recorderCallback,// callback_t lpCallbackData,// void* user 0, // notificationFrames, true, // threadCanCallJava sessionId); if (lpRecorder->initCheck() != NO_ERROR) { ALOGE("Error creating AudioRecord instance: initialization check failed."); goto native_init_failure; } nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL); if (nSession == NULL) { ALOGE("Error creating AudioRecord: Error retrieving session id pointer"); goto native_init_failure; } // read the audio session ID back from AudioRecord in case a new session was created during set() nSession[0] = lpRecorder->getSessionId(); env->ReleasePrimitiveArrayCritical(jSession, nSession, 0); nSession = NULL; { // scope for the lock Mutex::Autolock l(sLock); sAudioRecordCallBackCookies.add(lpCallbackData); } // save our newly created C++ AudioRecord in the "nativeRecorderInJavaObj" field // of the Java object setAudioRecord(env, thiz, lpRecorder); // save our newly created callback information in the "nativeCallbackCookie" field // of the Java object (in mNativeCallbackCookie) so we can free the memory in finalize() env->SetIntField(thiz, javaAudioRecordFields.nativeCallbackCookie, (int)lpCallbackData); return AUDIORECORD_SUCCESS; // failure: native_init_failure: env->DeleteGlobalRef(lpCallbackData->audioRecord_class); env->DeleteGlobalRef(lpCallbackData->audioRecord_ref); delete lpCallbackData; env->SetIntField(thiz, javaAudioRecordFields.nativeCallbackCookie, 0); return AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED; }
int doDump(Bundle* bundle) { status_t result = UNKNOWN_ERROR; if (bundle->getFileSpecCount() < 1) { fprintf(stderr, "ERROR: no dump option specified\n"); return 1; } if (bundle->getFileSpecCount() < 2) { fprintf(stderr, "ERROR: no dump file specified\n"); return 1; } const char* option = bundle->getFileSpecEntry(0); const char* filename = bundle->getFileSpecEntry(1); AssetManager assets; int32_t assetsCookie; if (!assets.addAssetPath(String8(filename), &assetsCookie)) { fprintf(stderr, "ERROR: dump failed because assets could not be loaded\n"); return 1; } // Make a dummy config for retrieving resources... we need to supply // non-default values for some configs so that we can retrieve resources // in the app that don't have a default. The most important of these is // the API version because key resources like icons will have an implicit // version if they are using newer config types like density. ResTable_config config; memset(&config, 0, sizeof(ResTable_config)); config.language[0] = 'e'; config.language[1] = 'n'; config.country[0] = 'U'; config.country[1] = 'S'; config.orientation = ResTable_config::ORIENTATION_PORT; config.density = ResTable_config::DENSITY_MEDIUM; config.sdkVersion = 10000; // Very high. config.screenWidthDp = 320; config.screenHeightDp = 480; config.smallestScreenWidthDp = 320; config.screenLayout |= ResTable_config::SCREENSIZE_NORMAL; assets.setConfiguration(config); const ResTable& res = assets.getResources(false); if (res.getError() != NO_ERROR) { fprintf(stderr, "ERROR: dump failed because the resource table is invalid/corrupt.\n"); return 1; } // The dynamicRefTable can be null if there are no resources for this asset cookie. // This fine. const DynamicRefTable* dynamicRefTable = res.getDynamicRefTableForCookie(assetsCookie); Asset* asset = NULL; if (strcmp("resources", option) == 0) { #ifndef __ANDROID__ res.print(bundle->getValues()); #endif } else if (strcmp("strings", option) == 0) { const ResStringPool* pool = res.getTableStringBlock(0); printStringPool(pool); } else if (strcmp("xmltree", option) == 0) { if (bundle->getFileSpecCount() < 3) { fprintf(stderr, "ERROR: no dump xmltree resource file specified\n"); goto bail; } for (int i=2; i<bundle->getFileSpecCount(); i++) { const char* resname = bundle->getFileSpecEntry(i); ResXMLTree tree(dynamicRefTable); asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER); if (asset == NULL) { fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname); goto bail; } if (tree.setTo(asset->getBuffer(true), asset->getLength()) != NO_ERROR) { fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname); goto bail; } tree.restart(); printXMLBlock(&tree); tree.uninit(); delete asset; asset = NULL; } } else if (strcmp("xmlstrings", option) == 0) { if (bundle->getFileSpecCount() < 3) { fprintf(stderr, "ERROR: no dump xmltree resource file specified\n"); goto bail; } for (int i=2; i<bundle->getFileSpecCount(); i++) { const char* resname = bundle->getFileSpecEntry(i); asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER); if (asset == NULL) { fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname); goto bail; } ResXMLTree tree(dynamicRefTable); if (tree.setTo(asset->getBuffer(true), asset->getLength()) != NO_ERROR) { fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname); goto bail; } printStringPool(&tree.getStrings()); delete asset; asset = NULL; } } else { asset = assets.openNonAsset(assetsCookie, "AndroidManifest.xml", Asset::ACCESS_BUFFER); if (asset == NULL) { fprintf(stderr, "ERROR: dump failed because no AndroidManifest.xml found\n"); goto bail; } ResXMLTree tree(dynamicRefTable); if (tree.setTo(asset->getBuffer(true), asset->getLength()) != NO_ERROR) { fprintf(stderr, "ERROR: AndroidManifest.xml is corrupt\n"); goto bail; } tree.restart(); if (strcmp("permissions", option) == 0) { size_t len; ResXMLTree::event_code_t code; int depth = 0; while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { if (code == ResXMLTree::END_TAG) { depth--; continue; } if (code != ResXMLTree::START_TAG) { continue; } depth++; const char16_t* ctag16 = tree.getElementName(&len); if (ctag16 == NULL) { fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n"); goto bail; } String8 tag(ctag16); //printf("Depth %d tag %s\n", depth, tag.string()); if (depth == 1) { if (tag != "manifest") { fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n"); goto bail; } String8 pkg = AaptXml::getAttribute(tree, NULL, "package", NULL); printf("package: %s\n", ResTable::normalizeForOutput(pkg.string()).string()); } else if (depth == 2 && tag == "permission") { String8 error; String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); if (error != "") { fprintf(stderr, "ERROR: %s\n", error.string()); goto bail; } printf("permission: %s\n", ResTable::normalizeForOutput(name.string()).string()); } else if (depth == 2 && tag == "uses-permission") { String8 error; String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); if (error != "") { fprintf(stderr, "ERROR: %s\n", error.string()); goto bail; } printUsesPermission(name, AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0, AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR)); } } } else if (strcmp("badging", option) == 0) { Vector<String8> locales; res.getLocales(&locales); Vector<ResTable_config> configs; res.getConfigurations(&configs); SortedVector<int> densities; const size_t NC = configs.size(); for (size_t i=0; i<NC; i++) { int dens = configs[i].density; if (dens == 0) { dens = 160; } densities.add(dens); } size_t len; ResXMLTree::event_code_t code; int depth = 0; String8 error; bool withinActivity = false; bool isMainActivity = false; bool isLauncherActivity = false; bool isLeanbackLauncherActivity = false; bool isSearchable = false; bool withinApplication = false; bool withinSupportsInput = false; bool withinFeatureGroup = false; bool withinReceiver = false; bool withinService = false; bool withinProvider = false; bool withinIntentFilter = false; bool hasMainActivity = false; bool hasOtherActivities = false; bool hasOtherReceivers = false; bool hasOtherServices = false; bool hasIntentFilter = false; bool hasWallpaperService = false; bool hasImeService = false; bool hasAccessibilityService = false; bool hasPrintService = false; bool hasWidgetReceivers = false; bool hasDeviceAdminReceiver = false; bool hasPaymentService = false; bool hasDocumentsProvider = false; bool hasCameraActivity = false; bool hasCameraSecureActivity = false; bool hasLauncher = false; bool hasNotificationListenerService = false; bool hasDreamService = false; bool actMainActivity = false; bool actWidgetReceivers = false; bool actDeviceAdminEnabled = false; bool actImeService = false; bool actWallpaperService = false; bool actAccessibilityService = false; bool actPrintService = false; bool actHostApduService = false; bool actOffHostApduService = false; bool actDocumentsProvider = false; bool actNotificationListenerService = false; bool actDreamService = false; bool actCamera = false; bool actCameraSecure = false; bool catLauncher = false; bool hasMetaHostPaymentCategory = false; bool hasMetaOffHostPaymentCategory = false; // These permissions are required by services implementing services // the system binds to (IME, Accessibility, PrintServices, etc.) bool hasBindDeviceAdminPermission = false; bool hasBindInputMethodPermission = false; bool hasBindAccessibilityServicePermission = false; bool hasBindPrintServicePermission = false; bool hasBindNfcServicePermission = false; bool hasRequiredSafAttributes = false; bool hasBindNotificationListenerServicePermission = false; bool hasBindDreamServicePermission = false; // These two implement the implicit permissions that are granted // to pre-1.6 applications. bool hasWriteExternalStoragePermission = false; bool hasReadPhoneStatePermission = false; // If an app requests write storage, they will also get read storage. bool hasReadExternalStoragePermission = false; // Implement transition to read and write call log. bool hasReadContactsPermission = false; bool hasWriteContactsPermission = false; bool hasReadCallLogPermission = false; bool hasWriteCallLogPermission = false; // If an app declares itself as multiArch, we report the // native libraries differently. bool hasMultiArch = false; // This next group of variables is used to implement a group of // backward-compatibility heuristics necessitated by the addition of // some new uses-feature constants in 2.1 and 2.2. In most cases, the // heuristic is "if an app requests a permission but doesn't explicitly // request the corresponding <uses-feature>, presume it's there anyway". // 2.2 also added some other features that apps can request, but that // have no corresponding permission, so we cannot implement any // back-compatibility heuristic for them. The below are thus unnecessary // (but are retained here for documentary purposes.) //bool specCompassFeature = false; //bool specAccelerometerFeature = false; //bool specProximityFeature = false; //bool specAmbientLightFeature = false; //bool specLiveWallpaperFeature = false; int targetSdk = 0; int smallScreen = 1; int normalScreen = 1; int largeScreen = 1; int xlargeScreen = 1; int anyDensity = 1; int requiresSmallestWidthDp = 0; int compatibleWidthLimitDp = 0; int largestWidthLimitDp = 0; String8 pkg; String8 activityName; String8 activityLabel; String8 activityIcon; String8 activityBanner; String8 receiverName; String8 serviceName; Vector<String8> supportedInput; FeatureGroup commonFeatures; Vector<FeatureGroup> featureGroups; KeyedVector<String8, ImpliedFeature> impliedFeatures; while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { if (code == ResXMLTree::END_TAG) { depth--; if (depth < 2) { if (withinSupportsInput && !supportedInput.isEmpty()) { printf("supports-input: '"); const size_t N = supportedInput.size(); for (size_t i=0; i<N; i++) { printf("%s", ResTable::normalizeForOutput( supportedInput[i].string()).string()); if (i != N - 1) { printf("' '"); } else { printf("'\n"); } } supportedInput.clear(); } withinApplication = false; withinSupportsInput = false; withinFeatureGroup = false; } else if (depth < 3) { if (withinActivity && isMainActivity) { String8 aName(getComponentName(pkg, activityName)); if (isLauncherActivity) { printf("launchable-activity:"); if (aName.length() > 0) { printf(" name='%s' ", ResTable::normalizeForOutput(aName.string()).string()); } printf(" label='%s' icon='%s'\n", ResTable::normalizeForOutput(activityLabel.string()).string(), ResTable::normalizeForOutput(activityIcon.string()).string()); } if (isLeanbackLauncherActivity) { printf("leanback-launchable-activity:"); if (aName.length() > 0) { printf(" name='%s' ", ResTable::normalizeForOutput(aName.string()).string()); } printf(" label='%s' icon='%s' banner='%s'\n", ResTable::normalizeForOutput(activityLabel.string()).string(), ResTable::normalizeForOutput(activityIcon.string()).string(), ResTable::normalizeForOutput(activityBanner.string()).string()); } } if (!hasIntentFilter) { hasOtherActivities |= withinActivity; hasOtherReceivers |= withinReceiver; hasOtherServices |= withinService; } else { if (withinService) { hasPaymentService |= (actHostApduService && hasMetaHostPaymentCategory && hasBindNfcServicePermission); hasPaymentService |= (actOffHostApduService && hasMetaOffHostPaymentCategory && hasBindNfcServicePermission); } } withinActivity = false; withinService = false; withinReceiver = false; withinProvider = false; hasIntentFilter = false; isMainActivity = isLauncherActivity = isLeanbackLauncherActivity = false; } else if (depth < 4) { if (withinIntentFilter) { if (withinActivity) { hasMainActivity |= actMainActivity; hasLauncher |= catLauncher; hasCameraActivity |= actCamera; hasCameraSecureActivity |= actCameraSecure; hasOtherActivities |= !actMainActivity && !actCamera && !actCameraSecure; } else if (withinReceiver) { hasWidgetReceivers |= actWidgetReceivers; hasDeviceAdminReceiver |= (actDeviceAdminEnabled && hasBindDeviceAdminPermission); hasOtherReceivers |= (!actWidgetReceivers && !actDeviceAdminEnabled); } else if (withinService) { hasImeService |= actImeService; hasWallpaperService |= actWallpaperService; hasAccessibilityService |= (actAccessibilityService && hasBindAccessibilityServicePermission); hasPrintService |= (actPrintService && hasBindPrintServicePermission); hasNotificationListenerService |= actNotificationListenerService && hasBindNotificationListenerServicePermission; hasDreamService |= actDreamService && hasBindDreamServicePermission; hasOtherServices |= (!actImeService && !actWallpaperService && !actAccessibilityService && !actPrintService && !actHostApduService && !actOffHostApduService && !actNotificationListenerService); } else if (withinProvider) { hasDocumentsProvider |= actDocumentsProvider && hasRequiredSafAttributes; } } withinIntentFilter = false; } continue; } if (code != ResXMLTree::START_TAG) { continue; } depth++; const char16_t* ctag16 = tree.getElementName(&len); if (ctag16 == NULL) { fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n"); goto bail; } String8 tag(ctag16); //printf("Depth %d, %s\n", depth, tag.string()); if (depth == 1) { if (tag != "manifest") { fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n"); goto bail; } pkg = AaptXml::getAttribute(tree, NULL, "package", NULL); printf("package: name='%s' ", ResTable::normalizeForOutput(pkg.string()).string()); int32_t versionCode = AaptXml::getIntegerAttribute(tree, VERSION_CODE_ATTR, &error); if (error != "") { fprintf(stderr, "ERROR getting 'android:versionCode' attribute: %s\n", error.string()); goto bail; } if (versionCode > 0) { printf("versionCode='%d' ", versionCode); } else { printf("versionCode='' "); } String8 versionName = AaptXml::getResolvedAttribute(res, tree, VERSION_NAME_ATTR, &error); if (error != "") { fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n", error.string()); goto bail; } printf("versionName='%s'", ResTable::normalizeForOutput(versionName.string()).string()); String8 splitName = AaptXml::getAttribute(tree, NULL, "split"); if (!splitName.isEmpty()) { printf(" split='%s'", ResTable::normalizeForOutput( splitName.string()).string()); } String8 platformVersionName = AaptXml::getAttribute(tree, NULL, "platformBuildVersionName"); printf(" platformBuildVersionName='%s'", platformVersionName.string()); printf("\n"); int32_t installLocation = AaptXml::getResolvedIntegerAttribute(res, tree, INSTALL_LOCATION_ATTR, &error); if (error != "") { fprintf(stderr, "ERROR getting 'android:installLocation' attribute: %s\n", error.string()); goto bail; } if (installLocation >= 0) { printf("install-location:'"); switch (installLocation) { case 0: printf("auto"); break; case 1: printf("internalOnly"); break; case 2: printf("preferExternal"); break; default: fprintf(stderr, "Invalid installLocation %d\n", installLocation); goto bail; } printf("'\n"); } } else if (depth == 2) { withinApplication = false; if (tag == "application") {
ssize_t AaptAssets::slurpResourceZip(Bundle* bundle, const char* filename) { int count = 0; SortedVector<AaptGroupEntry> entries; ZipFile* zip = new ZipFile; status_t err = zip->open(filename, ZipFile::kOpenReadOnly); if (err != NO_ERROR) { fprintf(stderr, "error opening zip file %s\n", filename); count = err; delete zip; return -1; } const int N = zip->getNumEntries(); for (int i=0; i<N; i++) { ZipEntry* entry = zip->getEntryByIndex(i); if (entry->getDeleted()) { continue; } String8 entryName(entry->getFileName()); String8 dirName = entryName.getPathDir(); sp<AaptDir> dir = dirName == "" ? this : makeDir(dirName); String8 resType; AaptGroupEntry kind; String8 remain; if (entryName.walkPath(&remain) == kResourceDir) { // these are the resources, pull their type out of the directory name kind.initFromDirName(remain.walkPath().string(), &resType); } else { // these are untyped and don't have an AaptGroupEntry } if (entries.indexOf(kind) < 0) { entries.add(kind); mGroupEntries.add(kind); } // use the one from the zip file if they both exist. dir->removeFile(entryName.getPathLeaf()); sp<AaptFile> file = new AaptFile(entryName, kind, resType); status_t err = dir->addLeafFile(entryName.getPathLeaf(), file); if (err != NO_ERROR) { fprintf(stderr, "err=%s entryName=%s\n", strerror(err), entryName.string()); count = err; goto bail; } file->setCompressionMethod(entry->getCompressionMethod()); #if 0 if (entryName == "AndroidManifest.xml") { printf("AndroidManifest.xml\n"); } printf("\n\nfile: %s\n", entryName.string()); #endif size_t len = entry->getUncompressedLen(); void* data = zip->uncompress(entry); void* buf = file->editData(len); memcpy(buf, data, len); #if 0 const int OFF = 0; const unsigned char* p = (unsigned char*)data; const unsigned char* end = p+len; p += OFF; for (int i=0; i<32 && p < end; i++) { printf("0x%03x ", i*0x10 + OFF); for (int j=0; j<0x10 && p < end; j++) { printf(" %02x", *p); p++; } printf("\n"); } #endif free(data); count++; } bail: delete zip; return count; }
status_t VendorTagDescriptor::createDescriptorFromOps(const vendor_tag_ops_t* vOps, /*out*/ sp<VendorTagDescriptor>& descriptor) { if (vOps == NULL) { ALOGE("%s: vendor_tag_ops argument was NULL.", __FUNCTION__); return BAD_VALUE; } int tagCount = vOps->get_tag_count(vOps); if (tagCount < 0 || tagCount > INT32_MAX) { ALOGE("%s: tag count %d from vendor ops is invalid.", __FUNCTION__, tagCount); return BAD_VALUE; } Vector<uint32_t> tagArray; LOG_ALWAYS_FATAL_IF(tagArray.resize(tagCount) != tagCount, "%s: too many (%u) vendor tags defined.", __FUNCTION__, tagCount); vOps->get_all_tags(vOps, /*out*/tagArray.editArray()); sp<VendorTagDescriptor> desc = new VendorTagDescriptor(); desc->mTagCount = tagCount; SortedVector<String8> sections; KeyedVector<uint32_t, String8> tagToSectionMap; for (size_t i = 0; i < static_cast<size_t>(tagCount); ++i) { uint32_t tag = tagArray[i]; if (tag < CAMERA_METADATA_VENDOR_TAG_BOUNDARY) { ALOGE("%s: vendor tag %d not in vendor tag section.", __FUNCTION__, tag); return BAD_VALUE; } const char *tagName = vOps->get_tag_name(vOps, tag); if (tagName == NULL) { ALOGE("%s: no tag name defined for vendor tag %d.", __FUNCTION__, tag); return BAD_VALUE; } desc->mTagToNameMap.add(tag, String8(tagName)); const char *sectionName = vOps->get_section_name(vOps, tag); if (sectionName == NULL) { ALOGE("%s: no section name defined for vendor tag %d.", __FUNCTION__, tag); return BAD_VALUE; } String8 sectionString(sectionName); sections.add(sectionString); tagToSectionMap.add(tag, sectionString); int tagType = vOps->get_tag_type(vOps, tag); if (tagType < 0 || tagType >= NUM_TYPES) { ALOGE("%s: tag type %d from vendor ops does not exist.", __FUNCTION__, tagType); return BAD_VALUE; } desc->mTagToTypeMap.add(tag, tagType); } desc->mSections = sections; for (size_t i = 0; i < static_cast<size_t>(tagCount); ++i) { uint32_t tag = tagArray[i]; String8 sectionString = tagToSectionMap.valueFor(tag); // Set up tag to section index map ssize_t index = sections.indexOf(sectionString); LOG_ALWAYS_FATAL_IF(index < 0, "index %zd must be non-negative", index); desc->mTagToSectionMap.add(tag, static_cast<uint32_t>(index)); // Set up reverse mapping ssize_t reverseIndex = -1; if ((reverseIndex = desc->mReverseMapping.indexOfKey(sectionString)) < 0) { KeyedVector<String8, uint32_t>* nameMapper = new KeyedVector<String8, uint32_t>(); reverseIndex = desc->mReverseMapping.add(sectionString, nameMapper); } desc->mReverseMapping[reverseIndex]->add(desc->mTagToNameMap.valueFor(tag), tag); } descriptor = desc; return OK; }
void StringPool::sortByConfig() { LOG_ALWAYS_FATAL_IF(mOriginalPosToNewPos.size() > 0, "Can't sort string pool after already sorted."); const size_t N = mEntryArray.size(); // This is a vector that starts out with a 1:1 mapping to entries // in the array, which we will sort to come up with the desired order. // At that point it maps from the new position in the array to the // original position the entry appeared. Vector<size_t> newPosToOriginalPos; newPosToOriginalPos.setCapacity(N); for (size_t i=0; i < N; i++) { newPosToOriginalPos.add(i); } // Sort the array. NOISY(printf("SORTING STRINGS BY CONFIGURATION...\n")); // Vector::sort uses insertion sort, which is very slow for this data set. // Use quicksort instead because we don't need a stable sort here. qsort_r_compat(newPosToOriginalPos.editArray(), N, sizeof(size_t), this, config_sort); //newPosToOriginalPos.sort(config_sort, this); NOISY(printf("DONE SORTING STRINGS BY CONFIGURATION.\n")); // Create the reverse mapping from the original position in the array // to the new position where it appears in the sorted array. This is // so that clients can re-map any positions they had previously stored. mOriginalPosToNewPos = newPosToOriginalPos; for (size_t i=0; i<N; i++) { mOriginalPosToNewPos.editItemAt(newPosToOriginalPos[i]) = i; } #if 0 SortedVector<entry> entries; for (size_t i=0; i<N; i++) { printf("#%d was %d: %s\n", i, newPosToOriginalPos[i], mEntries[mEntryArray[newPosToOriginalPos[i]]].makeConfigsString().string()); entries.add(mEntries[mEntryArray[i]]); } for (size_t i=0; i<entries.size(); i++) { printf("Sorted config #%d: %s\n", i, entries[i].makeConfigsString().string()); } #endif // Now we rebuild the arrays. Vector<entry> newEntries; Vector<size_t> newEntryArray; Vector<entry_style> newEntryStyleArray; DefaultKeyedVector<size_t, size_t> origOffsetToNewOffset; for (size_t i=0; i<N; i++) { // We are filling in new offset 'i'; oldI is where we can find it // in the original data structure. size_t oldI = newPosToOriginalPos[i]; // This is the actual entry associated with the old offset. const entry& oldEnt = mEntries[mEntryArray[oldI]]; // This is the same entry the last time we added it to the // new entry array, if any. ssize_t newIndexOfOffset = origOffsetToNewOffset.indexOfKey(oldI); size_t newOffset; if (newIndexOfOffset < 0) { // This is the first time we have seen the entry, so add // it. newOffset = newEntries.add(oldEnt); newEntries.editItemAt(newOffset).indices.clear(); } else { // We have seen this entry before, use the existing one // instead of adding it again. newOffset = origOffsetToNewOffset.valueAt(newIndexOfOffset); } // Update the indices to include this new position. newEntries.editItemAt(newOffset).indices.add(i); // And add the offset of the entry to the new entry array. newEntryArray.add(newOffset); // Add any old style to the new style array. if (mEntryStyleArray.size() > 0) { if (oldI < mEntryStyleArray.size()) { newEntryStyleArray.add(mEntryStyleArray[oldI]); } else { newEntryStyleArray.add(entry_style()); } } } // Now trim any entries at the end of the new style array that are // not needed. for (ssize_t i=newEntryStyleArray.size()-1; i>=0; i--) { const entry_style& style = newEntryStyleArray[i]; if (style.spans.size() > 0) { // That's it. break; } // This one is not needed; remove. newEntryStyleArray.removeAt(i); } // All done, install the new data structures and upate mValues with // the new positions. mEntries = newEntries; mEntryArray = newEntryArray; mEntryStyleArray = newEntryStyleArray; mValues.clear(); for (size_t i=0; i<mEntries.size(); i++) { const entry& ent = mEntries[i]; mValues.add(ent.value, ent.indices[0]); } #if 0 printf("FINAL SORTED STRING CONFIGS:\n"); for (size_t i=0; i<mEntries.size(); i++) { const entry& ent = mEntries[i]; printf("#" ZD " %s: %s\n", (ZD_TYPE)i, ent.makeConfigsString().string(), String8(ent.value).string()); } #endif }
// ---------------------------------------------------------------------------- static jint android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this, jobject jaa, jint sampleRateInHertz, jint channelMask, jint channelIndexMask, jint audioFormat, jint buffSizeInBytes, jintArray jSession, jstring opPackageName) { //ALOGV(">> Entering android_media_AudioRecord_setup"); //ALOGV("sampleRate=%d, audioFormat=%d, channel mask=%x, buffSizeInBytes=%d", // sampleRateInHertz, audioFormat, channelMask, buffSizeInBytes); if (jaa == 0) { ALOGE("Error creating AudioRecord: invalid audio attributes"); return (jint) AUDIO_JAVA_ERROR; } // channel index mask takes priority over channel position masks. if (channelIndexMask) { // Java channel index masks need the representation bits set. channelMask = audio_channel_mask_from_representation_and_bits( AUDIO_CHANNEL_REPRESENTATION_INDEX, channelIndexMask); } // Java channel position masks map directly to the native definition if (!audio_is_input_channel(channelMask)) { ALOGE("Error creating AudioRecord: channel mask %#x is not valid.", channelMask); return (jint) AUDIORECORD_ERROR_SETUP_INVALIDCHANNELMASK; } uint32_t channelCount = audio_channel_count_from_in_mask(channelMask); // compare the format against the Java constants audio_format_t format = audioFormatToNative(audioFormat); if (format == AUDIO_FORMAT_INVALID) { ALOGE("Error creating AudioRecord: unsupported audio format %d.", audioFormat); return (jint) AUDIORECORD_ERROR_SETUP_INVALIDFORMAT; } size_t bytesPerSample = audio_bytes_per_sample(format); if (buffSizeInBytes == 0) { ALOGE("Error creating AudioRecord: frameCount is 0."); return (jint) AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT; } size_t frameSize = channelCount * bytesPerSample; size_t frameCount = buffSizeInBytes / frameSize; jclass clazz = env->GetObjectClass(thiz); if (clazz == NULL) { ALOGE("Can't find %s when setting up callback.", kClassPathName); return (jint) AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED; } if (jSession == NULL) { ALOGE("Error creating AudioRecord: invalid session ID pointer"); return (jint) AUDIO_JAVA_ERROR; } jint* nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL); if (nSession == NULL) { ALOGE("Error creating AudioRecord: Error retrieving session id pointer"); return (jint) AUDIO_JAVA_ERROR; } int sessionId = nSession[0]; env->ReleasePrimitiveArrayCritical(jSession, nSession, 0); nSession = NULL; ScopedUtfChars opPackageNameStr(env, opPackageName); // create an uninitialized AudioRecord object sp<AudioRecord> lpRecorder = new AudioRecord(String16(opPackageNameStr.c_str())); audio_attributes_t *paa = NULL; // read the AudioAttributes values paa = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t)); const jstring jtags = (jstring) env->GetObjectField(jaa, javaAudioAttrFields.fieldFormattedTags); const char* tags = env->GetStringUTFChars(jtags, NULL); // copying array size -1, char array for tags was calloc'd, no need to NULL-terminate it strncpy(paa->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1); env->ReleaseStringUTFChars(jtags, tags); paa->source = (audio_source_t) env->GetIntField(jaa, javaAudioAttrFields.fieldRecSource); paa->flags = (audio_flags_mask_t)env->GetIntField(jaa, javaAudioAttrFields.fieldFlags); ALOGV("AudioRecord_setup for source=%d tags=%s flags=%08x", paa->source, paa->tags, paa->flags); audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE; if (paa->flags & AUDIO_FLAG_HW_HOTWORD) { flags = AUDIO_INPUT_FLAG_HW_HOTWORD; } // create the callback information: // this data will be passed with every AudioRecord callback audiorecord_callback_cookie *lpCallbackData = new audiorecord_callback_cookie; lpCallbackData->audioRecord_class = (jclass)env->NewGlobalRef(clazz); // we use a weak reference so the AudioRecord object can be garbage collected. lpCallbackData->audioRecord_ref = env->NewGlobalRef(weak_this); lpCallbackData->busy = false; const status_t status = lpRecorder->set(paa->source, sampleRateInHertz, format, // word length, PCM channelMask, frameCount, recorderCallback,// callback_t lpCallbackData,// void* user 0, // notificationFrames, true, // threadCanCallJava sessionId, AudioRecord::TRANSFER_DEFAULT, flags, -1, -1, // default uid, pid paa); if (status != NO_ERROR) { ALOGE("Error creating AudioRecord instance: initialization check failed with status %d.", status); goto native_init_failure; } nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL); if (nSession == NULL) { ALOGE("Error creating AudioRecord: Error retrieving session id pointer"); goto native_init_failure; } // read the audio session ID back from AudioRecord in case a new session was created during set() nSession[0] = lpRecorder->getSessionId(); env->ReleasePrimitiveArrayCritical(jSession, nSession, 0); nSession = NULL; { // scope for the lock Mutex::Autolock l(sLock); sAudioRecordCallBackCookies.add(lpCallbackData); } // save our newly created C++ AudioRecord in the "nativeRecorderInJavaObj" field // of the Java object setAudioRecord(env, thiz, lpRecorder); // save our newly created callback information in the "nativeCallbackCookie" field // of the Java object (in mNativeCallbackCookie) so we can free the memory in finalize() env->SetLongField(thiz, javaAudioRecordFields.nativeCallbackCookie, (jlong)lpCallbackData); return (jint) AUDIO_JAVA_SUCCESS; // failure: native_init_failure: env->DeleteGlobalRef(lpCallbackData->audioRecord_class); env->DeleteGlobalRef(lpCallbackData->audioRecord_ref); delete lpCallbackData; env->SetLongField(thiz, javaAudioRecordFields.nativeCallbackCookie, 0); // lpRecorder goes out of scope, so reference count drops to zero return (jint) AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED; }
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; }