Merge "TIAF cleanup: add missing APIs for main use cases"

This commit is contained in:
TreeHugger Robot
2021-12-24 11:26:22 +00:00
committed by Android (Google) Code Review
15 changed files with 1086 additions and 25 deletions

View File

@@ -20,8 +20,8 @@ import android.content.ComponentName;
import android.media.tv.AitInfo;
import android.media.tv.BroadcastInfoResponse;
import android.media.tv.ITvInputSession;
import android.net.Uri;
import android.media.tv.TvTrackInfo;
import android.net.Uri;
import android.os.Bundle;
import android.view.InputChannel;

View File

@@ -104,6 +104,7 @@ interface ITvInputManager {
// For broadcast info
void requestBroadcastInfo(in IBinder sessionToken, in BroadcastInfoRequest request, int userId);
void removeBroadcastInfo(in IBinder sessionToken, int id, int userId);
// For TV input hardware binding
List<TvInputHardwareInfo> getHardwareList();

View File

@@ -66,4 +66,5 @@ oneway interface ITvInputSession {
// For broadcast info
void requestBroadcastInfo(in BroadcastInfoRequest request);
void removeBroadcastInfo(int id);
}

View File

@@ -71,7 +71,8 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand
private static final int DO_PAUSE_RECORDING = 22;
private static final int DO_RESUME_RECORDING = 23;
private static final int DO_REQUEST_BROADCAST_INFO = 24;
private static final int DO_SET_IAPP_NOTIFICATION_ENABLED = 25;
private static final int DO_REMOVE_BROADCAST_INFO = 25;
private static final int DO_SET_IAPP_NOTIFICATION_ENABLED = 26;
private final boolean mIsRecordingSession;
private final HandlerCaller mCaller;
@@ -240,6 +241,10 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand
mTvInputSessionImpl.requestBroadcastInfo((BroadcastInfoRequest) msg.obj);
break;
}
case DO_REMOVE_BROADCAST_INFO: {
mTvInputSessionImpl.removeBroadcastInfo(msg.arg1);
break;
}
case DO_SET_IAPP_NOTIFICATION_ENABLED: {
mTvInputSessionImpl.setIAppNotificationEnabled((Boolean) msg.obj);
break;
@@ -404,6 +409,11 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand
mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_REQUEST_BROADCAST_INFO, request));
}
@Override
public void removeBroadcastInfo(int requestId) {
mCaller.executeOrSendMessage(mCaller.obtainMessageI(DO_REMOVE_BROADCAST_INFO, requestId));
}
private final class TvInputEventReceiver extends InputEventReceiver {
public TvInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);

View File

@@ -731,6 +731,9 @@ public final class TvInputManager {
@Override
public void run() {
mSessionCallback.onTracksChanged(mSession, tracks);
if (mSession.mIAppNotificationEnabled && mSession.getIAppSession() != null) {
mSession.getIAppSession().notifyTracksChanged(tracks);
}
}
});
}
@@ -740,6 +743,9 @@ public final class TvInputManager {
@Override
public void run() {
mSessionCallback.onTrackSelected(mSession, type, trackId);
if (mSession.mIAppNotificationEnabled && mSession.getIAppSession() != null) {
mSession.getIAppSession().notifyTrackSelected(type, trackId);
}
}
});
}
@@ -1273,12 +1279,6 @@ public final class TvInputManager {
}
record.postTuned(channelUri);
// TODO: synchronized and wrap the channelUri
if (record.mSession.mIAppNotificationEnabled) {
TvIAppManager.Session iappSession = record.mSession.mIAppSession;
if (iappSession != null) {
iappSession.notifyTuned(channelUri);
}
}
}
}
@@ -3014,7 +3014,23 @@ public final class TvInputManager {
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Removes broadcast info.
* @param requestId the corresponding request ID sent from
* {@link #requestBroadcastInfo(android.media.tv.BroadcastInfoRequest)}
*/
public void removeBroadcastInfo(int requestId) {
if (mToken == null) {
Log.w(TAG, "The session has been already released");
return;
}
try {
mService.removeBroadcastInfo(mToken, requestId, mUserId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
private final class InputEventHandler extends Handler {

View File

@@ -1044,6 +1044,12 @@ public abstract class TvInputService extends Service {
public void onRequestBroadcastInfo(@NonNull BroadcastInfoRequest request) {
}
/**
* @hide
*/
public void onRemoveBroadcastInfo(int requestId) {
}
/**
* Tunes to a given channel.
*
@@ -1653,6 +1659,10 @@ public abstract class TvInputService extends Service {
onRequestBroadcastInfo(request);
}
void removeBroadcastInfo(int requestId) {
onRemoveBroadcastInfo(requestId);
}
/**
* Takes care of dispatching incoming input events and tells whether the event was handled.
*/

View File

@@ -16,6 +16,7 @@
package android.media.tv.interactive;
import android.graphics.Rect;
import android.media.tv.BroadcastInfoRequest;
import android.net.Uri;
import android.os.Bundle;
@@ -31,7 +32,13 @@ oneway interface ITvIAppClient {
void onSessionReleased(int seq);
void onLayoutSurface(int left, int top, int right, int bottom, int seq);
void onBroadcastInfoRequest(in BroadcastInfoRequest request, int seq);
void onRemoveBroadcastInfo(int id, int seq);
void onSessionStateChanged(int state, int seq);
void onBiInteractiveAppCreated(in Uri biIAppUri, in String biIAppId, int seq);
void onCommandRequest(in String cmdType, in Bundle parameters, int seq);
void onSetVideoBounds(in Rect rect, int seq);
void onRequestCurrentChannelUri(int seq);
void onRequestCurrentChannelLcn(int seq);
void onRequestStreamVolume(int seq);
void onRequestTrackInfoList(int seq);
}

View File

@@ -18,6 +18,7 @@ package android.media.tv.interactive;
import android.graphics.Rect;
import android.media.tv.BroadcastInfoResponse;
import android.media.tv.TvTrackInfo;
import android.media.tv.interactive.ITvIAppClient;
import android.media.tv.interactive.ITvIAppManagerCallback;
import android.media.tv.interactive.TvIAppInfo;
@@ -35,13 +36,20 @@ interface ITvIAppManager {
void notifyAppLinkInfo(String tiasId, in Bundle info, int userId);
void sendAppLinkCommand(String tiasId, in Bundle command, int userId);
void startIApp(in IBinder sessionToken, int userId);
void stopIApp(in IBinder sessionToken, int userId);
void createBiInteractiveApp(
in IBinder sessionToken, in Uri biIAppUri, in Bundle params, int userId);
void destroyBiInteractiveApp(in IBinder sessionToken, in String biIAppId, int userId);
void sendCurrentChannelUri(in IBinder sessionToken, in Uri channelUri, int userId);
void sendCurrentChannelLcn(in IBinder sessionToken, int lcn, int userId);
void sendStreamVolume(in IBinder sessionToken, float volume, int userId);
void sendTrackInfoList(in IBinder sessionToken, in List<TvTrackInfo> tracks, int userId);
void createSession(
in ITvIAppClient client, in String iAppServiceId, int type, int seq, int userId);
void releaseSession(in IBinder sessionToken, int userId);
void notifyTuned(in IBinder sessionToken, in Uri channelUri, int userId);
void notifyTrackSelected(in IBinder sessionToken, int type, in String trackId, int userId);
void notifyTracksChanged(in IBinder sessionToken, in List<TvTrackInfo> tracks, int userId);
void setSurface(in IBinder sessionToken, in Surface surface, int userId);
void dispatchSurfaceChanged(in IBinder sessionToken, int format, int width, int height,
int userId);

View File

@@ -19,6 +19,8 @@ package android.media.tv.interactive;
import android.graphics.Rect;
import android.media.tv.BroadcastInfoResponse;
import android.net.Uri;
import android.media.tv.BroadcastInfoResponse;
import android.media.tv.TvTrackInfo;
import android.os.Bundle;
import android.view.Surface;
@@ -28,10 +30,17 @@ import android.view.Surface;
*/
oneway interface ITvIAppSession {
void startIApp();
void stopIApp();
void createBiInteractiveApp(in Uri biIAppUri, in Bundle params);
void destroyBiInteractiveApp(in String biIAppId);
void sendCurrentChannelUri(in Uri channelUri);
void sendCurrentChannelLcn(int lcn);
void sendStreamVolume(float volume);
void sendTrackInfoList(in List<TvTrackInfo> tracks);
void release();
void notifyTuned(in Uri channelUri);
void notifyTrackSelected(int type, in String trackId);
void notifyTracksChanged(in List<TvTrackInfo> tracks);
void setSurface(in Surface surface);
void dispatchSurfaceChanged(int format, int width, int height);
void notifyBroadcastInfoResponse(in BroadcastInfoResponse response);

View File

@@ -16,6 +16,7 @@
package android.media.tv.interactive;
import android.graphics.Rect;
import android.media.tv.BroadcastInfoRequest;
import android.media.tv.interactive.ITvIAppSession;
import android.media.tv.BroadcastInfoRequest;
@@ -31,7 +32,13 @@ oneway interface ITvIAppSessionCallback {
void onSessionCreated(in ITvIAppSession session);
void onLayoutSurface(int left, int top, int right, int bottom);
void onBroadcastInfoRequest(in BroadcastInfoRequest request);
void onRemoveBroadcastInfo(int id);
void onSessionStateChanged(int state);
void onBiInteractiveAppCreated(in Uri biIAppUri, in String biIAppId);
void onCommandRequest(in String cmdType, in Bundle parameters);
void onSetVideoBounds(in Rect rect);
void onRequestCurrentChannelUri();
void onRequestCurrentChannelLcn();
void onRequestStreamVolume();
void onRequestTrackInfoList();
}

View File

@@ -25,6 +25,7 @@ import android.graphics.Rect;
import android.media.tv.BroadcastInfoRequest;
import android.media.tv.BroadcastInfoResponse;
import android.media.tv.TvInputManager;
import android.media.tv.TvTrackInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -243,6 +244,18 @@ public final class TvIAppManager {
}
}
@Override
public void onRemoveBroadcastInfo(int requestId, int seq) {
synchronized (mSessionCallbackRecordMap) {
SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
if (record == null) {
Log.e(TAG, "Callback not found for seq " + seq);
return;
}
record.postRemoveBroadcastInfo(requestId);
}
}
@Override
public void onCommandRequest(@TvIAppService.IAppServiceCommandType String cmdType,
Bundle parameters, int seq) {
@@ -256,6 +269,66 @@ public final class TvIAppManager {
}
}
@Override
public void onSetVideoBounds(Rect rect, int seq) {
synchronized (mSessionCallbackRecordMap) {
SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
if (record == null) {
Log.e(TAG, "Callback not found for seq " + seq);
return;
}
record.postSetVideoBounds(rect);
}
}
@Override
public void onRequestCurrentChannelUri(int seq) {
synchronized (mSessionCallbackRecordMap) {
SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
if (record == null) {
Log.e(TAG, "Callback not found for seq " + seq);
return;
}
record.postRequestCurrentChannelUri();
}
}
@Override
public void onRequestCurrentChannelLcn(int seq) {
synchronized (mSessionCallbackRecordMap) {
SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
if (record == null) {
Log.e(TAG, "Callback not found for seq " + seq);
return;
}
record.postRequestCurrentChannelLcn();
}
}
@Override
public void onRequestStreamVolume(int seq) {
synchronized (mSessionCallbackRecordMap) {
SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
if (record == null) {
Log.e(TAG, "Callback not found for seq " + seq);
return;
}
record.postRequestStreamVolume();
}
}
@Override
public void onRequestTrackInfoList(int seq) {
synchronized (mSessionCallbackRecordMap) {
SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
if (record == null) {
Log.e(TAG, "Callback not found for seq " + seq);
return;
}
record.postRequestTrackInfoList();
}
}
@Override
public void onSessionStateChanged(int state, int seq) {
synchronized (mSessionCallbackRecordMap) {
@@ -634,6 +707,18 @@ public final class TvIAppManager {
}
}
void stopIApp() {
if (mToken == null) {
Log.w(TAG, "The session has been already released");
return;
}
try {
mService.stopIApp(mToken, mUserId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
void createBiInteractiveApp(Uri biIAppUri, Bundle params) {
if (mToken == null) {
Log.w(TAG, "The session has been already released");
@@ -658,6 +743,54 @@ public final class TvIAppManager {
}
}
void sendCurrentChannelUri(@Nullable Uri channelUri) {
if (mToken == null) {
Log.w(TAG, "The session has been already released");
return;
}
try {
mService.sendCurrentChannelUri(mToken, channelUri, mUserId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
void sendCurrentChannelLcn(int lcn) {
if (mToken == null) {
Log.w(TAG, "The session has been already released");
return;
}
try {
mService.sendCurrentChannelLcn(mToken, lcn, mUserId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
void sendStreamVolume(float volume) {
if (mToken == null) {
Log.w(TAG, "The session has been already released");
return;
}
try {
mService.sendStreamVolume(mToken, volume, mUserId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
void sendTrackInfoList(@NonNull List<TvTrackInfo> tracks) {
if (mToken == null) {
Log.w(TAG, "The session has been already released");
return;
}
try {
mService.sendTrackInfoList(mToken, tracks, mUserId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Sets the {@link android.view.Surface} for this session.
*
@@ -829,7 +962,7 @@ public final class TvIAppManager {
}
/**
* Notifies IAPP session when a channels is tuned.
* Notifies IAPP session when a channel is tuned.
*/
public void notifyTuned(Uri channelUri) {
if (mToken == null) {
@@ -843,6 +976,36 @@ public final class TvIAppManager {
}
}
/**
* Notifies IAPP session when a track is selected.
*/
public void notifyTrackSelected(int type, String trackId) {
if (mToken == null) {
Log.w(TAG, "The session has been already released");
return;
}
try {
mService.notifyTrackSelected(mToken, type, trackId, mUserId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Notifies IAPP session when tracks are changed.
*/
public void notifyTracksChanged(List<TvTrackInfo> tracks) {
if (mToken == null) {
Log.w(TAG, "The session has been already released");
return;
}
try {
mService.notifyTracksChanged(mToken, tracks, mUserId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
private void flushPendingEventsLocked() {
mHandler.removeMessages(InputEventHandler.MSG_FLUSH_INPUT_EVENT);
@@ -1095,6 +1258,15 @@ public final class TvIAppManager {
});
}
void postRemoveBroadcastInfo(final int requestId) {
mHandler.post(new Runnable() {
@Override
public void run() {
mSession.getInputSession().removeBroadcastInfo(requestId);
}
});
}
void postCommandRequest(final @TvIAppService.IAppServiceCommandType String cmdType,
final Bundle parameters) {
mHandler.post(new Runnable() {
@@ -1105,6 +1277,51 @@ public final class TvIAppManager {
});
}
void postSetVideoBounds(Rect rect) {
mHandler.post(new Runnable() {
@Override
public void run() {
mSessionCallback.onSetVideoBounds(mSession, rect);
}
});
}
void postRequestCurrentChannelUri() {
mHandler.post(new Runnable() {
@Override
public void run() {
mSessionCallback.onRequestCurrentChannelUri(mSession);
}
});
}
void postRequestCurrentChannelLcn() {
mHandler.post(new Runnable() {
@Override
public void run() {
mSessionCallback.onRequestCurrentChannelLcn(mSession);
}
});
}
void postRequestStreamVolume() {
mHandler.post(new Runnable() {
@Override
public void run() {
mSessionCallback.onRequestStreamVolume(mSession);
}
});
}
void postRequestTrackInfoList() {
mHandler.post(new Runnable() {
@Override
public void run() {
mSessionCallback.onRequestTrackInfoList(mSession);
}
});
}
void postSessionStateChanged(int state) {
mHandler.post(new Runnable() {
@Override
@@ -1171,6 +1388,46 @@ public final class TvIAppManager {
@TvIAppService.IAppServiceCommandType String cmdType, Bundle parameters) {
}
/**
* This is called when {@link TvIAppService.Session#SetVideoBounds} is called.
*
* @param session A {@link TvIAppManager.Session} associated with this callback.
*/
public void onSetVideoBounds(Session session, Rect rect) {
}
/**
* This is called when {@link TvIAppService.Session#RequestCurrentChannelUri} is called.
*
* @param session A {@link TvIAppManager.Session} associated with this callback.
*/
public void onRequestCurrentChannelUri(Session session) {
}
/**
* This is called when {@link TvIAppService.Session#RequestCurrentChannelLcn} is called.
*
* @param session A {@link TvIAppManager.Session} associated with this callback.
*/
public void onRequestCurrentChannelLcn(Session session) {
}
/**
* This is called when {@link TvIAppService.Session#RequestStreamVolume} is called.
*
* @param session A {@link TvIAppManager.Session} associated with this callback.
*/
public void onRequestStreamVolume(Session session) {
}
/**
* This is called when {@link TvIAppService.Session#RequestTrackInfoList} is called.
*
* @param session A {@link TvIAppManager.Session} associated with this callback.
*/
public void onRequestTrackInfoList(Session session) {
}
/**
* This is called when {@link TvIAppService.Session#notifySessionStateChanged} is called.
*

View File

@@ -29,6 +29,7 @@ import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.media.tv.BroadcastInfoRequest;
import android.media.tv.BroadcastInfoResponse;
import android.media.tv.TvTrackInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
@@ -90,23 +91,26 @@ public abstract class TvIAppService extends Service {
@Retention(RetentionPolicy.SOURCE)
@StringDef(prefix = "IAPP_SERVICE_COMMAND_TYPE_", value = {
IAPP_SERVICE_COMMAND_TYPE_TUNE,
IAPP_SERVICE_COMMAND_TYPE_TUNENEXT,
IAPP_SERVICE_COMMAND_TYPE_TUNEPREV,
IAPP_SERVICE_COMMAND_TYPE_TUNE_NEXT,
IAPP_SERVICE_COMMAND_TYPE_TUNE_PREV,
IAPP_SERVICE_COMMAND_TYPE_STOP,
IAPP_SERVICE_COMMAND_TYPE_SETSTREAMVOLUME
IAPP_SERVICE_COMMAND_TYPE_SET_STREAM_VOLUME,
IAPP_SERVICE_COMMAND_TYPE_SELECT_TRACK
})
public @interface IAppServiceCommandType {}
/** @hide */
public static final String IAPP_SERVICE_COMMAND_TYPE_TUNE = "Tune";
public static final String IAPP_SERVICE_COMMAND_TYPE_TUNE = "tune";
/** @hide */
public static final String IAPP_SERVICE_COMMAND_TYPE_TUNENEXT = "TuneNext";
public static final String IAPP_SERVICE_COMMAND_TYPE_TUNE_NEXT = "tune_next";
/** @hide */
public static final String IAPP_SERVICE_COMMAND_TYPE_TUNEPREV = "TunePrevious";
public static final String IAPP_SERVICE_COMMAND_TYPE_TUNE_PREV = "tune_previous";
/** @hide */
public static final String IAPP_SERVICE_COMMAND_TYPE_STOP = "Stop";
public static final String IAPP_SERVICE_COMMAND_TYPE_STOP = "stop";
/** @hide */
public static final String IAPP_SERVICE_COMMAND_TYPE_SETSTREAMVOLUME = "setStreamVolume";
public static final String IAPP_SERVICE_COMMAND_TYPE_SET_STREAM_VOLUME = "set_stream_volume";
/** @hide */
public static final String IAPP_SERVICE_COMMAND_TYPE_SELECT_TRACK = "select_track";
private final Handler mServiceHandler = new ServiceHandler();
private final RemoteCallbackList<ITvIAppServiceCallback> mCallbacks =
@@ -287,6 +291,13 @@ public abstract class TvIAppService extends Service {
public void onStartIApp() {
}
/**
* Stops TvIAppService session.
* @hide
*/
public void onStopIApp() {
}
/**
* Creates broadcast-independent(BI) interactive application.
*
@@ -309,6 +320,34 @@ public abstract class TvIAppService extends Service {
public void onDestroyBiInteractiveApp(@NonNull String biIAppId) {
}
/**
* Receives current channel URI.
* @hide
*/
public void onCurrentChannelUri(@Nullable Uri channelUri) {
}
/**
* Receives logical channel number (LCN) of current channel.
* @hide
*/
public void onCurrentChannelLcn(int lcn) {
}
/**
* Receives stream volume.
* @hide
*/
public void onStreamVolume(float volume) {
}
/**
* Receives track list.
* @hide
*/
public void onTrackInfoList(@NonNull List<TvTrackInfo> tracks) {
}
/**
* Called when the application sets the surface.
*
@@ -373,6 +412,20 @@ public abstract class TvIAppService extends Service {
public void onTuned(@NonNull Uri channelUri) {
}
/**
* Called when the corresponding TV input selected to a track.
* @hide
*/
public void onTrackSelected(int type, String trackId) {
}
/**
* Called when the tracks are changed.
* @hide
*/
public void onTracksChanged(List<TvTrackInfo> tracks) {
}
/**
* Called when a broadcast info response is received.
* @hide
@@ -491,6 +544,30 @@ public abstract class TvIAppService extends Service {
});
}
/**
* Remove broadcast information request from the related TV input.
* @param requestId the ID of the request
*/
public void removeBroadcastInfo(final int requestId) {
executeOrPostRunnableOnMainThread(new Runnable() {
@MainThread
@Override
public void run() {
try {
if (DEBUG) {
Log.d(TAG, "removeBroadcastInfo (requestId="
+ requestId + ")");
}
if (mSessionCallback != null) {
mSessionCallback.onRemoveBroadcastInfo(requestId);
}
} catch (RemoteException e) {
Log.w(TAG, "error in removeBroadcastInfo", e);
}
}
});
}
/**
* requests a specific command to be processed by the related TV input.
* @param cmdType type of the specific command
@@ -516,10 +593,124 @@ public abstract class TvIAppService extends Service {
});
}
/**
* Sets broadcast video bounds.
*/
public void setVideoBounds(Rect rect) {
executeOrPostRunnableOnMainThread(new Runnable() {
@MainThread
@Override
public void run() {
try {
if (DEBUG) {
Log.d(TAG, "setVideoBounds (rect=" + rect + ")");
}
if (mSessionCallback != null) {
mSessionCallback.onSetVideoBounds(rect);
}
} catch (RemoteException e) {
Log.w(TAG, "error in setVideoBounds", e);
}
}
});
}
/**
* Requests the URI of the current channel.
*/
public void requestCurrentChannelUri() {
executeOrPostRunnableOnMainThread(new Runnable() {
@MainThread
@Override
public void run() {
try {
if (DEBUG) {
Log.d(TAG, "requestCurrentChannelUri");
}
if (mSessionCallback != null) {
mSessionCallback.onRequestCurrentChannelUri();
}
} catch (RemoteException e) {
Log.w(TAG, "error in requestCurrentChannelUri", e);
}
}
});
}
/**
* Requests the logic channel number (LCN) of the current channel.
*/
public void requestCurrentChannelLcn() {
executeOrPostRunnableOnMainThread(new Runnable() {
@MainThread
@Override
public void run() {
try {
if (DEBUG) {
Log.d(TAG, "requestCurrentChannelLcn");
}
if (mSessionCallback != null) {
mSessionCallback.onRequestCurrentChannelLcn();
}
} catch (RemoteException e) {
Log.w(TAG, "error in requestCurrentChannelLcn", e);
}
}
});
}
/**
* Requests stream volume.
*/
public void requestStreamVolume() {
executeOrPostRunnableOnMainThread(new Runnable() {
@MainThread
@Override
public void run() {
try {
if (DEBUG) {
Log.d(TAG, "requestStreamVolume");
}
if (mSessionCallback != null) {
mSessionCallback.onRequestStreamVolume();
}
} catch (RemoteException e) {
Log.w(TAG, "error in requestStreamVolume", e);
}
}
});
}
/**
* Requests the list of {@link TvTrackInfo}.
*/
public void requestTrackInfoList() {
executeOrPostRunnableOnMainThread(new Runnable() {
@MainThread
@Override
public void run() {
try {
if (DEBUG) {
Log.d(TAG, "requestTrackInfoList");
}
if (mSessionCallback != null) {
mSessionCallback.onRequestTrackInfoList();
}
} catch (RemoteException e) {
Log.w(TAG, "error in requestTrackInfoList", e);
}
}
});
}
void startIApp() {
onStartIApp();
}
void stopIApp() {
onStopIApp();
}
void createBiInteractiveApp(@NonNull Uri biIAppUri, @Nullable Bundle params) {
onCreateBiInteractiveApp(biIAppUri, params);
}
@@ -528,6 +719,22 @@ public abstract class TvIAppService extends Service {
onDestroyBiInteractiveApp(biIAppId);
}
void sendCurrentChannelUri(@Nullable Uri channelUri) {
onCurrentChannelUri(channelUri);
}
void sendCurrentChannelLcn(int lcn) {
onCurrentChannelLcn(lcn);
}
void sendStreamVolume(float volume) {
onStreamVolume(volume);
}
void sendTrackInfoList(@NonNull List<TvTrackInfo> tracks) {
onTrackInfoList(tracks);
}
void release() {
onRelease();
if (mSurface != null) {
@@ -550,6 +757,20 @@ public abstract class TvIAppService extends Service {
onTuned(channelUri);
}
void notifyTrackSelected(int type, String trackId) {
if (DEBUG) {
Log.d(TAG, "notifyTrackSelected (type=" + type + "trackId=" + trackId + ")");
}
onTrackSelected(type, trackId);
}
void notifyTracksChanged(List<TvTrackInfo> tracks) {
if (DEBUG) {
Log.d(TAG, "notifyTracksChanged (tracks=" + tracks + ")");
}
onTracksChanged(tracks);
}
/**
* Calls {@link #onBroadcastInfoResponse}.
@@ -850,15 +1071,40 @@ public abstract class TvIAppService extends Service {
}
@Override
public void createBiInteractiveApp(Uri biIAppUri, Bundle params) {
public void stopIApp() {
mSessionImpl.stopIApp();
}
@Override
public void createBiInteractiveApp(@NonNull Uri biIAppUri, @Nullable Bundle params) {
mSessionImpl.createBiInteractiveApp(biIAppUri, params);
}
@Override
public void destroyBiInteractiveApp(String biIAppId) {
public void destroyBiInteractiveApp(@NonNull String biIAppId) {
mSessionImpl.destroyBiInteractiveApp(biIAppId);
}
@Override
public void sendCurrentChannelUri(@Nullable Uri channelUri) {
mSessionImpl.sendCurrentChannelUri(channelUri);
}
@Override
public void sendCurrentChannelLcn(int lcn) {
mSessionImpl.sendCurrentChannelLcn(lcn);
}
@Override
public void sendStreamVolume(float volume) {
mSessionImpl.sendStreamVolume(volume);
}
@Override
public void sendTrackInfoList(@NonNull List<TvTrackInfo> tracks) {
mSessionImpl.sendTrackInfoList(tracks);
}
@Override
public void release() {
mSessionImpl.scheduleMediaViewCleanup();
@@ -870,6 +1116,16 @@ public abstract class TvIAppService extends Service {
mSessionImpl.notifyTuned(channelUri);
}
@Override
public void notifyTrackSelected(int type, final String trackId) {
mSessionImpl.notifyTrackSelected(type, trackId);
}
@Override
public void notifyTracksChanged(List<TvTrackInfo> tracks) {
mSessionImpl.notifyTracksChanged(tracks);
}
@Override
public void setSurface(Surface surface) {
mSessionImpl.setSurface(surface);

View File

@@ -24,6 +24,7 @@ import android.content.res.XmlResourceParser;
import android.graphics.Rect;
import android.graphics.RectF;
import android.media.tv.TvInputManager;
import android.media.tv.TvTrackInfo;
import android.media.tv.TvView;
import android.media.tv.interactive.TvIAppManager.Session;
import android.media.tv.interactive.TvIAppManager.SessionCallback;
@@ -39,6 +40,8 @@ import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
/**
* Displays contents of interactive TV applications.
* @hide
@@ -291,6 +294,66 @@ public class TvIAppView extends ViewGroup {
}
}
/**
* Stops the interactive application.
*/
public void stopIApp() {
if (DEBUG) {
Log.d(TAG, "stopIApp");
}
if (mSession != null) {
mSession.stopIApp();
}
}
/**
* Sends current channel URI to related TV interactive app.
*/
public void sendCurrentChannelUri(Uri channelUri) {
if (DEBUG) {
Log.d(TAG, "sendCurrentChannelUri");
}
if (mSession != null) {
mSession.sendCurrentChannelUri(channelUri);
}
}
/**
* Sends current channel logical channel number (LCN) to related TV interactive app.
*/
public void sendCurrentChannelLcn(int lcn) {
if (DEBUG) {
Log.d(TAG, "sendCurrentChannelLcn");
}
if (mSession != null) {
mSession.sendCurrentChannelLcn(lcn);
}
}
/**
* Sends stream volume to related TV interactive app.
*/
public void sendStreamVolume(float volume) {
if (DEBUG) {
Log.d(TAG, "sendStreamVolume");
}
if (mSession != null) {
mSession.sendStreamVolume(volume);
}
}
/**
* Sends track info list to related TV interactive app.
*/
public void sendTrackInfoList(List<TvTrackInfo> tracks) {
if (DEBUG) {
Log.d(TAG, "sendTrackInfoList");
}
if (mSession != null) {
mSession.sendTrackInfoList(tracks);
}
}
private void resetInternal() {
mSessionCallback = null;
if (mSession != null) {
@@ -380,8 +443,10 @@ public class TvIAppView extends ViewGroup {
* @param cmdType type of the command
* @param parameters parameters of the command
*/
public void onCommandRequest(String iAppServiceId,
@TvIAppService.IAppServiceCommandType String cmdType, Bundle parameters) {
public void onCommandRequest(
@NonNull String iAppServiceId,
@NonNull @TvIAppService.IAppServiceCommandType String cmdType,
@Nullable Bundle parameters) {
}
/**
@@ -390,7 +455,7 @@ public class TvIAppView extends ViewGroup {
* @param iAppServiceId The ID of the TV interactive app service bound to this view.
* @param state current session state.
*/
public void onSessionStateChanged(String iAppServiceId, int state) {
public void onSessionStateChanged(@NonNull String iAppServiceId, int state) {
}
/**
@@ -402,8 +467,48 @@ public class TvIAppView extends ViewGroup {
* @param biIAppId BI interactive app ID, which can be used to destroy the BI interactive
* app.
*/
public void onBiInteractiveAppCreated(String iAppServiceId, Uri biIAppUri,
String biIAppId) {
public void onBiInteractiveAppCreated(@NonNull String iAppServiceId, @NonNull Uri biIAppUri,
@Nullable String biIAppId) {
}
/**
* This is called when {@link TvIAppService.Session#SetVideoBounds} is called.
*
* @param iAppServiceId The ID of the TV interactive app service bound to this view.
*/
public void onSetVideoBounds(@NonNull String iAppServiceId, @NonNull Rect rect) {
}
/**
* This is called when {@link TvIAppService.Session#RequestCurrentChannelUri} is called.
*
* @param iAppServiceId The ID of the TV interactive app service bound to this view.
*/
public void onRequestCurrentChannelUri(@NonNull String iAppServiceId) {
}
/**
* This is called when {@link TvIAppService.Session#RequestCurrentChannelLcn} is called.
*
* @param iAppServiceId The ID of the TV interactive app service bound to this view.
*/
public void onRequestCurrentChannelLcn(@NonNull String iAppServiceId) {
}
/**
* This is called when {@link TvIAppService.Session#RequestStreamVolume} is called.
*
* @param iAppServiceId The ID of the TV interactive app service bound to this view.
*/
public void onRequestStreamVolume(@NonNull String iAppServiceId) {
}
/**
* This is called when {@link TvIAppService.Session#RequestTrackInfoList} is called.
*
* @param iAppServiceId The ID of the TV interactive app service bound to this view.
*/
public void onRequestTrackInfoList(@NonNull String iAppServiceId) {
}
}
@@ -525,5 +630,75 @@ public class TvIAppView extends ViewGroup {
mCallback.onBiInteractiveAppCreated(mIAppServiceId, biIAppUri, biIAppId);
}
}
@Override
public void onSetVideoBounds(Session session, Rect rect) {
if (DEBUG) {
Log.d(TAG, "onSetVideoBounds (rect=" + rect + ")");
}
if (this != mSessionCallback) {
Log.w(TAG, "onSetVideoBounds - session not created");
return;
}
if (mCallback != null) {
mCallback.onSetVideoBounds(mIAppServiceId, rect);
}
}
@Override
public void onRequestCurrentChannelUri(Session session) {
if (DEBUG) {
Log.d(TAG, "onRequestCurrentChannelUri");
}
if (this != mSessionCallback) {
Log.w(TAG, "onRequestCurrentChannelUri - session not created");
return;
}
if (mCallback != null) {
mCallback.onRequestCurrentChannelUri(mIAppServiceId);
}
}
@Override
public void onRequestCurrentChannelLcn(Session session) {
if (DEBUG) {
Log.d(TAG, "onRequestCurrentChannelLcn");
}
if (this != mSessionCallback) {
Log.w(TAG, "onRequestCurrentChannelLcn - session not created");
return;
}
if (mCallback != null) {
mCallback.onRequestCurrentChannelLcn(mIAppServiceId);
}
}
@Override
public void onRequestStreamVolume(Session session) {
if (DEBUG) {
Log.d(TAG, "onRequestStreamVolume");
}
if (this != mSessionCallback) {
Log.w(TAG, "onRequestStreamVolume - session not created");
return;
}
if (mCallback != null) {
mCallback.onRequestStreamVolume(mIAppServiceId);
}
}
@Override
public void onRequestTrackInfoList(Session session) {
if (DEBUG) {
Log.d(TAG, "onRequestTrackInfoList");
}
if (this != mSessionCallback) {
Log.w(TAG, "onRequestTrackInfoList - session not created");
return;
}
if (mCallback != null) {
mCallback.onRequestTrackInfoList(mIAppServiceId);
}
}
}
}

View File

@@ -2468,7 +2468,29 @@ public final class TvInputManagerService extends SystemService {
}
} finally {
Binder.restoreCallingIdentity(identity);
};
}
}
@Override
public void removeBroadcastInfo(IBinder sessionToken, int requestId, int userId) {
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
final int resolvedUserId = resolveCallingUserId(callingPid, callingUid,
userId, "removeBroadcastInfo");
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
try {
SessionState sessionState = getSessionStateLocked(sessionToken, callingUid,
resolvedUserId);
getSessionLocked(sessionState).removeBroadcastInfo(requestId);
} catch (RemoteException | SessionNotFoundException e) {
Slog.e(TAG, "error in removeBroadcastInfo", e);
}
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override

View File

@@ -31,6 +31,7 @@ import android.content.pm.UserInfo;
import android.graphics.Rect;
import android.media.tv.BroadcastInfoRequest;
import android.media.tv.BroadcastInfoResponse;
import android.media.tv.TvTrackInfo;
import android.media.tv.interactive.ITvIAppClient;
import android.media.tv.interactive.ITvIAppManager;
import android.media.tv.interactive.ITvIAppManagerCallback;
@@ -847,6 +848,60 @@ public class TvIAppManagerService extends SystemService {
}
}
@Override
public void notifyTrackSelected(IBinder sessionToken, int type, String trackId,
int userId) {
if (DEBUG) {
Slogf.d(TAG, "notifyTrackSelected(sessionToken=" + sessionToken
+ ", type=" + type + ", trackId=" + trackId + ")");
}
final int callingUid = Binder.getCallingUid();
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
userId, "notifyTrackSelected");
SessionState sessionState = null;
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
try {
sessionState = getSessionStateLocked(sessionToken, callingUid,
resolvedUserId);
getSessionLocked(sessionState).notifyTrackSelected(type, trackId);
} catch (RemoteException | SessionNotFoundException e) {
Slogf.e(TAG, "error in notifyTrackSelected", e);
}
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void notifyTracksChanged(IBinder sessionToken, List<TvTrackInfo> tracks,
int userId) {
if (DEBUG) {
Slogf.d(TAG, "notifyTracksChanged(sessionToken=" + sessionToken
+ ", tracks=" + tracks + ")");
}
final int callingUid = Binder.getCallingUid();
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
userId, "notifyTracksChanged");
SessionState sessionState = null;
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
try {
sessionState = getSessionStateLocked(sessionToken, callingUid,
resolvedUserId);
getSessionLocked(sessionState).notifyTracksChanged(tracks);
} catch (RemoteException | SessionNotFoundException e) {
Slogf.e(TAG, "error in notifyTracksChanged", e);
}
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void startIApp(IBinder sessionToken, int userId) {
if (DEBUG) {
@@ -872,6 +927,31 @@ public class TvIAppManagerService extends SystemService {
}
}
@Override
public void stopIApp(IBinder sessionToken, int userId) {
if (DEBUG) {
Slogf.d(TAG, "BinderService#stop(userId=%d)", userId);
}
final int callingUid = Binder.getCallingUid();
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
userId, "stopIApp");
SessionState sessionState = null;
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
try {
sessionState = getSessionStateLocked(sessionToken, callingUid,
resolvedUserId);
getSessionLocked(sessionState).stopIApp();
} catch (RemoteException | SessionNotFoundException e) {
Slogf.e(TAG, "error in stop", e);
}
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void createBiInteractiveApp(
IBinder sessionToken, Uri biIAppUri, Bundle params, int userId) {
@@ -924,6 +1004,106 @@ public class TvIAppManagerService extends SystemService {
}
}
@Override
public void sendCurrentChannelUri(IBinder sessionToken, Uri channelUri, int userId) {
if (DEBUG) {
Slogf.d(TAG, "sendCurrentChannelUri(channelUri=%s)", channelUri.toString());
}
final int callingUid = Binder.getCallingUid();
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
userId, "sendCurrentChannelUri");
SessionState sessionState = null;
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
try {
sessionState = getSessionStateLocked(sessionToken, callingUid,
resolvedUserId);
getSessionLocked(sessionState).sendCurrentChannelUri(channelUri);
} catch (RemoteException | SessionNotFoundException e) {
Slogf.e(TAG, "error in sendCurrentChannelUri", e);
}
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void sendCurrentChannelLcn(IBinder sessionToken, int lcn, int userId) {
if (DEBUG) {
Slogf.d(TAG, "sendCurrentChannelLcn(lcn=%d)", lcn);
}
final int callingUid = Binder.getCallingUid();
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
userId, "sendCurrentChannelLcn");
SessionState sessionState = null;
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
try {
sessionState = getSessionStateLocked(sessionToken, callingUid,
resolvedUserId);
getSessionLocked(sessionState).sendCurrentChannelLcn(lcn);
} catch (RemoteException | SessionNotFoundException e) {
Slogf.e(TAG, "error in sendCurrentChannelLcn", e);
}
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void sendStreamVolume(IBinder sessionToken, float volume, int userId) {
if (DEBUG) {
Slogf.d(TAG, "sendStreamVolume(volume=%f)", volume);
}
final int callingUid = Binder.getCallingUid();
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
userId, "sendStreamVolume");
SessionState sessionState = null;
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
try {
sessionState = getSessionStateLocked(sessionToken, callingUid,
resolvedUserId);
getSessionLocked(sessionState).sendStreamVolume(volume);
} catch (RemoteException | SessionNotFoundException e) {
Slogf.e(TAG, "error in sendStreamVolume", e);
}
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void sendTrackInfoList(IBinder sessionToken, List<TvTrackInfo> tracks, int userId) {
if (DEBUG) {
Slogf.d(TAG, "sendTrackInfoList(tracks=%s)", tracks.toString());
}
final int callingUid = Binder.getCallingUid();
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
userId, "sendTrackInfoList");
SessionState sessionState = null;
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
try {
sessionState = getSessionStateLocked(sessionToken, callingUid,
resolvedUserId);
getSessionLocked(sessionState).sendTrackInfoList(tracks);
} catch (RemoteException | SessionNotFoundException e) {
Slogf.e(TAG, "error in sendTrackInfoList", e);
}
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void setSurface(IBinder sessionToken, Surface surface, int userId) {
final int callingUid = Binder.getCallingUid();
@@ -1605,6 +1785,23 @@ public class TvIAppManagerService extends SystemService {
}
}
@Override
public void onRemoveBroadcastInfo(int requestId) {
synchronized (mLock) {
if (DEBUG) {
Slogf.d(TAG, "onRemoveBroadcastInfo (requestId=" + requestId + ")");
}
if (mSessionState.mSession == null || mSessionState.mClient == null) {
return;
}
try {
mSessionState.mClient.onRemoveBroadcastInfo(requestId, mSessionState.mSeq);
} catch (RemoteException e) {
Slogf.e(TAG, "error in onRemoveBroadcastInfo", e);
}
}
}
@Override
public void onCommandRequest(@TvIAppService.IAppServiceCommandType String cmdType,
Bundle parameters) {
@@ -1624,6 +1821,91 @@ public class TvIAppManagerService extends SystemService {
}
}
@Override
public void onSetVideoBounds(Rect rect) {
synchronized (mLock) {
if (DEBUG) {
Slogf.d(TAG, "onSetVideoBounds(rect=" + rect + ")");
}
if (mSessionState.mSession == null || mSessionState.mClient == null) {
return;
}
try {
mSessionState.mClient.onSetVideoBounds(rect, mSessionState.mSeq);
} catch (RemoteException e) {
Slogf.e(TAG, "error in onSetVideoBounds", e);
}
}
}
@Override
public void onRequestCurrentChannelUri() {
synchronized (mLock) {
if (DEBUG) {
Slogf.d(TAG, "onRequestCurrentChannelUri");
}
if (mSessionState.mSession == null || mSessionState.mClient == null) {
return;
}
try {
mSessionState.mClient.onRequestCurrentChannelUri(mSessionState.mSeq);
} catch (RemoteException e) {
Slogf.e(TAG, "error in onRequestCurrentChannelUri", e);
}
}
}
@Override
public void onRequestCurrentChannelLcn() {
synchronized (mLock) {
if (DEBUG) {
Slogf.d(TAG, "onRequestCurrentChannelLcn");
}
if (mSessionState.mSession == null || mSessionState.mClient == null) {
return;
}
try {
mSessionState.mClient.onRequestCurrentChannelLcn(mSessionState.mSeq);
} catch (RemoteException e) {
Slogf.e(TAG, "error in onRequestCurrentChannelLcn", e);
}
}
}
@Override
public void onRequestStreamVolume() {
synchronized (mLock) {
if (DEBUG) {
Slogf.d(TAG, "onRequestStreamVolume");
}
if (mSessionState.mSession == null || mSessionState.mClient == null) {
return;
}
try {
mSessionState.mClient.onRequestStreamVolume(mSessionState.mSeq);
} catch (RemoteException e) {
Slogf.e(TAG, "error in onRequestStreamVolume", e);
}
}
}
@Override
public void onRequestTrackInfoList() {
synchronized (mLock) {
if (DEBUG) {
Slogf.d(TAG, "onRequestTrackInfoList");
}
if (mSessionState.mSession == null || mSessionState.mClient == null) {
return;
}
try {
mSessionState.mClient.onRequestTrackInfoList(mSessionState.mSeq);
} catch (RemoteException e) {
Slogf.e(TAG, "error in onRequestTrackInfoList", e);
}
}
}
@Override
public void onSessionStateChanged(int state) {
synchronized (mLock) {