/*
 * Copyright (C) 2014 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.tv;

import android.annotation.FloatRange;
import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.media.PlaybackParams;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputEventReceiver;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
import android.view.WindowManager;
import android.view.accessibility.CaptioningManager;
import android.widget.FrameLayout;

import com.android.internal.os.SomeArgs;
import com.android.internal.util.Preconditions;

import java.util.ArrayList;
import java.util.List;

/**
 * The TvInputService class represents a TV input or source such as HDMI or built-in tuner which
 * provides pass-through video or broadcast TV programs.
 *
 * <p>Applications will not normally use this service themselves, instead relying on the standard
 * interaction provided by {@link TvView}. Those implementing TV input services should normally do
 * so by deriving from this class and providing their own session implementation based on
 * {@link TvInputService.Session}. All TV input services must require that clients hold the
 * {@link android.Manifest.permission#BIND_TV_INPUT} in order to interact with the service; if this
 * permission is not specified in the manifest, the system will refuse to bind to that TV input
 * service.
 */
public abstract class TvInputService extends Service {
    private static final boolean DEBUG = false;
    private static final String TAG = "TvInputService";

    private static final int DETACH_OVERLAY_VIEW_TIMEOUT_MS = 5000;

    /**
     * This is the interface name that a service implementing a TV input should say that it support
     * -- that is, this is the action it uses for its intent filter. To be supported, the service
     * must also require the {@link android.Manifest.permission#BIND_TV_INPUT} permission so that
     * other applications cannot abuse it.
     */
    public static final String SERVICE_INTERFACE = "android.media.tv.TvInputService";

    /**
     * Name under which a TvInputService component publishes information about itself.
     * This meta-data must reference an XML resource containing an
     * <code>&lt;{@link android.R.styleable#TvInputService tv-input}&gt;</code>
     * tag.
     */
    public static final String SERVICE_META_DATA = "android.media.tv.input";

    /**
     * Handler instance to handle request from TV Input Manager Service. Should be run in the main
     * looper to be synchronously run with {@code Session.mHandler}.
     */
    private final Handler mServiceHandler = new ServiceHandler();
    private final RemoteCallbackList<ITvInputServiceCallback> mCallbacks =
            new RemoteCallbackList<>();

    private TvInputManager mTvInputManager;

    @Override
    public final IBinder onBind(Intent intent) {
        return new ITvInputService.Stub() {
            @Override
            public void registerCallback(ITvInputServiceCallback cb) {
                if (cb != null) {
                    mCallbacks.register(cb);
                }
            }

            @Override
            public void unregisterCallback(ITvInputServiceCallback cb) {
                if (cb != null) {
                    mCallbacks.unregister(cb);
                }
            }

            @Override
            public void createSession(InputChannel channel, ITvInputSessionCallback cb,
                    String inputId) {
                if (channel == null) {
                    Log.w(TAG, "Creating session without input channel");
                }
                if (cb == null) {
                    return;
                }
                SomeArgs args = SomeArgs.obtain();
                args.arg1 = channel;
                args.arg2 = cb;
                args.arg3 = inputId;
                mServiceHandler.obtainMessage(ServiceHandler.DO_CREATE_SESSION, args).sendToTarget();
            }

            @Override
            public void createRecordingSession(ITvInputSessionCallback cb, String inputId) {
                if (cb == null) {
                    return;
                }
                SomeArgs args = SomeArgs.obtain();
                args.arg1 = cb;
                args.arg2 = inputId;
                mServiceHandler.obtainMessage(ServiceHandler.DO_CREATE_RECORDING_SESSION, args)
                        .sendToTarget();
            }

            @Override
            public void notifyHardwareAdded(TvInputHardwareInfo hardwareInfo) {
                mServiceHandler.obtainMessage(ServiceHandler.DO_ADD_HARDWARE_INPUT,
                        hardwareInfo).sendToTarget();
            }

            @Override
            public void notifyHardwareRemoved(TvInputHardwareInfo hardwareInfo) {
                mServiceHandler.obtainMessage(ServiceHandler.DO_REMOVE_HARDWARE_INPUT,
                        hardwareInfo).sendToTarget();
            }

            @Override
            public void notifyHdmiDeviceAdded(HdmiDeviceInfo deviceInfo) {
                mServiceHandler.obtainMessage(ServiceHandler.DO_ADD_HDMI_INPUT,
                        deviceInfo).sendToTarget();
            }

            @Override
            public void notifyHdmiDeviceRemoved(HdmiDeviceInfo deviceInfo) {
                mServiceHandler.obtainMessage(ServiceHandler.DO_REMOVE_HDMI_INPUT,
                        deviceInfo).sendToTarget();
            }
        };
    }

    /**
     * Returns a concrete implementation of {@link Session}.
     *
     * <p>May return {@code null} if this TV input service fails to create a session for some
     * reason. If TV input represents an external device connected to a hardware TV input,
     * {@link HardwareSession} should be returned.
     *
     * @param inputId The ID of the TV input associated with the session.
     */
    @Nullable
    public abstract Session onCreateSession(String inputId);

    /**
     * Returns a concrete implementation of {@link RecordingSession}.
     *
     * <p>May return {@code null} if this TV input service fails to create a recording session for
     * some reason.
     *
     * @param inputId The ID of the TV input associated with the recording session.
     */
    @Nullable
    public RecordingSession onCreateRecordingSession(String inputId) {
        return null;
    }

    /**
     * Returns a new {@link TvInputInfo} object if this service is responsible for
     * {@code hardwareInfo}; otherwise, return {@code null}. Override to modify default behavior of
     * ignoring all hardware input.
     *
     * @param hardwareInfo {@link TvInputHardwareInfo} object just added.
     * @hide
     */
    @Nullable
    @SystemApi
    public TvInputInfo onHardwareAdded(TvInputHardwareInfo hardwareInfo) {
        return null;
    }

    /**
     * Returns the input ID for {@code deviceId} if it is handled by this service;
     * otherwise, return {@code null}. Override to modify default behavior of ignoring all hardware
     * input.
     *
     * @param hardwareInfo {@link TvInputHardwareInfo} object just removed.
     * @hide
     */
    @Nullable
    @SystemApi
    public String onHardwareRemoved(TvInputHardwareInfo hardwareInfo) {
        return null;
    }

    /**
     * Returns a new {@link TvInputInfo} object if this service is responsible for
     * {@code deviceInfo}; otherwise, return {@code null}. Override to modify default behavior of
     * ignoring all HDMI logical input device.
     *
     * @param deviceInfo {@link HdmiDeviceInfo} object just added.
     * @hide
     */
    @Nullable
    @SystemApi
    public TvInputInfo onHdmiDeviceAdded(HdmiDeviceInfo deviceInfo) {
        return null;
    }

    /**
     * Returns the input ID for {@code deviceInfo} if it is handled by this service; otherwise,
     * return {@code null}. Override to modify default behavior of ignoring all HDMI logical input
     * device.
     *
     * @param deviceInfo {@link HdmiDeviceInfo} object just removed.
     * @hide
     */
    @Nullable
    @SystemApi
    public String onHdmiDeviceRemoved(HdmiDeviceInfo deviceInfo) {
        return null;
    }

    private boolean isPassthroughInput(String inputId) {
        if (mTvInputManager == null) {
            mTvInputManager = (TvInputManager) getSystemService(Context.TV_INPUT_SERVICE);
        }
        TvInputInfo info = mTvInputManager.getTvInputInfo(inputId);
        return info != null && info.isPassthroughInput();
    }

    /**
     * Base class for derived classes to implement to provide a TV input session.
     */
    public abstract static class Session implements KeyEvent.Callback {
        private static final int POSITION_UPDATE_INTERVAL_MS = 1000;

        private final KeyEvent.DispatcherState mDispatcherState = new KeyEvent.DispatcherState();
        private final WindowManager mWindowManager;
        final Handler mHandler;
        private WindowManager.LayoutParams mWindowParams;
        private Surface mSurface;
        private final Context mContext;
        private FrameLayout mOverlayViewContainer;
        private View mOverlayView;
        private OverlayViewCleanUpTask mOverlayViewCleanUpTask;
        private boolean mOverlayViewEnabled;
        private IBinder mWindowToken;
        @UnsupportedAppUsage
        private Rect mOverlayFrame;
        private long mStartPositionMs = TvInputManager.TIME_SHIFT_INVALID_TIME;
        private long mCurrentPositionMs = TvInputManager.TIME_SHIFT_INVALID_TIME;
        private final TimeShiftPositionTrackingRunnable
                mTimeShiftPositionTrackingRunnable = new TimeShiftPositionTrackingRunnable();

        private final Object mLock = new Object();
        // @GuardedBy("mLock")
        private ITvInputSessionCallback mSessionCallback;
        // @GuardedBy("mLock")
        private final List<Runnable> mPendingActions = new ArrayList<>();

        /**
         * Creates a new Session.
         *
         * @param context The context of the application
         */
        public Session(Context context) {
            mContext = context;
            mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            mHandler = new Handler(context.getMainLooper());
        }

        /**
         * Enables or disables the overlay view.
         *
         * <p>By default, the overlay view is disabled. Must be called explicitly after the
         * session is created to enable the overlay view.
         *
         * <p>The TV input service can disable its overlay view when the size of the overlay view is
         * insufficient to display the whole information, such as when used in Picture-in-picture.
         * Override {@link #onOverlayViewSizeChanged} to get the size of the overlay view, which
         * then can be used to determine whether to enable/disable the overlay view.
         *
         * @param enable {@code true} if you want to enable the overlay view. {@code false}
         *            otherwise.
         */
        public void setOverlayViewEnabled(final boolean enable) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (enable == mOverlayViewEnabled) {
                        return;
                    }
                    mOverlayViewEnabled = enable;
                    if (enable) {
                        if (mWindowToken != null) {
                            createOverlayView(mWindowToken, mOverlayFrame);
                        }
                    } else {
                        removeOverlayView(false);
                    }
                }
            });
        }

        /**
         * Dispatches an event to the application using this session.
         *
         * @param eventType The type of the event.
         * @param eventArgs Optional arguments of the event.
         * @hide
         */
        @SystemApi
        public void notifySessionEvent(@NonNull final String eventType, final Bundle eventArgs) {
            Preconditions.checkNotNull(eventType);
            executeOrPostRunnableOnMainThread(new Runnable() {
                @Override
                public void run() {
                    try {
                        if (DEBUG) Log.d(TAG, "notifySessionEvent(" + eventType + ")");
                        if (mSessionCallback != null) {
                            mSessionCallback.onSessionEvent(eventType, eventArgs);
                        }
                    } catch (RemoteException e) {
                        Log.w(TAG, "error in sending event (event=" + eventType + ")", e);
                    }
                }
            });
        }

        /**
         * Informs the application that the current channel is re-tuned for some reason and the
         * session now displays the content from a new channel. This is used to handle special cases
         * such as when the current channel becomes unavailable, it is necessary to send the user to
         * a certain channel or the user changes channel in some other way (e.g. by using a
         * dedicated remote).
         *
         * @param channelUri The URI of the new channel.
         */
        public void notifyChannelRetuned(final Uri channelUri) {
            executeOrPostRunnableOnMainThread(new Runnable() {
                @MainThread
                @Override
                public void run() {
                    try {
                        if (DEBUG) Log.d(TAG, "notifyChannelRetuned");
                        if (mSessionCallback != null) {
                            mSessionCallback.onChannelRetuned(channelUri);
                        }
                    } catch (RemoteException e) {
                        Log.w(TAG, "error in notifyChannelRetuned", e);
                    }
                }
            });
        }

        /**
         * Sends the list of all audio/video/subtitle tracks. The is used by the framework to
         * maintain the track information for a given session, which in turn is used by
         * {@link TvView#getTracks} for the application to retrieve metadata for a given track type.
         * The TV input service must call this method as soon as the track information becomes
         * available or is updated. Note that in a case where a part of the information for a
         * certain track is updated, it is not necessary to create a new {@link TvTrackInfo} object
         * with a different track ID.
         *
         * @param tracks A list which includes track information.
         */
        public void notifyTracksChanged(final List<TvTrackInfo> tracks) {
            final List<TvTrackInfo> tracksCopy = new ArrayList<>(tracks);
            executeOrPostRunnableOnMainThread(new Runnable() {
                @MainThread
                @Override
                public void run() {
                    try {
                        if (DEBUG) Log.d(TAG, "notifyTracksChanged");
                        if (mSessionCallback != null) {
                            mSessionCallback.onTracksChanged(tracksCopy);
                        }
                    } catch (RemoteException e) {
                        Log.w(TAG, "error in notifyTracksChanged", e);
                    }
                }
            });
        }

        /**
         * Sends the type and ID of a selected track. This is used to inform the application that a
         * specific track is selected. The TV input service must call this method as soon as a track
         * is selected either by default or in response to a call to {@link #onSelectTrack}. The
         * selected track ID for a given type is maintained in the framework until the next call to
         * this method even after the entire track list is updated (but is reset when the session is
         * tuned to a new channel), so care must be taken not to result in an obsolete track ID.
         *
         * @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}.
         * @param trackId The ID of the selected track.
         * @see #onSelectTrack
         */
        public void notifyTrackSelected(final int type, final String trackId) {
            executeOrPostRunnableOnMainThread(new Runnable() {
                @MainThread
                @Override
                public void run() {
                    try {
                        if (DEBUG) Log.d(TAG, "notifyTrackSelected");
                        if (mSessionCallback != null) {
                            mSessionCallback.onTrackSelected(type, trackId);
                        }
                    } catch (RemoteException e) {
                        Log.w(TAG, "error in notifyTrackSelected", e);
                    }
                }
            });
        }

        /**
         * Informs the application that the video is now available for watching. Video is blocked
         * until this method is called.
         *
         * <p>The TV input service must call this method as soon as the content rendered onto its
         * surface is ready for viewing. This method must be called each time {@link #onTune}
         * is called.
         *
         * @see #notifyVideoUnavailable
         */
        public void notifyVideoAvailable() {
            executeOrPostRunnableOnMainThread(new Runnable() {
                @MainThread
                @Override
                public void run() {
                    try {
                        if (DEBUG) Log.d(TAG, "notifyVideoAvailable");
                        if (mSessionCallback != null) {
                            mSessionCallback.onVideoAvailable();
                        }
                    } catch (RemoteException e) {
                        Log.w(TAG, "error in notifyVideoAvailable", e);
                    }
                }
            });
        }

        /**
         * Informs the application that the video became unavailable for some reason. This is
         * primarily used to signal the application to block the screen not to show any intermittent
         * video artifacts.
         *
         * @param reason The reason why the video became unavailable:
         *            <ul>
         *            <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_UNKNOWN}
         *            <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_TUNING}
         *            <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL}
         *            <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_BUFFERING}
         *            <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY}
         *            </ul>
         * @see #notifyVideoAvailable
         */
        public void notifyVideoUnavailable(
                @TvInputManager.VideoUnavailableReason final int reason) {
            if (reason < TvInputManager.VIDEO_UNAVAILABLE_REASON_START
                    || reason > TvInputManager.VIDEO_UNAVAILABLE_REASON_END) {
                Log.e(TAG, "notifyVideoUnavailable - unknown reason: " + reason);
            }
            executeOrPostRunnableOnMainThread(new Runnable() {
                @MainThread
                @Override
                public void run() {
                    try {
                        if (DEBUG) Log.d(TAG, "notifyVideoUnavailable");
                        if (mSessionCallback != null) {
                            mSessionCallback.onVideoUnavailable(reason);
                        }
                    } catch (RemoteException e) {
                        Log.w(TAG, "error in notifyVideoUnavailable", e);
                    }
                }
            });
        }

        /**
         * Informs the application that the user is allowed to watch the current program content.
         *
         * <p>Each TV input service is required to query the system whether the user is allowed to
         * watch the current program before showing it to the user if the parental controls is
         * enabled (i.e. {@link TvInputManager#isParentalControlsEnabled
         * TvInputManager.isParentalControlsEnabled()} returns {@code true}). Whether the TV input
         * service should block the content or not is determined by invoking
         * {@link TvInputManager#isRatingBlocked TvInputManager.isRatingBlocked(TvContentRating)}
         * with the content rating for the current program. Then the {@link TvInputManager} makes a
         * judgment based on the user blocked ratings stored in the secure settings and returns the
         * result. If the rating in question turns out to be allowed by the user, the TV input
         * service must call this method to notify the application that is permitted to show the
         * content.
         *
         * <p>Each TV input service also needs to continuously listen to any changes made to the
         * parental controls settings by registering a broadcast receiver to receive
         * {@link TvInputManager#ACTION_BLOCKED_RATINGS_CHANGED} and
         * {@link TvInputManager#ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED} and immediately
         * reevaluate the current program with the new parental controls settings.
         *
         * @see #notifyContentBlocked
         * @see TvInputManager
         */
        public void notifyContentAllowed() {
            executeOrPostRunnableOnMainThread(new Runnable() {
                @MainThread
                @Override
                public void run() {
                    try {
                        if (DEBUG) Log.d(TAG, "notifyContentAllowed");
                        if (mSessionCallback != null) {
                            mSessionCallback.onContentAllowed();
                        }
                    } catch (RemoteException e) {
                        Log.w(TAG, "error in notifyContentAllowed", e);
                    }
                }
            });
        }

        /**
         * Informs the application that the current program content is blocked by parent controls.
         *
         * <p>Each TV input service is required to query the system whether the user is allowed to
         * watch the current program before showing it to the user if the parental controls is
         * enabled (i.e. {@link TvInputManager#isParentalControlsEnabled
         * TvInputManager.isParentalControlsEnabled()} returns {@code true}). Whether the TV input
         * service should block the content or not is determined by invoking
         * {@link TvInputManager#isRatingBlocked TvInputManager.isRatingBlocked(TvContentRating)}
         * with the content rating for the current program or {@link TvContentRating#UNRATED} in
         * case the rating information is missing. Then the {@link TvInputManager} makes a judgment
         * based on the user blocked ratings stored in the secure settings and returns the result.
         * If the rating in question turns out to be blocked, the TV input service must immediately
         * block the content and call this method with the content rating of the current program to
         * prompt the PIN verification screen.
         *
         * <p>Each TV input service also needs to continuously listen to any changes made to the
         * parental controls settings by registering a broadcast receiver to receive
         * {@link TvInputManager#ACTION_BLOCKED_RATINGS_CHANGED} and
         * {@link TvInputManager#ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED} and immediately
         * reevaluate the current program with the new parental controls settings.
         *
         * @param rating The content rating for the current TV program. Can be
         *            {@link TvContentRating#UNRATED}.
         * @see #notifyContentAllowed
         * @see TvInputManager
         */
        public void notifyContentBlocked(@NonNull final TvContentRating rating) {
            Preconditions.checkNotNull(rating);
            executeOrPostRunnableOnMainThread(new Runnable() {
                @MainThread
                @Override
                public void run() {
                    try {
                        if (DEBUG) Log.d(TAG, "notifyContentBlocked");
                        if (mSessionCallback != null) {
                            mSessionCallback.onContentBlocked(rating.flattenToString());
                        }
                    } catch (RemoteException e) {
                        Log.w(TAG, "error in notifyContentBlocked", e);
                    }
                }
            });
        }

        /**
         * Informs the application that the time shift status is changed.
         *
         * <p>Prior to calling this method, the application assumes the status
         * {@link TvInputManager#TIME_SHIFT_STATUS_UNKNOWN}. Right after the session is created, it
         * is important to invoke the method with the status
         * {@link TvInputManager#TIME_SHIFT_STATUS_AVAILABLE} if the implementation does support
         * time shifting, or {@link TvInputManager#TIME_SHIFT_STATUS_UNSUPPORTED} otherwise. Failure
         * to notifying the current status change immediately might result in an undesirable
         * behavior in the application such as hiding the play controls.
         *
         * <p>If the status {@link TvInputManager#TIME_SHIFT_STATUS_AVAILABLE} is reported, the
         * application assumes it can pause/resume playback, seek to a specified time position and
         * set playback rate and audio mode. The implementation should override
         * {@link #onTimeShiftPause}, {@link #onTimeShiftResume}, {@link #onTimeShiftSeekTo},
         * {@link #onTimeShiftGetStartPosition}, {@link #onTimeShiftGetCurrentPosition} and
         * {@link #onTimeShiftSetPlaybackParams}.
         *
         * @param status The current time shift status. Should be one of the followings.
         * <ul>
         * <li>{@link TvInputManager#TIME_SHIFT_STATUS_UNSUPPORTED}
         * <li>{@link TvInputManager#TIME_SHIFT_STATUS_UNAVAILABLE}
         * <li>{@link TvInputManager#TIME_SHIFT_STATUS_AVAILABLE}
         * </ul>
         */
        public void notifyTimeShiftStatusChanged(@TvInputManager.TimeShiftStatus final int status) {
            executeOrPostRunnableOnMainThread(new Runnable() {
                @MainThread
                @Override
                public void run() {
                    timeShiftEnablePositionTracking(
                            status == TvInputManager.TIME_SHIFT_STATUS_AVAILABLE);
                    try {
                        if (DEBUG) Log.d(TAG, "notifyTimeShiftStatusChanged");
                        if (mSessionCallback != null) {
                            mSessionCallback.onTimeShiftStatusChanged(status);
                        }
                    } catch (RemoteException e) {
                        Log.w(TAG, "error in notifyTimeShiftStatusChanged", e);
                    }
                }
            });
        }

        private void notifyTimeShiftStartPositionChanged(final long timeMs) {
            executeOrPostRunnableOnMainThread(new Runnable() {
                @MainThread
                @Override
                public void run() {
                    try {
                        if (DEBUG) Log.d(TAG, "notifyTimeShiftStartPositionChanged");
                        if (mSessionCallback != null) {
                            mSessionCallback.onTimeShiftStartPositionChanged(timeMs);
                        }
                    } catch (RemoteException e) {
                        Log.w(TAG, "error in notifyTimeShiftStartPositionChanged", e);
                    }
                }
            });
        }

        private void notifyTimeShiftCurrentPositionChanged(final long timeMs) {
            executeOrPostRunnableOnMainThread(new Runnable() {
                @MainThread
                @Override
                public void run() {
                    try {
                        if (DEBUG) Log.d(TAG, "notifyTimeShiftCurrentPositionChanged");
                        if (mSessionCallback != null) {
                            mSessionCallback.onTimeShiftCurrentPositionChanged(timeMs);
                        }
                    } catch (RemoteException e) {
                        Log.w(TAG, "error in notifyTimeShiftCurrentPositionChanged", e);
                    }
                }
            });
        }

        /**
         * Assigns a size and position to the surface passed in {@link #onSetSurface}. The position
         * is relative to the overlay view that sits on top of this surface.
         *
         * @param left Left position in pixels, relative to the overlay view.
         * @param top Top position in pixels, relative to the overlay view.
         * @param right Right position in pixels, relative to the overlay view.
         * @param bottom Bottom position in pixels, relative to the overlay view.
         * @see #onOverlayViewSizeChanged
         */
        public void layoutSurface(final int left, final int top, final int right,
                final int bottom) {
            if (left > right || top > bottom) {
                throw new IllegalArgumentException("Invalid parameter");
            }
            executeOrPostRunnableOnMainThread(new Runnable() {
                @MainThread
                @Override
                public void run() {
                    try {
                        if (DEBUG) Log.d(TAG, "layoutSurface (l=" + left + ", t=" + top + ", r="
                                + right + ", b=" + bottom + ",)");
                        if (mSessionCallback != null) {
                            mSessionCallback.onLayoutSurface(left, top, right, bottom);
                        }
                    } catch (RemoteException e) {
                        Log.w(TAG, "error in layoutSurface", e);
                    }
                }
            });
        }

        /**
         * Called when the session is released.
         */
        public abstract void onRelease();

        /**
         * Sets the current session as the main session. The main session is a session whose
         * corresponding TV input determines the HDMI-CEC active source device.
         *
         * <p>TV input service that manages HDMI-CEC logical device should implement {@link
         * #onSetMain} to (1) select the corresponding HDMI logical device as the source device
         * when {@code isMain} is {@code true}, and to (2) select the internal device (= TV itself)
         * as the source device when {@code isMain} is {@code false} and the session is still main.
         * Also, if a surface is passed to a non-main session and active source is changed to
         * initiate the surface, the active source should be returned to the main session.
         *
         * <p>{@link TvView} guarantees that, when tuning involves a session transition, {@code
         * onSetMain(true)} for new session is called first, {@code onSetMain(false)} for old
         * session is called afterwards. This allows {@code onSetMain(false)} to be no-op when TV
         * input service knows that the next main session corresponds to another HDMI logical
         * device. Practically, this implies that one TV input service should handle all HDMI port
         * and HDMI-CEC logical devices for smooth active source transition.
         *
         * @param isMain If true, session should become main.
         * @see TvView#setMain
         * @hide
         */
        @SystemApi
        public void onSetMain(boolean isMain) {
        }

        /**
         * Called when the application sets the surface.
         *
         * <p>The TV input service should render video onto the given surface. When called with
         * {@code null}, the input service should immediately free any references to the
         * currently set surface and stop using it.
         *
         * @param surface The surface to be used for video rendering. Can be {@code null}.
         * @return {@code true} if the surface was set successfully, {@code false} otherwise.
         */
        public abstract boolean onSetSurface(@Nullable Surface surface);

        /**
         * Called after any structural changes (format or size) have been made to the surface passed
         * in {@link #onSetSurface}. This method is always called at least once, after
         * {@link #onSetSurface} is called with non-null surface.
         *
         * @param format The new PixelFormat of the surface.
         * @param width The new width of the surface.
         * @param height The new height of the surface.
         */
        public void onSurfaceChanged(int format, int width, int height) {
        }

        /**
         * Called when the size of the overlay view is changed by the application.
         *
         * <p>This is always called at least once when the session is created regardless of whether
         * the overlay view is enabled or not. The overlay view size is the same as the containing
         * {@link TvView}. Note that the size of the underlying surface can be different if the
         * surface was changed by calling {@link #layoutSurface}.
         *
         * @param width The width of the overlay view.
         * @param height The height of the overlay view.
         */
        public void onOverlayViewSizeChanged(int width, int height) {
        }

        /**
         * Sets the relative stream volume of the current TV input session.
         *
         * <p>The implementation should honor this request in order to handle audio focus changes or
         * mute the current session when multiple sessions, possibly from different inputs are
         * active. If the method has not yet been called, the implementation should assume the
         * default value of {@code 1.0f}.
         *
         * @param volume A volume value between {@code 0.0f} to {@code 1.0f}.
         */
        public abstract void onSetStreamVolume(@FloatRange(from = 0.0, to = 1.0) float volume);

        /**
         * Tunes to a given channel.
         *
         * <p>No video will be displayed until {@link #notifyVideoAvailable()} is called.
         * Also, {@link #notifyVideoUnavailable(int)} should be called when the TV input cannot
         * continue playing the given channel.
         *
         * @param channelUri The URI of the channel.
         * @return {@code true} if the tuning was successful, {@code false} otherwise.
         */
        public abstract boolean onTune(Uri channelUri);

        /**
         * Tunes to a given channel. Override this method in order to handle domain-specific
         * features that are only known between certain TV inputs and their clients.
         *
         * <p>The default implementation calls {@link #onTune(Uri)}.
         *
         * @param channelUri The URI of the channel.
         * @param params Domain-specific data for this tune request. Keys <em>must</em> be a scoped
         *            name, i.e. prefixed with a package name you own, so that different developers
         *            will not create conflicting keys.
         * @return {@code true} if the tuning was successful, {@code false} otherwise.
         */
        public boolean onTune(Uri channelUri, Bundle params) {
            return onTune(channelUri);
        }

        /**
         * Enables or disables the caption.
         *
         * <p>The locale for the user's preferred captioning language can be obtained by calling
         * {@link CaptioningManager#getLocale CaptioningManager.getLocale()}.
         *
         * @param enabled {@code true} to enable, {@code false} to disable.
         * @see CaptioningManager
         */
        public abstract void onSetCaptionEnabled(boolean enabled);

        /**
         * Requests to unblock the content according to the given rating.
         *
         * <p>The implementation should unblock the content.
         * TV input service has responsibility to decide when/how the unblock expires
         * while it can keep previously unblocked ratings in order not to ask a user
         * to unblock whenever a content rating is changed.
         * Therefore an unblocked rating can be valid for a channel, a program,
         * or certain amount of time depending on the implementation.
         *
         * @param unblockedRating An unblocked content rating
         */
        public void onUnblockContent(TvContentRating unblockedRating) {
        }

        /**
         * Selects a given track.
         *
         * <p>If this is done successfully, the implementation should call
         * {@link #notifyTrackSelected} to help applications maintain the up-to-date list of the
         * selected tracks.
         *
         * @param trackId The ID of the track to select. {@code null} means to unselect the current
         *            track for a given type.
         * @param type The type of the track to select. The type can be
         *            {@link TvTrackInfo#TYPE_AUDIO}, {@link TvTrackInfo#TYPE_VIDEO} or
         *            {@link TvTrackInfo#TYPE_SUBTITLE}.
         * @return {@code true} if the track selection was successful, {@code false} otherwise.
         * @see #notifyTrackSelected
         */
        public boolean onSelectTrack(int type, @Nullable String trackId) {
            return false;
        }

        /**
         * Processes a private command sent from the application to the TV input. This can be used
         * to provide domain-specific features that are only known between certain TV inputs and
         * their clients.
         *
         * @param action Name of the command to be performed. This <em>must</em> be a scoped name,
         *            i.e. prefixed with a package name you own, so that different developers will
         *            not create conflicting commands.
         * @param data Any data to include with the command.
         */
        public void onAppPrivateCommand(@NonNull String action, Bundle data) {
        }

        /**
         * Called when the application requests to create an overlay view. Each session
         * implementation can override this method and return its own view.
         *
         * @return a view attached to the overlay window
         */
        public View onCreateOverlayView() {
            return null;
        }

        /**
         * Called when the application requests to play a given recorded TV program.
         *
         * @param recordedProgramUri The URI of a recorded TV program.
         * @see #onTimeShiftResume()
         * @see #onTimeShiftPause()
         * @see #onTimeShiftSeekTo(long)
         * @see #onTimeShiftSetPlaybackParams(PlaybackParams)
         * @see #onTimeShiftGetStartPosition()
         * @see #onTimeShiftGetCurrentPosition()
         */
        public void onTimeShiftPlay(Uri recordedProgramUri) {
        }

        /**
         * Called when the application requests to pause playback.
         *
         * @see #onTimeShiftPlay(Uri)
         * @see #onTimeShiftResume()
         * @see #onTimeShiftSeekTo(long)
         * @see #onTimeShiftSetPlaybackParams(PlaybackParams)
         * @see #onTimeShiftGetStartPosition()
         * @see #onTimeShiftGetCurrentPosition()
         */
        public void onTimeShiftPause() {
        }

        /**
         * Called when the application requests to resume playback.
         *
         * @see #onTimeShiftPlay(Uri)
         * @see #onTimeShiftPause()
         * @see #onTimeShiftSeekTo(long)
         * @see #onTimeShiftSetPlaybackParams(PlaybackParams)
         * @see #onTimeShiftGetStartPosition()
         * @see #onTimeShiftGetCurrentPosition()
         */
        public void onTimeShiftResume() {
        }

        /**
         * Called when the application requests to seek to a specified time position. Normally, the
         * position is given within range between the start and the current time, inclusively. The
         * implementation is expected to seek to the nearest time position if the given position is
         * not in the range.
         *
         * @param timeMs The time position to seek to, in milliseconds since the epoch.
         * @see #onTimeShiftPlay(Uri)
         * @see #onTimeShiftResume()
         * @see #onTimeShiftPause()
         * @see #onTimeShiftSetPlaybackParams(PlaybackParams)
         * @see #onTimeShiftGetStartPosition()
         * @see #onTimeShiftGetCurrentPosition()
         */
        public void onTimeShiftSeekTo(long timeMs) {
        }

        /**
         * Called when the application sets playback parameters containing the speed and audio mode.
         *
         * <p>Once the playback parameters are set, the implementation should honor the current
         * settings until the next tune request. Pause/resume/seek request does not reset the
         * parameters previously set.
         *
         * @param params The playback params.
         * @see #onTimeShiftPlay(Uri)
         * @see #onTimeShiftResume()
         * @see #onTimeShiftPause()
         * @see #onTimeShiftSeekTo(long)
         * @see #onTimeShiftGetStartPosition()
         * @see #onTimeShiftGetCurrentPosition()
         */
        public void onTimeShiftSetPlaybackParams(PlaybackParams params) {
        }

        /**
         * Returns the start position for time shifting, in milliseconds since the epoch.
         * Returns {@link TvInputManager#TIME_SHIFT_INVALID_TIME} if the position is unknown at the
         * moment.
         *
         * <p>The start position for time shifting indicates the earliest possible time the user can
         * seek to. Initially this is equivalent to the time when the implementation starts
         * recording. Later it may be adjusted because there is insufficient space or the duration
         * of recording is limited by the implementation. The application does not allow the user to
         * seek to a position earlier than the start position.
         *
         * <p>For playback of a recorded program initiated by {@link #onTimeShiftPlay(Uri)}, the
         * start position should be 0 and does not change.
         *
         * @see #onTimeShiftPlay(Uri)
         * @see #onTimeShiftResume()
         * @see #onTimeShiftPause()
         * @see #onTimeShiftSeekTo(long)
         * @see #onTimeShiftSetPlaybackParams(PlaybackParams)
         * @see #onTimeShiftGetCurrentPosition()
         */
        public long onTimeShiftGetStartPosition() {
            return TvInputManager.TIME_SHIFT_INVALID_TIME;
        }

        /**
         * Returns the current position for time shifting, in milliseconds since the epoch.
         * Returns {@link TvInputManager#TIME_SHIFT_INVALID_TIME} if the position is unknown at the
         * moment.
         *
         * <p>The current position for time shifting is the same as the current position of
         * playback. It should be equal to or greater than the start position reported by
         * {@link #onTimeShiftGetStartPosition()}. When playback is completed, the current position
         * should stay where the playback ends, in other words, the returned value of this mehtod
         * should be equal to the start position plus the duration of the program.
         *
         * @see #onTimeShiftPlay(Uri)
         * @see #onTimeShiftResume()
         * @see #onTimeShiftPause()
         * @see #onTimeShiftSeekTo(long)
         * @see #onTimeShiftSetPlaybackParams(PlaybackParams)
         * @see #onTimeShiftGetStartPosition()
         */
        public long onTimeShiftGetCurrentPosition() {
            return TvInputManager.TIME_SHIFT_INVALID_TIME;
        }

        /**
         * Default implementation of {@link android.view.KeyEvent.Callback#onKeyDown(int, KeyEvent)
         * KeyEvent.Callback.onKeyDown()}: always returns false (doesn't handle the event).
         *
         * <p>Override this to intercept key down events before they are processed by the
         * application. If you return true, the application will not process the event itself. If
         * you return false, the normal application processing will occur as if the TV input had not
         * seen the event at all.
         *
         * @param keyCode The value in event.getKeyCode().
         * @param event Description of the key event.
         * @return If you handled the event, return {@code true}. If you want to allow the event to
         *         be handled by the next receiver, return {@code false}.
         */
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            return false;
        }

        /**
         * Default implementation of
         * {@link android.view.KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
         * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle the event).
         *
         * <p>Override this to intercept key long press events before they are processed by the
         * application. If you return true, the application will not process the event itself. If
         * you return false, the normal application processing will occur as if the TV input had not
         * seen the event at all.
         *
         * @param keyCode The value in event.getKeyCode().
         * @param event Description of the key event.
         * @return If you handled the event, return {@code true}. If you want to allow the event to
         *         be handled by the next receiver, return {@code false}.
         */
        @Override
        public boolean onKeyLongPress(int keyCode, KeyEvent event) {
            return false;
        }

        /**
         * Default implementation of
         * {@link android.view.KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
         * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle the event).
         *
         * <p>Override this to intercept special key multiple events before they are processed by
         * the application. If you return true, the application will not itself process the event.
         * If you return false, the normal application processing will occur as if the TV input had
         * not seen the event at all.
         *
         * @param keyCode The value in event.getKeyCode().
         * @param count The number of times the action was made.
         * @param event Description of the key event.
         * @return If you handled the event, return {@code true}. If you want to allow the event to
         *         be handled by the next receiver, return {@code false}.
         */
        @Override
        public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) {
            return false;
        }

        /**
         * Default implementation of {@link android.view.KeyEvent.Callback#onKeyUp(int, KeyEvent)
         * KeyEvent.Callback.onKeyUp()}: always returns false (doesn't handle the event).
         *
         * <p>Override this to intercept key up events before they are processed by the application.
         * If you return true, the application will not itself process the event. If you return false,
         * the normal application processing will occur as if the TV input had not seen the event at
         * all.
         *
         * @param keyCode The value in event.getKeyCode().
         * @param event Description of the key event.
         * @return If you handled the event, return {@code true}. If you want to allow the event to
         *         be handled by the next receiver, return {@code false}.
         */
        @Override
        public boolean onKeyUp(int keyCode, KeyEvent event) {
            return false;
        }

        /**
         * Implement this method to handle touch screen motion events on the current input session.
         *
         * @param event The motion event being received.
         * @return If you handled the event, return {@code true}. If you want to allow the event to
         *         be handled by the next receiver, return {@code false}.
         * @see View#onTouchEvent
         */
        public boolean onTouchEvent(MotionEvent event) {
            return false;
        }

        /**
         * Implement this method to handle trackball events on the current input session.
         *
         * @param event The motion event being received.
         * @return If you handled the event, return {@code true}. If you want to allow the event to
         *         be handled by the next receiver, return {@code false}.
         * @see View#onTrackballEvent
         */
        public boolean onTrackballEvent(MotionEvent event) {
            return false;
        }

        /**
         * Implement this method to handle generic motion events on the current input session.
         *
         * @param event The motion event being received.
         * @return If you handled the event, return {@code true}. If you want to allow the event to
         *         be handled by the next receiver, return {@code false}.
         * @see View#onGenericMotionEvent
         */
        public boolean onGenericMotionEvent(MotionEvent event) {
            return false;
        }

        /**
         * This method is called when the application would like to stop using the current input
         * session.
         */
        void release() {
            onRelease();
            if (mSurface != null) {
                mSurface.release();
                mSurface = null;
            }
            synchronized(mLock) {
                mSessionCallback = null;
                mPendingActions.clear();
            }
            // Removes the overlay view lastly so that any hanging on the main thread can be handled
            // in {@link #scheduleOverlayViewCleanup}.
            removeOverlayView(true);
            mHandler.removeCallbacks(mTimeShiftPositionTrackingRunnable);
        }

        /**
         * Calls {@link #onSetMain}.
         */
        void setMain(boolean isMain) {
            onSetMain(isMain);
        }

        /**
         * Calls {@link #onSetSurface}.
         */
        void setSurface(Surface surface) {
            onSetSurface(surface);
            if (mSurface != null) {
                mSurface.release();
            }
            mSurface = surface;
            // TODO: Handle failure.
        }

        /**
         * Calls {@link #onSurfaceChanged}.
         */
        void dispatchSurfaceChanged(int format, int width, int height) {
            if (DEBUG) {
                Log.d(TAG, "dispatchSurfaceChanged(format=" + format + ", width=" + width
                        + ", height=" + height + ")");
            }
            onSurfaceChanged(format, width, height);
        }

        /**
         * Calls {@link #onSetStreamVolume}.
         */
        void setStreamVolume(float volume) {
            onSetStreamVolume(volume);
        }

        /**
         * Calls {@link #onTune(Uri, Bundle)}.
         */
        void tune(Uri channelUri, Bundle params) {
            mCurrentPositionMs = TvInputManager.TIME_SHIFT_INVALID_TIME;
            onTune(channelUri, params);
            // TODO: Handle failure.
        }

        /**
         * Calls {@link #onSetCaptionEnabled}.
         */
        void setCaptionEnabled(boolean enabled) {
            onSetCaptionEnabled(enabled);
        }

        /**
         * Calls {@link #onSelectTrack}.
         */
        void selectTrack(int type, String trackId) {
            onSelectTrack(type, trackId);
        }

        /**
         * Calls {@link #onUnblockContent}.
         */
        void unblockContent(String unblockedRating) {
            onUnblockContent(TvContentRating.unflattenFromString(unblockedRating));
            // TODO: Handle failure.
        }

        /**
         * Calls {@link #onAppPrivateCommand}.
         */
        void appPrivateCommand(String action, Bundle data) {
            onAppPrivateCommand(action, data);
        }

        /**
         * Creates an overlay view. This calls {@link #onCreateOverlayView} to get a view to attach
         * to the overlay window.
         *
         * @param windowToken A window token of the application.
         * @param frame A position of the overlay view.
         */
        void createOverlayView(IBinder windowToken, Rect frame) {
            if (mOverlayViewContainer != null) {
                removeOverlayView(false);
            }
            if (DEBUG) Log.d(TAG, "create overlay view(" + frame + ")");
            mWindowToken = windowToken;
            mOverlayFrame = frame;
            onOverlayViewSizeChanged(frame.right - frame.left, frame.bottom - frame.top);
            if (!mOverlayViewEnabled) {
                return;
            }
            mOverlayView = onCreateOverlayView();
            if (mOverlayView == null) {
                return;
            }
            if (mOverlayViewCleanUpTask != null) {
                mOverlayViewCleanUpTask.cancel(true);
                mOverlayViewCleanUpTask = null;
            }
            // Creates a container view to check hanging on the overlay view detaching.
            // Adding/removing the overlay view to/from the container make the view attach/detach
            // logic run on the main thread.
            mOverlayViewContainer = new FrameLayout(mContext.getApplicationContext());
            mOverlayViewContainer.addView(mOverlayView);
            // TvView's window type is TYPE_APPLICATION_MEDIA and we want to create
            // an overlay window above the media window but below the application window.
            int type = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
            // We make the overlay view non-focusable and non-touchable so that
            // the application that owns the window token can decide whether to consume or
            // dispatch the input events.
            int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                    | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
            if (ActivityManager.isHighEndGfx()) {
                flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
            }
            mWindowParams = new WindowManager.LayoutParams(
                    frame.right - frame.left, frame.bottom - frame.top,
                    frame.left, frame.top, type, flags, PixelFormat.TRANSPARENT);
            mWindowParams.privateFlags |=
                    WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
            mWindowParams.gravity = Gravity.START | Gravity.TOP;
            mWindowParams.token = windowToken;
            mWindowManager.addView(mOverlayViewContainer, mWindowParams);
        }

        /**
         * Relayouts the current overlay view.
         *
         * @param frame A new position of the overlay view.
         */
        void relayoutOverlayView(Rect frame) {
            if (DEBUG) Log.d(TAG, "relayoutOverlayView(" + frame + ")");
            if (mOverlayFrame == null || mOverlayFrame.width() != frame.width()
                    || mOverlayFrame.height() != frame.height()) {
                // Note: relayoutOverlayView is called whenever TvView's layout is changed
                // regardless of setOverlayViewEnabled.
                onOverlayViewSizeChanged(frame.right - frame.left, frame.bottom - frame.top);
            }
            mOverlayFrame = frame;
            if (!mOverlayViewEnabled || mOverlayViewContainer == null) {
                return;
            }
            mWindowParams.x = frame.left;
            mWindowParams.y = frame.top;
            mWindowParams.width = frame.right - frame.left;
            mWindowParams.height = frame.bottom - frame.top;
            mWindowManager.updateViewLayout(mOverlayViewContainer, mWindowParams);
        }

        /**
         * Removes the current overlay view.
         */
        void removeOverlayView(boolean clearWindowToken) {
            if (DEBUG) Log.d(TAG, "removeOverlayView(" + mOverlayViewContainer + ")");
            if (clearWindowToken) {
                mWindowToken = null;
                mOverlayFrame = null;
            }
            if (mOverlayViewContainer != null) {
                // Removes the overlay view from the view hierarchy in advance so that it can be
                // cleaned up in the {@link OverlayViewCleanUpTask} if the remove process is
                // hanging.
                mOverlayViewContainer.removeView(mOverlayView);
                mOverlayView = null;
                mWindowManager.removeView(mOverlayViewContainer);
                mOverlayViewContainer = null;
                mWindowParams = null;
            }
        }

        /**
         * Calls {@link #onTimeShiftPlay(Uri)}.
         */
        void timeShiftPlay(Uri recordedProgramUri) {
            mCurrentPositionMs = 0;
            onTimeShiftPlay(recordedProgramUri);
        }

        /**
         * Calls {@link #onTimeShiftPause}.
         */
        void timeShiftPause() {
            onTimeShiftPause();
        }

        /**
         * Calls {@link #onTimeShiftResume}.
         */
        void timeShiftResume() {
            onTimeShiftResume();
        }

        /**
         * Calls {@link #onTimeShiftSeekTo}.
         */
        void timeShiftSeekTo(long timeMs) {
            onTimeShiftSeekTo(timeMs);
        }

        /**
         * Calls {@link #onTimeShiftSetPlaybackParams}.
         */
        void timeShiftSetPlaybackParams(PlaybackParams params) {
            onTimeShiftSetPlaybackParams(params);
        }

        /**
         * Enable/disable position tracking.
         *
         * @param enable {@code true} to enable tracking, {@code false} otherwise.
         */
        void timeShiftEnablePositionTracking(boolean enable) {
            if (enable) {
                mHandler.post(mTimeShiftPositionTrackingRunnable);
            } else {
                mHandler.removeCallbacks(mTimeShiftPositionTrackingRunnable);
                mStartPositionMs = TvInputManager.TIME_SHIFT_INVALID_TIME;
                mCurrentPositionMs = TvInputManager.TIME_SHIFT_INVALID_TIME;
            }
        }

        /**
         * Schedules a task which checks whether the overlay view is detached and kills the process
         * if it is not. Note that this method is expected to be called in a non-main thread.
         */
        void scheduleOverlayViewCleanup() {
            View overlayViewParent = mOverlayViewContainer;
            if (overlayViewParent != null) {
                mOverlayViewCleanUpTask = new OverlayViewCleanUpTask();
                mOverlayViewCleanUpTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
                        overlayViewParent);
            }
        }

        /**
         * Takes care of dispatching incoming input events and tells whether the event was handled.
         */
        int dispatchInputEvent(InputEvent event, InputEventReceiver receiver) {
            if (DEBUG) Log.d(TAG, "dispatchInputEvent(" + event + ")");
            boolean isNavigationKey = false;
            boolean skipDispatchToOverlayView = false;
            if (event instanceof KeyEvent) {
                KeyEvent keyEvent = (KeyEvent) event;
                if (keyEvent.dispatch(this, mDispatcherState, this)) {
                    return TvInputManager.Session.DISPATCH_HANDLED;
                }
                isNavigationKey = isNavigationKey(keyEvent.getKeyCode());
                // When media keys and KEYCODE_MEDIA_AUDIO_TRACK are dispatched to ViewRootImpl,
                // ViewRootImpl always consumes the keys. In this case, the application loses
                // a chance to handle media keys. Therefore, media keys are not dispatched to
                // ViewRootImpl.
                skipDispatchToOverlayView = KeyEvent.isMediaSessionKey(keyEvent.getKeyCode())
                        || keyEvent.getKeyCode() == KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK;
            } else if (event instanceof MotionEvent) {
                MotionEvent motionEvent = (MotionEvent) event;
                final int source = motionEvent.getSource();
                if (motionEvent.isTouchEvent()) {
                    if (onTouchEvent(motionEvent)) {
                        return TvInputManager.Session.DISPATCH_HANDLED;
                    }
                } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
                    if (onTrackballEvent(motionEvent)) {
                        return TvInputManager.Session.DISPATCH_HANDLED;
                    }
                } else {
                    if (onGenericMotionEvent(motionEvent)) {
                        return TvInputManager.Session.DISPATCH_HANDLED;
                    }
                }
            }
            if (mOverlayViewContainer == null || !mOverlayViewContainer.isAttachedToWindow()
                    || skipDispatchToOverlayView) {
                return TvInputManager.Session.DISPATCH_NOT_HANDLED;
            }
            if (!mOverlayViewContainer.hasWindowFocus()) {
                mOverlayViewContainer.getViewRootImpl().windowFocusChanged(true, true);
            }
            if (isNavigationKey && mOverlayViewContainer.hasFocusable()) {
                // If mOverlayView has focusable views, navigation key events should be always
                // handled. If not, it can make the application UI navigation messed up.
                // For example, in the case that the left-most view is focused, a left key event
                // will not be handled in ViewRootImpl. Then, the left key event will be handled in
                // the application during the UI navigation of the TV input.
                mOverlayViewContainer.getViewRootImpl().dispatchInputEvent(event);
                return TvInputManager.Session.DISPATCH_HANDLED;
            } else {
                mOverlayViewContainer.getViewRootImpl().dispatchInputEvent(event, receiver);
                return TvInputManager.Session.DISPATCH_IN_PROGRESS;
            }
        }

        private void initialize(ITvInputSessionCallback callback) {
            synchronized(mLock) {
                mSessionCallback = callback;
                for (Runnable runnable : mPendingActions) {
                    runnable.run();
                }
                mPendingActions.clear();
            }
        }

        private void executeOrPostRunnableOnMainThread(Runnable action) {
            synchronized(mLock) {
                if (mSessionCallback == null) {
                    // The session is not initialized yet.
                    mPendingActions.add(action);
                } else {
                    if (mHandler.getLooper().isCurrentThread()) {
                        action.run();
                    } else {
                        // Posts the runnable if this is not called from the main thread
                        mHandler.post(action);
                    }
                }
            }
        }

        private final class TimeShiftPositionTrackingRunnable implements Runnable {
            @Override
            public void run() {
                long startPositionMs = onTimeShiftGetStartPosition();
                if (mStartPositionMs == TvInputManager.TIME_SHIFT_INVALID_TIME
                        || mStartPositionMs != startPositionMs) {
                    mStartPositionMs = startPositionMs;
                    notifyTimeShiftStartPositionChanged(startPositionMs);
                }
                long currentPositionMs = onTimeShiftGetCurrentPosition();
                if (currentPositionMs < mStartPositionMs) {
                    Log.w(TAG, "Current position (" + currentPositionMs + ") cannot be earlier than"
                            + " start position (" + mStartPositionMs + "). Reset to the start "
                            + "position.");
                    currentPositionMs = mStartPositionMs;
                }
                if (mCurrentPositionMs == TvInputManager.TIME_SHIFT_INVALID_TIME
                        || mCurrentPositionMs != currentPositionMs) {
                    mCurrentPositionMs = currentPositionMs;
                    notifyTimeShiftCurrentPositionChanged(currentPositionMs);
                }
                mHandler.removeCallbacks(mTimeShiftPositionTrackingRunnable);
                mHandler.postDelayed(mTimeShiftPositionTrackingRunnable,
                        POSITION_UPDATE_INTERVAL_MS);
            }
        }
    }

    private static final class OverlayViewCleanUpTask extends AsyncTask<View, Void, Void> {
        @Override
        protected Void doInBackground(View... views) {
            View overlayViewParent = views[0];
            try {
                Thread.sleep(DETACH_OVERLAY_VIEW_TIMEOUT_MS);
            } catch (InterruptedException e) {
                return null;
            }
            if (isCancelled()) {
                return null;
            }
            if (overlayViewParent.isAttachedToWindow()) {
                Log.e(TAG, "Time out on releasing overlay view. Killing "
                        + overlayViewParent.getContext().getPackageName());
                Process.killProcess(Process.myPid());
            }
            return null;
        }
    }

    /**
     * Base class for derived classes to implement to provide a TV input recording session.
     */
    public abstract static class RecordingSession {
        final Handler mHandler;

        private final Object mLock = new Object();
        // @GuardedBy("mLock")
        private ITvInputSessionCallback mSessionCallback;
        // @GuardedBy("mLock")
        private final List<Runnable> mPendingActions = new ArrayList<>();

        /**
         * Creates a new RecordingSession.
         *
         * @param context The context of the application
         */
        public RecordingSession(Context context) {
            mHandler = new Handler(context.getMainLooper());
        }

        /**
         * Informs the application that this recording session has been tuned to the given channel
         * and is ready to start recording.
         *
         * <p>Upon receiving a call to {@link #onTune(Uri)}, the session is expected to tune to the
         * passed channel and call this method to indicate that it is now available for immediate
         * recording. When {@link #onStartRecording(Uri)} is called, recording must start with
         * minimal delay.
         *
         * @param channelUri The URI of a channel.
         */
        public void notifyTuned(Uri channelUri) {
            executeOrPostRunnableOnMainThread(new Runnable() {
                @MainThread
                @Override
                public void run() {
                    try {
                        if (DEBUG) Log.d(TAG, "notifyTuned");
                        if (mSessionCallback != null) {
                            mSessionCallback.onTuned(channelUri);
                        }
                    } catch (RemoteException e) {
                        Log.w(TAG, "error in notifyTuned", e);
                    }
                }
            });
        }

        /**
         * Informs the application that this recording session has stopped recording and created a
         * new data entry in the {@link TvContract.RecordedPrograms} table that describes the newly
         * recorded program.
         *
         * <p>The recording session must call this method in response to {@link #onStopRecording()}.
         * The session may call it even before receiving a call to {@link #onStopRecording()} if a
         * partially recorded program is available when there is an error.
         *
         * @param recordedProgramUri The URI of the newly recorded program.
         */
        public void notifyRecordingStopped(final Uri recordedProgramUri) {
            executeOrPostRunnableOnMainThread(new Runnable() {
                @MainThread
                @Override
                public void run() {
                    try {
                        if (DEBUG) Log.d(TAG, "notifyRecordingStopped");
                        if (mSessionCallback != null) {
                            mSessionCallback.onRecordingStopped(recordedProgramUri);
                        }
                    } catch (RemoteException e) {
                        Log.w(TAG, "error in notifyRecordingStopped", e);
                    }
                }
            });
        }

        /**
         * Informs the application that there is an error and this recording session is no longer
         * able to start or continue recording. It may be called at any time after the recording
         * session is created until {@link #onRelease()} is called.
         *
         * <p>The application may release the current session upon receiving the error code through
         * {@link TvRecordingClient.RecordingCallback#onError(int)}. The session may call
         * {@link #notifyRecordingStopped(Uri)} if a partially recorded but still playable program
         * is available, before calling this method.
         *
         * @param error The error code. Should be one of the followings.
         * <ul>
         * <li>{@link TvInputManager#RECORDING_ERROR_UNKNOWN}
         * <li>{@link TvInputManager#RECORDING_ERROR_INSUFFICIENT_SPACE}
         * <li>{@link TvInputManager#RECORDING_ERROR_RESOURCE_BUSY}
         * </ul>
         */
        public void notifyError(@TvInputManager.RecordingError int error) {
            if (error < TvInputManager.RECORDING_ERROR_START
                    || error > TvInputManager.RECORDING_ERROR_END) {
                Log.w(TAG, "notifyError - invalid error code (" + error
                        + ") is changed to RECORDING_ERROR_UNKNOWN.");
                error = TvInputManager.RECORDING_ERROR_UNKNOWN;
            }
            final int validError = error;
            executeOrPostRunnableOnMainThread(new Runnable() {
                @MainThread
                @Override
                public void run() {
                    try {
                        if (DEBUG) Log.d(TAG, "notifyError");
                        if (mSessionCallback != null) {
                            mSessionCallback.onError(validError);
                        }
                    } catch (RemoteException e) {
                        Log.w(TAG, "error in notifyError", e);
                    }
                }
            });
        }

        /**
         * Dispatches an event to the application using this recording session.
         *
         * @param eventType The type of the event.
         * @param eventArgs Optional arguments of the event.
         * @hide
         */
        @SystemApi
        public void notifySessionEvent(@NonNull final String eventType, final Bundle eventArgs) {
            Preconditions.checkNotNull(eventType);
            executeOrPostRunnableOnMainThread(new Runnable() {
                @MainThread
                @Override
                public void run() {
                    try {
                        if (DEBUG) Log.d(TAG, "notifySessionEvent(" + eventType + ")");
                        if (mSessionCallback != null) {
                            mSessionCallback.onSessionEvent(eventType, eventArgs);
                        }
                    } catch (RemoteException e) {
                        Log.w(TAG, "error in sending event (event=" + eventType + ")", e);
                    }
                }
            });
        }

        /**
         * Called when the application requests to tune to a given channel for TV program recording.
         *
         * <p>The application may call this method before starting or after stopping recording, but
         * not during recording.
         *
         * <p>The session must call {@link #notifyTuned(Uri)} if the tune request was fulfilled, or
         * {@link #notifyError(int)} otherwise.
         *
         * @param channelUri The URI of a channel.
         */
        public abstract void onTune(Uri channelUri);

        /**
         * Called when the application requests to tune to a given channel for TV program recording.
         * Override this method in order to handle domain-specific features that are only known
         * between certain TV inputs and their clients.
         *
         * <p>The application may call this method before starting or after stopping recording, but
         * not during recording. The default implementation calls {@link #onTune(Uri)}.
         *
         * <p>The session must call {@link #notifyTuned(Uri)} if the tune request was fulfilled, or
         * {@link #notifyError(int)} otherwise.
         *
         * @param channelUri The URI of a channel.
         * @param params Domain-specific data for this tune request. Keys <em>must</em> be a scoped
         *            name, i.e. prefixed with a package name you own, so that different developers
         *            will not create conflicting keys.
         */
        public void onTune(Uri channelUri, Bundle params) {
            onTune(channelUri);
        }

        /**
         * Called when the application requests to start TV program recording. Recording must start
         * immediately when this method is called.
         *
         * <p>The application may supply the URI for a TV program for filling in program specific
         * data fields in the {@link android.media.tv.TvContract.RecordedPrograms} table.
         * A non-null {@code programUri} implies the started recording should be of that specific
         * program, whereas null {@code programUri} does not impose such a requirement and the
         * recording can span across multiple TV programs. In either case, the application must call
         * {@link TvRecordingClient#stopRecording()} to stop the recording.
         *
         * <p>The session must call {@link #notifyError(int)} if the start request cannot be
         * fulfilled.
         *
         * @param programUri The URI for the TV program to record, built by
         *            {@link TvContract#buildProgramUri(long)}. Can be {@code null}.
         */
        public abstract void onStartRecording(@Nullable Uri programUri);

        /**
         * Called when the application requests to stop TV program recording. Recording must stop
         * immediately when this method is called.
         *
         * <p>The session must create a new data entry in the
         * {@link android.media.tv.TvContract.RecordedPrograms} table that describes the newly
         * recorded program and call {@link #notifyRecordingStopped(Uri)} with the URI to that
         * entry.
         * If the stop request cannot be fulfilled, the session must call {@link #notifyError(int)}.
         *
         */
        public abstract void onStopRecording();


        /**
         * Called when the application requests to release all the resources held by this recording
         * session.
         */
        public abstract void onRelease();

        /**
         * Processes a private command sent from the application to the TV input. This can be used
         * to provide domain-specific features that are only known between certain TV inputs and
         * their clients.
         *
         * @param action Name of the command to be performed. This <em>must</em> be a scoped name,
         *            i.e. prefixed with a package name you own, so that different developers will
         *            not create conflicting commands.
         * @param data Any data to include with the command.
         */
        public void onAppPrivateCommand(@NonNull String action, Bundle data) {
        }

        /**
         * Calls {@link #onTune(Uri, Bundle)}.
         *
         */
        void tune(Uri channelUri, Bundle params) {
            onTune(channelUri, params);
        }

        /**
         * Calls {@link #onRelease()}.
         *
         */
        void release() {
            onRelease();
        }

        /**
         * Calls {@link #onStartRecording(Uri)}.
         *
         */
        void startRecording(@Nullable  Uri programUri) {
            onStartRecording(programUri);
        }

        /**
         * Calls {@link #onStopRecording()}.
         *
         */
        void stopRecording() {
            onStopRecording();
        }

        /**
         * Calls {@link #onAppPrivateCommand(String, Bundle)}.
         */
        void appPrivateCommand(String action, Bundle data) {
            onAppPrivateCommand(action, data);
        }

        private void initialize(ITvInputSessionCallback callback) {
            synchronized(mLock) {
                mSessionCallback = callback;
                for (Runnable runnable : mPendingActions) {
                    runnable.run();
                }
                mPendingActions.clear();
            }
        }

        private void executeOrPostRunnableOnMainThread(Runnable action) {
            synchronized(mLock) {
                if (mSessionCallback == null) {
                    // The session is not initialized yet.
                    mPendingActions.add(action);
                } else {
                    if (mHandler.getLooper().isCurrentThread()) {
                        action.run();
                    } else {
                        // Posts the runnable if this is not called from the main thread
                        mHandler.post(action);
                    }
                }
            }
        }
    }

    /**
     * Base class for a TV input session which represents an external device connected to a
     * hardware TV input.
     *
     * <p>This class is for an input which provides channels for the external set-top box to the
     * application. Once a TV input returns an implementation of this class on
     * {@link #onCreateSession(String)}, the framework will create a separate session for
     * a hardware TV Input (e.g. HDMI 1) and forward the application's surface to the session so
     * that the user can see the screen of the hardware TV Input when she tunes to a channel from
     * this TV input. The implementation of this class is expected to change the channel of the
     * external set-top box via a proprietary protocol when {@link HardwareSession#onTune} is
     * requested by the application.
     *
     * <p>Note that this class is not for inputs for internal hardware like built-in tuner and HDMI
     * 1.
     *
     * @see #onCreateSession(String)
     */
    public abstract static class HardwareSession extends Session {

        /**
         * Creates a new HardwareSession.
         *
         * @param context The context of the application
         */
        public HardwareSession(Context context) {
            super(context);
        }

        private TvInputManager.Session mHardwareSession;
        private ITvInputSession mProxySession;
        private ITvInputSessionCallback mProxySessionCallback;
        private Handler mServiceHandler;

        /**
         * Returns the hardware TV input ID the external device is connected to.
         *
         * <p>TV input is expected to provide {@link android.R.attr#setupActivity} so that
         * the application can launch it before using this TV input. The setup activity may let
         * the user select the hardware TV input to which the external device is connected. The ID
         * of the selected one should be stored in the TV input so that it can be returned here.
         */
        public abstract String getHardwareInputId();

        private final TvInputManager.SessionCallback mHardwareSessionCallback =
                new TvInputManager.SessionCallback() {
            @Override
            public void onSessionCreated(TvInputManager.Session session) {
                mHardwareSession = session;
                SomeArgs args = SomeArgs.obtain();
                if (session != null) {
                    args.arg1 = HardwareSession.this;
                    args.arg2 = mProxySession;
                    args.arg3 = mProxySessionCallback;
                    args.arg4 = session.getToken();
                    session.tune(TvContract.buildChannelUriForPassthroughInput(
                            getHardwareInputId()));
                } else {
                    args.arg1 = null;
                    args.arg2 = null;
                    args.arg3 = mProxySessionCallback;
                    args.arg4 = null;
                    onRelease();
                }
                mServiceHandler.obtainMessage(ServiceHandler.DO_NOTIFY_SESSION_CREATED, args)
                        .sendToTarget();
            }

            @Override
            public void onVideoAvailable(final TvInputManager.Session session) {
                if (mHardwareSession == session) {
                    onHardwareVideoAvailable();
                }
            }

            @Override
            public void onVideoUnavailable(final TvInputManager.Session session,
                    final int reason) {
                if (mHardwareSession == session) {
                    onHardwareVideoUnavailable(reason);
                }
            }
        };

        /**
         * This method will not be called in {@link HardwareSession}. Framework will
         * forward the application's surface to the hardware TV input.
         */
        @Override
        public final boolean onSetSurface(Surface surface) {
            Log.e(TAG, "onSetSurface() should not be called in HardwareProxySession.");
            return false;
        }

        /**
         * Called when the underlying hardware TV input session calls
         * {@link TvInputService.Session#notifyVideoAvailable()}.
         */
        public void onHardwareVideoAvailable() { }

        /**
         * Called when the underlying hardware TV input session calls
         * {@link TvInputService.Session#notifyVideoUnavailable(int)}.
         *
         * @param reason The reason that the hardware TV input stopped the playback:
         * <ul>
         * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_UNKNOWN}
         * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_TUNING}
         * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL}
         * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_BUFFERING}
         * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY}
         * </ul>
         */
        public void onHardwareVideoUnavailable(int reason) { }

        @Override
        void release() {
            if (mHardwareSession != null) {
                mHardwareSession.release();
                mHardwareSession = null;
            }
            super.release();
        }
    }

    /** @hide */
    public static boolean isNavigationKey(int keyCode) {
        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_LEFT:
            case KeyEvent.KEYCODE_DPAD_RIGHT:
            case KeyEvent.KEYCODE_DPAD_UP:
            case KeyEvent.KEYCODE_DPAD_DOWN:
            case KeyEvent.KEYCODE_DPAD_CENTER:
            case KeyEvent.KEYCODE_PAGE_UP:
            case KeyEvent.KEYCODE_PAGE_DOWN:
            case KeyEvent.KEYCODE_MOVE_HOME:
            case KeyEvent.KEYCODE_MOVE_END:
            case KeyEvent.KEYCODE_TAB:
            case KeyEvent.KEYCODE_SPACE:
            case KeyEvent.KEYCODE_ENTER:
                return true;
        }
        return false;
    }

    @SuppressLint("HandlerLeak")
    private final class ServiceHandler extends Handler {
        private static final int DO_CREATE_SESSION = 1;
        private static final int DO_NOTIFY_SESSION_CREATED = 2;
        private static final int DO_CREATE_RECORDING_SESSION = 3;
        private static final int DO_ADD_HARDWARE_INPUT = 4;
        private static final int DO_REMOVE_HARDWARE_INPUT = 5;
        private static final int DO_ADD_HDMI_INPUT = 6;
        private static final int DO_REMOVE_HDMI_INPUT = 7;

        private void broadcastAddHardwareInput(int deviceId, TvInputInfo inputInfo) {
            int n = mCallbacks.beginBroadcast();
            for (int i = 0; i < n; ++i) {
                try {
                    mCallbacks.getBroadcastItem(i).addHardwareInput(deviceId, inputInfo);
                } catch (RemoteException e) {
                    Log.e(TAG, "error in broadcastAddHardwareInput", e);
                }
            }
            mCallbacks.finishBroadcast();
        }

        private void broadcastAddHdmiInput(int id, TvInputInfo inputInfo) {
            int n = mCallbacks.beginBroadcast();
            for (int i = 0; i < n; ++i) {
                try {
                    mCallbacks.getBroadcastItem(i).addHdmiInput(id, inputInfo);
                } catch (RemoteException e) {
                    Log.e(TAG, "error in broadcastAddHdmiInput", e);
                }
            }
            mCallbacks.finishBroadcast();
        }

        private void broadcastRemoveHardwareInput(String inputId) {
            int n = mCallbacks.beginBroadcast();
            for (int i = 0; i < n; ++i) {
                try {
                    mCallbacks.getBroadcastItem(i).removeHardwareInput(inputId);
                } catch (RemoteException e) {
                    Log.e(TAG, "error in broadcastRemoveHardwareInput", e);
                }
            }
            mCallbacks.finishBroadcast();
        }

        @Override
        public final void handleMessage(Message msg) {
            switch (msg.what) {
                case DO_CREATE_SESSION: {
                    SomeArgs args = (SomeArgs) msg.obj;
                    InputChannel channel = (InputChannel) args.arg1;
                    ITvInputSessionCallback cb = (ITvInputSessionCallback) args.arg2;
                    String inputId = (String) args.arg3;
                    args.recycle();
                    Session sessionImpl = onCreateSession(inputId);
                    if (sessionImpl == null) {
                        try {
                            // Failed to create a session.
                            cb.onSessionCreated(null, null);
                        } catch (RemoteException e) {
                            Log.e(TAG, "error in onSessionCreated", e);
                        }
                        return;
                    }
                    ITvInputSession stub = new ITvInputSessionWrapper(TvInputService.this,
                            sessionImpl, channel);
                    if (sessionImpl instanceof HardwareSession) {
                        HardwareSession proxySession =
                                ((HardwareSession) sessionImpl);
                        String hardwareInputId = proxySession.getHardwareInputId();
                        if (TextUtils.isEmpty(hardwareInputId) ||
                                !isPassthroughInput(hardwareInputId)) {
                            if (TextUtils.isEmpty(hardwareInputId)) {
                                Log.w(TAG, "Hardware input id is not setup yet.");
                            } else {
                                Log.w(TAG, "Invalid hardware input id : " + hardwareInputId);
                            }
                            sessionImpl.onRelease();
                            try {
                                cb.onSessionCreated(null, null);
                            } catch (RemoteException e) {
                                Log.e(TAG, "error in onSessionCreated", e);
                            }
                            return;
                        }
                        proxySession.mProxySession = stub;
                        proxySession.mProxySessionCallback = cb;
                        proxySession.mServiceHandler = mServiceHandler;
                        TvInputManager manager = (TvInputManager) getSystemService(
                                Context.TV_INPUT_SERVICE);
                        manager.createSession(hardwareInputId,
                                proxySession.mHardwareSessionCallback, mServiceHandler);
                    } else {
                        SomeArgs someArgs = SomeArgs.obtain();
                        someArgs.arg1 = sessionImpl;
                        someArgs.arg2 = stub;
                        someArgs.arg3 = cb;
                        someArgs.arg4 = null;
                        mServiceHandler.obtainMessage(ServiceHandler.DO_NOTIFY_SESSION_CREATED,
                                someArgs).sendToTarget();
                    }
                    return;
                }
                case DO_NOTIFY_SESSION_CREATED: {
                    SomeArgs args = (SomeArgs) msg.obj;
                    Session sessionImpl = (Session) args.arg1;
                    ITvInputSession stub = (ITvInputSession) args.arg2;
                    ITvInputSessionCallback cb = (ITvInputSessionCallback) args.arg3;
                    IBinder hardwareSessionToken = (IBinder) args.arg4;
                    try {
                        cb.onSessionCreated(stub, hardwareSessionToken);
                    } catch (RemoteException e) {
                        Log.e(TAG, "error in onSessionCreated", e);
                    }
                    if (sessionImpl != null) {
                        sessionImpl.initialize(cb);
                    }
                    args.recycle();
                    return;
                }
                case DO_CREATE_RECORDING_SESSION: {
                    SomeArgs args = (SomeArgs) msg.obj;
                    ITvInputSessionCallback cb = (ITvInputSessionCallback) args.arg1;
                    String inputId = (String) args.arg2;
                    args.recycle();
                    RecordingSession recordingSessionImpl = onCreateRecordingSession(inputId);
                    if (recordingSessionImpl == null) {
                        try {
                            // Failed to create a recording session.
                            cb.onSessionCreated(null, null);
                        } catch (RemoteException e) {
                            Log.e(TAG, "error in onSessionCreated", e);
                        }
                        return;
                    }
                    ITvInputSession stub = new ITvInputSessionWrapper(TvInputService.this,
                            recordingSessionImpl);
                    try {
                        cb.onSessionCreated(stub, null);
                    } catch (RemoteException e) {
                        Log.e(TAG, "error in onSessionCreated", e);
                    }
                    recordingSessionImpl.initialize(cb);
                    return;
                }
                case DO_ADD_HARDWARE_INPUT: {
                    TvInputHardwareInfo hardwareInfo = (TvInputHardwareInfo) msg.obj;
                    TvInputInfo inputInfo = onHardwareAdded(hardwareInfo);
                    if (inputInfo != null) {
                        broadcastAddHardwareInput(hardwareInfo.getDeviceId(), inputInfo);
                    }
                    return;
                }
                case DO_REMOVE_HARDWARE_INPUT: {
                    TvInputHardwareInfo hardwareInfo = (TvInputHardwareInfo) msg.obj;
                    String inputId = onHardwareRemoved(hardwareInfo);
                    if (inputId != null) {
                        broadcastRemoveHardwareInput(inputId);
                    }
                    return;
                }
                case DO_ADD_HDMI_INPUT: {
                    HdmiDeviceInfo deviceInfo = (HdmiDeviceInfo) msg.obj;
                    TvInputInfo inputInfo = onHdmiDeviceAdded(deviceInfo);
                    if (inputInfo != null) {
                        broadcastAddHdmiInput(deviceInfo.getId(), inputInfo);
                    }
                    return;
                }
                case DO_REMOVE_HDMI_INPUT: {
                    HdmiDeviceInfo deviceInfo = (HdmiDeviceInfo) msg.obj;
                    String inputId = onHdmiDeviceRemoved(deviceInfo);
                    if (inputId != null) {
                        broadcastRemoveHardwareInput(inputId);
                    }
                    return;
                }
                default: {
                    Log.w(TAG, "Unhandled message code: " + msg.what);
                    return;
                }
            }
        }
    }
}
