19a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho/* 29a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho * Copyright (C) 2014 The Android Open Source Project 39a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho * 49a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho * Licensed under the Apache License, Version 2.0 (the "License"); 59a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho * you may not use this file except in compliance with the License. 69a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho * You may obtain a copy of the License at 79a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho * 89a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho * http://www.apache.org/licenses/LICENSE-2.0 99a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho * 109a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho * Unless required by applicable law or agreed to in writing, software 119a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho * distributed under the License is distributed on an "AS IS" BASIS, 129a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho * See the License for the specific language governing permissions and 149a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho * limitations under the License. 159a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho */ 169a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 17d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seopackage android.media.tv; 189a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 19cdfbc488c675a9800dfc8f15aec24b65a7558d29Jae Seoimport android.annotation.FloatRange; 20c8b7356434f665c494504661a943323c0bbe702eJae Seoimport android.annotation.NonNull; 214bf607b00c14c031e991ac9dc0ad49b9249c9162Dongwon Kangimport android.annotation.Nullable; 22e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kangimport android.annotation.RequiresPermission; 23a759b111a1c9cb00284038f8a1554bf29709b952Jae Seoimport android.annotation.SystemApi; 249a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Choimport android.content.Context; 255f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kangimport android.graphics.Canvas; 265f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kangimport android.graphics.PorterDuff; 279a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Choimport android.graphics.Rect; 285f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kangimport android.graphics.Region; 293d04b7693428dd887c93e2ac7f4e90fd0cc87859Jae Seoimport android.media.PlaybackParams; 30d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvInputManager.Session; 31d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvInputManager.Session.FinishedInputEventCallback; 32d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvInputManager.SessionCallback; 33b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seoimport android.net.Uri; 34832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Choimport android.os.Bundle; 359a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Choimport android.os.Handler; 36d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Limimport android.text.TextUtils; 379a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Choimport android.util.AttributeSet; 389a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Choimport android.util.Log; 39411d58d330eafb093fe7edfa3fcccfadfc470076Jae Seoimport android.util.Pair; 406a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seoimport android.view.InputEvent; 416a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seoimport android.view.KeyEvent; 426a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seoimport android.view.MotionEvent; 439a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Choimport android.view.Surface; 449a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Choimport android.view.SurfaceHolder; 459a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Choimport android.view.SurfaceView; 4607b7c5fa4cb705eea5d89f98e84341db5465d663Youngsang Choimport android.view.View; 471bfce9fb9bffe8bd620fd1683572ae620f91772fJae Seoimport android.view.ViewGroup; 48c3e00c3ffc3b1406712f1f19b8d1cd815eee88daChulwoo Leeimport android.view.ViewRootImpl; 499a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 50c7f440dcd86ae88fc1b51e4394d66e4e80c9e53eJi-Hwan Leeimport java.lang.ref.WeakReference; 51411d58d330eafb093fe7edfa3fcccfadfc470076Jae Seoimport java.util.ArrayDeque; 521f213914c45c23c653f721690da2ce0718e63139Dongwon Kangimport java.util.List; 53411d58d330eafb093fe7edfa3fcccfadfc470076Jae Seoimport java.util.Queue; 541f213914c45c23c653f721690da2ce0718e63139Dongwon Kang 559a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho/** 569551e92507564c597a7764473945114d3c3bfff3Jae Seo * Displays TV contents. The TvView class provides a high level interface for applications to show 579551e92507564c597a7764473945114d3c3bfff3Jae Seo * TV programs from various TV sources that implement {@link TvInputService}. (Note that the list of 589551e92507564c597a7764473945114d3c3bfff3Jae Seo * TV inputs available on the system can be obtained by calling 599551e92507564c597a7764473945114d3c3bfff3Jae Seo * {@link TvInputManager#getTvInputList() TvInputManager.getTvInputList()}.) 600610e12733875a267f59d87a2a68aebbf486066eDongwon Kang * 61e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * <p>Once the application supplies the URI for a specific TV channel to {@link #tune} 629551e92507564c597a7764473945114d3c3bfff3Jae Seo * method, it takes care of underlying service binding (and unbinding if the current TvView is 639551e92507564c597a7764473945114d3c3bfff3Jae Seo * already bound to a service) and automatically allocates/deallocates resources needed. In addition 649551e92507564c597a7764473945114d3c3bfff3Jae Seo * to a few essential methods to control how the contents are presented, it also provides a way to 659551e92507564c597a7764473945114d3c3bfff3Jae Seo * dispatch input events to the connected TvInputService in order to enable custom key actions for 669551e92507564c597a7764473945114d3c3bfff3Jae Seo * the TV input. 679a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho */ 681bfce9fb9bffe8bd620fd1683572ae620f91772fJae Seopublic class TvView extends ViewGroup { 69b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo private static final String TAG = "TvView"; 70ee2ec05ed7c0d3cb9115f4ddd7c3613269c4a57bJae Seo private static final boolean DEBUG = false; 71b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo 72bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho private static final int ZORDER_MEDIA = 0; 73bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho private static final int ZORDER_MEDIA_OVERLAY = 1; 74bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho private static final int ZORDER_ON_TOP = 2; 75bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho 766320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo private static final WeakReference<TvView> NULL_TV_VIEW = new WeakReference<>(null); 77c7f440dcd86ae88fc1b51e4394d66e4e80c9e53eJi-Hwan Lee 784c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee private static final Object sMainTvViewLock = new Object(); 79c7f440dcd86ae88fc1b51e4394d66e4e80c9e53eJi-Hwan Lee private static WeakReference<TvView> sMainTvView = NULL_TV_VIEW; 804c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 819a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho private final Handler mHandler = new Handler(); 82903d6b72cd572665309633e925485464d08bb25aJaewan Kim private Session mSession; 8371b282fad429dfa5e98287aa34af6aecd155321bYoungsang Cho private SurfaceView mSurfaceView; 849a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho private Surface mSurface; 859a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho private boolean mOverlayViewCreated; 869a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho private Rect mOverlayViewFrame; 876a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo private final TvInputManager mTvInputManager; 88b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo private MySessionCallback mSessionCallback; 892778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo private TvInputCallback mCallback; 906a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo private OnUnhandledInputEventListener mOnUnhandledInputEventListener; 911da8fb39499e8f5a962f7307fefdfd2ab6b79224Jae Seo private Float mStreamVolume; 921da8fb39499e8f5a962f7307fefdfd2ab6b79224Jae Seo private Boolean mCaptionEnabled; 93411d58d330eafb093fe7edfa3fcccfadfc470076Jae Seo private final Queue<Pair<String, Bundle>> mPendingAppPrivateCommands = new ArrayDeque<>(); 94887f52144eeea8d5812d64a29e207af6b97a763dJae Seo 95e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho private boolean mSurfaceChanged; 96e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho private int mSurfaceFormat; 97e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho private int mSurfaceWidth; 98e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho private int mSurfaceHeight; 9971b282fad429dfa5e98287aa34af6aecd155321bYoungsang Cho private final AttributeSet mAttrs; 10071b282fad429dfa5e98287aa34af6aecd155321bYoungsang Cho private final int mDefStyleAttr; 101bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho private int mWindowZOrder; 102ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho private boolean mUseRequestedSurfaceLayout; 103ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho private int mSurfaceViewLeft; 104ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho private int mSurfaceViewRight; 105ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho private int mSurfaceViewTop; 106ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho private int mSurfaceViewBottom; 107465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo private TimeShiftPositionCallback mTimeShiftPositionCallback; 1089a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 1096a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo private final SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() { 1109a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 1119a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 11215c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee if (DEBUG) { 11315c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee Log.d(TAG, "surfaceChanged(holder=" + holder + ", format=" + format + ", width=" 11415c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee + width + ", height=" + height + ")"); 11515c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee } 116e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho mSurfaceFormat = format; 117e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho mSurfaceWidth = width; 118e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho mSurfaceHeight = height; 119e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho mSurfaceChanged = true; 120e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho dispatchSurfaceChanged(mSurfaceFormat, mSurfaceWidth, mSurfaceHeight); 1219a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 1229a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 1239a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 1249a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void surfaceCreated(SurfaceHolder holder) { 1259a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho mSurface = holder.getSurface(); 1269a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho setSessionSurface(mSurface); 1279a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 1289a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 1299a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 1309a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void surfaceDestroyed(SurfaceHolder holder) { 1319a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho mSurface = null; 132e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho mSurfaceChanged = false; 1339a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho setSessionSurface(null); 1349a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 1359a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho }; 1369a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 1376a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo private final FinishedInputEventCallback mFinishedInputEventCallback = 1386a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo new FinishedInputEventCallback() { 1396a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo @Override 1406a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo public void onFinishedInputEvent(Object token, boolean handled) { 1416a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo if (DEBUG) { 1426a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo Log.d(TAG, "onFinishedInputEvent(token=" + token + ", handled=" + handled + ")"); 1436a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo } 1446a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo if (handled) { 1456a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo return; 1466a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo } 1476a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo // TODO: Re-order unhandled events. 1486a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo InputEvent event = (InputEvent) token; 1496a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo if (dispatchUnhandledInputEvent(event)) { 1506a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo return; 1516a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo } 152c3e00c3ffc3b1406712f1f19b8d1cd815eee88daChulwoo Lee ViewRootImpl viewRootImpl = getViewRootImpl(); 153c3e00c3ffc3b1406712f1f19b8d1cd815eee88daChulwoo Lee if (viewRootImpl != null) { 154c3e00c3ffc3b1406712f1f19b8d1cd815eee88daChulwoo Lee viewRootImpl.dispatchUnhandledInputEvent(event); 155c3e00c3ffc3b1406712f1f19b8d1cd815eee88daChulwoo Lee } 1566a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo } 1576a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo }; 1586a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 1599a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public TvView(Context context) { 1609a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho this(context, null, 0); 1619a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 1629a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 1639a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public TvView(Context context, AttributeSet attrs) { 1649a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho this(context, attrs, 0); 1659a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 1669a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 1679a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public TvView(Context context, AttributeSet attrs, int defStyleAttr) { 1689a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho super(context, attrs, defStyleAttr); 16971b282fad429dfa5e98287aa34af6aecd155321bYoungsang Cho mAttrs = attrs; 17071b282fad429dfa5e98287aa34af6aecd155321bYoungsang Cho mDefStyleAttr = defStyleAttr; 17171b282fad429dfa5e98287aa34af6aecd155321bYoungsang Cho resetSurfaceView(); 1729a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho mTvInputManager = (TvInputManager) getContext().getSystemService(Context.TV_INPUT_SERVICE); 1739a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 1749a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 1759a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho /** 1762778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo * Sets the callback to be invoked when an event is dispatched to this TvView. 1779a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho * 178465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo * @param callback The callback to receive events. A value of {@code null} removes the existing 179465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo * callback. 1809a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho */ 1814bf607b00c14c031e991ac9dc0ad49b9249c9162Dongwon Kang public void setCallback(@Nullable TvInputCallback callback) { 1822778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo mCallback = callback; 1839a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 1849a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 1856a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo /** 18615c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee * Sets this as the main {@link TvView}. 1870610e12733875a267f59d87a2a68aebbf486066eDongwon Kang * 1880610e12733875a267f59d87a2a68aebbf486066eDongwon Kang * <p>The main {@link TvView} is a {@link TvView} whose corresponding TV input determines the 18915c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee * HDMI-CEC active source device. For an HDMI port input, one of source devices that is 19015c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee * connected to that HDMI port becomes the active source. For an HDMI-CEC logical device input, 19115c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee * the corresponding HDMI-CEC logical device becomes the active source. For any non-HDMI input 19215c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee * (including the tuner, composite, S-Video, etc.), the internal device (= TV itself) becomes 19315c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee * the active source. 1940610e12733875a267f59d87a2a68aebbf486066eDongwon Kang * 1950610e12733875a267f59d87a2a68aebbf486066eDongwon Kang * <p>First tuned {@link TvView} becomes main automatically, and keeps to be main until either 1966e4cbfd2e5ffb739269e5e4affc2b6894bc4090eJae Seo * {@link #reset} is called for the main {@link TvView} or {@code setMain()} is called for other 197c7f440dcd86ae88fc1b51e4394d66e4e80c9e53eJi-Hwan Lee * {@link TvView}. 1984c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee * @hide 1994c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee */ 2004c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee @SystemApi 20115c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee public void setMain() { 2024c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee synchronized (sMainTvViewLock) { 2036320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo sMainTvView = new WeakReference<>(this); 2044c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee if (hasWindowFocus() && mSession != null) { 20515c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee mSession.setMain(); 2064c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 2074c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 2084c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 2094c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 2104c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee /** 211e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * Controls whether the TvView's surface is placed on top of another regular surface view in the 212e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * window (but still behind the window itself). 213e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * This is typically used to place overlays on top of an underlying TvView. 214bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho * 215e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * <p>Note that this must be set before the TvView's containing window is attached to the 216e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * window manager. 217e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * 218e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * <p>Calling this overrides any previous call to {@link #setZOrderOnTop}. 219e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * 220e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * @param isMediaOverlay {@code true} to be on top of another regular surface, {@code false} 221e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * otherwise. 222bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho */ 223bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho public void setZOrderMediaOverlay(boolean isMediaOverlay) { 224bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho if (isMediaOverlay) { 225bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho mWindowZOrder = ZORDER_MEDIA_OVERLAY; 226bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho removeSessionOverlayView(); 227bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho } else { 228bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho mWindowZOrder = ZORDER_MEDIA; 229bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho createSessionOverlayView(); 230bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho } 231bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho if (mSurfaceView != null) { 232bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho // ZOrderOnTop(false) removes WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM 233bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho // from WindowLayoutParam as well as changes window type. 234bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho mSurfaceView.setZOrderOnTop(false); 235bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho mSurfaceView.setZOrderMediaOverlay(isMediaOverlay); 236bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho } 237bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho } 238bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho 239bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho /** 240e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * Controls whether the TvView's surface is placed on top of its window. Normally it is placed 241e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * behind the window, to allow it to (for the most part) appear to composite with the views in 242e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * the hierarchy. By setting this, you cause it to be placed above the window. This means that 243e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * none of the contents of the window this TvView is in will be visible on top of its surface. 244bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho * 245e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * <p>Note that this must be set before the TvView's containing window is attached to the window 246e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * manager. 247e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * 248e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * <p>Calling this overrides any previous call to {@link #setZOrderMediaOverlay}. 249e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * 250e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * @param onTop {@code true} to be on top of its window, {@code false} otherwise. 251bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho */ 252bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho public void setZOrderOnTop(boolean onTop) { 253bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho if (onTop) { 254bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho mWindowZOrder = ZORDER_ON_TOP; 255bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho removeSessionOverlayView(); 256bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho } else { 257bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho mWindowZOrder = ZORDER_MEDIA; 258bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho createSessionOverlayView(); 259bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho } 260bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho if (mSurfaceView != null) { 261bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho mSurfaceView.setZOrderMediaOverlay(false); 262bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho mSurfaceView.setZOrderOnTop(onTop); 263bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho } 264bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho } 265bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho 266bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho /** 2671da8fb39499e8f5a962f7307fefdfd2ab6b79224Jae Seo * Sets the relative stream volume of this TvView. 2681da8fb39499e8f5a962f7307fefdfd2ab6b79224Jae Seo * 2691da8fb39499e8f5a962f7307fefdfd2ab6b79224Jae Seo * <p>This method is primarily used to handle audio focus changes or mute a specific TvView when 2701da8fb39499e8f5a962f7307fefdfd2ab6b79224Jae Seo * multiple views are displayed. If the method has not yet been called, the TvView assumes the 2711da8fb39499e8f5a962f7307fefdfd2ab6b79224Jae Seo * default value of {@code 1.0f}. 272782f7345471072b630e58c7abd3579b0015273b1Jae Seo * 2731da8fb39499e8f5a962f7307fefdfd2ab6b79224Jae Seo * @param volume A volume value between {@code 0.0f} to {@code 1.0f}. 274782f7345471072b630e58c7abd3579b0015273b1Jae Seo */ 275cdfbc488c675a9800dfc8f15aec24b65a7558d29Jae Seo public void setStreamVolume(@FloatRange(from = 0.0, to = 1.0) float volume) { 276782f7345471072b630e58c7abd3579b0015273b1Jae Seo if (DEBUG) Log.d(TAG, "setStreamVolume(" + volume + ")"); 277336cdf20dd44ee93b5173be73e26e966a2609eb0Dongwon Kang mStreamVolume = volume; 278782f7345471072b630e58c7abd3579b0015273b1Jae Seo if (mSession == null) { 279336cdf20dd44ee93b5173be73e26e966a2609eb0Dongwon Kang // Volume will be set once the connection has been made. 280782f7345471072b630e58c7abd3579b0015273b1Jae Seo return; 281782f7345471072b630e58c7abd3579b0015273b1Jae Seo } 282782f7345471072b630e58c7abd3579b0015273b1Jae Seo mSession.setStreamVolume(volume); 283782f7345471072b630e58c7abd3579b0015273b1Jae Seo } 284782f7345471072b630e58c7abd3579b0015273b1Jae Seo 285782f7345471072b630e58c7abd3579b0015273b1Jae Seo /** 286b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo * Tunes to a given channel. 287b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo * 288b1ae00ec628d16c2fd1354c70e971d4757201753Jae Seo * @param inputId The ID of the TV input for the given channel. 289b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo * @param channelUri The URI of a channel. 290b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo */ 291c8b7356434f665c494504661a943323c0bbe702eJae Seo public void tune(@NonNull String inputId, Uri channelUri) { 2921a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim tune(inputId, channelUri, null); 2931a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 2941a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim 2951a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim /** 296e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * Tunes to a given channel. This can be used to provide domain-specific features that are only 297f714e62c12d99d816d70d09da60b6885a1368cefDongwon Kang * known between certain clients and their TV inputs. 2981a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim * 299b1ae00ec628d16c2fd1354c70e971d4757201753Jae Seo * @param inputId The ID of TV input for the given channel. 3001a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim * @param channelUri The URI of a channel. 301e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * @param params Domain-specific data for this tune request. Keys <em>must</em> be a scoped 302e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * name, i.e. prefixed with a package name you own, so that different developers will 303e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * not create conflicting keys. 3041a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim */ 3051a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim public void tune(String inputId, Uri channelUri, Bundle params) { 306b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo if (DEBUG) Log.d(TAG, "tune(" + channelUri + ")"); 307b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo if (TextUtils.isEmpty(inputId)) { 308b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo throw new IllegalArgumentException("inputId cannot be null or an empty string"); 309b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo } 3104c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee synchronized (sMainTvViewLock) { 311c7f440dcd86ae88fc1b51e4394d66e4e80c9e53eJi-Hwan Lee if (sMainTvView.get() == null) { 3126320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo sMainTvView = new WeakReference<>(this); 3134c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 3144c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 315b1ae00ec628d16c2fd1354c70e971d4757201753Jae Seo if (mSessionCallback != null && TextUtils.equals(mSessionCallback.mInputId, inputId)) { 316b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo if (mSession != null) { 3171a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim mSession.tune(channelUri, params); 318b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo } else { 319b1ae00ec628d16c2fd1354c70e971d4757201753Jae Seo // createSession() was called but the actual session for the given inputId has not 320b1ae00ec628d16c2fd1354c70e971d4757201753Jae Seo // yet been created. Just replace the existing tuning params in the callback with 321b1ae00ec628d16c2fd1354c70e971d4757201753Jae Seo // the new ones and tune later in onSessionCreated(). It is not necessary to create 322b1ae00ec628d16c2fd1354c70e971d4757201753Jae Seo // a new callback because this tuning request was made on the same inputId. 323b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo mSessionCallback.mChannelUri = channelUri; 3241a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim mSessionCallback.mTuneParams = params; 325b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo } 326b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo } else { 327d0f00588834806d3f52c95c2d5fb13d9a92bddfcJi-Hwan Lee resetInternal(); 328b1ae00ec628d16c2fd1354c70e971d4757201753Jae Seo // In case createSession() is called multiple times across different inputId's before 329b1ae00ec628d16c2fd1354c70e971d4757201753Jae Seo // any session is created (e.g. when quickly tuning to a channel from input A and then 330b1ae00ec628d16c2fd1354c70e971d4757201753Jae Seo // to another channel from input B), only the callback for the last createSession() 331b1ae00ec628d16c2fd1354c70e971d4757201753Jae Seo // should be invoked. (The previous callbacks are simply ignored.) To do that, we create 332b1ae00ec628d16c2fd1354c70e971d4757201753Jae Seo // a new callback each time and keep mSessionCallback pointing to the last one. If 333b1ae00ec628d16c2fd1354c70e971d4757201753Jae Seo // MySessionCallback.this is different from mSessionCallback, we know that this callback 334b1ae00ec628d16c2fd1354c70e971d4757201753Jae Seo // is obsolete and should ignore it. 3351a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim mSessionCallback = new MySessionCallback(inputId, channelUri, params); 3369127e4580c618bc1afae5c2c280f5a271f7a7635Jae Seo if (mTvInputManager != null) { 3379127e4580c618bc1afae5c2c280f5a271f7a7635Jae Seo mTvInputManager.createSession(inputId, mSessionCallback, mHandler); 3389127e4580c618bc1afae5c2c280f5a271f7a7635Jae Seo } 339b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo } 340b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo } 341b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo 342b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo /** 343b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo * Resets this TvView. 3440610e12733875a267f59d87a2a68aebbf486066eDongwon Kang * 3450610e12733875a267f59d87a2a68aebbf486066eDongwon Kang * <p>This method is primarily used to un-tune the current TvView. 346b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo */ 347b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo public void reset() { 34815c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee if (DEBUG) Log.d(TAG, "reset()"); 349c7f440dcd86ae88fc1b51e4394d66e4e80c9e53eJi-Hwan Lee synchronized (sMainTvViewLock) { 350c7f440dcd86ae88fc1b51e4394d66e4e80c9e53eJi-Hwan Lee if (this == sMainTvView.get()) { 351c7f440dcd86ae88fc1b51e4394d66e4e80c9e53eJi-Hwan Lee sMainTvView = NULL_TV_VIEW; 352c7f440dcd86ae88fc1b51e4394d66e4e80c9e53eJi-Hwan Lee } 353c7f440dcd86ae88fc1b51e4394d66e4e80c9e53eJi-Hwan Lee } 354d0f00588834806d3f52c95c2d5fb13d9a92bddfcJi-Hwan Lee resetInternal(); 355d0f00588834806d3f52c95c2d5fb13d9a92bddfcJi-Hwan Lee } 356d0f00588834806d3f52c95c2d5fb13d9a92bddfcJi-Hwan Lee 357d0f00588834806d3f52c95c2d5fb13d9a92bddfcJi-Hwan Lee private void resetInternal() { 358b1ae00ec628d16c2fd1354c70e971d4757201753Jae Seo mSessionCallback = null; 35917345072864b9aeb4e5535257e83e6809859ae0fJae Seo mPendingAppPrivateCommands.clear(); 360b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo if (mSession != null) { 36117345072864b9aeb4e5535257e83e6809859ae0fJae Seo setSessionSurface(null); 36217345072864b9aeb4e5535257e83e6809859ae0fJae Seo removeSessionOverlayView(); 36317345072864b9aeb4e5535257e83e6809859ae0fJae Seo mUseRequestedSurfaceLayout = false; 36417345072864b9aeb4e5535257e83e6809859ae0fJae Seo mSession.release(); 36517345072864b9aeb4e5535257e83e6809859ae0fJae Seo mSession = null; 36671b282fad429dfa5e98287aa34af6aecd155321bYoungsang Cho resetSurfaceView(); 367b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo } 368b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo } 369b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo 370b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo /** 3719bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim * Requests to unblock TV content according to the given rating. 3720610e12733875a267f59d87a2a68aebbf486066eDongwon Kang * 3730610e12733875a267f59d87a2a68aebbf486066eDongwon Kang * <p>This notifies TV input that blocked content is now OK to play. 374903d6b72cd572665309633e925485464d08bb25aJaewan Kim * 3759bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim * @param unblockedRating A TvContentRating to unblock. 37691a801d42f3acc35404da51ba26605093922503aJae Seo * @see TvInputService.Session#notifyContentBlocked(TvContentRating) 377e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * @removed 378903d6b72cd572665309633e925485464d08bb25aJaewan Kim */ 3799bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim public void requestUnblockContent(TvContentRating unblockedRating) { 380a90338396c90f19b062b696cdb1ffcb8600755b2Jae Seo unblockContent(unblockedRating); 381a90338396c90f19b062b696cdb1ffcb8600755b2Jae Seo } 382a90338396c90f19b062b696cdb1ffcb8600755b2Jae Seo 383a90338396c90f19b062b696cdb1ffcb8600755b2Jae Seo /** 384a90338396c90f19b062b696cdb1ffcb8600755b2Jae Seo * Requests to unblock TV content according to the given rating. 385a90338396c90f19b062b696cdb1ffcb8600755b2Jae Seo * 386a90338396c90f19b062b696cdb1ffcb8600755b2Jae Seo * <p>This notifies TV input that blocked content is now OK to play. 387a90338396c90f19b062b696cdb1ffcb8600755b2Jae Seo * 388a90338396c90f19b062b696cdb1ffcb8600755b2Jae Seo * @param unblockedRating A TvContentRating to unblock. 389a90338396c90f19b062b696cdb1ffcb8600755b2Jae Seo * @see TvInputService.Session#notifyContentBlocked(TvContentRating) 390a90338396c90f19b062b696cdb1ffcb8600755b2Jae Seo * @hide 391a90338396c90f19b062b696cdb1ffcb8600755b2Jae Seo */ 392a90338396c90f19b062b696cdb1ffcb8600755b2Jae Seo @SystemApi 393e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) 394a90338396c90f19b062b696cdb1ffcb8600755b2Jae Seo public void unblockContent(TvContentRating unblockedRating) { 395903d6b72cd572665309633e925485464d08bb25aJaewan Kim if (mSession != null) { 396a90338396c90f19b062b696cdb1ffcb8600755b2Jae Seo mSession.unblockContent(unblockedRating); 397903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 398903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 399903d6b72cd572665309633e925485464d08bb25aJaewan Kim 400903d6b72cd572665309633e925485464d08bb25aJaewan Kim /** 4012c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo * Enables or disables the caption in this TvView. 4020610e12733875a267f59d87a2a68aebbf486066eDongwon Kang * 4030610e12733875a267f59d87a2a68aebbf486066eDongwon Kang * <p>Note that this method does not take any effect unless the current TvView is tuned. 4042c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo * 4052c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo * @param enabled {@code true} to enable, {@code false} to disable. 4062c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo */ 4072c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo public void setCaptionEnabled(boolean enabled) { 4081da8fb39499e8f5a962f7307fefdfd2ab6b79224Jae Seo if (DEBUG) Log.d(TAG, "setCaptionEnabled(" + enabled + ")"); 4091da8fb39499e8f5a962f7307fefdfd2ab6b79224Jae Seo mCaptionEnabled = enabled; 4102c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo if (mSession != null) { 4112c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo mSession.setCaptionEnabled(enabled); 4122c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 4132c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 4142c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo 4152c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo /** 4161f81b1040f40a3233981f34268b11e5c9ad9f34cDongwon Kang * Selects a track. 4172c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo * 41810d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo * @param type The type of the track to select. The type can be {@link TvTrackInfo#TYPE_AUDIO}, 41910d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo * {@link TvTrackInfo#TYPE_VIDEO} or {@link TvTrackInfo#TYPE_SUBTITLE}. 42010d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo * @param trackId The ID of the track to select. {@code null} means to unselect the current 42110d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo * track for a given type. 42210d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo * @see #getTracks 42310d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo * @see #getSelectedTrack 4241f213914c45c23c653f721690da2ce0718e63139Dongwon Kang */ 42510d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo public void selectTrack(int type, String trackId) { 4261f213914c45c23c653f721690da2ce0718e63139Dongwon Kang if (mSession != null) { 42710d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo mSession.selectTrack(type, trackId); 4281f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 4291f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 4301f213914c45c23c653f721690da2ce0718e63139Dongwon Kang 4311f213914c45c23c653f721690da2ce0718e63139Dongwon Kang /** 43210d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo * Returns the list of tracks. Returns {@code null} if the information is not available. 4331f213914c45c23c653f721690da2ce0718e63139Dongwon Kang * 43410d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo * @param type The type of the tracks. The type can be {@link TvTrackInfo#TYPE_AUDIO}, 43510d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo * {@link TvTrackInfo#TYPE_VIDEO} or {@link TvTrackInfo#TYPE_SUBTITLE}. 43610d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo * @see #selectTrack 43710d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo * @see #getSelectedTrack 4381f213914c45c23c653f721690da2ce0718e63139Dongwon Kang */ 43910d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo public List<TvTrackInfo> getTracks(int type) { 4401f213914c45c23c653f721690da2ce0718e63139Dongwon Kang if (mSession == null) { 4411f213914c45c23c653f721690da2ce0718e63139Dongwon Kang return null; 4421f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 44310d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo return mSession.getTracks(type); 4441f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 4451f213914c45c23c653f721690da2ce0718e63139Dongwon Kang 4461f213914c45c23c653f721690da2ce0718e63139Dongwon Kang /** 44710d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo * Returns the ID of the selected track for a given type. Returns {@code null} if the 44810d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo * information is not available or the track is not selected. 44910d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo * 45010d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo * @param type The type of the selected tracks. The type can be {@link TvTrackInfo#TYPE_AUDIO}, 45110d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo * {@link TvTrackInfo#TYPE_VIDEO} or {@link TvTrackInfo#TYPE_SUBTITLE}. 45210d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo * @see #selectTrack 45310d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo * @see #getTracks 454d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo */ 45510d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo public String getSelectedTrack(int type) { 456d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo if (mSession == null) { 457d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo return null; 458d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 45910d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo return mSession.getSelectedTrack(type); 460d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 461d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo 462d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo /** 463a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo * Plays a given recorded TV program. 464a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo * 465a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo * @param inputId The ID of the TV input that created the given recorded program. 466a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo * @param recordedProgramUri The URI of a recorded program. 467a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo */ 468a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo public void timeShiftPlay(String inputId, Uri recordedProgramUri) { 469a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo if (DEBUG) Log.d(TAG, "timeShiftPlay(" + recordedProgramUri + ")"); 470a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo if (TextUtils.isEmpty(inputId)) { 471a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo throw new IllegalArgumentException("inputId cannot be null or an empty string"); 472a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo } 473a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo synchronized (sMainTvViewLock) { 474a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo if (sMainTvView.get() == null) { 475a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo sMainTvView = new WeakReference<>(this); 476a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo } 477a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo } 478a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo if (mSessionCallback != null && TextUtils.equals(mSessionCallback.mInputId, inputId)) { 479a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo if (mSession != null) { 480a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo mSession.timeShiftPlay(recordedProgramUri); 481a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo } else { 482a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo mSessionCallback.mRecordedProgramUri = recordedProgramUri; 483a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo } 484a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo } else { 485a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo resetInternal(); 486a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo mSessionCallback = new MySessionCallback(inputId, recordedProgramUri); 487a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo if (mTvInputManager != null) { 488a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo mTvInputManager.createSession(inputId, mSessionCallback, mHandler); 489a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo } 490a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo } 491a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo } 492a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo 493a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo /** 494465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo * Pauses playback. No-op if it is already paused. Call {@link #timeShiftResume} to resume. 4956f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang */ 4966f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang public void timeShiftPause() { 4976f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang if (mSession != null) { 4986f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang mSession.timeShiftPause(); 4996f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 5006f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 5016f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang 5026f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang /** 503465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo * Resumes playback. No-op if it is already resumed. Call {@link #timeShiftPause} to pause. 5046f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang */ 5056f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang public void timeShiftResume() { 5066f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang if (mSession != null) { 5076f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang mSession.timeShiftResume(); 5086f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 5096f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 5106f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang 5116f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang /** 512465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo * Seeks to a specified time position. {@code timeMs} must be equal to or greater than the start 513465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo * position returned by {@link TimeShiftPositionCallback#onTimeShiftStartPositionChanged} and 514465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo * equal to or less than the current time. 5156f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang * 516465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo * @param timeMs The time position to seek to, in milliseconds since the epoch. 5176f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang */ 5186f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang public void timeShiftSeekTo(long timeMs) { 5196f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang if (mSession != null) { 5206f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang mSession.timeShiftSeekTo(timeMs); 5216f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 5226f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 5236f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang 5246f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang /** 5254b34cc77630112d00e9a87498d05f5f8803a9ff6Jae Seo * Sets playback rate using {@link android.media.PlaybackParams}. 5266f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang * 5273d04b7693428dd887c93e2ac7f4e90fd0cc87859Jae Seo * @param params The playback params. 5286f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang */ 5293d04b7693428dd887c93e2ac7f4e90fd0cc87859Jae Seo public void timeShiftSetPlaybackParams(@NonNull PlaybackParams params) { 5306f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang if (mSession != null) { 5314b34cc77630112d00e9a87498d05f5f8803a9ff6Jae Seo mSession.timeShiftSetPlaybackParams(params); 5326f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 5336f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 5346f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang 5356f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang /** 536465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo * Sets the callback to be invoked when the time shift position is changed. 5376f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang * 538465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo * @param callback The callback to receive time shift position changes. A value of {@code null} 539465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo * removes the existing callback. 5406f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang */ 5414bf607b00c14c031e991ac9dc0ad49b9249c9162Dongwon Kang public void setTimeShiftPositionCallback(@Nullable TimeShiftPositionCallback callback) { 542465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo mTimeShiftPositionCallback = callback; 543465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo ensurePositionTracking(); 5446f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 5456f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang 546465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo private void ensurePositionTracking() { 5476f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang if (mSession == null) { 5486f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang return; 5496f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 550465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo mSession.timeShiftEnablePositionTracking(mTimeShiftPositionCallback != null); 5516f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 5526f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang 5536f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang /** 554f714e62c12d99d816d70d09da60b6885a1368cefDongwon Kang * Sends a private command to the underlying TV input. This can be used to provide 555f714e62c12d99d816d70d09da60b6885a1368cefDongwon Kang * domain-specific features that are only known between certain clients and their TV inputs. 556a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo * 557887f52144eeea8d5812d64a29e207af6b97a763dJae Seo * @param action The name of the private command to send. This <em>must</em> be a scoped name, 558887f52144eeea8d5812d64a29e207af6b97a763dJae Seo * i.e. prefixed with a package name you own, so that different developers will not 559887f52144eeea8d5812d64a29e207af6b97a763dJae Seo * create conflicting commands. 560887f52144eeea8d5812d64a29e207af6b97a763dJae Seo * @param data An optional bundle to send with the command. 561a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo */ 562c8b7356434f665c494504661a943323c0bbe702eJae Seo public void sendAppPrivateCommand(@NonNull String action, Bundle data) { 563a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo if (TextUtils.isEmpty(action)) { 564a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo throw new IllegalArgumentException("action cannot be null or an empty string"); 565a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 566a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo if (mSession != null) { 567a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo mSession.sendAppPrivateCommand(action, data); 568887f52144eeea8d5812d64a29e207af6b97a763dJae Seo } else { 569411d58d330eafb093fe7edfa3fcccfadfc470076Jae Seo Log.w(TAG, "sendAppPrivateCommand - session not yet created (action \"" + action 570411d58d330eafb093fe7edfa3fcccfadfc470076Jae Seo + "\" pending)"); 571411d58d330eafb093fe7edfa3fcccfadfc470076Jae Seo mPendingAppPrivateCommands.add(Pair.create(action, data)); 572a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 573a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 574a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo 575a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo /** 5766a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo * Dispatches an unhandled input event to the next receiver. 5770610e12733875a267f59d87a2a68aebbf486066eDongwon Kang * 5780610e12733875a267f59d87a2a68aebbf486066eDongwon Kang * <p>Except system keys, TvView always consumes input events in the normal flow. This is called 5796a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo * asynchronously from where the event is dispatched. It gives the host application a chance to 5806a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo * dispatch the unhandled input events. 5816a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo * 5826a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo * @param event The input event. 5836a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo * @return {@code true} if the event was handled by the view, {@code false} otherwise. 5846a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo */ 5856a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo public boolean dispatchUnhandledInputEvent(InputEvent event) { 5866a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo if (mOnUnhandledInputEventListener != null) { 5876a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo if (mOnUnhandledInputEventListener.onUnhandledInputEvent(event)) { 5886a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo return true; 5896a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo } 5906a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo } 5916a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo return onUnhandledInputEvent(event); 5926a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo } 5936a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 5946a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo /** 5951f81b1040f40a3233981f34268b11e5c9ad9f34cDongwon Kang * Called when an unhandled input event also has not been handled by the user provided 5961f81b1040f40a3233981f34268b11e5c9ad9f34cDongwon Kang * callback. This is the last chance to handle the unhandled input event in the TvView. 5976a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo * 5986a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo * @param event The input event. 5996a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo * @return If you handled the event, return {@code true}. If you want to allow the event to be 6006a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo * handled by the next receiver, return {@code false}. 6016a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo */ 6026a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo public boolean onUnhandledInputEvent(InputEvent event) { 6036a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo return false; 6046a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo } 6056a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 6066a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo /** 6071f81b1040f40a3233981f34268b11e5c9ad9f34cDongwon Kang * Registers a callback to be invoked when an input event is not handled by the bound TV input. 6086a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo * 6091f81b1040f40a3233981f34268b11e5c9ad9f34cDongwon Kang * @param listener The callback to be invoked when the unhandled input event is received. 6106a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo */ 6116a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo public void setOnUnhandledInputEventListener(OnUnhandledInputEventListener listener) { 6126a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo mOnUnhandledInputEventListener = listener; 6136a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo } 6146a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 6156a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo @Override 6166a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo public boolean dispatchKeyEvent(KeyEvent event) { 6176a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo if (super.dispatchKeyEvent(event)) { 6186a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo return true; 6196a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo } 6206a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo if (DEBUG) Log.d(TAG, "dispatchKeyEvent(" + event + ")"); 6216a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo if (mSession == null) { 6226a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo return false; 6236a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo } 624f982613c81ef89cf33cc99498649e624b2a94a58Youngsang Cho InputEvent copiedEvent = event.copy(); 625f982613c81ef89cf33cc99498649e624b2a94a58Youngsang Cho int ret = mSession.dispatchInputEvent(copiedEvent, copiedEvent, mFinishedInputEventCallback, 626f982613c81ef89cf33cc99498649e624b2a94a58Youngsang Cho mHandler); 6276a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo return ret != Session.DISPATCH_NOT_HANDLED; 6286a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo } 6296a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 6306a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo @Override 6316a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo public boolean dispatchTouchEvent(MotionEvent event) { 6326a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo if (super.dispatchTouchEvent(event)) { 6336a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo return true; 6346a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo } 6356a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo if (DEBUG) Log.d(TAG, "dispatchTouchEvent(" + event + ")"); 6366a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo if (mSession == null) { 6376a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo return false; 6386a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo } 639f982613c81ef89cf33cc99498649e624b2a94a58Youngsang Cho InputEvent copiedEvent = event.copy(); 640f982613c81ef89cf33cc99498649e624b2a94a58Youngsang Cho int ret = mSession.dispatchInputEvent(copiedEvent, copiedEvent, mFinishedInputEventCallback, 641f982613c81ef89cf33cc99498649e624b2a94a58Youngsang Cho mHandler); 6426a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo return ret != Session.DISPATCH_NOT_HANDLED; 6436a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo } 6446a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 6456a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo @Override 6466a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo public boolean dispatchTrackballEvent(MotionEvent event) { 6476a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo if (super.dispatchTrackballEvent(event)) { 6486a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo return true; 6496a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo } 6506a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo if (DEBUG) Log.d(TAG, "dispatchTrackballEvent(" + event + ")"); 6516a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo if (mSession == null) { 6526a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo return false; 6536a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo } 654f982613c81ef89cf33cc99498649e624b2a94a58Youngsang Cho InputEvent copiedEvent = event.copy(); 655f982613c81ef89cf33cc99498649e624b2a94a58Youngsang Cho int ret = mSession.dispatchInputEvent(copiedEvent, copiedEvent, mFinishedInputEventCallback, 656f982613c81ef89cf33cc99498649e624b2a94a58Youngsang Cho mHandler); 6576a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo return ret != Session.DISPATCH_NOT_HANDLED; 6586a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo } 6596a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 6606a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo @Override 6616a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo public boolean dispatchGenericMotionEvent(MotionEvent event) { 6626a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo if (super.dispatchGenericMotionEvent(event)) { 6636a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo return true; 6646a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo } 6656a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo if (DEBUG) Log.d(TAG, "dispatchGenericMotionEvent(" + event + ")"); 6666a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo if (mSession == null) { 6676a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo return false; 6686a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo } 669f982613c81ef89cf33cc99498649e624b2a94a58Youngsang Cho InputEvent copiedEvent = event.copy(); 670f982613c81ef89cf33cc99498649e624b2a94a58Youngsang Cho int ret = mSession.dispatchInputEvent(copiedEvent, copiedEvent, mFinishedInputEventCallback, 671f982613c81ef89cf33cc99498649e624b2a94a58Youngsang Cho mHandler); 6726a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo return ret != Session.DISPATCH_NOT_HANDLED; 6736a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo } 6746a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 6759a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 6764c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee public void dispatchWindowFocusChanged(boolean hasFocus) { 6774c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee super.dispatchWindowFocusChanged(hasFocus); 6784c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee // Other app may have shown its own main TvView. 6794c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee // Set main again to regain main session. 6804c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee synchronized (sMainTvViewLock) { 681c7f440dcd86ae88fc1b51e4394d66e4e80c9e53eJi-Hwan Lee if (hasFocus && this == sMainTvView.get() && mSession != null) { 68215c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee mSession.setMain(); 6834c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 6844c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 6854c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 6864c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 6874c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee @Override 6889a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho protected void onAttachedToWindow() { 6899a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho super.onAttachedToWindow(); 6909a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho createSessionOverlayView(); 6919a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 6929a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 6939a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 6949a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho protected void onDetachedFromWindow() { 6959a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho removeSessionOverlayView(); 6969a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho super.onDetachedFromWindow(); 6979a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 6989a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 6999a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 7001bfce9fb9bffe8bd620fd1683572ae620f91772fJae Seo protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 701ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho if (DEBUG) { 702ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho Log.d(TAG, "onLayout (left=" + left + ", top=" + top + ", right=" + right 703ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho + ", bottom=" + bottom + ",)"); 704ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 705ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho if (mUseRequestedSurfaceLayout) { 706ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho mSurfaceView.layout(mSurfaceViewLeft, mSurfaceViewTop, mSurfaceViewRight, 707ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho mSurfaceViewBottom); 708ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } else { 709ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho mSurfaceView.layout(0, 0, right - left, bottom - top); 710ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 7111bfce9fb9bffe8bd620fd1683572ae620f91772fJae Seo } 7121bfce9fb9bffe8bd620fd1683572ae620f91772fJae Seo 7131bfce9fb9bffe8bd620fd1683572ae620f91772fJae Seo @Override 7141bfce9fb9bffe8bd620fd1683572ae620f91772fJae Seo protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 7151bfce9fb9bffe8bd620fd1683572ae620f91772fJae Seo mSurfaceView.measure(widthMeasureSpec, heightMeasureSpec); 7161bfce9fb9bffe8bd620fd1683572ae620f91772fJae Seo int width = mSurfaceView.getMeasuredWidth(); 7171bfce9fb9bffe8bd620fd1683572ae620f91772fJae Seo int height = mSurfaceView.getMeasuredHeight(); 7181bfce9fb9bffe8bd620fd1683572ae620f91772fJae Seo int childState = mSurfaceView.getMeasuredState(); 7191bfce9fb9bffe8bd620fd1683572ae620f91772fJae Seo setMeasuredDimension(resolveSizeAndState(width, widthMeasureSpec, childState), 7201bfce9fb9bffe8bd620fd1683572ae620f91772fJae Seo resolveSizeAndState(height, heightMeasureSpec, 7211bfce9fb9bffe8bd620fd1683572ae620f91772fJae Seo childState << MEASURED_HEIGHT_STATE_SHIFT)); 7221bfce9fb9bffe8bd620fd1683572ae620f91772fJae Seo } 7231bfce9fb9bffe8bd620fd1683572ae620f91772fJae Seo 7241bfce9fb9bffe8bd620fd1683572ae620f91772fJae Seo @Override 7255f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang public boolean gatherTransparentRegion(Region region) { 7265f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang if (mWindowZOrder != ZORDER_ON_TOP) { 7275f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang if (region != null) { 7285f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang int width = getWidth(); 7295f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang int height = getHeight(); 7305f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang if (width > 0 && height > 0) { 7315f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang int location[] = new int[2]; 7325f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang getLocationInWindow(location); 7335f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang int left = location[0]; 7345f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang int top = location[1]; 7355f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang region.op(left, top, left + width, top + height, Region.Op.UNION); 7365f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang } 7375f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang } 7385f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang } 7395f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang return super.gatherTransparentRegion(region); 7405f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang } 7415f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang 7425f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang @Override 7435f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang public void draw(Canvas canvas) { 7445f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang if (mWindowZOrder != ZORDER_ON_TOP) { 7455f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang // Punch a hole so that the underlying overlay view and surface can be shown. 7465f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang canvas.drawColor(0, PorterDuff.Mode.CLEAR); 7475f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang } 7485f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang super.draw(canvas); 7495f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang } 7505f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang 7515f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang @Override 7525f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang protected void dispatchDraw(Canvas canvas) { 7535f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang if (mWindowZOrder != ZORDER_ON_TOP) { 7545f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang // Punch a hole so that the underlying overlay view and surface can be shown. 7555f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang canvas.drawColor(0, PorterDuff.Mode.CLEAR); 7565f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang } 7575f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang super.dispatchDraw(canvas); 7585f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang } 7595f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang 7605f3cb4a584545927b3dcecb7cb47eb7edb6d2d5dDongwon Kang @Override 7616a1f2649a917ddec808e75f31efeb227133dd096Christofer Ã…kersten protected void onVisibilityChanged(View changedView, int visibility) { 7626a1f2649a917ddec808e75f31efeb227133dd096Christofer Ã…kersten super.onVisibilityChanged(changedView, visibility); 7631bfce9fb9bffe8bd620fd1683572ae620f91772fJae Seo mSurfaceView.setVisibility(visibility); 76407b7c5fa4cb705eea5d89f98e84341db5465d663Youngsang Cho if (visibility == View.VISIBLE) { 76507b7c5fa4cb705eea5d89f98e84341db5465d663Youngsang Cho createSessionOverlayView(); 76607b7c5fa4cb705eea5d89f98e84341db5465d663Youngsang Cho } else { 76707b7c5fa4cb705eea5d89f98e84341db5465d663Youngsang Cho removeSessionOverlayView(); 76807b7c5fa4cb705eea5d89f98e84341db5465d663Youngsang Cho } 7699a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 7709a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 77171b282fad429dfa5e98287aa34af6aecd155321bYoungsang Cho private void resetSurfaceView() { 77271b282fad429dfa5e98287aa34af6aecd155321bYoungsang Cho if (mSurfaceView != null) { 77371b282fad429dfa5e98287aa34af6aecd155321bYoungsang Cho mSurfaceView.getHolder().removeCallback(mSurfaceHolderCallback); 77471b282fad429dfa5e98287aa34af6aecd155321bYoungsang Cho removeView(mSurfaceView); 77571b282fad429dfa5e98287aa34af6aecd155321bYoungsang Cho } 77615c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee mSurface = null; 77771b282fad429dfa5e98287aa34af6aecd155321bYoungsang Cho mSurfaceView = new SurfaceView(getContext(), mAttrs, mDefStyleAttr) { 77871b282fad429dfa5e98287aa34af6aecd155321bYoungsang Cho @Override 77971b282fad429dfa5e98287aa34af6aecd155321bYoungsang Cho protected void updateWindow(boolean force, boolean redrawNeeded) { 78071b282fad429dfa5e98287aa34af6aecd155321bYoungsang Cho super.updateWindow(force, redrawNeeded); 78171b282fad429dfa5e98287aa34af6aecd155321bYoungsang Cho relayoutSessionOverlayView(); 78271b282fad429dfa5e98287aa34af6aecd155321bYoungsang Cho }}; 78322168a7dfccab1865bc43b4c43a340b27deee9bbJae Seo // The surface view's content should be treated as secure all the time. 78422168a7dfccab1865bc43b4c43a340b27deee9bbJae Seo mSurfaceView.setSecure(true); 78571b282fad429dfa5e98287aa34af6aecd155321bYoungsang Cho mSurfaceView.getHolder().addCallback(mSurfaceHolderCallback); 786bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho if (mWindowZOrder == ZORDER_MEDIA_OVERLAY) { 787bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho mSurfaceView.setZOrderMediaOverlay(true); 788bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho } else if (mWindowZOrder == ZORDER_ON_TOP) { 789bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho mSurfaceView.setZOrderOnTop(true); 790bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho } 79171b282fad429dfa5e98287aa34af6aecd155321bYoungsang Cho addView(mSurfaceView); 79271b282fad429dfa5e98287aa34af6aecd155321bYoungsang Cho } 79371b282fad429dfa5e98287aa34af6aecd155321bYoungsang Cho 7949a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho private void setSessionSurface(Surface surface) { 7959a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho if (mSession == null) { 7969a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho return; 7979a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 7989a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho mSession.setSurface(surface); 7999a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 8009a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 801e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho private void dispatchSurfaceChanged(int format, int width, int height) { 802e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho if (mSession == null) { 803e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho return; 804e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 805e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho mSession.dispatchSurfaceChanged(format, width, height); 806e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 807e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho 8089a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho private void createSessionOverlayView() { 8099a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho if (mSession == null || !isAttachedToWindow() 810bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho || mOverlayViewCreated || mWindowZOrder != ZORDER_MEDIA) { 8119a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho return; 8129a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 8139a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho mOverlayViewFrame = getViewFrameOnScreen(); 8149a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho mSession.createOverlayView(this, mOverlayViewFrame); 8159a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho mOverlayViewCreated = true; 8169a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 8179a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 8189a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho private void removeSessionOverlayView() { 8199a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho if (mSession == null || !mOverlayViewCreated) { 8209a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho return; 8219a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 8229a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho mSession.removeOverlayView(); 8239a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho mOverlayViewCreated = false; 8249a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho mOverlayViewFrame = null; 8259a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 8269a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 8279a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho private void relayoutSessionOverlayView() { 828bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho if (mSession == null || !isAttachedToWindow() || !mOverlayViewCreated 829bf0a4eb158ff5352dd2e7c456339cd36c28bcb43Youngsang Cho || mWindowZOrder != ZORDER_MEDIA) { 8309a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho return; 8319a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 8329a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Rect viewFrame = getViewFrameOnScreen(); 8339a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho if (viewFrame.equals(mOverlayViewFrame)) { 8349a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho return; 8359a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 8369a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho mSession.relayoutOverlayView(viewFrame); 8379a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho mOverlayViewFrame = viewFrame; 8389a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 8399a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 8409a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho private Rect getViewFrameOnScreen() { 8419a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho int[] location = new int[2]; 8429a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getLocationOnScreen(location); 8439a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho return new Rect(location[0], location[1], 8449a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho location[0] + getWidth(), location[1] + getHeight()); 8459a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 8469a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 8476a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo /** 848465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo * Callback used to receive time shift position changes. 8496f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang */ 8506f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang public abstract static class TimeShiftPositionCallback { 851465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo 8526f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang /** 8534e3ded556100f674ccba0d0e40adcbd0d30f9b23Jae Seo * This is called when the start position for time shifting has changed. 8540610e12733875a267f59d87a2a68aebbf486066eDongwon Kang * 8554e3ded556100f674ccba0d0e40adcbd0d30f9b23Jae Seo * <p>The start position for time shifting indicates the earliest possible time the user can 8564e3ded556100f674ccba0d0e40adcbd0d30f9b23Jae Seo * seek to. Initially this is equivalent to the time when the underlying TV input starts 8574e3ded556100f674ccba0d0e40adcbd0d30f9b23Jae Seo * recording. Later it may be adjusted because there is insufficient space or the duration 8584e3ded556100f674ccba0d0e40adcbd0d30f9b23Jae Seo * of recording is limited. The application must not allow the user to seek to a position 8594e3ded556100f674ccba0d0e40adcbd0d30f9b23Jae Seo * earlier than the start position. 8606f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang * 8614e3ded556100f674ccba0d0e40adcbd0d30f9b23Jae Seo * <p>For playback of a recorded program initiated by {@link #timeShiftPlay(String, Uri)}, 8624e3ded556100f674ccba0d0e40adcbd0d30f9b23Jae Seo * the start position is the time when playback starts. It does not change. 8633d04b7693428dd887c93e2ac7f4e90fd0cc87859Jae Seo * 8646f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang * @param inputId The ID of the TV input bound to this view. 8654e3ded556100f674ccba0d0e40adcbd0d30f9b23Jae Seo * @param timeMs The start position for time shifting, in milliseconds since the epoch. 8666f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang */ 8676f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang public void onTimeShiftStartPositionChanged(String inputId, long timeMs) { 8686f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 8696f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang 8706f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang /** 8714e3ded556100f674ccba0d0e40adcbd0d30f9b23Jae Seo * This is called when the current position for time shifting has changed. 8726f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang * 8734e3ded556100f674ccba0d0e40adcbd0d30f9b23Jae Seo * <p>The current position for time shifting is the same as the current position of 8744e3ded556100f674ccba0d0e40adcbd0d30f9b23Jae Seo * playback. During playback, the current position changes continuously. When paused, it 8754e3ded556100f674ccba0d0e40adcbd0d30f9b23Jae Seo * does not change. 8764e3ded556100f674ccba0d0e40adcbd0d30f9b23Jae Seo * 8774e3ded556100f674ccba0d0e40adcbd0d30f9b23Jae Seo * <p>Note that {@code timeMs} is wall-clock time. 8783d04b7693428dd887c93e2ac7f4e90fd0cc87859Jae Seo * 8796f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang * @param inputId The ID of the TV input bound to this view. 8804e3ded556100f674ccba0d0e40adcbd0d30f9b23Jae Seo * @param timeMs The current position for time shifting, in milliseconds since the epoch. 8816f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang */ 8826f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang public void onTimeShiftCurrentPositionChanged(String inputId, long timeMs) { 8836f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 8846f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 8856f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang 8866f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang /** 8872778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo * Callback used to receive various status updates on the {@link TvView}. 888b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo */ 8892778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo public abstract static class TvInputCallback { 890b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo 891b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo /** 8921553a528a5e2a2eeb94318601943fad2d9484bb3Jae Seo * This is invoked when an error occurred while establishing a connection to the underlying 8931553a528a5e2a2eeb94318601943fad2d9484bb3Jae Seo * TV input. 8941553a528a5e2a2eeb94318601943fad2d9484bb3Jae Seo * 8951553a528a5e2a2eeb94318601943fad2d9484bb3Jae Seo * @param inputId The ID of the TV input bound to this view. 8961553a528a5e2a2eeb94318601943fad2d9484bb3Jae Seo */ 8971553a528a5e2a2eeb94318601943fad2d9484bb3Jae Seo public void onConnectionFailed(String inputId) { 8981553a528a5e2a2eeb94318601943fad2d9484bb3Jae Seo } 8991553a528a5e2a2eeb94318601943fad2d9484bb3Jae Seo 9001553a528a5e2a2eeb94318601943fad2d9484bb3Jae Seo /** 9011553a528a5e2a2eeb94318601943fad2d9484bb3Jae Seo * This is invoked when the existing connection to the underlying TV input is lost. 902b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo * 903b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo * @param inputId The ID of the TV input bound to this view. 904b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo */ 9051553a528a5e2a2eeb94318601943fad2d9484bb3Jae Seo public void onDisconnected(String inputId) { 906b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo } 907b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo 908b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo /** 9091f213914c45c23c653f721690da2ce0718e63139Dongwon Kang * This is invoked when the channel of this TvView is changed by the underlying TV input 910e12d810e99da093d3cf38f89c81e3e8d1e75b404Dongwon Kang * without any {@link TvView#tune} request. 911b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo * 912b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo * @param inputId The ID of the TV input bound to this view. 9131f213914c45c23c653f721690da2ce0718e63139Dongwon Kang * @param channelUri The URI of a channel. 914b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo */ 9151f213914c45c23c653f721690da2ce0718e63139Dongwon Kang public void onChannelRetuned(String inputId, Uri channelUri) { 916b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo } 917b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo 918b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo /** 9191f213914c45c23c653f721690da2ce0718e63139Dongwon Kang * This is called when the track information has been changed. 920b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang * 921b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang * @param inputId The ID of the TV input bound to this view. 9221f213914c45c23c653f721690da2ce0718e63139Dongwon Kang * @param tracks A list which includes track information. 923b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang */ 92410d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo public void onTracksChanged(String inputId, List<TvTrackInfo> tracks) { 925b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 926b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang 927b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang /** 928d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo * This is called when there is a change on the selected tracks. 929d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo * 930d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo * @param inputId The ID of the TV input bound to this view. 93110d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo * @param type The type of the track selected. The type can be 93210d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo * {@link TvTrackInfo#TYPE_AUDIO}, {@link TvTrackInfo#TYPE_VIDEO} or 93310d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo * {@link TvTrackInfo#TYPE_SUBTITLE}. 93410d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo * @param trackId The ID of the track selected. 935d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo */ 93610d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo public void onTrackSelected(String inputId, int type, String trackId) { 937d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 938d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo 939d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo /** 9406320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo * This is invoked when the video size has been changed. It is also called when the first 9416320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo * time video size information becomes available after this view is tuned to a specific 9426320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo * channel. 9436320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo * 9446320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo * @param inputId The ID of the TV input bound to this view. 9456320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo * @param width The width of the video. 9466320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo * @param height The height of the video. 9476320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo */ 9486320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo public void onVideoSizeChanged(String inputId, int width, int height) { 9496320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo } 9506320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo 9516320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo /** 9529b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang * This is called when the video is available, so the TV input starts the playback. 9539b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang * 9549b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang * @param inputId The ID of the TV input bound to this view. 9559b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang */ 9569b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang public void onVideoAvailable(String inputId) { 9579b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 9589b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang 9599b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang /** 9609b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang * This is called when the video is not available, so the TV input stops the playback. 9619b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang * 9629b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang * @param inputId The ID of the TV input bound to this view. 9639b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang * @param reason The reason why the TV input stopped the playback: 9649b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang * <ul> 9659b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_UNKNOWN} 9666e62a1508cb7a5efcdde2ae9e51672fea4296dcaJae Seo * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_TUNING} 9679b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL} 9689b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_BUFFERING} 969ff1f29e1b112e68d16908b1a89225315089f8e50Dongwon Kang * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY} 9709b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang * </ul> 9719b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang */ 9723b9be6700fd631e25559693820d03389f8de3893Jae Seo public void onVideoUnavailable( 9733b9be6700fd631e25559693820d03389f8de3893Jae Seo String inputId, @TvInputManager.VideoUnavailableReason int reason) { 9749b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 9759b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang 9769b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang /** 977bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo * This is called when the current program content turns out to be allowed to watch since 978bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo * its content rating is not blocked by parental controls. 979bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo * 980bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo * @param inputId The ID of the TV input bound to this view. 981bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo */ 982bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo public void onContentAllowed(String inputId) { 983bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 984bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo 985bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo /** 986bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo * This is called when the current program content turns out to be not allowed to watch 987bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo * since its content rating is blocked by parental controls. 9886057102dbb746593a7d59cf377c969b62e38c664Jae Seo * 9896057102dbb746593a7d59cf377c969b62e38c664Jae Seo * @param inputId The ID of the TV input bound to this view. 9906057102dbb746593a7d59cf377c969b62e38c664Jae Seo * @param rating The content rating of the blocked program. 9916057102dbb746593a7d59cf377c969b62e38c664Jae Seo */ 9926057102dbb746593a7d59cf377c969b62e38c664Jae Seo public void onContentBlocked(String inputId, TvContentRating rating) { 9936057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 9946057102dbb746593a7d59cf377c969b62e38c664Jae Seo 9956057102dbb746593a7d59cf377c969b62e38c664Jae Seo /** 996b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo * This is invoked when a custom event from the bound TV input is sent to this view. 997b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo * 9986f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang * @param inputId The ID of the TV input bound to this view. 999b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo * @param eventType The type of the event. 1000b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo * @param eventArgs Optional arguments of the event. 1001b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo * @hide 1002b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo */ 100315bbf3b220fdd22df62f2bfa04452f4cdf11d2bbJae Seo @SystemApi 1004b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo public void onEvent(String inputId, String eventType, Bundle eventArgs) { 1005b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo } 10066f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang 10076f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang /** 10086f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang * This is called when the time shift status is changed. 10096f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang * 10106f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang * @param inputId The ID of the TV input bound to this view. 1011465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo * @param status The current time shift status. Should be one of the followings. 10126f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang * <ul> 1013465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo * <li>{@link TvInputManager#TIME_SHIFT_STATUS_UNSUPPORTED} 10146f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang * <li>{@link TvInputManager#TIME_SHIFT_STATUS_UNAVAILABLE} 1015465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo * <li>{@link TvInputManager#TIME_SHIFT_STATUS_AVAILABLE} 10166f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang * </ul> 10176f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang */ 10183b9be6700fd631e25559693820d03389f8de3893Jae Seo public void onTimeShiftStatusChanged( 10193b9be6700fd631e25559693820d03389f8de3893Jae Seo String inputId, @TvInputManager.TimeShiftStatus int status) { 10206f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 1021b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo } 1022b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo 1023b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo /** 10246a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo * Interface definition for a callback to be invoked when the unhandled input event is received. 10256a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo */ 10266a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo public interface OnUnhandledInputEventListener { 10276a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo /** 10286a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo * Called when an input event was not handled by the bound TV input. 10290610e12733875a267f59d87a2a68aebbf486066eDongwon Kang * 10300610e12733875a267f59d87a2a68aebbf486066eDongwon Kang * <p>This is called asynchronously from where the event is dispatched. It gives the host 10316a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo * application a chance to handle the unhandled input events. 10326a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo * 10336a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo * @param event The input event. 10346a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo * @return If you handled the event, return {@code true}. If you want to allow the event to 10356a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo * be handled by the next receiver, return {@code false}. 10366a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo */ 10376a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo boolean onUnhandledInputEvent(InputEvent event); 10386a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo } 10396a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 10402b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private class MySessionCallback extends SessionCallback { 1041b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo final String mInputId; 1042b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo Uri mChannelUri; 10431a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim Bundle mTuneParams; 1044a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo Uri mRecordedProgramUri; 10459a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 10461a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim MySessionCallback(String inputId, Uri channelUri, Bundle tuneParams) { 1047b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo mInputId = inputId; 1048b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo mChannelUri = channelUri; 10491a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim mTuneParams = tuneParams; 10509a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 10519a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 1052a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo MySessionCallback(String inputId, Uri recordedProgramUri) { 1053a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo mInputId = inputId; 1054a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo mRecordedProgramUri = recordedProgramUri; 1055a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo } 1056a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo 10579a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 10589a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void onSessionCreated(Session session) { 10596320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo if (DEBUG) { 10606320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo Log.d(TAG, "onSessionCreated()"); 10616320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo } 10622b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (this != mSessionCallback) { 10636320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo Log.w(TAG, "onSessionCreated - session already created"); 10649a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho // This callback is obsolete. 1065c31c450f5dd1436189fc4ac7a1ae26ef2fb19798Youngsang Cho if (session != null) { 1066c31c450f5dd1436189fc4ac7a1ae26ef2fb19798Youngsang Cho session.release(); 1067c31c450f5dd1436189fc4ac7a1ae26ef2fb19798Youngsang Cho } 10689a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho return; 10699a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 10709a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho mSession = session; 10719a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho if (session != null) { 1072411d58d330eafb093fe7edfa3fcccfadfc470076Jae Seo // Sends the pending app private commands first. 1073411d58d330eafb093fe7edfa3fcccfadfc470076Jae Seo for (Pair<String, Bundle> command : mPendingAppPrivateCommands) { 1074411d58d330eafb093fe7edfa3fcccfadfc470076Jae Seo mSession.sendAppPrivateCommand(command.first, command.second); 1075411d58d330eafb093fe7edfa3fcccfadfc470076Jae Seo } 1076411d58d330eafb093fe7edfa3fcccfadfc470076Jae Seo mPendingAppPrivateCommands.clear(); 1077411d58d330eafb093fe7edfa3fcccfadfc470076Jae Seo 10784c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee synchronized (sMainTvViewLock) { 1079c7f440dcd86ae88fc1b51e4394d66e4e80c9e53eJi-Hwan Lee if (hasWindowFocus() && TvView.this == sMainTvView.get()) { 108015c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee mSession.setMain(); 10814c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 10824c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 10839a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho // mSurface may not be ready yet as soon as starting an application. 10849a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho // In the case, we don't send Session.setSurface(null) unnecessarily. 10859a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho // setSessionSurface will be called in surfaceCreated. 10869a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho if (mSurface != null) { 10879a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho setSessionSurface(mSurface); 1088e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho if (mSurfaceChanged) { 1089e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho dispatchSurfaceChanged(mSurfaceFormat, mSurfaceWidth, mSurfaceHeight); 1090e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 10919a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 10929a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho createSessionOverlayView(); 10931da8fb39499e8f5a962f7307fefdfd2ab6b79224Jae Seo if (mStreamVolume != null) { 1094336cdf20dd44ee93b5173be73e26e966a2609eb0Dongwon Kang mSession.setStreamVolume(mStreamVolume); 1095336cdf20dd44ee93b5173be73e26e966a2609eb0Dongwon Kang } 10961da8fb39499e8f5a962f7307fefdfd2ab6b79224Jae Seo if (mCaptionEnabled != null) { 10971da8fb39499e8f5a962f7307fefdfd2ab6b79224Jae Seo mSession.setCaptionEnabled(mCaptionEnabled); 10981da8fb39499e8f5a962f7307fefdfd2ab6b79224Jae Seo } 1099a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo if (mChannelUri != null) { 1100a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo mSession.tune(mChannelUri, mTuneParams); 1101a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo } else { 1102a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo mSession.timeShiftPlay(mRecordedProgramUri); 1103a826d0172aae5e91d633ffe606059a2355fbf7e5Jae Seo } 1104465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo ensurePositionTracking(); 1105b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo } else { 11067cf67054550e8e6ea2379d7b0f0653796ce85062Youngsang Cho mSessionCallback = null; 11072778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo if (mCallback != null) { 11082778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo mCallback.onConnectionFailed(mInputId); 1109b8a64416e5e7cf39fd899fa600a940b0ef3c15fdJae Seo } 11109a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 11119a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 11122b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 11132b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim @Override 11142b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim public void onSessionReleased(Session session) { 11156320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo if (DEBUG) { 11166320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo Log.d(TAG, "onSessionReleased()"); 11176320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo } 1118e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho if (this != mSessionCallback) { 11196320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo Log.w(TAG, "onSessionReleased - session not created"); 1120e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho return; 11211f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 1122ffad70bb7efe08ab8f03cb93e783714232a101acChulwoo Lee mOverlayViewCreated = false; 1123ffad70bb7efe08ab8f03cb93e783714232a101acChulwoo Lee mOverlayViewFrame = null; 1124e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho mSessionCallback = null; 11252b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mSession = null; 11262778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo if (mCallback != null) { 11272778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo mCallback.onDisconnected(mInputId); 11282b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 11292b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 1130832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho 1131832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho @Override 11321f213914c45c23c653f721690da2ce0718e63139Dongwon Kang public void onChannelRetuned(Session session, Uri channelUri) { 1133a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (DEBUG) { 11341f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Log.d(TAG, "onChannelChangedByTvInput(" + channelUri + ")"); 1135a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 11366320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo if (this != mSessionCallback) { 11376320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo Log.w(TAG, "onChannelRetuned - session not created"); 11386320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo return; 11396320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo } 11402778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo if (mCallback != null) { 11412778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo mCallback.onChannelRetuned(mInputId, channelUri); 1142a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 1143a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 1144a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang 1145a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang @Override 114610d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo public void onTracksChanged(Session session, List<TvTrackInfo> tracks) { 11476320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo if (DEBUG) { 11486320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo Log.d(TAG, "onTracksChanged(" + tracks + ")"); 11496320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo } 11501f213914c45c23c653f721690da2ce0718e63139Dongwon Kang if (this != mSessionCallback) { 11516320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo Log.w(TAG, "onTracksChanged - session not created"); 11521f213914c45c23c653f721690da2ce0718e63139Dongwon Kang return; 1153832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 11542778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo if (mCallback != null) { 11552778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo mCallback.onTracksChanged(mInputId, tracks); 1156b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 1157b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 1158b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang 11596057102dbb746593a7d59cf377c969b62e38c664Jae Seo @Override 116010d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo public void onTrackSelected(Session session, int type, String trackId) { 11616320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo if (DEBUG) { 11626320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo Log.d(TAG, "onTrackSelected(type=" + type + ", trackId=" + trackId + ")"); 11636320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo } 1164d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo if (this != mSessionCallback) { 11656320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo Log.w(TAG, "onTrackSelected - session not created"); 1166d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo return; 1167d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 11682778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo if (mCallback != null) { 11692778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo mCallback.onTrackSelected(mInputId, type, trackId); 1170d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 1171d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 1172d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo 1173d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo @Override 11746320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo public void onVideoSizeChanged(Session session, int width, int height) { 11756320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo if (DEBUG) { 11766320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo Log.d(TAG, "onVideoSizeChanged()"); 11776320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo } 1178e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho if (this != mSessionCallback) { 11796320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo Log.w(TAG, "onVideoSizeChanged - session not created"); 1180e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho return; 1181e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 11826320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo if (mCallback != null) { 11836320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo mCallback.onVideoSizeChanged(mInputId, width, height); 11846320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo } 11856320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo } 11866320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo 11876320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo @Override 11886320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo public void onVideoAvailable(Session session) { 11899b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (DEBUG) { 11909b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Log.d(TAG, "onVideoAvailable()"); 11919b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 11926320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo if (this != mSessionCallback) { 11936320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo Log.w(TAG, "onVideoAvailable - session not created"); 11946320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo return; 11956320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo } 11962778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo if (mCallback != null) { 11972778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo mCallback.onVideoAvailable(mInputId); 11989b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 11999b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 12009b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang 12016057102dbb746593a7d59cf377c969b62e38c664Jae Seo @Override 12029b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang public void onVideoUnavailable(Session session, int reason) { 12036320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo if (DEBUG) { 12046320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo Log.d(TAG, "onVideoUnavailable(reason=" + reason + ")"); 12056320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo } 1206e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho if (this != mSessionCallback) { 12076320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo Log.w(TAG, "onVideoUnavailable - session not created"); 1208e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho return; 1209e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 12102778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo if (mCallback != null) { 12112778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo mCallback.onVideoUnavailable(mInputId, reason); 12129b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 12139b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 12149b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang 1215b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang @Override 1216bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo public void onContentAllowed(Session session) { 1217bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo if (DEBUG) { 1218bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo Log.d(TAG, "onContentAllowed()"); 1219bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 12206320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo if (this != mSessionCallback) { 12216320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo Log.w(TAG, "onContentAllowed - session not created"); 12226320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo return; 12236320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo } 12242778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo if (mCallback != null) { 12252778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo mCallback.onContentAllowed(mInputId); 1226bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 1227bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 1228bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo 1229bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo @Override 12306057102dbb746593a7d59cf377c969b62e38c664Jae Seo public void onContentBlocked(Session session, TvContentRating rating) { 12316320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo if (DEBUG) { 12326320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo Log.d(TAG, "onContentBlocked(rating=" + rating + ")"); 12336320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo } 1234774f6c3657dff9f05ffd90d9a4a90153d06180e1Ji-Hwan Lee if (this != mSessionCallback) { 12356320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo Log.w(TAG, "onContentBlocked - session not created"); 1236774f6c3657dff9f05ffd90d9a4a90153d06180e1Ji-Hwan Lee return; 1237774f6c3657dff9f05ffd90d9a4a90153d06180e1Ji-Hwan Lee } 12382778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo if (mCallback != null) { 12392778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo mCallback.onContentBlocked(mInputId, rating); 12406057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 12416057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 12426057102dbb746593a7d59cf377c969b62e38c664Jae Seo 1243bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo @Override 1244ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho public void onLayoutSurface(Session session, int left, int top, int right, int bottom) { 1245ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho if (DEBUG) { 1246ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho Log.d(TAG, "onLayoutSurface (left=" + left + ", top=" + top + ", right=" 1247ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho + right + ", bottom=" + bottom + ",)"); 1248ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 12496320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo if (this != mSessionCallback) { 12506320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo Log.w(TAG, "onLayoutSurface - session not created"); 12516320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo return; 12526320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo } 1253ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho mSurfaceViewLeft = left; 1254ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho mSurfaceViewTop = top; 1255ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho mSurfaceViewRight = right; 1256ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho mSurfaceViewBottom = bottom; 1257ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho mUseRequestedSurfaceLayout = true; 1258ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho requestLayout(); 1259ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 1260ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho 1261ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho @Override 1262903d6b72cd572665309633e925485464d08bb25aJaewan Kim public void onSessionEvent(Session session, String eventType, Bundle eventArgs) { 1263903d6b72cd572665309633e925485464d08bb25aJaewan Kim if (DEBUG) { 1264903d6b72cd572665309633e925485464d08bb25aJaewan Kim Log.d(TAG, "onSessionEvent(" + eventType + ")"); 1265903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 12666320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo if (this != mSessionCallback) { 12676320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo Log.w(TAG, "onSessionEvent - session not created"); 12686320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo return; 12696320fc490fe73b089cdccfc617e4b09f31f5d203Jae Seo } 12702778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo if (mCallback != null) { 12712778f5a7bd7c45861b6f2fc5639509e327495a4aJae Seo mCallback.onEvent(mInputId, eventType, eventArgs); 1272832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 1273832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 12746f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang 12756f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang @Override 12766f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang public void onTimeShiftStatusChanged(Session session, int status) { 12776f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang if (DEBUG) { 12786f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang Log.d(TAG, "onTimeShiftStatusChanged()"); 12796f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 12806f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang if (this != mSessionCallback) { 12816f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang Log.w(TAG, "onTimeShiftStatusChanged - session not created"); 12826f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang return; 12836f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 12846f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang if (mCallback != null) { 12856f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang mCallback.onTimeShiftStatusChanged(mInputId, status); 12866f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 12876f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 12886f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang 12896f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang @Override 12906f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang public void onTimeShiftStartPositionChanged(Session session, long timeMs) { 12916f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang if (DEBUG) { 12926f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang Log.d(TAG, "onTimeShiftStartPositionChanged()"); 12936f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 12946f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang if (this != mSessionCallback) { 12956f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang Log.w(TAG, "onTimeShiftStartPositionChanged - session not created"); 12966f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang return; 12976f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 1298465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo if (mTimeShiftPositionCallback != null) { 1299465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo mTimeShiftPositionCallback.onTimeShiftStartPositionChanged(mInputId, timeMs); 13006f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 13016f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 13026f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang 13036f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang @Override 13046f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang public void onTimeShiftCurrentPositionChanged(Session session, long timeMs) { 13056f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang if (DEBUG) { 13066f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang Log.d(TAG, "onTimeShiftCurrentPositionChanged()"); 13076f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 13086f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang if (this != mSessionCallback) { 13096f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang Log.w(TAG, "onTimeShiftCurrentPositionChanged - session not created"); 13106f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang return; 13116f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 1312465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo if (mTimeShiftPositionCallback != null) { 1313465f0d6aa36f2f1db88603aa487bcba9f5af068dJae Seo mTimeShiftPositionCallback.onTimeShiftCurrentPositionChanged(mInputId, timeMs); 13146f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 13156f0240cf63fe62b0af2c7d5112f9881d1e167bfcDongwon Kang } 13169a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13179a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho} 1318