Loading core/jni/android_media_AudioSystem.cpp +25 −0 Original line number Diff line number Diff line Loading @@ -180,6 +180,7 @@ static struct { jmethodID postDynPolicyEventFromNative; jmethodID postRecordConfigEventFromNative; jmethodID postRoutingUpdatedFromNative; jmethodID postVolRangeInitReqFromNative; } gAudioPolicyEventHandlerMethods; jclass gListClass; Loading Loading @@ -585,6 +586,20 @@ android_media_AudioSystem_routing_callback() env->DeleteLocalRef(clazz); } static void android_media_AudioSystem_vol_range_init_req_callback() { JNIEnv *env = AndroidRuntime::getJNIEnv(); if (env == NULL) { return; } // callback into java jclass clazz = env->FindClass(kClassPathName); env->CallStaticVoidMethod(clazz, gAudioPolicyEventHandlerMethods.postVolRangeInitReqFromNative); env->DeleteLocalRef(clazz); } static jint android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint state, jobject jParcel, jint codec) { Loading Loading @@ -2063,6 +2078,11 @@ android_media_AudioSystem_registerRoutingCallback(JNIEnv *env, jobject thiz) AudioSystem::setRoutingCallback(android_media_AudioSystem_routing_callback); } static void android_media_AudioSystem_registerVolRangeInitReqCallback(JNIEnv *env, jobject thiz) { AudioSystem::setVolInitReqCallback(android_media_AudioSystem_vol_range_init_req_callback); } void javaAudioFormatToNativeAudioConfig(JNIEnv *env, audio_config_t *nConfig, const jobject jFormat, bool isInput) { *nConfig = AUDIO_CONFIG_INITIALIZER; Loading Loading @@ -2990,6 +3010,8 @@ static const JNINativeMethod gMethods[] = (void *)android_media_AudioSystem_registerRecordingCallback}, {"native_register_routing_callback", "()V", (void *)android_media_AudioSystem_registerRoutingCallback}, {"native_register_vol_range_init_req_callback", "()V", (void *)android_media_AudioSystem_registerVolRangeInitReqCallback}, {"systemReady", "()I", (void *)android_media_AudioSystem_systemReady}, {"getStreamVolumeDB", "(III)F", (void *)android_media_AudioSystem_getStreamVolumeDB}, {"native_get_offload_support", "(IIIII)I", Loading Loading @@ -3202,6 +3224,9 @@ int register_android_media_AudioSystem(JNIEnv *env) gAudioPolicyEventHandlerMethods.postRoutingUpdatedFromNative = GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName), "routingCallbackFromNative", "()V"); gAudioPolicyEventHandlerMethods.postVolRangeInitReqFromNative = GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName), "volRangeInitReqCallbackFromNative", "()V"); jclass audioMixClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMix"); gAudioMixClass = MakeGlobalRefOrDie(env, audioMixClass); Loading media/java/android/media/AudioSystem.java +36 −0 Original line number Diff line number Diff line Loading @@ -828,6 +828,40 @@ public class AudioSystem cb.onRoutingUpdated(); } /** * @hide * Handles requests from the audio policy manager to (re-)initialize the volume ranges */ public interface VolumeRangeInitRequestCallback { /** * Callback to notify volume ranges need to be initialized */ void onVolumeRangeInitializationRequested(); } @GuardedBy("AudioSystem.class") private static VolumeRangeInitRequestCallback sVolRangeInitReqCallback; /** @hide */ public static void setVolumeRangeInitRequestCallback(VolumeRangeInitRequestCallback cb) { synchronized (AudioSystem.class) { sVolRangeInitReqCallback = cb; native_register_vol_range_init_req_callback(); } } private static void volRangeInitReqCallbackFromNative() { final VolumeRangeInitRequestCallback cb; synchronized (AudioSystem.class) { cb = sVolRangeInitReqCallback; } if (cb == null) { Log.e(TAG, "APM requested volume range initialization, but no callback found"); return; } cb.onVolumeRangeInitializationRequested(); } /* * Error codes used by public APIs (AudioTrack, AudioRecord, AudioManager ...) * Must be kept in sync with frameworks/base/core/jni/android_media_AudioErrors.h Loading Loading @@ -1812,6 +1846,8 @@ public class AudioSystem private static native final void native_register_recording_callback(); // declare this instance as having a routing update callback handler private static native void native_register_routing_callback(); // declare this instance as having a volume range init request handler private static native void native_register_vol_range_init_req_callback(); // must be kept in sync with value in include/system/audio.h /** @hide */ public static final int AUDIO_HW_SYNC_INVALID = 0; Loading services/core/java/com/android/server/audio/AudioService.java +13 −1 Original line number Diff line number Diff line Loading @@ -223,7 +223,8 @@ import java.util.stream.Collectors; public class AudioService extends IAudioService.Stub implements AccessibilityManager.TouchExplorationStateChangeListener, AccessibilityManager.AccessibilityServicesStateChangeListener, AudioSystemAdapter.OnRoutingUpdatedListener { AudioSystemAdapter.OnRoutingUpdatedListener, AudioSystemAdapter.OnVolRangeInitRequestListener { private static final String TAG = "AS.AudioService"; Loading Loading @@ -1137,6 +1138,9 @@ public class AudioService extends IAudioService.Stub // monitor routing updates coming from native mAudioSystem.setRoutingListener(this); // monitor requests for volume range initialization coming from native (typically when // errors are found by AudioPolicyManager mAudioSystem.setVolRangeInitReqListener(this); // done with service initialization, continue additional work in our Handler thread queueMsgUnderWakeLock(mAudioHandler, MSG_INIT_STREAMS_VOLUMES, Loading Loading @@ -1357,6 +1361,14 @@ public class AudioService extends IAudioService.Stub checkMuteAwaitConnection(); } //----------------------------------------------------------------- // monitoring requests for volume range initialization @Override // AudioSystemAdapter.OnVolRangeInitRequestListener public void onVolumeRangeInitRequestFromNative() { sendMsg(mAudioHandler, MSG_REINIT_VOLUMES, SENDMSG_REPLACE, 0, 0, "onVolumeRangeInitRequestFromNative" /*obj: caller, for dumpsys*/, /*delay*/ 0); } //----------------------------------------------------------------- RoleObserver mRoleObserver; Loading services/core/java/com/android/server/audio/AudioSystemAdapter.java +38 −1 Original line number Diff line number Diff line Loading @@ -40,7 +40,8 @@ import java.util.concurrent.ConcurrentHashMap; * Use the "real" AudioSystem through the default adapter. * Use the "always ok" adapter to avoid dealing with the APM behaviors during a test. */ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback { public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback, AudioSystem.VolumeRangeInitRequestCallback { private static final String TAG = "AudioSystemAdapter"; Loading @@ -65,6 +66,9 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback { private static final Object sRoutingListenerLock = new Object(); @GuardedBy("sRoutingListenerLock") private static @Nullable OnRoutingUpdatedListener sRoutingListener; private static final Object sVolRangeInitReqListenerLock = new Object(); @GuardedBy("sVolRangeInitReqListenerLock") private static @Nullable OnVolRangeInitRequestListener sVolRangeInitReqListener; /** * should be false except when trying to debug caching errors. When true, the value retrieved Loading Loading @@ -101,6 +105,30 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback { } } /** * Implementation of AudioSystem.VolumeRangeInitRequestCallback */ @Override public void onVolumeRangeInitializationRequested() { final OnVolRangeInitRequestListener listener; synchronized (sVolRangeInitReqListenerLock) { listener = sVolRangeInitReqListener; } if (listener != null) { listener.onVolumeRangeInitRequestFromNative(); } } interface OnVolRangeInitRequestListener { void onVolumeRangeInitRequestFromNative(); } static void setVolRangeInitReqListener(@Nullable OnVolRangeInitRequestListener listener) { synchronized (sVolRangeInitReqListenerLock) { sVolRangeInitReqListener = listener; } } /** * Create a wrapper around the {@link AudioSystem} static methods, all functions are directly * forwarded to the AudioSystem class. Loading @@ -110,6 +138,7 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback { if (sSingletonDefaultAdapter == null) { sSingletonDefaultAdapter = new AudioSystemAdapter(); AudioSystem.setRoutingCallback(sSingletonDefaultAdapter); AudioSystem.setVolumeRangeInitRequestCallback(sSingletonDefaultAdapter); if (USE_CACHE_FOR_GETDEVICES) { sSingletonDefaultAdapter.mDevicesForAttrCache = new ConcurrentHashMap<>(AudioSystem.getNumStreamTypes()); Loading Loading @@ -160,7 +189,15 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback { synchronized (mDevicesForAttrCache) { res = mDevicesForAttrCache.get(key); if (res == null) { // result from AudioSystem guaranteed non-null, but could be invalid // if there is a failure to talk to APM res = AudioSystem.getDevicesForAttributes(attributes, forVolume); if (res.size() > 1 && res.get(0) != null && res.get(0).getInternalType() == AudioSystem.DEVICE_NONE) { Log.e(TAG, "unable to get devices for " + attributes); // return now, do not put invalid value in cache return res; } mDevicesForAttrCache.put(key, res); if (DEBUG_CACHE) { Log.d(TAG, mMethodNames[METHOD_GETDEVICESFORATTRIBUTES] Loading Loading
core/jni/android_media_AudioSystem.cpp +25 −0 Original line number Diff line number Diff line Loading @@ -180,6 +180,7 @@ static struct { jmethodID postDynPolicyEventFromNative; jmethodID postRecordConfigEventFromNative; jmethodID postRoutingUpdatedFromNative; jmethodID postVolRangeInitReqFromNative; } gAudioPolicyEventHandlerMethods; jclass gListClass; Loading Loading @@ -585,6 +586,20 @@ android_media_AudioSystem_routing_callback() env->DeleteLocalRef(clazz); } static void android_media_AudioSystem_vol_range_init_req_callback() { JNIEnv *env = AndroidRuntime::getJNIEnv(); if (env == NULL) { return; } // callback into java jclass clazz = env->FindClass(kClassPathName); env->CallStaticVoidMethod(clazz, gAudioPolicyEventHandlerMethods.postVolRangeInitReqFromNative); env->DeleteLocalRef(clazz); } static jint android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint state, jobject jParcel, jint codec) { Loading Loading @@ -2063,6 +2078,11 @@ android_media_AudioSystem_registerRoutingCallback(JNIEnv *env, jobject thiz) AudioSystem::setRoutingCallback(android_media_AudioSystem_routing_callback); } static void android_media_AudioSystem_registerVolRangeInitReqCallback(JNIEnv *env, jobject thiz) { AudioSystem::setVolInitReqCallback(android_media_AudioSystem_vol_range_init_req_callback); } void javaAudioFormatToNativeAudioConfig(JNIEnv *env, audio_config_t *nConfig, const jobject jFormat, bool isInput) { *nConfig = AUDIO_CONFIG_INITIALIZER; Loading Loading @@ -2990,6 +3010,8 @@ static const JNINativeMethod gMethods[] = (void *)android_media_AudioSystem_registerRecordingCallback}, {"native_register_routing_callback", "()V", (void *)android_media_AudioSystem_registerRoutingCallback}, {"native_register_vol_range_init_req_callback", "()V", (void *)android_media_AudioSystem_registerVolRangeInitReqCallback}, {"systemReady", "()I", (void *)android_media_AudioSystem_systemReady}, {"getStreamVolumeDB", "(III)F", (void *)android_media_AudioSystem_getStreamVolumeDB}, {"native_get_offload_support", "(IIIII)I", Loading Loading @@ -3202,6 +3224,9 @@ int register_android_media_AudioSystem(JNIEnv *env) gAudioPolicyEventHandlerMethods.postRoutingUpdatedFromNative = GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName), "routingCallbackFromNative", "()V"); gAudioPolicyEventHandlerMethods.postVolRangeInitReqFromNative = GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName), "volRangeInitReqCallbackFromNative", "()V"); jclass audioMixClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMix"); gAudioMixClass = MakeGlobalRefOrDie(env, audioMixClass); Loading
media/java/android/media/AudioSystem.java +36 −0 Original line number Diff line number Diff line Loading @@ -828,6 +828,40 @@ public class AudioSystem cb.onRoutingUpdated(); } /** * @hide * Handles requests from the audio policy manager to (re-)initialize the volume ranges */ public interface VolumeRangeInitRequestCallback { /** * Callback to notify volume ranges need to be initialized */ void onVolumeRangeInitializationRequested(); } @GuardedBy("AudioSystem.class") private static VolumeRangeInitRequestCallback sVolRangeInitReqCallback; /** @hide */ public static void setVolumeRangeInitRequestCallback(VolumeRangeInitRequestCallback cb) { synchronized (AudioSystem.class) { sVolRangeInitReqCallback = cb; native_register_vol_range_init_req_callback(); } } private static void volRangeInitReqCallbackFromNative() { final VolumeRangeInitRequestCallback cb; synchronized (AudioSystem.class) { cb = sVolRangeInitReqCallback; } if (cb == null) { Log.e(TAG, "APM requested volume range initialization, but no callback found"); return; } cb.onVolumeRangeInitializationRequested(); } /* * Error codes used by public APIs (AudioTrack, AudioRecord, AudioManager ...) * Must be kept in sync with frameworks/base/core/jni/android_media_AudioErrors.h Loading Loading @@ -1812,6 +1846,8 @@ public class AudioSystem private static native final void native_register_recording_callback(); // declare this instance as having a routing update callback handler private static native void native_register_routing_callback(); // declare this instance as having a volume range init request handler private static native void native_register_vol_range_init_req_callback(); // must be kept in sync with value in include/system/audio.h /** @hide */ public static final int AUDIO_HW_SYNC_INVALID = 0; Loading
services/core/java/com/android/server/audio/AudioService.java +13 −1 Original line number Diff line number Diff line Loading @@ -223,7 +223,8 @@ import java.util.stream.Collectors; public class AudioService extends IAudioService.Stub implements AccessibilityManager.TouchExplorationStateChangeListener, AccessibilityManager.AccessibilityServicesStateChangeListener, AudioSystemAdapter.OnRoutingUpdatedListener { AudioSystemAdapter.OnRoutingUpdatedListener, AudioSystemAdapter.OnVolRangeInitRequestListener { private static final String TAG = "AS.AudioService"; Loading Loading @@ -1137,6 +1138,9 @@ public class AudioService extends IAudioService.Stub // monitor routing updates coming from native mAudioSystem.setRoutingListener(this); // monitor requests for volume range initialization coming from native (typically when // errors are found by AudioPolicyManager mAudioSystem.setVolRangeInitReqListener(this); // done with service initialization, continue additional work in our Handler thread queueMsgUnderWakeLock(mAudioHandler, MSG_INIT_STREAMS_VOLUMES, Loading Loading @@ -1357,6 +1361,14 @@ public class AudioService extends IAudioService.Stub checkMuteAwaitConnection(); } //----------------------------------------------------------------- // monitoring requests for volume range initialization @Override // AudioSystemAdapter.OnVolRangeInitRequestListener public void onVolumeRangeInitRequestFromNative() { sendMsg(mAudioHandler, MSG_REINIT_VOLUMES, SENDMSG_REPLACE, 0, 0, "onVolumeRangeInitRequestFromNative" /*obj: caller, for dumpsys*/, /*delay*/ 0); } //----------------------------------------------------------------- RoleObserver mRoleObserver; Loading
services/core/java/com/android/server/audio/AudioSystemAdapter.java +38 −1 Original line number Diff line number Diff line Loading @@ -40,7 +40,8 @@ import java.util.concurrent.ConcurrentHashMap; * Use the "real" AudioSystem through the default adapter. * Use the "always ok" adapter to avoid dealing with the APM behaviors during a test. */ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback { public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback, AudioSystem.VolumeRangeInitRequestCallback { private static final String TAG = "AudioSystemAdapter"; Loading @@ -65,6 +66,9 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback { private static final Object sRoutingListenerLock = new Object(); @GuardedBy("sRoutingListenerLock") private static @Nullable OnRoutingUpdatedListener sRoutingListener; private static final Object sVolRangeInitReqListenerLock = new Object(); @GuardedBy("sVolRangeInitReqListenerLock") private static @Nullable OnVolRangeInitRequestListener sVolRangeInitReqListener; /** * should be false except when trying to debug caching errors. When true, the value retrieved Loading Loading @@ -101,6 +105,30 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback { } } /** * Implementation of AudioSystem.VolumeRangeInitRequestCallback */ @Override public void onVolumeRangeInitializationRequested() { final OnVolRangeInitRequestListener listener; synchronized (sVolRangeInitReqListenerLock) { listener = sVolRangeInitReqListener; } if (listener != null) { listener.onVolumeRangeInitRequestFromNative(); } } interface OnVolRangeInitRequestListener { void onVolumeRangeInitRequestFromNative(); } static void setVolRangeInitReqListener(@Nullable OnVolRangeInitRequestListener listener) { synchronized (sVolRangeInitReqListenerLock) { sVolRangeInitReqListener = listener; } } /** * Create a wrapper around the {@link AudioSystem} static methods, all functions are directly * forwarded to the AudioSystem class. Loading @@ -110,6 +138,7 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback { if (sSingletonDefaultAdapter == null) { sSingletonDefaultAdapter = new AudioSystemAdapter(); AudioSystem.setRoutingCallback(sSingletonDefaultAdapter); AudioSystem.setVolumeRangeInitRequestCallback(sSingletonDefaultAdapter); if (USE_CACHE_FOR_GETDEVICES) { sSingletonDefaultAdapter.mDevicesForAttrCache = new ConcurrentHashMap<>(AudioSystem.getNumStreamTypes()); Loading Loading @@ -160,7 +189,15 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback { synchronized (mDevicesForAttrCache) { res = mDevicesForAttrCache.get(key); if (res == null) { // result from AudioSystem guaranteed non-null, but could be invalid // if there is a failure to talk to APM res = AudioSystem.getDevicesForAttributes(attributes, forVolume); if (res.size() > 1 && res.get(0) != null && res.get(0).getInternalType() == AudioSystem.DEVICE_NONE) { Log.e(TAG, "unable to get devices for " + attributes); // return now, do not put invalid value in cache return res; } mDevicesForAttrCache.put(key, res); if (DEBUG_CACHE) { Log.d(TAG, mMethodNames[METHOD_GETDEVICESFORATTRIBUTES] Loading