1 /* 2 * Copyright 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.tv.common.support.tis; 17 18 import android.annotation.TargetApi; 19 import android.media.PlaybackParams; 20 import android.media.tv.TvContentRating; 21 import android.media.tv.TvInputManager; 22 import android.media.tv.TvInputService.Session; 23 import android.media.tv.TvTrackInfo; 24 import android.net.Uri; 25 import android.os.Build; 26 import android.os.Build.VERSION_CODES; 27 import android.support.annotation.FloatRange; 28 import android.support.annotation.NonNull; 29 import android.support.annotation.Nullable; 30 import android.view.Surface; 31 import android.view.View; 32 import java.util.List; 33 34 /** 35 * Custom {@link android.media.tv.TvInputService.Session} class that uses delegation and a callback 36 * to separate it from the TvInputService for easier testing. 37 */ 38 public abstract class TifSession { 39 40 private final TifSessionCallbacks callback; 41 42 /** 43 * Creates TV Input Framework Session with the given callback. 44 * 45 * <p>The callback is used to pass notification to the actual {@link 46 * android.media.tv.TvInputService.Session}. 47 * 48 * <p>Pass a mock callback for tests. 49 */ TifSession(TifSessionCallbacks callback)50 protected TifSession(TifSessionCallbacks callback) { 51 this.callback = callback; 52 } 53 54 /** 55 * Called after this session had been created and the callback is attached. 56 * 57 * <p>Do not call notify methods in the constructor, instead call them here if needed at 58 * creation time. eg @{@link Session#notifyTimeShiftStatusChanged(int)}. 59 */ onSessionCreated()60 public void onSessionCreated() {} 61 62 /** @see Session#onRelease() */ onRelease()63 public void onRelease() {} 64 65 /** @see Session#onSetSurface(Surface) */ onSetSurface(@ullable Surface surface)66 public abstract boolean onSetSurface(@Nullable Surface surface); 67 68 /** @see Session#onSurfaceChanged(int, int, int) */ onSurfaceChanged(int format, int width, int height)69 public abstract void onSurfaceChanged(int format, int width, int height); 70 71 /** @see Session#onSetStreamVolume(float) */ onSetStreamVolume(@loatRangefrom = 0.0, to = 1.0) float volume)72 public abstract void onSetStreamVolume(@FloatRange(from = 0.0, to = 1.0) float volume); 73 74 /** @see Session#onTune(Uri) */ onTune(Uri channelUri)75 public abstract boolean onTune(Uri channelUri); 76 77 /** @see Session#onSetCaptionEnabled(boolean) */ onSetCaptionEnabled(boolean enabled)78 public abstract void onSetCaptionEnabled(boolean enabled); 79 80 /** @see Session#onUnblockContent(TvContentRating) */ onUnblockContent(TvContentRating unblockedRating)81 public abstract void onUnblockContent(TvContentRating unblockedRating); 82 83 /** @see Session#onTimeShiftGetCurrentPosition() */ 84 @TargetApi(Build.VERSION_CODES.M) onTimeShiftGetCurrentPosition()85 public long onTimeShiftGetCurrentPosition() { 86 return TvInputManager.TIME_SHIFT_INVALID_TIME; 87 } 88 89 /** @see Session#onTimeShiftGetStartPosition() */ 90 @TargetApi(Build.VERSION_CODES.M) onTimeShiftGetStartPosition()91 public long onTimeShiftGetStartPosition() { 92 return TvInputManager.TIME_SHIFT_INVALID_TIME; 93 } 94 95 /** @see Session#onTimeShiftPause() */ 96 @TargetApi(Build.VERSION_CODES.M) onTimeShiftPause()97 public void onTimeShiftPause() {} 98 99 /** @see Session#onTimeShiftResume() */ 100 @TargetApi(Build.VERSION_CODES.M) onTimeShiftResume()101 public void onTimeShiftResume() {} 102 103 /** @see Session#onTimeShiftSeekTo(long) */ 104 @TargetApi(Build.VERSION_CODES.M) onTimeShiftSeekTo(long timeMs)105 public void onTimeShiftSeekTo(long timeMs) {} 106 107 /** @see Session#onTimeShiftSetPlaybackParams(PlaybackParams) */ 108 @TargetApi(Build.VERSION_CODES.M) onTimeShiftSetPlaybackParams(PlaybackParams params)109 public void onTimeShiftSetPlaybackParams(PlaybackParams params) {} 110 onParentalControlsChanged()111 public void onParentalControlsChanged() {} 112 113 /** @see Session#notifyChannelRetuned(Uri) */ notifyChannelRetuned(final Uri channelUri)114 public final void notifyChannelRetuned(final Uri channelUri) { 115 callback.notifyChannelRetuned(channelUri); 116 } 117 118 /** @see Session#notifyTracksChanged(List) */ notifyTracksChanged(final List<TvTrackInfo> tracks)119 public final void notifyTracksChanged(final List<TvTrackInfo> tracks) { 120 callback.notifyTracksChanged(tracks); 121 } 122 123 /** @see Session#notifyTrackSelected(int, String) */ notifyTrackSelected(final int type, final String trackId)124 public final void notifyTrackSelected(final int type, final String trackId) { 125 callback.notifyTrackSelected(type, trackId); 126 } 127 128 /** @see Session#notifyVideoAvailable() */ notifyVideoAvailable()129 public final void notifyVideoAvailable() { 130 callback.notifyVideoAvailable(); 131 } 132 133 /** @see Session#notifyVideoUnavailable(int) */ notifyVideoUnavailable(final int reason)134 public final void notifyVideoUnavailable(final int reason) { 135 callback.notifyVideoUnavailable(reason); 136 } 137 138 /** @see Session#notifyContentAllowed() */ notifyContentAllowed()139 public final void notifyContentAllowed() { 140 callback.notifyContentAllowed(); 141 } 142 143 /** @see Session#notifyContentBlocked(TvContentRating) */ notifyContentBlocked(@onNull final TvContentRating rating)144 public final void notifyContentBlocked(@NonNull final TvContentRating rating) { 145 callback.notifyContentBlocked(rating); 146 } 147 148 /** @see Session#notifyTimeShiftStatusChanged(int) */ 149 @TargetApi(VERSION_CODES.M) notifyTimeShiftStatusChanged(final int status)150 public final void notifyTimeShiftStatusChanged(final int status) { 151 callback.notifyTimeShiftStatusChanged(status); 152 } 153 154 /** @see Session#setOverlayViewEnabled(boolean) */ setOverlayViewEnabled(boolean enabled)155 public void setOverlayViewEnabled(boolean enabled) { 156 callback.setOverlayViewEnabled(enabled); 157 } 158 159 /** @see Session#onCreateOverlayView() */ onCreateOverlayView()160 public View onCreateOverlayView() { 161 return null; 162 } 163 164 /** @see Session#onOverlayViewSizeChanged(int, int) */ onOverlayViewSizeChanged(int width, int height)165 public void onOverlayViewSizeChanged(int width, int height) {} 166 167 /** 168 * Callbacks used to notify the {@link android.media.tv.TvInputService.Session}. 169 * 170 * <p>This is implemented internally by {@link WrappedSession}, and can be mocked for tests. 171 */ 172 public interface TifSessionCallbacks { 173 /** @see Session#notifyChannelRetuned(Uri) */ notifyChannelRetuned(final Uri channelUri)174 void notifyChannelRetuned(final Uri channelUri); 175 /** @see Session#notifyTracksChanged(List) */ notifyTracksChanged(final List<TvTrackInfo> tracks)176 void notifyTracksChanged(final List<TvTrackInfo> tracks); 177 /** @see Session#notifyTrackSelected(int, String) */ notifyTrackSelected(final int type, final String trackId)178 void notifyTrackSelected(final int type, final String trackId); 179 /** @see Session#notifyVideoAvailable() */ notifyVideoAvailable()180 void notifyVideoAvailable(); 181 /** @see Session#notifyVideoUnavailable(int) */ notifyVideoUnavailable(final int reason)182 void notifyVideoUnavailable(final int reason); 183 /** @see Session#notifyContentAllowed() */ notifyContentAllowed()184 void notifyContentAllowed(); 185 /** @see Session#notifyContentBlocked(TvContentRating) */ notifyContentBlocked(@onNull final TvContentRating rating)186 void notifyContentBlocked(@NonNull final TvContentRating rating); 187 /** @see Session#notifyTimeShiftStatusChanged(int) */ 188 @TargetApi(VERSION_CODES.M) notifyTimeShiftStatusChanged(final int status)189 void notifyTimeShiftStatusChanged(final int status); 190 /** @see Session#setOverlayViewEnabled(boolean) */ setOverlayViewEnabled(boolean enabled)191 void setOverlayViewEnabled(boolean enabled); 192 } 193 194 /** 195 * Creates a {@link TifSession}. 196 * 197 * <p>This is used by {@link WrappedSession} to create the desired {@code TifSession}. Should be 198 * used with <a href="http://go/autofactory">go/autofactory</a>. 199 */ 200 public interface TifSessionFactory { create(TifSessionCallbacks callbacks, String inputId)201 TifSession create(TifSessionCallbacks callbacks, String inputId); 202 } 203 } 204