Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 477f1a28 authored by Jean-Michel Trivi's avatar Jean-Michel Trivi Committed by Android (Google) Code Review
Browse files

Merge "AudioService: reset volume ranges when requested by APM" into tm-dev

parents 73871cad a44a5f91
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -180,6 +180,7 @@ static struct {
    jmethodID postDynPolicyEventFromNative;
    jmethodID postRecordConfigEventFromNative;
    jmethodID postRoutingUpdatedFromNative;
    jmethodID postVolRangeInitReqFromNative;
} gAudioPolicyEventHandlerMethods;

jclass gListClass;
@@ -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) {
@@ -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;
@@ -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",
@@ -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);
+36 −0
Original line number Diff line number Diff line
@@ -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
@@ -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;
+13 −1
Original line number Diff line number Diff line
@@ -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";

@@ -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,
@@ -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;

+38 −1
Original line number Diff line number Diff line
@@ -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";

@@ -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
@@ -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.
@@ -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());
@@ -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]