diff options
| -rw-r--r-- | media/java/android/media/AudioService.java | 8 | ||||
| -rw-r--r-- | media/java/android/media/SoundPool.java | 76 | ||||
| -rw-r--r-- | media/jni/soundpool/android_media_SoundPool_SoundPoolImpl.cpp | 75 |
3 files changed, 137 insertions, 22 deletions
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index b01323c1c14c..e94f8c1910a2 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -3500,7 +3500,13 @@ public class AudioService extends IAudioService.Stub { loadTouchSoundAssets(); - mSoundPool = new SoundPool(NUM_SOUNDPOOL_CHANNELS, AudioSystem.STREAM_SYSTEM, 0); + mSoundPool = new SoundPool.Builder() + .setMaxStreams(NUM_SOUNDPOOL_CHANNELS) + .setAudioAttributes(new AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .build()) + .build(); mSoundPoolCallBack = null; mSoundPoolListenerThread = new SoundPoolListenerThread(); mSoundPoolListenerThread.start(); diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java index 44c193fe5a47..56079ad42c72 100644 --- a/media/java/android/media/SoundPool.java +++ b/media/java/android/media/SoundPool.java @@ -128,10 +128,69 @@ public class SoundPool { * @return a SoundPool object, or null if creation failed */ public SoundPool(int maxStreams, int streamType, int srcQuality) { + this(maxStreams, + new AudioAttributes.Builder().setInternalLegacyStreamType(streamType).build()); + } + + private SoundPool(int maxStreams, AudioAttributes attributes) { if (SystemProperties.getBoolean("config.disable_media", false)) { mImpl = new SoundPoolStub(); } else { - mImpl = new SoundPoolImpl(this, maxStreams, streamType, srcQuality); + mImpl = new SoundPoolImpl(this, maxStreams, attributes); + } + } + + /** + * @hide + * CANDIDATE FOR PUBLIC API + * Builder class for {@link SoundPool} objects. + */ + public static class Builder { + private int mMaxStreams = 1; + private AudioAttributes mAudioAttributes; + + /** + * Constructs a new Builder with the defaults format values. + */ + public Builder() { + } + + /** + * Sets the maximum of number of simultaneous streams that can be played simultaneously. + * @param maxStreams a value equal to 1 or greater. + * @return the same Builder instance + * @throws IllegalArgumentException + */ + public Builder setMaxStreams(int maxStreams) throws IllegalArgumentException { + if (maxStreams <= 0) { + throw new IllegalArgumentException( + "Strictly position value required for the maximum number of streams"); + } + mMaxStreams = maxStreams; + return this; + } + + /** + * Sets the {@link AudioAttributes}. For examples, game applications will use attributes + * built with usage information set to {@link AudioAttributes#USAGE_GAME}. + * @param attributes a non-null + * @return + */ + public Builder setAudioAttributes(AudioAttributes attributes) + throws IllegalArgumentException { + if (attributes == null) { + throw new IllegalArgumentException("Invalid null AudioAttributes"); + } + mAudioAttributes = attributes; + return this; + } + + public SoundPool build() { + if (mAudioAttributes == null) { + mAudioAttributes = new AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_MEDIA).build(); + } + return new SoundPool(mMaxStreams, mAudioAttributes); } } @@ -457,7 +516,7 @@ public class SoundPool { private SoundPool mProxy; private final Object mLock; - private final int mStreamType; + private final AudioAttributes mAttributes; private final IAppOpsService mAppOps; // SoundPool messages @@ -465,15 +524,15 @@ public class SoundPool { // must match SoundPool.h private static final int SAMPLE_LOADED = 1; - public SoundPoolImpl(SoundPool proxy, int maxStreams, int streamType, int srcQuality) { + public SoundPoolImpl(SoundPool proxy, int maxStreams, AudioAttributes attr) { // do native setup - if (native_setup(new WeakReference(this), maxStreams, streamType, srcQuality) != 0) { + if (native_setup(new WeakReference(this), maxStreams, attr) != 0) { throw new RuntimeException("Native setup failed"); } mLock = new Object(); mProxy = proxy; - mStreamType = streamType; + mAttributes = attr; IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE); mAppOps = IAppOpsService.Stub.asInterface(b); } @@ -548,9 +607,9 @@ public class SoundPool { private boolean isRestricted() { try { - final int usage = AudioAttributes.usageForLegacyStreamType(mStreamType); final int mode = mAppOps.checkAudioOperation(AppOpsManager.OP_PLAY_AUDIO, - usage, Process.myUid(), ActivityThread.currentPackageName()); + mAttributes.getUsage(), + Process.myUid(), ActivityThread.currentPackageName()); return mode != AppOpsManager.MODE_ALLOWED; } catch (RemoteException e) { return false; @@ -648,7 +707,8 @@ public class SoundPool { public native final void release(); - private native final int native_setup(Object weakRef, int maxStreams, int streamType, int srcQuality); + private native final int native_setup(Object weakRef, int maxStreams, + Object/*AudioAttributes*/ attributes); protected void finalize() { release(); } } diff --git a/media/jni/soundpool/android_media_SoundPool_SoundPoolImpl.cpp b/media/jni/soundpool/android_media_SoundPool_SoundPoolImpl.cpp index bda3b6bd3f8a..89b2893a648a 100644 --- a/media/jni/soundpool/android_media_SoundPool_SoundPoolImpl.cpp +++ b/media/jni/soundpool/android_media_SoundPool_SoundPoolImpl.cpp @@ -32,10 +32,17 @@ static struct fields_t { jmethodID mPostEvent; jclass mSoundPoolClass; } fields; - static inline SoundPool* MusterSoundPool(JNIEnv *env, jobject thiz) { return (SoundPool*)env->GetLongField(thiz, fields.mNativeContext); } +static const char* const kAudioAttributesClassPathName = "android/media/AudioAttributes"; +struct audio_attributes_fields_t { + jfieldID fieldUsage; // AudioAttributes.mUsage + jfieldID fieldContentType; // AudioAttributes.mContentType + jfieldID fieldFlags; // AudioAttributes.mFlags + jfieldID fieldFormattedTags;// AudioAttributes.mFormattedTags +}; +static audio_attributes_fields_t javaAudioAttrFields; // ---------------------------------------------------------------------------- static jint @@ -176,10 +183,30 @@ static void android_media_callback(SoundPoolEvent event, SoundPool* soundPool, v } static jint -android_media_SoundPool_SoundPoolImpl_native_setup(JNIEnv *env, jobject thiz, jobject weakRef, jint maxChannels, jint streamType, jint srcQuality) +android_media_SoundPool_SoundPoolImpl_native_setup(JNIEnv *env, jobject thiz, jobject weakRef, + jint maxChannels, jobject jaa) { + if (jaa == 0) { + ALOGE("Error creating SoundPool: invalid audio attributes"); + return -1; + } + + 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->usage = (audio_usage_t) env->GetIntField(jaa, javaAudioAttrFields.fieldUsage); + paa->content_type = + (audio_content_type_t) env->GetIntField(jaa, javaAudioAttrFields.fieldContentType); + paa->flags = env->GetIntField(jaa, javaAudioAttrFields.fieldFlags); + ALOGV("android_media_SoundPool_SoundPoolImpl_native_setup"); - SoundPool *ap = new SoundPool(maxChannels, (audio_stream_type_t) streamType, srcQuality); + SoundPool *ap = new SoundPool(maxChannels, paa); if (ap == NULL) { return -1; } @@ -190,6 +217,10 @@ android_media_SoundPool_SoundPoolImpl_native_setup(JNIEnv *env, jobject thiz, jo // set callback with weak reference jobject globalWeakRef = env->NewGlobalRef(weakRef); ap->setCallback(android_media_callback, globalWeakRef); + + // audio attributes were copied in SoundPool creation + free(paa); + return 0; } @@ -270,7 +301,7 @@ static JNINativeMethod gMethods[] = { (void *)android_media_SoundPool_SoundPoolImpl_setRate }, { "native_setup", - "(Ljava/lang/Object;III)I", + "(Ljava/lang/Object;ILjava/lang/Object;)I", (void*)android_media_SoundPool_SoundPoolImpl_native_setup }, { "release", @@ -289,27 +320,27 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { ALOGE("ERROR: GetEnv failed\n"); - goto bail; + return result; } assert(env != NULL); clazz = env->FindClass(kClassPathName); if (clazz == NULL) { ALOGE("Can't find %s", kClassPathName); - goto bail; + return result; } fields.mNativeContext = env->GetFieldID(clazz, "mNativeContext", "J"); if (fields.mNativeContext == NULL) { ALOGE("Can't find SoundPoolImpl.mNativeContext"); - goto bail; + return result; } fields.mPostEvent = env->GetStaticMethodID(clazz, "postEventFromNative", "(Ljava/lang/Object;IIILjava/lang/Object;)V"); if (fields.mPostEvent == NULL) { ALOGE("Can't find android/media/SoundPoolImpl.postEventFromNative"); - goto bail; + return result; } // create a reference to class. Technically, we're leaking this reference @@ -317,11 +348,29 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) fields.mSoundPoolClass = (jclass) env->NewGlobalRef(clazz); if (AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)) < 0) - goto bail; + return result; - /* success -- return valid version number */ - result = JNI_VERSION_1_4; + // Get the AudioAttributes class and fields + jclass audioAttrClass = env->FindClass(kAudioAttributesClassPathName); + if (audioAttrClass == NULL) { + ALOGE("Can't find %s", kAudioAttributesClassPathName); + return result; + } + jclass audioAttributesClassRef = (jclass)env->NewGlobalRef(audioAttrClass); + javaAudioAttrFields.fieldUsage = env->GetFieldID(audioAttributesClassRef, "mUsage", "I"); + javaAudioAttrFields.fieldContentType + = env->GetFieldID(audioAttributesClassRef, "mContentType", "I"); + javaAudioAttrFields.fieldFlags = env->GetFieldID(audioAttributesClassRef, "mFlags", "I"); + javaAudioAttrFields.fieldFormattedTags = + env->GetFieldID(audioAttributesClassRef, "mFormattedTags", "Ljava/lang/String;"); + env->DeleteGlobalRef(audioAttributesClassRef); + if (javaAudioAttrFields.fieldUsage == NULL || javaAudioAttrFields.fieldContentType == NULL + || javaAudioAttrFields.fieldFlags == NULL + || javaAudioAttrFields.fieldFormattedTags == NULL) { + ALOGE("Can't initialize AudioAttributes fields"); + return result; + } -bail: - return result; + /* success -- return valid version number */ + return JNI_VERSION_1_4; } |
