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

Commit 55011657 authored by RoboErik's avatar RoboErik
Browse files

Add API to set a default session in Activity

We may have multiple remote sessions at once so an app needs a way
to specify a default session to route media and volume commands to
when its activity is in the foreground. This adds an api that works
in parallel with the default stream api on Activity.

bug:15727927
Change-Id: I5b67cb3e20647f9437d90aa65be63efe8c7865cf
parent a4ab7808
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -3309,6 +3309,7 @@ package android.app {
    method public android.view.LayoutInflater getLayoutInflater();
    method public android.app.LoaderManager getLoaderManager();
    method public java.lang.String getLocalClassName();
    method public final android.media.session.MediaController getMediaController();
    method public android.view.MenuInflater getMenuInflater();
    method public final android.app.Activity getParent();
    method public android.content.Intent getParentActivityIntent();
@@ -3432,6 +3433,7 @@ package android.app {
    method public void setFinishOnTouchOutside(boolean);
    method public void setImmersive(boolean);
    method public void setIntent(android.content.Intent);
    method public final void setMediaController(android.media.session.MediaController);
    method public boolean setMediaPlaying(boolean);
    method public final void setProgress(int);
    method public final void setProgressBarIndeterminate(boolean);
@@ -34276,6 +34278,7 @@ package android.view {
    method protected final int getForcedWindowFlags();
    method public abstract android.view.LayoutInflater getLayoutInflater();
    method protected final int getLocalFeatures();
    method public android.media.session.MediaController getMediaController();
    method public abstract int getNavigationBarColor();
    method public android.transition.Transition getSharedElementEnterTransition();
    method public android.transition.Transition getSharedElementExitTransition();
@@ -34332,6 +34335,7 @@ package android.view {
    method public void setLayout(int, int);
    method public void setLocalFocus(boolean, boolean);
    method public void setLogo(int);
    method public void setMediaController(android.media.session.MediaController);
    method public abstract void setNavigationBarColor(int);
    method public void setSharedElementEnterTransition(android.transition.Transition);
    method public void setSharedElementExitTransition(android.transition.Transition);
+413 −377
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.transition.TransitionManager;
import android.util.ArrayMap;
import android.util.SuperNotCalledException;
import android.widget.Toolbar;

import com.android.internal.app.IVoiceInteractor;
import com.android.internal.app.WindowDecorActionBar;
import com.android.internal.app.ToolbarActionBar;
@@ -51,6 +52,8 @@ import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.media.session.MediaController;
import android.media.session.MediaSession;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -5104,16 +5107,16 @@ public class Activity extends ContextThemeWrapper
     * volume controls.
     * <p>
     * The suggested audio stream will be tied to the window of this Activity.
     * If the Activity is switched, the stream set here is no longer the
     * suggested stream. The client does not need to save and restore the old
     * suggested stream value in onPause and onResume.
     * Volume requests which are received while the Activity is in the
     * foreground will affect this stream.
     * <p>
     * It is not guaranteed that the hardware volume controls will always change
     * this stream's volume (for example, if a call is in progress, its stream's
     * volume may be changed instead). To reset back to the default, use
     * {@link AudioManager#USE_DEFAULT_STREAM_TYPE}.
     *
     * @param streamType The type of the audio stream whose volume should be
     *        changed by the hardware volume controls. It is not guaranteed that
     *        the hardware volume controls will always change this stream's
     *        volume (for example, if a call is in progress, its stream's volume
     *        may be changed instead). To reset back to the default, use
     *        {@link AudioManager#USE_DEFAULT_STREAM_TYPE}.
     *            changed by the hardware volume controls.
     */
    public final void setVolumeControlStream(int streamType) {
        getWindow().setVolumeControlStream(streamType);
@@ -5131,6 +5134,39 @@ public class Activity extends ContextThemeWrapper
        return getWindow().getVolumeControlStream();
    }

    /**
     * Sets a {@link MediaController} to send media keys and volume changes to.
     * <p>
     * The controller will be tied to the window of this Activity. Media key and
     * volume events which are received while the Activity is in the foreground
     * will be forwarded to the controller and used to invoke transport controls
     * or adjust the volume. This may be used instead of or in addition to
     * {@link #setVolumeControlStream} to affect a specific session instead of a
     * specific stream.
     * <p>
     * It is not guaranteed that the hardware volume controls will always change
     * this session's volume (for example, if a call is in progress, its
     * stream's volume may be changed instead). To reset back to the default use
     * null as the controller.
     *
     * @param controller The controller for the session which should receive
     *            media keys and volume changes.
     */
    public final void setMediaController(MediaController controller) {
        getWindow().setMediaController(controller);
    }

    /**
     * Gets the controller which should be receiving media key and volume events
     * while this activity is in the foreground.
     *
     * @return The controller which should receive events.
     * @see #setMediaController(android.media.session.MediaController)
     */
    public final MediaController getMediaController() {
        return getWindow().getMediaController();
    }

    /**
     * Runs the specified action on the UI thread. If the current thread is the UI
     * thread, then the action is executed immediately. If the current thread is
+57 −42
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@ import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.media.session.MediaController;
import android.media.session.MediaSession;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
@@ -1301,6 +1303,19 @@ public abstract class Window {
     */
    public abstract int getVolumeControlStream();

    /**
     * @see android.app.Activity#setMediaController(android.media.session.MediaController)
     */
    public void setMediaController(MediaController controller) {
    }

    /**
     * @see android.app.Activity#getMediaController()
     */
    public MediaController getMediaController() {
        return null;
    }

    /**
     * Set extra options that will influence the UI for this window.
     * @param uiOptions Flags specifying extra options for this window.
+78 −6
Original line number Diff line number Diff line
@@ -49,6 +49,9 @@ import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.media.session.MediaController;
import android.media.session.MediaSession;
import android.media.session.MediaSessionLegacyHelper;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -224,6 +227,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
    private boolean mClosingActionMenu;

    private int mVolumeControlStreamType = AudioManager.USE_DEFAULT_STREAM_TYPE;
    private MediaController mMediaController;

    private AudioManager mAudioManager;
    private KeyguardManager mKeyguardManager;
@@ -1688,15 +1692,42 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {

        switch (keyCode) {
            case KeyEvent.KEYCODE_VOLUME_UP:
            case KeyEvent.KEYCODE_VOLUME_DOWN:
            case KeyEvent.KEYCODE_VOLUME_DOWN: {
                int direction = keyCode == KeyEvent.KEYCODE_VOLUME_UP ? AudioManager.ADJUST_RAISE
                        : AudioManager.ADJUST_LOWER;
                // If we have a session send it the volume command, otherwise
                // use the suggested stream.
                if (mMediaController != null) {
                    mMediaController.adjustVolumeBy(direction, AudioManager.FLAG_SHOW_UI);
                } else {
                    MediaSessionLegacyHelper.getHelper(getContext()).sendAdjustVolumeBy(
                            mVolumeControlStreamType, direction, AudioManager.FLAG_SHOW_UI);
                }
                return true;
            }
            case KeyEvent.KEYCODE_VOLUME_MUTE: {
                // Similar code is in PhoneFallbackEventHandler in case the window
                // doesn't have one of these.  In this case, we execute it here and
                // eat the event instead, because we have mVolumeControlStreamType
                // and they don't.
                getAudioManager().handleKeyDown(event, mVolumeControlStreamType);
                return true;
            }
            // These are all the recognized media key codes in
            // KeyEvent.isMediaKey()
            case KeyEvent.KEYCODE_MEDIA_PLAY:
            case KeyEvent.KEYCODE_MEDIA_PAUSE:
            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
            case KeyEvent.KEYCODE_MUTE:
            case KeyEvent.KEYCODE_HEADSETHOOK:
            case KeyEvent.KEYCODE_MEDIA_STOP:
            case KeyEvent.KEYCODE_MEDIA_NEXT:
            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
            case KeyEvent.KEYCODE_MEDIA_REWIND:
            case KeyEvent.KEYCODE_MEDIA_RECORD:
            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
                if (mMediaController != null) {
                    if (mMediaController.dispatchMediaButtonEvent(event)) {
                        return true;
                    }
                }
            }

            case KeyEvent.KEYCODE_MENU: {
                onKeyDownPanel((featureId < 0) ? FEATURE_OPTIONS_PANEL : featureId, event);
@@ -1750,7 +1781,19 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {

        switch (keyCode) {
            case KeyEvent.KEYCODE_VOLUME_UP:
            case KeyEvent.KEYCODE_VOLUME_DOWN:
            case KeyEvent.KEYCODE_VOLUME_DOWN: {
                // If we have a session send it the volume command, otherwise
                // use the suggested stream.
                if (mMediaController != null) {
                    mMediaController.adjustVolumeBy(0, AudioManager.FLAG_PLAY_SOUND
                            | AudioManager.FLAG_VIBRATE);
                } else {
                    MediaSessionLegacyHelper.getHelper(getContext()).sendAdjustVolumeBy(
                            mVolumeControlStreamType, 0,
                            AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE);
                }
                return true;
            }
            case KeyEvent.KEYCODE_VOLUME_MUTE: {
                // Similar code is in PhoneFallbackEventHandler in case the window
                // doesn't have one of these.  In this case, we execute it here and
@@ -1759,6 +1802,25 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
                getAudioManager().handleKeyUp(event, mVolumeControlStreamType);
                return true;
            }
            // These are all the recognized media key codes in
            // KeyEvent.isMediaKey()
            case KeyEvent.KEYCODE_MEDIA_PLAY:
            case KeyEvent.KEYCODE_MEDIA_PAUSE:
            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
            case KeyEvent.KEYCODE_MUTE:
            case KeyEvent.KEYCODE_HEADSETHOOK:
            case KeyEvent.KEYCODE_MEDIA_STOP:
            case KeyEvent.KEYCODE_MEDIA_NEXT:
            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
            case KeyEvent.KEYCODE_MEDIA_REWIND:
            case KeyEvent.KEYCODE_MEDIA_RECORD:
            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
                if (mMediaController != null) {
                    if (mMediaController.dispatchMediaButtonEvent(event)) {
                        return true;
                    }
                }
            }

            case KeyEvent.KEYCODE_MENU: {
                onKeyUpPanel(featureId < 0 ? FEATURE_OPTIONS_PANEL : featureId,
@@ -3773,6 +3835,16 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
        return mVolumeControlStreamType;
    }

    @Override
    public void setMediaController(MediaController controller) {
        mMediaController = controller;
    }

    @Override
    public MediaController getMediaController() {
        return mMediaController;
    }

    private boolean isTranslucent() {
        TypedArray a = getWindowStyle();
        return a.getBoolean(a.getResourceId(
+9 −3
Original line number Diff line number Diff line
@@ -18,12 +18,14 @@ package com.android.onemedia;

import android.media.MediaMetadata;
import android.media.session.MediaController;
import android.media.session.MediaSession;
import android.media.session.MediaSessionManager;
import android.media.session.PlaybackState;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -43,7 +45,7 @@ public class PlayerController {
    protected MediaController.TransportControls mTransportControls;

    private final Intent mServiceIntent;
    private Context mContext;
    private Activity mContext;
    private Listener mListener;
    private SessionCallback mControllerCb;
    private MediaSessionManager mManager;
@@ -51,7 +53,7 @@ public class PlayerController {

    private boolean mResumed;

    public PlayerController(Context context, Intent serviceIntent) {
    public PlayerController(Activity context, Intent serviceIntent) {
        mContext = context;
        if (serviceIntent == null) {
            mServiceIntent = new Intent(mContext, PlayerService.class);
@@ -140,6 +142,7 @@ public class PlayerController {
            mBinder = null;
            mController = null;
            mTransportControls = null;
            mContext.setMediaController(null);
            Log.d(TAG, "Disconnected from PlayerService");

            if (mListener != null) {
@@ -151,12 +154,15 @@ public class PlayerController {
        public void onServiceConnected(ComponentName name, IBinder service) {
            mBinder = IPlayerService.Stub.asInterface(service);
            Log.d(TAG, "service is " + service + " binder is " + mBinder);
            MediaSession.Token token;
            try {
                mController = MediaController.fromToken(mBinder.getSessionToken());
                token = mBinder.getSessionToken();
            } catch (RemoteException e) {
                Log.e(TAG, "Error getting session", e);
                return;
            }
            mController = MediaController.fromToken(token);
            mContext.setMediaController(mController);
            mController.addCallback(mControllerCb, mHandler);
            mTransportControls = mController.getTransportControls();
            Log.d(TAG, "Ready to use PlayerService");