Loading core/res/AndroidManifest.xml +7 −0 Original line number Diff line number Diff line Loading @@ -3256,6 +3256,13 @@ <permission android:name="android.permission.MODIFY_AUDIO_ROUTING" android:protectionLevel="signature|privileged" /> <!-- Allows an application to modify what effects are applied to all audio (matching certain criteria) from any application. <p>Not for use by third-party applications.</p> @hide --> <permission android:name="android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS" android:protectionLevel="signature|privileged" /> <!-- @SystemApi Allows an application to capture video output. <p>Not for use by third-party applications.</p> --> <permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT" Loading media/java/android/media/audiofx/DefaultEffect.java 0 → 100644 +40 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.media.audiofx; /** * DefaultEffect is the base class for controlling default audio effects linked into the * Android audio framework. * <p>DefaultEffects are effects that get attached automatically to all AudioTracks, * AudioRecords, and MediaPlayer instances meeting some criteria. * <p>Applications should not use the DefaultEffect class directly but one of its derived classes * to control specific types of defaults: * <ul> * <li> {@link android.media.audiofx.StreamDefaultEffect}</li> * </ul> * <p>Creating a DefaultEffect object will register the corresponding effect engine as a default * for the specified criteria. Whenever an audio session meets the criteria, an AudioEffect will * be created and attached to it using the specified priority. * @hide */ public abstract class DefaultEffect { /** * System wide unique default effect ID. */ int mId; } media/java/android/media/audiofx/StreamDefaultEffect.java 0 → 100644 +117 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.media.audiofx; import android.annotation.RequiresPermission; import android.app.ActivityThread; import android.util.Log; import java.util.UUID; /** * StreamDefaultEffect is a default effect that attaches automatically to all AudioTracks and * MediaPlayer instances of a given stream type. * <p>see {@link android.media.audiofx.DefaultEffect} class for more details on default effects. * @hide */ public class StreamDefaultEffect extends DefaultEffect { static { System.loadLibrary("audioeffect_jni"); } private final static String TAG = "StreamDefaultEffect-JAVA"; /** * Class constructor. * * @param type type of effect engine to be default. This parameter is ignored if uuid is set, * and can be set to {@link android.media.audiofx.AudioEffect#EFFECT_TYPE_NULL} * in that case. * @param uuid unique identifier of a particular effect implementation to be default. This * parameter can be set to * {@link android.media.audiofx.AudioEffect#EFFECT_TYPE_NULL}, in which case only * the type will be used to select the effect. * @param priority the priority level requested by the application for controlling the effect * engine. As the same engine can be shared by several applications, this parameter * indicates how much the requesting application needs control of effect parameters. * The normal priority is 0, above normal is a positive number, below normal a * negative number. * @param streamUsage a USAGE_* constant from {@link android.media.AudioAttributes} indicating * what streams the given effect should attach to by default. Note that similar * usages may share defaults. * * @throws java.lang.IllegalArgumentException * @throws java.lang.UnsupportedOperationException * @throws java.lang.RuntimeException */ @RequiresPermission(value = android.Manifest.permission.MODIFY_DEFAULT_AUDIO_EFFECTS, conditional = true) // Android Things uses an alternate permission. public StreamDefaultEffect(UUID type, UUID uuid, int priority, int streamUsage) { int[] id = new int[1]; int initResult = native_setup(type.toString(), uuid.toString(), priority, streamUsage, ActivityThread.currentOpPackageName(), id); if (initResult != AudioEffect.SUCCESS) { Log.e(TAG, "Error code " + initResult + " when initializing StreamDefaultEffect"); switch (initResult) { case AudioEffect.ERROR_BAD_VALUE: throw (new IllegalArgumentException( "Stream usage, type uuid, or implementation uuid not supported.")); case AudioEffect.ERROR_INVALID_OPERATION: throw (new UnsupportedOperationException( "Effect library not loaded")); default: throw (new RuntimeException( "Cannot initialize effect engine for type: " + type + " Error: " + initResult)); } } mId = id[0]; } /** * Releases the native StreamDefaultEffect resources. It is a good practice to * release the default effect when done with use as control can be returned to * other applications or the native resources released. */ public void release() { native_release(mId); } @Override protected void finalize() { release(); } // --------------------------------------------------------- // Native methods called from the Java side // -------------------- private native final int native_setup(String type, String uuid, int priority, int streamUsage, String opPackageName, int[] id); private native final void native_release(int id); } media/jni/audioeffect/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ cc_library_shared { srcs: [ "android_media_AudioEffect.cpp", "android_media_StreamDefaultEffect.cpp", "android_media_Visualizer.cpp", ], Loading media/jni/audioeffect/android_media_AudioEffect.cpp +23 −11 Original line number Diff line number Diff line Loading @@ -14,6 +14,8 @@ * limitations under the License. */ #include "android_media_AudioEffect.h" #include <stdio.h> //#define LOG_NDEBUG 0 Loading Loading @@ -71,7 +73,7 @@ class AudioEffectJniStorage { }; static jint translateError(int code) { jint AudioEffectJni::translateNativeErrorToJava(int code) { switch(code) { case NO_ERROR: return AUDIOEFFECT_SUCCESS; Loading @@ -81,6 +83,10 @@ static jint translateError(int code) { return AUDIOEFFECT_ERROR_NO_INIT; case BAD_VALUE: return AUDIOEFFECT_ERROR_BAD_VALUE; case NAME_NOT_FOUND: // Name not found means the client tried to create an effect not found on the system, // which is a form of bad value. return AUDIOEFFECT_ERROR_BAD_VALUE; case INVALID_OPERATION: return AUDIOEFFECT_ERROR_INVALID_OPERATION; case NO_MEMORY: Loading Loading @@ -359,7 +365,7 @@ android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_t goto setup_failure; } lStatus = translateError(lpAudioEffect->initCheck()); lStatus = AudioEffectJni::translateNativeErrorToJava(lpAudioEffect->initCheck()); if (lStatus != AUDIOEFFECT_SUCCESS && lStatus != AUDIOEFFECT_ERROR_ALREADY_EXISTS) { ALOGE("AudioEffect initCheck failed %d", lStatus); goto setup_failure; Loading Loading @@ -495,7 +501,7 @@ android_media_AudioEffect_native_setEnabled(JNIEnv *env, jobject thiz, jboolean return AUDIOEFFECT_ERROR_NO_INIT; } return (jint) translateError(lpAudioEffect->setEnabled(enabled)); return AudioEffectJni::translateNativeErrorToJava(lpAudioEffect->setEnabled(enabled)); } static jboolean Loading Loading @@ -590,7 +596,7 @@ setParameter_Exit: if (lpValue != NULL) { env->ReleasePrimitiveArrayCritical(pJavaValue, lpValue, 0); } return (jint) translateError(lStatus); return AudioEffectJni::translateNativeErrorToJava(lStatus); } static jint Loading Loading @@ -658,7 +664,7 @@ getParameter_Exit: if (lStatus == NO_ERROR) { return vsize; } return (jint) translateError(lStatus); return AudioEffectJni::translateNativeErrorToJava(lStatus); } static jint android_media_AudioEffect_native_command(JNIEnv *env, jobject thiz, Loading Loading @@ -697,7 +703,8 @@ static jint android_media_AudioEffect_native_command(JNIEnv *env, jobject thiz, } } lStatus = translateError(lpAudioEffect->command((uint32_t)cmdCode, lStatus = AudioEffectJni::translateNativeErrorToJava( lpAudioEffect->command((uint32_t)cmdCode, (uint32_t)cmdSize, pCmdData, (uint32_t *)&replySize, Loading Loading @@ -900,6 +907,7 @@ static const JNINativeMethod gMethods[] = { // ---------------------------------------------------------------------------- extern int register_android_media_StreamDefaultEffect(JNIEnv *env); extern int register_android_media_visualizer(JNIEnv *env); int register_android_media_AudioEffect(JNIEnv *env) Loading @@ -924,6 +932,11 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved __unused) goto bail; } if (register_android_media_StreamDefaultEffect(env) < 0) { ALOGE("ERROR: StreamDefaultEffect native registration failed\n"); goto bail; } if (register_android_media_visualizer(env) < 0) { ALOGE("ERROR: Visualizer native registration failed\n"); goto bail; Loading @@ -935,4 +948,3 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved __unused) bail: return result; } Loading
core/res/AndroidManifest.xml +7 −0 Original line number Diff line number Diff line Loading @@ -3256,6 +3256,13 @@ <permission android:name="android.permission.MODIFY_AUDIO_ROUTING" android:protectionLevel="signature|privileged" /> <!-- Allows an application to modify what effects are applied to all audio (matching certain criteria) from any application. <p>Not for use by third-party applications.</p> @hide --> <permission android:name="android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS" android:protectionLevel="signature|privileged" /> <!-- @SystemApi Allows an application to capture video output. <p>Not for use by third-party applications.</p> --> <permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT" Loading
media/java/android/media/audiofx/DefaultEffect.java 0 → 100644 +40 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.media.audiofx; /** * DefaultEffect is the base class for controlling default audio effects linked into the * Android audio framework. * <p>DefaultEffects are effects that get attached automatically to all AudioTracks, * AudioRecords, and MediaPlayer instances meeting some criteria. * <p>Applications should not use the DefaultEffect class directly but one of its derived classes * to control specific types of defaults: * <ul> * <li> {@link android.media.audiofx.StreamDefaultEffect}</li> * </ul> * <p>Creating a DefaultEffect object will register the corresponding effect engine as a default * for the specified criteria. Whenever an audio session meets the criteria, an AudioEffect will * be created and attached to it using the specified priority. * @hide */ public abstract class DefaultEffect { /** * System wide unique default effect ID. */ int mId; }
media/java/android/media/audiofx/StreamDefaultEffect.java 0 → 100644 +117 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.media.audiofx; import android.annotation.RequiresPermission; import android.app.ActivityThread; import android.util.Log; import java.util.UUID; /** * StreamDefaultEffect is a default effect that attaches automatically to all AudioTracks and * MediaPlayer instances of a given stream type. * <p>see {@link android.media.audiofx.DefaultEffect} class for more details on default effects. * @hide */ public class StreamDefaultEffect extends DefaultEffect { static { System.loadLibrary("audioeffect_jni"); } private final static String TAG = "StreamDefaultEffect-JAVA"; /** * Class constructor. * * @param type type of effect engine to be default. This parameter is ignored if uuid is set, * and can be set to {@link android.media.audiofx.AudioEffect#EFFECT_TYPE_NULL} * in that case. * @param uuid unique identifier of a particular effect implementation to be default. This * parameter can be set to * {@link android.media.audiofx.AudioEffect#EFFECT_TYPE_NULL}, in which case only * the type will be used to select the effect. * @param priority the priority level requested by the application for controlling the effect * engine. As the same engine can be shared by several applications, this parameter * indicates how much the requesting application needs control of effect parameters. * The normal priority is 0, above normal is a positive number, below normal a * negative number. * @param streamUsage a USAGE_* constant from {@link android.media.AudioAttributes} indicating * what streams the given effect should attach to by default. Note that similar * usages may share defaults. * * @throws java.lang.IllegalArgumentException * @throws java.lang.UnsupportedOperationException * @throws java.lang.RuntimeException */ @RequiresPermission(value = android.Manifest.permission.MODIFY_DEFAULT_AUDIO_EFFECTS, conditional = true) // Android Things uses an alternate permission. public StreamDefaultEffect(UUID type, UUID uuid, int priority, int streamUsage) { int[] id = new int[1]; int initResult = native_setup(type.toString(), uuid.toString(), priority, streamUsage, ActivityThread.currentOpPackageName(), id); if (initResult != AudioEffect.SUCCESS) { Log.e(TAG, "Error code " + initResult + " when initializing StreamDefaultEffect"); switch (initResult) { case AudioEffect.ERROR_BAD_VALUE: throw (new IllegalArgumentException( "Stream usage, type uuid, or implementation uuid not supported.")); case AudioEffect.ERROR_INVALID_OPERATION: throw (new UnsupportedOperationException( "Effect library not loaded")); default: throw (new RuntimeException( "Cannot initialize effect engine for type: " + type + " Error: " + initResult)); } } mId = id[0]; } /** * Releases the native StreamDefaultEffect resources. It is a good practice to * release the default effect when done with use as control can be returned to * other applications or the native resources released. */ public void release() { native_release(mId); } @Override protected void finalize() { release(); } // --------------------------------------------------------- // Native methods called from the Java side // -------------------- private native final int native_setup(String type, String uuid, int priority, int streamUsage, String opPackageName, int[] id); private native final void native_release(int id); }
media/jni/audioeffect/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ cc_library_shared { srcs: [ "android_media_AudioEffect.cpp", "android_media_StreamDefaultEffect.cpp", "android_media_Visualizer.cpp", ], Loading
media/jni/audioeffect/android_media_AudioEffect.cpp +23 −11 Original line number Diff line number Diff line Loading @@ -14,6 +14,8 @@ * limitations under the License. */ #include "android_media_AudioEffect.h" #include <stdio.h> //#define LOG_NDEBUG 0 Loading Loading @@ -71,7 +73,7 @@ class AudioEffectJniStorage { }; static jint translateError(int code) { jint AudioEffectJni::translateNativeErrorToJava(int code) { switch(code) { case NO_ERROR: return AUDIOEFFECT_SUCCESS; Loading @@ -81,6 +83,10 @@ static jint translateError(int code) { return AUDIOEFFECT_ERROR_NO_INIT; case BAD_VALUE: return AUDIOEFFECT_ERROR_BAD_VALUE; case NAME_NOT_FOUND: // Name not found means the client tried to create an effect not found on the system, // which is a form of bad value. return AUDIOEFFECT_ERROR_BAD_VALUE; case INVALID_OPERATION: return AUDIOEFFECT_ERROR_INVALID_OPERATION; case NO_MEMORY: Loading Loading @@ -359,7 +365,7 @@ android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_t goto setup_failure; } lStatus = translateError(lpAudioEffect->initCheck()); lStatus = AudioEffectJni::translateNativeErrorToJava(lpAudioEffect->initCheck()); if (lStatus != AUDIOEFFECT_SUCCESS && lStatus != AUDIOEFFECT_ERROR_ALREADY_EXISTS) { ALOGE("AudioEffect initCheck failed %d", lStatus); goto setup_failure; Loading Loading @@ -495,7 +501,7 @@ android_media_AudioEffect_native_setEnabled(JNIEnv *env, jobject thiz, jboolean return AUDIOEFFECT_ERROR_NO_INIT; } return (jint) translateError(lpAudioEffect->setEnabled(enabled)); return AudioEffectJni::translateNativeErrorToJava(lpAudioEffect->setEnabled(enabled)); } static jboolean Loading Loading @@ -590,7 +596,7 @@ setParameter_Exit: if (lpValue != NULL) { env->ReleasePrimitiveArrayCritical(pJavaValue, lpValue, 0); } return (jint) translateError(lStatus); return AudioEffectJni::translateNativeErrorToJava(lStatus); } static jint Loading Loading @@ -658,7 +664,7 @@ getParameter_Exit: if (lStatus == NO_ERROR) { return vsize; } return (jint) translateError(lStatus); return AudioEffectJni::translateNativeErrorToJava(lStatus); } static jint android_media_AudioEffect_native_command(JNIEnv *env, jobject thiz, Loading Loading @@ -697,7 +703,8 @@ static jint android_media_AudioEffect_native_command(JNIEnv *env, jobject thiz, } } lStatus = translateError(lpAudioEffect->command((uint32_t)cmdCode, lStatus = AudioEffectJni::translateNativeErrorToJava( lpAudioEffect->command((uint32_t)cmdCode, (uint32_t)cmdSize, pCmdData, (uint32_t *)&replySize, Loading Loading @@ -900,6 +907,7 @@ static const JNINativeMethod gMethods[] = { // ---------------------------------------------------------------------------- extern int register_android_media_StreamDefaultEffect(JNIEnv *env); extern int register_android_media_visualizer(JNIEnv *env); int register_android_media_AudioEffect(JNIEnv *env) Loading @@ -924,6 +932,11 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved __unused) goto bail; } if (register_android_media_StreamDefaultEffect(env) < 0) { ALOGE("ERROR: StreamDefaultEffect native registration failed\n"); goto bail; } if (register_android_media_visualizer(env) < 0) { ALOGE("ERROR: Visualizer native registration failed\n"); goto bail; Loading @@ -935,4 +948,3 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved __unused) bail: return result; }