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

Commit 7678a7be authored by Jean-Michel Trivi's avatar Jean-Michel Trivi
Browse files

resolved conflicts for merge of 99bd302c to master

Change-Id: I858f67d0c61f6403b336c82a300f69027fc16bd1
parents d3289c60 99bd302c
Loading
Loading
Loading
Loading
+100 −19
Original line number Diff line number Diff line
@@ -166,6 +166,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
    private static final int MSG_PROMOTE_RCC = 29;
    private static final int MSG_BROADCAST_BT_CONNECTION_STATE = 30;
    private static final int MSG_UNLOAD_SOUND_EFFECTS = 31;
    private static final int MSG_RCC_NEW_PLAYBACK_STATE = 32;


    // flags for MSG_PERSIST_VOLUME indicating if current and/or last audible volume should be
@@ -3741,6 +3742,10 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
                    onRegisterVolumeObserverForRcc(msg.arg1 /* rccId */,
                            (IRemoteVolumeObserver)msg.obj /* rvo */);
                    break;
                case MSG_RCC_NEW_PLAYBACK_STATE:
                    onNewPlaybackStateForRcc(msg.arg1 /* rccId */, msg.arg2 /* state */,
                            (RccPlaybackState)msg.obj /* newState */);
                    break;

                case MSG_SET_RSX_CONNECTION_STATE:
                    onSetRsxConnectionState(msg.arg1/*available*/, msg.arg2/*address*/);
@@ -5001,6 +5006,59 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
     */
    private boolean mHasRemotePlayback;

    private static class RccPlaybackState {
        public int mState;
        public long mPositionMs;
        public float mSpeed;

        public RccPlaybackState(int state, long positionMs, float speed) {
            mState = state;
            mPositionMs = positionMs;
            mSpeed = speed;
        }

        public void reset() {
            mState = RemoteControlClient.PLAYSTATE_STOPPED;
            mPositionMs = RemoteControlClient.PLAYBACK_POSITION_INVALID;
            mSpeed = RemoteControlClient.PLAYBACK_SPEED_1X;
        }

        @Override
        public String toString() {
            return stateToString() + ", "
                    + ((mPositionMs == RemoteControlClient.PLAYBACK_POSITION_INVALID) ?
                            "PLAYBACK_POSITION_INVALID ," : String.valueOf(mPositionMs)) + "ms ,"
                    + mSpeed + "X";
        }

        private String stateToString() {
            switch (mState) {
                case RemoteControlClient.PLAYSTATE_NONE:
                    return "PLAYSTATE_NONE";
                case RemoteControlClient.PLAYSTATE_STOPPED:
                    return "PLAYSTATE_STOPPED";
                case RemoteControlClient.PLAYSTATE_PAUSED:
                    return "PLAYSTATE_PAUSED";
                case RemoteControlClient.PLAYSTATE_PLAYING:
                    return "PLAYSTATE_PLAYING";
                case RemoteControlClient.PLAYSTATE_FAST_FORWARDING:
                    return "PLAYSTATE_FAST_FORWARDING";
                case RemoteControlClient.PLAYSTATE_REWINDING:
                    return "PLAYSTATE_REWINDING";
                case RemoteControlClient.PLAYSTATE_SKIPPING_FORWARDS:
                    return "PLAYSTATE_SKIPPING_FORWARDS";
                case RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS:
                    return "PLAYSTATE_SKIPPING_BACKWARDS";
                case RemoteControlClient.PLAYSTATE_BUFFERING:
                    return "PLAYSTATE_BUFFERING";
                case RemoteControlClient.PLAYSTATE_ERROR:
                    return "PLAYSTATE_ERROR";
                default:
                    return "[invalid playstate]";
            }
        }
    }

    private static class RemoteControlStackEntry {
        public int mRccId = RemoteControlClient.RCSE_ID_UNREGISTERED;
        /**
@@ -5029,7 +5087,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
        public int mPlaybackVolumeMax;
        public int mPlaybackVolumeHandling;
        public int mPlaybackStream;
        public int mPlaybackState;
        public RccPlaybackState mPlaybackState;
        public IRemoteVolumeObserver mRemoteVolumeObs;

        public void resetPlaybackInfo() {
@@ -5038,7 +5096,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
            mPlaybackVolumeMax = RemoteControlClient.DEFAULT_PLAYBACK_VOLUME;
            mPlaybackVolumeHandling = RemoteControlClient.DEFAULT_PLAYBACK_VOLUME_HANDLING;
            mPlaybackStream = AudioManager.STREAM_MUSIC;
            mPlaybackState = RemoteControlClient.PLAYSTATE_STOPPED;
            mPlaybackState.reset();
            mRemoteVolumeObs = null;
        }

@@ -6007,31 +6065,54 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
                            case RemoteControlClient.PLAYBACKINFO_USES_STREAM:
                                rcse.mPlaybackStream = value;
                                break;
                            case RemoteControlClient.PLAYBACKINFO_PLAYSTATE:
                                rcse.mPlaybackState = value;
                            default:
                                Log.e(TAG, "unhandled key " + key + " for RCC " + rccId);
                                break;
                        }
                        return;
                    }
                }//for
            } catch (ArrayIndexOutOfBoundsException e) {
                // not expected to happen, indicates improper concurrent modification
                Log.e(TAG, "Wrong index mRCStack on onNewPlaybackInfoForRcc, lock error? ", e);
            }
        }
    }

    public void setPlaybackStateForRcc(int rccId, int state, long timeMs, float speed) {
        sendMsg(mAudioHandler, MSG_RCC_NEW_PLAYBACK_STATE, SENDMSG_QUEUE,
                rccId /* arg1 */, state /* arg2 */,
                new RccPlaybackState(state, timeMs, speed) /* obj */, 0 /* delay */);
    }

    public void onNewPlaybackStateForRcc(int rccId, int state, RccPlaybackState newState) {
        if(DEBUG_RC) Log.d(TAG, "onNewPlaybackStateForRcc(id=" + rccId + ", state=" + state
                + ", time=" + newState.mPositionMs + ", speed=" + newState.mSpeed + ")");
        synchronized(mRCStack) {
            // iterating from top of stack as playback information changes are more likely
            //   on entries at the top of the remote control stack
            try {
                for (int index = mRCStack.size()-1; index >= 0; index--) {
                    final RemoteControlStackEntry rcse = mRCStack.elementAt(index);
                    if (rcse.mRccId == rccId) {
                        rcse.mPlaybackState = newState;
                        synchronized (mMainRemote) {
                            if (rccId == mMainRemote.mRccId) {
                                        mMainRemoteIsActive = isPlaystateActive(value);
                                mMainRemoteIsActive = isPlaystateActive(state);
                                postReevaluateRemote();
                            }
                        }
                        // an RCC moving to a "playing" state should become the media button
                        //   event receiver so it can be controlled, without requiring the
                        //   app to re-register its receiver
                                if (isPlaystateActive(value)) {
                        if (isPlaystateActive(state)) {
                            postPromoteRcc(rccId);
                        }
                                break;
                            default:
                                Log.e(TAG, "unhandled key " + key + " for RCC " + rccId);
                                break;
                        }
                        return;
                    }
                }//for
            } catch (ArrayIndexOutOfBoundsException e) {
                // not expected to happen, indicates improper concurrent modification
                Log.e(TAG, "Wrong index accessing RC stack, lock error? ", e);
                Log.e(TAG, "Wrong index on mRCStack in onNewPlaybackStateForRcc, lock error? ", e);
            }
        }
    }
@@ -6075,7 +6156,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
                for (int index = mRCStack.size()-1; index >= 0; index--) {
                    final RemoteControlStackEntry rcse = mRCStack.elementAt(index);
                    if ((rcse.mPlaybackType == RemoteControlClient.PLAYBACK_TYPE_REMOTE)
                            && isPlaystateActive(rcse.mPlaybackState)
                            && isPlaystateActive(rcse.mPlaybackState.mState)
                            && (rcse.mPlaybackStream == streamType)) {
                        if (DEBUG_RC) Log.d(TAG, "remote playback active on stream " + streamType
                                + ", vol =" + rcse.mPlaybackVolume);
+1 −0
Original line number Diff line number Diff line
@@ -159,6 +159,7 @@ interface IAudioService {
    oneway void remoteControlDisplayUsesBitmapSize(in IRemoteControlDisplay rcd, int w, int h);

    oneway void setPlaybackInfoForRcc(int rccId, int what, int value);
           void setPlaybackStateForRcc(int rccId, int state, long timeMs, float speed);
           int  getRemoteStreamMaxVolume();
           int  getRemoteStreamVolume();
    oneway void registerRemoteVolumeObserverForRcc(int rccId, in IRemoteVolumeObserver rvo);
+2 −1
Original line number Diff line number Diff line
@@ -40,7 +40,8 @@ oneway interface IRemoteControlDisplay
    void setCurrentClientId(int clientGeneration, in PendingIntent clientMediaIntent,
            boolean clearing);

    void setPlaybackState(int generationId, int state, long stateChangeTimeMs);
    void setPlaybackState(int generationId, int state, long stateChangeTimeMs, long currentPosMs,
            float speed);

    void setTransportControlFlags(int generationId, int transportControlFlags);

+151 −16
Original line number Diff line number Diff line
@@ -172,6 +172,17 @@ public class RemoteControlClient
     */
    public final static int PLAYBACKINFO_INVALID_VALUE = Integer.MIN_VALUE;

    /**
     * @hide
     * An unknown or invalid playback position value.
     */
    public final static long PLAYBACK_POSITION_INVALID = -1;
    /**
     * @hide
     * The default playback speed, 1x.
     */
    public final static float PLAYBACK_SPEED_1X = 1.0f;

    //==========================================
    // Public keys for playback information
    /**
@@ -208,15 +219,7 @@ public class RemoteControlClient
    public final static int PLAYBACKINFO_USES_STREAM = 5;

    //==========================================
    // Private keys for playback information
    /**
     * @hide
     * Used internally to relay playback state (set by the application with
     * {@link #setPlaybackState(int)}) to AudioService
     */
    public final static int PLAYBACKINFO_PLAYSTATE = 255;


    // Public flags for the supported transport control capabililities
    /**
     * Flag indicating a RemoteControlClient makes use of the "previous" media key.
     *
@@ -273,6 +276,15 @@ public class RemoteControlClient
     * @see android.view.KeyEvent#KEYCODE_MEDIA_NEXT
     */
    public final static int FLAG_KEY_MEDIA_NEXT = 1 << 7;
    /**
     * @hide
     * (to be un-hidden and added in javadoc of setTransportControlFlags(int))
     * Flag indicating a RemoteControlClient can receive changes in the media playback position
     * through the {@link #OnPlaybackPositionUpdateListener} interface.
     *
     * @see #setTransportControlFlags(int)
     */
    public final static int FLAG_KEY_MEDIA_POSITION_UPDATE = 1 << 8;

    /**
     * @hide
@@ -588,17 +600,54 @@ public class RemoteControlClient
     *       {@link #PLAYSTATE_ERROR}.
     */
    public void setPlaybackState(int state) {
        setPlaybackState(state, PLAYBACK_POSITION_INVALID, PLAYBACK_SPEED_1X);
    }

    /**
     * @hide
     * (to be un-hidden)
     * Sets the current playback state and the matching media position for the current playback
     *   speed.
     * @param state The current playback state, one of the following values:
     *       {@link #PLAYSTATE_STOPPED},
     *       {@link #PLAYSTATE_PAUSED},
     *       {@link #PLAYSTATE_PLAYING},
     *       {@link #PLAYSTATE_FAST_FORWARDING},
     *       {@link #PLAYSTATE_REWINDING},
     *       {@link #PLAYSTATE_SKIPPING_FORWARDS},
     *       {@link #PLAYSTATE_SKIPPING_BACKWARDS},
     *       {@link #PLAYSTATE_BUFFERING},
     *       {@link #PLAYSTATE_ERROR}.
     * @param timeInMs a 0 or positive value for the current media position expressed in ms
     *    (same unit as for when sending the media duration, if applicable, with
     *    {@link android.media.MediaMetadataRetriever#METADATA_KEY_DURATION} in the
     *    {@link RemoteControlClient.MetadataEditor}). Negative values imply that position is not
     *    known (e.g. listening to a live stream of a radio) or not applicable (e.g. when state
     *    is {@link #PLAYSTATE_BUFFERING} and nothing had played yet).
     * @param playbackSpeed a value expressed as a ratio of 1x playback: 1.0f is normal playback,
     *    2.0f is 2x, 0.5f is half-speed, -2.0f is rewind at 2x speed. 0.0f means nothing is
     *    playing (e.g. when state is {@link #PLAYSTATE_ERROR}).
     */
    public void setPlaybackState(int state, long timeInMs, float playbackSpeed) {
        synchronized(mCacheLock) {
            if (mPlaybackState != state) {
            if (timeInMs != PLAYBACK_POSITION_INVALID) {
                mPlaybackPositionCapabilities |= MEDIA_POSITION_READABLE;
            } else {
                mPlaybackPositionCapabilities &= ~MEDIA_POSITION_READABLE;
            }
            if ((mPlaybackState != state) || (mPlaybackPositionMs != timeInMs)
                    || (mPlaybackSpeed != playbackSpeed)) {
                // store locally
                mPlaybackState = state;
                mPlaybackPositionMs = timeInMs;
                mPlaybackSpeed = playbackSpeed;
                // keep track of when the state change occurred
                mPlaybackStateChangeTimeMs = SystemClock.elapsedRealtime();

                // send to remote control display if conditions are met
                sendPlaybackState_syncCacheLock();
                // update AudioService
                sendAudioServiceNewPlaybackInfo_syncCacheLock(PLAYBACKINFO_PLAYSTATE, state);
                sendAudioServiceNewPlaybackState_syncCacheLock();
            }
        }
    }
@@ -625,6 +674,65 @@ public class RemoteControlClient
        }
    }

    /**
     * @hide
     * (to be un-hidden)
     * Interface definition for a callback to be invoked when the media playback position is
     * requested to be updated.
     */
    public interface OnPlaybackPositionUpdateListener {
        /**
         * Called on the listener to notify it that the playback head should be set at the given
         * position. If the position can be changed from its current value, the implementor of
         * the interface should also update the playback position using
         * {@link RemoteControlClient#setPlaybackState(int, long, int)} to reflect the actual new
         * position being used, regardless of whether it differs from the requested position.
         * @param newPositionMs the new requested position in the current media, expressed in ms.
         */
        void onPlaybackPositionUpdate(long newPositionMs);
    }

    /**
     * @hide
     * (to be un-hidden)
     * Sets the listener RemoteControlClient calls whenever the media playback position is requested
     * to be updated.
     * Notifications will be received in the same thread as the one in which RemoteControlClient
     * was created.
     * @param l
     */
    public void setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener l) {
        synchronized(mCacheLock) {
            if ((mPositionUpdateListener == null) && (l != null)) {
                mPlaybackPositionCapabilities |= MEDIA_POSITION_WRITABLE;
                // tell RCDs and AudioService this RCC accepts position updates
                // TODO implement
            } else if ((mPositionUpdateListener != null) && (l == null)) {
                mPlaybackPositionCapabilities &= ~MEDIA_POSITION_WRITABLE;
                // tell RCDs and AudioService this RCC doesn't handle position updates
                // TODO implement
            }
            mPositionUpdateListener = l;
        }
    }

    /**
     * @hide
     * Flag to reflect that the application controlling this RemoteControlClient sends playback
     * position updates. The playback position being "readable" is considered from the application's
     * point of view.
     */
    public static int MEDIA_POSITION_READABLE = 1 << 0;
    /**
     * @hide
     * Flag to reflect that the application controlling this RemoteControlClient can receive
     * playback position updates. The playback position being "writable"
     * is considered from the application's point of view.
     */
    public static int MEDIA_POSITION_WRITABLE = 1 << 1;

    private int mPlaybackPositionCapabilities = 0;

    /** @hide */
    public final static int DEFAULT_PLAYBACK_VOLUME_HANDLING = PLAYBACK_VOLUME_VARIABLE;
    /** @hide */
@@ -755,6 +863,14 @@ public class RemoteControlClient
     * Access synchronized on mCacheLock
     */
    private long mPlaybackStateChangeTimeMs = 0;
    /**
     * Last playback position in ms reported by the user
     */
    private long mPlaybackPositionMs = PLAYBACK_POSITION_INVALID;
    /**
     * Last playback speed reported by the user
     */
    private float mPlaybackSpeed = PLAYBACK_SPEED_1X;
    /**
     * Cache for the artwork bitmap.
     * Access synchronized on mCacheLock
@@ -774,9 +890,13 @@ public class RemoteControlClient
     * This is re-initialized in apply() and so cannot be final.
     */
    private Bundle mMetadata = new Bundle();

    /**
     * The current remote control client generation ID across the system
     * Listener registered by user of RemoteControlClient to receive requests for playback position
     * update requests.
     */
    private OnPlaybackPositionUpdateListener mPositionUpdateListener;
    /**
     * The current remote control client generation ID across the system, as known by this object
     */
    private int mCurrentClientGenId = -1;
    /**
@@ -789,7 +909,8 @@ public class RemoteControlClient

    /**
     * The media button intent description associated with this remote control client
     * (can / should include target component for intent handling)
     * (can / should include target component for intent handling, used when persisting media
     *    button event receiver across reboots).
     */
    private final PendingIntent mRcMediaIntent;

@@ -990,7 +1111,8 @@ public class RemoteControlClient
                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
                try {
                    di.mRcDisplay.setPlaybackState(mInternalClientGenId,
                            mPlaybackState, mPlaybackStateChangeTimeMs);
                            mPlaybackState, mPlaybackStateChangeTimeMs, mPlaybackPositionMs,
                            mPlaybackSpeed);
                } catch (RemoteException e) {
                    Log.e(TAG, "Error in setPlaybackState(), dead display " + di.mRcDisplay, e);
                    displayIterator.remove();
@@ -1109,7 +1231,20 @@ public class RemoteControlClient
        try {
            service.setPlaybackInfoForRcc(mRcseId, what, value);
        } catch (RemoteException e) {
            Log.e(TAG, "Dead object in sendAudioServiceNewPlaybackInfo_syncCacheLock", e);
            Log.e(TAG, "Dead object in setPlaybackInfoForRcc", e);
        }
    }

    private void sendAudioServiceNewPlaybackState_syncCacheLock() {
        if (mRcseId == RCSE_ID_UNREGISTERED) {
            return;
        }
        IAudioService service = getService();
        try {
            service.setPlaybackStateForRcc(mRcseId,
                    mPlaybackState, mPlaybackPositionMs, mPlaybackSpeed);
        } catch (RemoteException e) {
            Log.e(TAG, "Dead object in setPlaybackStateForRcc", e);
        }
    }

+2 −1
Original line number Diff line number Diff line
@@ -130,7 +130,8 @@ public class KeyguardTransportControlView extends FrameLayout implements OnClick
            mLocalHandler = new WeakReference<Handler>(handler);
        }

        public void setPlaybackState(int generationId, int state, long stateChangeTimeMs) {
        public void setPlaybackState(int generationId, int state, long stateChangeTimeMs,
                long currentPosMs, float speed) {
            Handler handler = mLocalHandler.get();
            if (handler != null) {
                handler.obtainMessage(MSG_UPDATE_STATE, generationId, state).sendToTarget();
Loading