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

Commit 6320fc49 authored by Jae Seo's avatar Jae Seo
Browse files

TIF: Notify of size change of the video in TvView

Put the necessary plumbing in place to notify of size change of the
video in TvView.
Put together the track related logic in TvInputManager.Session.
Protected track information with a lock.

Also modified debugging messages more consistently and fixed minor
warnings in TvView.

Bug: 17635300
Change-Id: I8d267d8a11056b5ccee1dacbf2d3391be16f811e
parent e41d967c
Loading
Loading
Loading
Loading
+187 −85
Original line number Diff line number Diff line
@@ -159,12 +159,12 @@ public final class TvInputManager {

    private final Object mLock = new Object();

    // @GuardedBy(mLock)
    // @GuardedBy("mLock")
    private final List<TvInputCallbackRecord> mCallbackRecords =
            new LinkedList<TvInputCallbackRecord>();

    // A mapping from TV input ID to the state of corresponding input.
    // @GuardedBy(mLock)
    // @GuardedBy("mLock")
    private final Map<String, Integer> mStateMap = new ArrayMap<String, Integer>();

    // A mapping from the sequence number of a session to its SessionCallbackRecord.
@@ -227,7 +227,7 @@ public final class TvInputManager {
        /**
         * This is called when a track for a given type is selected.
         *
         * @param session A {@link TvInputManager.Session} associated with this callback
         * @param session A {@link TvInputManager.Session} associated with this callback.
         * @param type The type of the selected track. The type can be
         *            {@link TvTrackInfo#TYPE_AUDIO}, {@link TvTrackInfo#TYPE_VIDEO} or
         *            {@link TvTrackInfo#TYPE_SUBTITLE}.
@@ -237,6 +237,18 @@ public final class TvInputManager {
        public void onTrackSelected(Session session, int type, String trackId) {
        }

        /**
         * This is invoked when the video size has been changed. It is also called when the first
         * time video size information becomes available after the session is tuned to a specific
         * channel.
         *
         * @param session A {@link TvInputManager.Session} associated with this callback.
         * @param width The width of the video.
         * @param height The height of the video.
         */
        public void onVideoSizeChanged(Session session, int width, int height) {
        }

        /**
         * This is called when the video is available, so the TV input starts the playback.
         *
@@ -312,13 +324,13 @@ public final class TvInputManager {
        private final Handler mHandler;
        private Session mSession;

        public SessionCallbackRecord(SessionCallback sessionCallback,
        SessionCallbackRecord(SessionCallback sessionCallback,
                Handler handler) {
            mSessionCallback = sessionCallback;
            mHandler = handler;
        }

        public void postSessionCreated(final Session session) {
        void postSessionCreated(final Session session) {
            mSession = session;
            mHandler.post(new Runnable() {
                @Override
@@ -328,7 +340,7 @@ public final class TvInputManager {
            });
        }

        public void postSessionReleased() {
        void postSessionReleased() {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
@@ -337,7 +349,7 @@ public final class TvInputManager {
            });
        }

        public void postChannelRetuned(final Uri channelUri) {
        void postChannelRetuned(final Uri channelUri) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
@@ -346,49 +358,34 @@ public final class TvInputManager {
            });
        }

        public void postTracksChanged(final List<TvTrackInfo> tracks) {
        void postTracksChanged(final List<TvTrackInfo> tracks) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mSession.mAudioTracks.clear();
                    mSession.mVideoTracks.clear();
                    mSession.mSubtitleTracks.clear();
                    for (TvTrackInfo track : tracks) {
                        if (track.getType() == TvTrackInfo.TYPE_AUDIO) {
                            mSession.mAudioTracks.add(track);
                        } else if (track.getType() == TvTrackInfo.TYPE_VIDEO) {
                            mSession.mVideoTracks.add(track);
                        } else if (track.getType() == TvTrackInfo.TYPE_SUBTITLE) {
                            mSession.mSubtitleTracks.add(track);
                        } else {
                            // Silently ignore.
                        }
                    }
                    mSessionCallback.onTracksChanged(mSession, tracks);
                }
            });
        }

        public void postTrackSelected(final int type, final String trackId) {
        void postTrackSelected(final int type, final String trackId) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (type == TvTrackInfo.TYPE_AUDIO) {
                        mSession.mSelectedAudioTrackId = trackId;
                    } else if (type == TvTrackInfo.TYPE_VIDEO) {
                        mSession.mSelectedVideoTrackId = trackId;
                    } else if (type == TvTrackInfo.TYPE_SUBTITLE) {
                        mSession.mSelectedSubtitleTrackId = trackId;
                    } else {
                        // Silently ignore.
                        return;
                    }
                    mSessionCallback.onTrackSelected(mSession, type, trackId);
                }
            });
        }

        public void postVideoAvailable() {
        void postVideoSizeChanged(final int width, final int height) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mSessionCallback.onVideoSizeChanged(mSession, width, height);
                }
            });
        }

        void postVideoAvailable() {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
@@ -397,7 +394,7 @@ public final class TvInputManager {
            });
        }

        public void postVideoUnavailable(final int reason) {
        void postVideoUnavailable(final int reason) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
@@ -406,7 +403,7 @@ public final class TvInputManager {
            });
        }

        public void postContentAllowed() {
        void postContentAllowed() {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
@@ -415,7 +412,7 @@ public final class TvInputManager {
            });
        }

        public void postContentBlocked(final TvContentRating rating) {
        void postContentBlocked(final TvContentRating rating) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
@@ -424,7 +421,7 @@ public final class TvInputManager {
            });
        }

        public void postLayoutSurface(final int left, final int top, final int right,
        void postLayoutSurface(final int left, final int top, final int right,
                final int bottom) {
            mHandler.post(new Runnable() {
                @Override
@@ -434,7 +431,7 @@ public final class TvInputManager {
            });
        }

        public void postSessionEvent(final String eventType, final Bundle eventArgs) {
        void postSessionEvent(final String eventType, final Bundle eventArgs) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
@@ -610,7 +607,10 @@ public final class TvInputManager {
                        Log.e(TAG, "Callback not found for seq " + seq);
                        return;
                    }
                    if (record.mSession.updateTracks(tracks)) {
                        record.postTracksChanged(tracks);
                        postVideoSizeChangedIfNeededLocked(record);
                    }
                }
            }

@@ -622,7 +622,17 @@ public final class TvInputManager {
                        Log.e(TAG, "Callback not found for seq " + seq);
                        return;
                    }
                    if (record.mSession.updateTrackSelection(type, trackId)) {
                        record.postTrackSelected(type, trackId);
                        postVideoSizeChangedIfNeededLocked(record);
                    }
                }
            }

            private void postVideoSizeChangedIfNeededLocked(SessionCallbackRecord record) {
                TvTrackInfo track = record.mSession.getVideoTrackToNotify();
                if (track != null) {
                    record.postVideoSizeChanged(track.getVideoWidth(), track.getVideoHeight());
                }
            }

@@ -778,7 +788,7 @@ public final class TvInputManager {
    }

    /**
     * Returns the state of a given TV input. It retuns one of the following:
     * Returns the state of a given TV input. It returns one of the following:
     * <ul>
     * <li>{@link #INPUT_STATE_CONNECTED}
     * <li>{@link #INPUT_STATE_CONNECTED_STANDBY}
@@ -1133,12 +1143,24 @@ public final class TvInputManager {
        private IBinder mToken;
        private TvInputEventSender mSender;
        private InputChannel mChannel;

        private final Object mTrackLock = new Object();
        // @GuardedBy("mTrackLock")
        private final List<TvTrackInfo> mAudioTracks = new ArrayList<TvTrackInfo>();
        // @GuardedBy("mTrackLock")
        private final List<TvTrackInfo> mVideoTracks = new ArrayList<TvTrackInfo>();
        // @GuardedBy("mTrackLock")
        private final List<TvTrackInfo> mSubtitleTracks = new ArrayList<TvTrackInfo>();
        // @GuardedBy("mTrackLock")
        private String mSelectedAudioTrackId;
        // @GuardedBy("mTrackLock")
        private String mSelectedVideoTrackId;
        // @GuardedBy("mTrackLock")
        private String mSelectedSubtitleTrackId;
        // @GuardedBy("mTrackLock")
        private int mVideoWidth;
        // @GuardedBy("mTrackLock")
        private int mVideoHeight;

        private Session(IBinder token, InputChannel channel, ITvInputManager service, int userId,
                int seq, SparseArray<SessionCallbackRecord> sessionCallbackRecordMap) {
@@ -1273,12 +1295,16 @@ public final class TvInputManager {
                Log.w(TAG, "The session has been already released");
                return;
            }
            synchronized (mTrackLock) {
                mAudioTracks.clear();
                mVideoTracks.clear();
                mSubtitleTracks.clear();
                mSelectedAudioTrackId = null;
                mSelectedVideoTrackId = null;
                mSelectedSubtitleTrackId = null;
                mVideoWidth = 0;
                mVideoHeight = 0;
            }
            try {
                mService.tune(mToken, channelUri, params, mUserId);
            } catch (RemoteException e) {
@@ -1314,6 +1340,7 @@ public final class TvInputManager {
         * @see #getTracks
         */
        public void selectTrack(int type, String trackId) {
            synchronized (mTrackLock) {
                if (type == TvTrackInfo.TYPE_AUDIO) {
                    if (trackId != null && !containsTrack(mAudioTracks, trackId)) {
                        Log.w(TAG, "Invalid audio trackId: " + trackId);
@@ -1332,6 +1359,7 @@ public final class TvInputManager {
                } else {
                    throw new IllegalArgumentException("invalid type: " + type);
                }
            }
            if (mToken == null) {
                Log.w(TAG, "The session has been already released");
                return;
@@ -1361,21 +1389,23 @@ public final class TvInputManager {
         * @return the list of tracks for the given type.
         */
        public List<TvTrackInfo> getTracks(int type) {
            synchronized (mTrackLock) {
                if (type == TvTrackInfo.TYPE_AUDIO) {
                    if (mAudioTracks == null) {
                        return null;
                    }
                return mAudioTracks;
                    return new ArrayList<TvTrackInfo>(mAudioTracks);
                } else if (type == TvTrackInfo.TYPE_VIDEO) {
                    if (mVideoTracks == null) {
                        return null;
                    }
                return mVideoTracks;
                    return new ArrayList<TvTrackInfo>(mVideoTracks);
                } else if (type == TvTrackInfo.TYPE_SUBTITLE) {
                    if (mSubtitleTracks == null) {
                        return null;
                    }
                return mSubtitleTracks;
                    return new ArrayList<TvTrackInfo>(mSubtitleTracks);
                }
            }
            throw new IllegalArgumentException("invalid type: " + type);
        }
@@ -1388,6 +1418,7 @@ public final class TvInputManager {
         * @see #selectTrack
         */
        public String getSelectedTrack(int type) {
            synchronized (mTrackLock) {
                if (type == TvTrackInfo.TYPE_AUDIO) {
                    return mSelectedAudioTrackId;
                } else if (type == TvTrackInfo.TYPE_VIDEO) {
@@ -1395,9 +1426,80 @@ public final class TvInputManager {
                } else if (type == TvTrackInfo.TYPE_SUBTITLE) {
                    return mSelectedSubtitleTrackId;
                }
            }
            throw new IllegalArgumentException("invalid type: " + type);
        }

        /**
         * Responds to onTracksChanged() and updates the internal track information. Returns true if
         * there is an update.
         */
        boolean updateTracks(List<TvTrackInfo> tracks) {
            synchronized (mTrackLock) {
                mAudioTracks.clear();
                mVideoTracks.clear();
                mSubtitleTracks.clear();
                for (TvTrackInfo track : tracks) {
                    if (track.getType() == TvTrackInfo.TYPE_AUDIO) {
                        mAudioTracks.add(track);
                    } else if (track.getType() == TvTrackInfo.TYPE_VIDEO) {
                        mVideoTracks.add(track);
                    } else if (track.getType() == TvTrackInfo.TYPE_SUBTITLE) {
                        mSubtitleTracks.add(track);
                    }
                }
                return !mAudioTracks.isEmpty() || !mVideoTracks.isEmpty()
                        || !mSubtitleTracks.isEmpty();
            }
        }

        /**
         * Responds to onTrackSelected() and updates the internal track selection information.
         * Returns true if there is an update.
         */
        boolean updateTrackSelection(int type, String trackId) {
            synchronized (mTrackLock) {
                if (type == TvTrackInfo.TYPE_AUDIO && trackId != mSelectedAudioTrackId) {
                    mSelectedAudioTrackId = trackId;
                    return true;
                } else if (type == TvTrackInfo.TYPE_VIDEO && trackId != mSelectedVideoTrackId) {
                    mSelectedVideoTrackId = trackId;
                    return true;
                } else if (type == TvTrackInfo.TYPE_SUBTITLE
                        && trackId != mSelectedSubtitleTrackId) {
                    mSelectedSubtitleTrackId = trackId;
                    return true;
                }
            }
            return false;
        }

        /**
         * Returns the new/updated video track that contains new video size information. Returns
         * null if there is no video track to notify. Subsequent calls of this method results in a
         * non-null video track returned only by the first call and null returned by following
         * calls. The caller should immediately notify of the video size change upon receiving the
         * track.
         */
        TvTrackInfo getVideoTrackToNotify() {
            synchronized (mTrackLock) {
                if (!mVideoTracks.isEmpty() && mSelectedVideoTrackId != null) {
                    for (TvTrackInfo track : mVideoTracks) {
                        if (track.getId().equals(mSelectedVideoTrackId)) {
                            int videoWidth = track.getVideoWidth();
                            int videoHeight = track.getVideoHeight();
                            if (mVideoWidth != videoWidth || mVideoHeight != videoHeight) {
                                mVideoWidth = videoWidth;
                                mVideoHeight = videoHeight;
                                return track;
                            }
                        }
                    }
                }
            }
            return null;
        }

        /**
         * Calls {@link TvInputService.Session#appPrivateCommand(String, Bundle)
         * TvInputService.Session.appPrivateCommand()} on the current TvView.
+72 −48

File changed.

Preview size limit exceeded, changes collapsed.