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

Commit b691ec7c authored by Dichen Zhang's avatar Dichen Zhang Committed by Android (Google) Code Review
Browse files

Merge "Add/remove routing change listener support"

parents 0c142ddd 149fd05f
Loading
Loading
Loading
Loading
+10 −41
Original line number Diff line number Diff line
@@ -34,7 +34,6 @@ import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.PowerManager;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;
import android.view.Surface;
@@ -835,46 +834,29 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
        return null;
    }

    // Call BEFORE adding a routing callback handler or AFTER removing a routing callback handler.
    @GuardedBy("mRoutingChangeListeners")
    private void enableNativeRoutingCallbacksLocked(boolean enabled) {
        if (mRoutingChangeListeners.size() == 0) {
            native_enableDeviceCallback(enabled);
        }
    }

    // The list of AudioRouting.OnRoutingChangedListener interfaces added with
    // addOnRoutingChangedListener by an app to receive (re)routing notifications.
    @GuardedBy("mRoutingChangeListeners")
    private ArrayMap<AudioRouting.OnRoutingChangedListener,
            NativeRoutingEventHandlerDelegate> mRoutingChangeListeners = new ArrayMap<>();

    @Override
    public void addOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener,
            Handler handler) {
        synchronized (mRoutingChangeListeners) {
            if (listener != null && !mRoutingChangeListeners.containsKey(listener)) {
                enableNativeRoutingCallbacksLocked(true);
                mRoutingChangeListeners.put(
                        listener, new NativeRoutingEventHandlerDelegate(this, listener,
                                handler != null ? handler : mTaskHandler));
            }
        if (listener == null) {
            throw new IllegalArgumentException("addOnRoutingChangedListener: listener is NULL");
        }
        RoutingDelegate routingDelegate = new RoutingDelegate(this, listener, handler);
        native_addDeviceCallback(routingDelegate);
    }

    @Override
    public void removeOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener) {
        synchronized (mRoutingChangeListeners) {
            if (mRoutingChangeListeners.containsKey(listener)) {
                mRoutingChangeListeners.remove(listener);
                enableNativeRoutingCallbacksLocked(false);
            }
        if (listener == null) {
            throw new IllegalArgumentException("removeOnRoutingChangedListener: listener is NULL");
        }
        native_removeDeviceCallback(listener);
    }

    private native final boolean native_setOutputDevice(int deviceId);
    private native final int native_getRoutedDeviceId();
    private native final void native_enableDeviceCallback(boolean enabled);
    private native void native_addDeviceCallback(RoutingDelegate rd);
    private native void native_removeDeviceCallback(
            AudioRouting.OnRoutingChangedListener listener);

    @Override
    public Object setWakeMode(Context context, int mode) {
@@ -1614,7 +1596,6 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
    private static final int MEDIA_SUBTITLE_DATA = 201;
    private static final int MEDIA_META_DATA = 202;
    private static final int MEDIA_DRM_INFO = 210;
    private static final int MEDIA_AUDIO_ROUTING_CHANGED = 10000;

    private class TaskHandler extends Handler {
        private MediaPlayer2Impl mMediaPlayer;
@@ -1946,18 +1927,6 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
                    break;
                }

                case MEDIA_AUDIO_ROUTING_CHANGED:
                {
                    AudioManager.resetAudioPortGeneration();
                    synchronized (mRoutingChangeListeners) {
                        for (NativeRoutingEventHandlerDelegate delegate
                                : mRoutingChangeListeners.values()) {
                            delegate.notifyClient();
                        }
                    }
                    return;
                }

                default:
                {
                    Log.e(TAG, "Unknown message type " + msg.what);
+48 −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;

import android.os.Handler;

class RoutingDelegate implements AudioRouting.OnRoutingChangedListener {
    private AudioRouting mAudioRouting;
    private AudioRouting.OnRoutingChangedListener mOnRoutingChangedListener;
    private Handler mHandler;

    RoutingDelegate(final AudioRouting audioRouting,
                    final AudioRouting.OnRoutingChangedListener listener,
                    Handler handler) {
        mAudioRouting = audioRouting;
        mOnRoutingChangedListener = listener;
        mHandler = handler;
    }

    public AudioRouting.OnRoutingChangedListener getListener() {
        return mOnRoutingChangedListener;
    }

    public Handler getHandler() {
        return mHandler;
    }

    @Override
    public void onRoutingChanged(AudioRouting router) {
        if (mOnRoutingChangedListener != null) {
            mOnRoutingChangedListener.onRoutingChanged(mAudioRouting);
        }
    }
}
+21 −4
Original line number Diff line number Diff line
@@ -1324,15 +1324,30 @@ static jint android_media_MediaPlayer2_getRoutedDeviceId(JNIEnv *env, jobject th
    return mp->getRoutedDeviceId();
}

static void android_media_MediaPlayer2_enableDeviceCallback(
        JNIEnv* env, jobject thiz, jboolean enabled)
static void android_media_MediaPlayer2_addDeviceCallback(
        JNIEnv* env, jobject thiz, jobject routingDelegate)
{
    sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
    if (mp == NULL) {
        return;
    }

    status_t status = mp->enableAudioDeviceCallback(enabled);
    status_t status = mp->addAudioDeviceCallback(routingDelegate);
    if (status != NO_ERROR) {
        jniThrowException(env, "java/lang/IllegalStateException", NULL);
        ALOGE("enable device callback failed: %d", status);
    }
}

static void android_media_MediaPlayer2_removeDeviceCallback(
        JNIEnv* env, jobject thiz, jobject listener)
{
    sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
    if (mp == NULL) {
        return;
    }

    status_t status = mp->removeAudioDeviceCallback(listener);
    if (status != NO_ERROR) {
        jniThrowException(env, "java/lang/IllegalStateException", NULL);
        ALOGE("enable device callback failed: %d", status);
@@ -1457,7 +1472,9 @@ static const JNINativeMethod gMethods[] = {
    // AudioRouting
    {"native_setOutputDevice", "(I)Z",                          (void *)android_media_MediaPlayer2_setOutputDevice},
    {"native_getRoutedDeviceId", "()I",                         (void *)android_media_MediaPlayer2_getRoutedDeviceId},
    {"native_enableDeviceCallback", "(Z)V",                     (void *)android_media_MediaPlayer2_enableDeviceCallback},
    {"native_addDeviceCallback", "(Landroid/media/RoutingDelegate;)V", (void *)android_media_MediaPlayer2_addDeviceCallback},
    {"native_removeDeviceCallback", "(Landroid/media/AudioRouting$OnRoutingChangedListener;)V",
            (void *)android_media_MediaPlayer2_removeDeviceCallback},

    // StreamEventCallback for JAudioTrack
    {"native_stream_event_onTearDown",                "(JJ)V",  (void *)android_media_MediaPlayer2_native_on_tear_down},