diff options
| author | 2023-01-13 10:28:03 +0000 | |
|---|---|---|
| committer | 2023-01-13 10:28:03 +0000 | |
| commit | b51e6c4811a89c6d1ff7c8625bb3c014c2595e79 (patch) | |
| tree | e06391578944ee00f2b5125bea45734019d1aced | |
| parent | ddefe02fb0700601405a844e6488f754e6919a2a (diff) | |
| parent | d931e912b40ce3941010d72edd6b207859b59306 (diff) | |
Merge "Extend TIAF APIs"
12 files changed, 346 insertions, 1 deletions
diff --git a/media/java/android/media/tv/TableRequest.java b/media/java/android/media/tv/TableRequest.java index a1a6b516859c..a9ea6d3999d0 100644 --- a/media/java/android/media/tv/TableRequest.java +++ b/media/java/android/media/tv/TableRequest.java @@ -33,11 +33,54 @@ public final class TableRequest extends BroadcastInfoRequest implements Parcelab /** @hide */ @Retention(RetentionPolicy.SOURCE) - @IntDef({TABLE_NAME_PAT, TABLE_NAME_PMT}) + @IntDef({TABLE_NAME_PAT, TABLE_NAME_PMT, TABLE_NAME_CAT}) public @interface TableName {} + /** Program Association Table */ public static final int TABLE_NAME_PAT = 0; + /** Program Mapping Table */ public static final int TABLE_NAME_PMT = 1; + /** + * Conditional Access Table + * @hide + */ + public static final int TABLE_NAME_CAT = 2; + /** + * Network Information Table + * @hide + */ + public static final int TABLE_NAME_NIT = 3; + /** + * Bouquet Association Table + * @hide + */ + public static final int TABLE_NAME_BAT = 4; + /** + * Service Description Table + * @hide + */ + public static final int TABLE_NAME_SDT = 5; + /** + * Event Information Table + * @hide + */ + public static final int TABLE_NAME_EIT = 6; + /** + * Time and Date Table + * @hide + */ + public static final int TABLE_NAME_TDT = 7; + /** + * Time Offset Table + * @hide + */ + public static final int TABLE_NAME_TOT = 8; + /** + * Selection Information Table + * @hide + */ + public static final int TABLE_NAME_SIT = 9; + public static final @NonNull Parcelable.Creator<TableRequest> CREATOR = new Parcelable.Creator<TableRequest>() { diff --git a/media/java/android/media/tv/TableResponse.java b/media/java/android/media/tv/TableResponse.java index afc9bee5fb85..1c314b09db9a 100644 --- a/media/java/android/media/tv/TableResponse.java +++ b/media/java/android/media/tv/TableResponse.java @@ -21,6 +21,7 @@ import android.annotation.Nullable; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; +import android.os.SharedMemory; /** * A response for Table from broadcast signal. @@ -46,6 +47,8 @@ public final class TableResponse extends BroadcastInfoResponse implements Parcel private final Uri mTableUri; private final int mVersion; private final int mSize; + private final byte[] mTableByteArray; + private final SharedMemory mTableSharedMemory; static TableResponse createFromParcelBody(Parcel in) { return new TableResponse(in); @@ -54,9 +57,33 @@ public final class TableResponse extends BroadcastInfoResponse implements Parcel public TableResponse(int requestId, int sequence, @ResponseResult int responseResult, @Nullable Uri tableUri, int version, int size) { super(RESPONSE_TYPE, requestId, sequence, responseResult); + mVersion = version; + mSize = size; mTableUri = tableUri; + mTableByteArray = null; + mTableSharedMemory = null; + } + + /** @hide */ + public TableResponse(int requestId, int sequence, @ResponseResult int responseResult, + @NonNull byte[] tableByteArray, int version, int size) { + super(RESPONSE_TYPE, requestId, sequence, responseResult); + mVersion = version; + mSize = size; + mTableUri = null; + mTableByteArray = tableByteArray; + mTableSharedMemory = null; + } + + /** @hide */ + public TableResponse(int requestId, int sequence, @ResponseResult int responseResult, + @NonNull SharedMemory tableSharedMemory, int version, int size) { + super(RESPONSE_TYPE, requestId, sequence, responseResult); mVersion = version; mSize = size; + mTableUri = null; + mTableByteArray = null; + mTableSharedMemory = tableSharedMemory; } TableResponse(Parcel source) { @@ -65,6 +92,14 @@ public final class TableResponse extends BroadcastInfoResponse implements Parcel mTableUri = uriString == null ? null : Uri.parse(uriString); mVersion = source.readInt(); mSize = source.readInt(); + int arrayLength = source.readInt(); + if (arrayLength >= 0) { + mTableByteArray = new byte[arrayLength]; + source.readByteArray(mTableByteArray); + } else { + mTableByteArray = null; + } + mTableSharedMemory = (SharedMemory) source.readTypedObject(SharedMemory.CREATOR); } /** @@ -76,6 +111,30 @@ public final class TableResponse extends BroadcastInfoResponse implements Parcel } /** + * Gets the data of the table as a byte array. + * + * @return the table data as a byte array, or {@code null} if the data is not stored as a byte + * array. + * @hide + */ + @Nullable + public byte[] getTableByteArray() { + return mTableByteArray; + } + + /** + * Gets the data of the table as a {@link SharedMemory} object. + * + * @return the table data as a {@link SharedMemory} object, or {@code null} if the data is not + * stored in shared memory. + * @hide + */ + @Nullable + public SharedMemory getTableSharedMemory() { + return mTableSharedMemory; + } + + /** * Gets the version number of requested table. If it is null, value will be -1. * <p>The consistency of version numbers between request and response depends on * {@link BroadcastInfoRequest.RequestOption}. If the request has RequestOption value @@ -106,5 +165,12 @@ public final class TableResponse extends BroadcastInfoResponse implements Parcel dest.writeString(uriString); dest.writeInt(mVersion); dest.writeInt(mSize); + if (mTableByteArray != null) { + dest.writeInt(mTableByteArray.length); + dest.writeByteArray(mTableByteArray); + } else { + dest.writeInt(-1); + } + dest.writeTypedObject(mTableSharedMemory, flags); } } diff --git a/media/java/android/media/tv/TimelineRequest.java b/media/java/android/media/tv/TimelineRequest.java index 03c62f0824f3..d04c58a9b869 100644 --- a/media/java/android/media/tv/TimelineRequest.java +++ b/media/java/android/media/tv/TimelineRequest.java @@ -42,6 +42,7 @@ public final class TimelineRequest extends BroadcastInfoRequest implements Parce }; private final int mIntervalMillis; + private final String mSelector; static TimelineRequest createFromParcelBody(Parcel in) { return new TimelineRequest(in); @@ -50,11 +51,21 @@ public final class TimelineRequest extends BroadcastInfoRequest implements Parce public TimelineRequest(int requestId, @RequestOption int option, int intervalMillis) { super(REQUEST_TYPE, requestId, option); mIntervalMillis = intervalMillis; + mSelector = null; + } + + /** @hide */ + public TimelineRequest(int requestId, @RequestOption int option, int intervalMillis, + @NonNull String selector) { + super(REQUEST_TYPE, requestId, option); + mIntervalMillis = intervalMillis; + mSelector = selector; } TimelineRequest(Parcel source) { super(REQUEST_TYPE, source); mIntervalMillis = source.readInt(); + mSelector = source.readString(); } /** @@ -64,6 +75,18 @@ public final class TimelineRequest extends BroadcastInfoRequest implements Parce return mIntervalMillis; } + /** + * Gets the timeline selector. + * <p>The selector describes the type and location of timeline signalling. For example + * {@code urn:dvb:css:timeline:pts} is a selector in DVB standard. + * + * @return the selector if it's set; {@code null} otherwise. + * @hide + */ + public String getSelector() { + return mSelector; + } + @Override public int describeContents() { return 0; @@ -73,5 +96,6 @@ public final class TimelineRequest extends BroadcastInfoRequest implements Parce public void writeToParcel(@NonNull Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeInt(mIntervalMillis); + dest.writeString(mSelector); } } diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppClient.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppClient.aidl index 494571fc37cf..ad9312f6975d 100644 --- a/media/java/android/media/tv/interactive/ITvInteractiveAppClient.aidl +++ b/media/java/android/media/tv/interactive/ITvInteractiveAppClient.aidl @@ -43,6 +43,7 @@ oneway interface ITvInteractiveAppClient { void onCommandRequest(in String cmdType, in Bundle parameters, int seq); void onTimeShiftCommandRequest(in String cmdType, in Bundle parameters, int seq); void onSetVideoBounds(in Rect rect, int seq); + void onRequestCurrentVideoBounds(int seq); void onRequestCurrentChannelUri(int seq); void onRequestCurrentChannelLcn(int seq); void onRequestStreamVolume(int seq); diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl index 599922c2bafb..c0723f7b9d78 100644 --- a/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl +++ b/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl @@ -48,6 +48,7 @@ interface ITvInteractiveAppManager { in IBinder sessionToken, in Uri biIAppUri, in Bundle params, int userId); void destroyBiInteractiveApp(in IBinder sessionToken, in String biIAppId, int userId); void setTeletextAppEnabled(in IBinder sessionToken, boolean enable, int userId); + void sendCurrentVideoBounds(in IBinder sessionToken, in Rect bounds, 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); diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl index 17a70d1d8a7d..9ae9ca791949 100644 --- a/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl +++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl @@ -40,6 +40,7 @@ oneway interface ITvInteractiveAppSession { void createBiInteractiveApp(in Uri biIAppUri, in Bundle params); void destroyBiInteractiveApp(in String biIAppId); void setTeletextAppEnabled(boolean enable); + void sendCurrentVideoBounds(in Rect bounds); void sendCurrentChannelUri(in Uri channelUri); void sendCurrentChannelLcn(int lcn); void sendStreamVolume(float volume); diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionCallback.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionCallback.aidl index 056574295cd8..d84affd850a9 100644 --- a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionCallback.aidl +++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionCallback.aidl @@ -42,6 +42,7 @@ oneway interface ITvInteractiveAppSessionCallback { void onCommandRequest(in String cmdType, in Bundle parameters); void onTimeShiftCommandRequest(in String cmdType, in Bundle parameters); void onSetVideoBounds(in Rect rect); + void onRequestCurrentVideoBounds(); void onRequestCurrentChannelUri(); void onRequestCurrentChannelLcn(); void onRequestStreamVolume(); diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java index b8158cd1d949..8a23e65ec3a6 100644 --- a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java +++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java @@ -94,6 +94,7 @@ public class ITvInteractiveAppSessionWrapper private static final int DO_NOTIFY_TIME_SHIFT_STATUS_CHANGED = 37; private static final int DO_NOTIFY_TIME_SHIFT_START_POSITION_CHANGED = 38; private static final int DO_NOTIFY_TIME_SHIFT_CURRENT_POSITION_CHANGED = 39; + private static final int DO_SEND_CURRENT_VIDEO_BOUNDS = 40; private final HandlerCaller mCaller; private Session mSessionImpl; @@ -157,6 +158,10 @@ public class ITvInteractiveAppSessionWrapper mSessionImpl.setTeletextAppEnabled((Boolean) msg.obj); break; } + case DO_SEND_CURRENT_VIDEO_BOUNDS: { + mSessionImpl.sendCurrentVideoBounds((Rect) msg.obj); + break; + } case DO_SEND_CURRENT_CHANNEL_URI: { mSessionImpl.sendCurrentChannelUri((Uri) msg.obj); break; @@ -355,6 +360,12 @@ public class ITvInteractiveAppSessionWrapper } @Override + public void sendCurrentVideoBounds(@Nullable Rect bounds) { + mCaller.executeOrSendMessage( + mCaller.obtainMessageO(DO_SEND_CURRENT_VIDEO_BOUNDS, bounds)); + } + + @Override public void sendCurrentChannelUri(@Nullable Uri channelUri) { mCaller.executeOrSendMessage( mCaller.obtainMessageO(DO_SEND_CURRENT_CHANNEL_URI, channelUri)); diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java index 7c91844519db..fd3c29bb24aa 100755 --- a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java +++ b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java @@ -445,6 +445,18 @@ public final class TvInteractiveAppManager { } @Override + public void onRequestCurrentVideoBounds(int seq) { + synchronized (mSessionCallbackRecordMap) { + SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq); + if (record == null) { + Log.e(TAG, "Callback not found for seq " + seq); + return; + } + record.postRequestCurrentVideoBounds(); + } + } + + @Override public void onRequestCurrentChannelUri(int seq) { synchronized (mSessionCallbackRecordMap) { SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq); @@ -1084,6 +1096,18 @@ public final class TvInteractiveAppManager { } } + void sendCurrentVideoBounds(@NonNull Rect bounds) { + if (mToken == null) { + Log.w(TAG, "The session has been already released"); + return; + } + try { + mService.sendCurrentVideoBounds(mToken, bounds, mUserId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + void sendCurrentChannelUri(@Nullable Uri channelUri) { if (mToken == null) { Log.w(TAG, "The session has been already released"); @@ -1898,6 +1922,15 @@ public final class TvInteractiveAppManager { }); } + void postRequestCurrentVideoBounds() { + mHandler.post(new Runnable() { + @Override + public void run() { + mSessionCallback.onRequestCurrentVideoBounds(mSession); + } + }); + } + void postRequestCurrentChannelUri() { mHandler.post(new Runnable() { @Override @@ -2119,6 +2152,15 @@ public final class TvInteractiveAppManager { } /** + * This is called when {@link TvInteractiveAppService.Session#RequestCurrentVideoBounds} is + * called. + * + * @param session A {@link TvInteractiveAppManager.Session} associated with this callback. + */ + public void onRequestCurrentVideoBounds(Session session) { + } + + /** * This is called when {@link TvInteractiveAppService.Session#RequestCurrentChannelUri} is * called. * diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppService.java b/media/java/android/media/tv/interactive/TvInteractiveAppService.java index 949e01775aeb..be2c16c90b9e 100755 --- a/media/java/android/media/tv/interactive/TvInteractiveAppService.java +++ b/media/java/android/media/tv/interactive/TvInteractiveAppService.java @@ -17,6 +17,7 @@ package android.media.tv.interactive; import android.annotation.CallSuper; +import android.annotation.IntDef; import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; @@ -139,6 +140,38 @@ public abstract class TvInteractiveAppService extends Service { * Playback command type: select the given track. */ public static final String PLAYBACK_COMMAND_TYPE_SELECT_TRACK = "select_track"; + + + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "PLAYBACK_COMMAND_STOP_MODE_", value = { + PLAYBACK_COMMAND_STOP_MODE_BLANK, + PLAYBACK_COMMAND_STOP_MODE_FREEZE + }) + public @interface PlaybackCommandStopMode {} + + /** + * Playback command stop mode: show a blank screen. + * @hide + */ + public static final int PLAYBACK_COMMAND_STOP_MODE_BLANK = 1; + + /** + * Playback command stop mode: freeze the video. + * @hide + */ + public static final int PLAYBACK_COMMAND_STOP_MODE_FREEZE = 2; + + /** + * Playback command parameter: stop mode. + * <p>Type: int + * + * @see #PLAYBACK_COMMAND_TYPE_STOP + * @hide + */ + public static final String COMMAND_PARAMETER_KEY_STOP_MODE = "command_stop_mode"; + /** * Playback command parameter: channel URI. * <p>Type: android.net.Uri @@ -498,6 +531,13 @@ public abstract class TvInteractiveAppService extends Service { } /** + * Receives current video bounds. + * @hide + */ + public void onCurrentVideoBounds(@NonNull Rect bounds) { + } + + /** * Receives current channel URI. */ public void onCurrentChannelUri(@Nullable Uri channelUri) { @@ -983,6 +1023,30 @@ public abstract class TvInteractiveAppService extends Service { } /** + * Requests the bounds of the current video. + * @hide + */ + @CallSuper + public void requestCurrentVideoBounds() { + executeOrPostRunnableOnMainThread(new Runnable() { + @MainThread + @Override + public void run() { + try { + if (DEBUG) { + Log.d(TAG, "requestCurrentVideoBounds"); + } + if (mSessionCallback != null) { + mSessionCallback.onRequestCurrentVideoBounds(); + } + } catch (RemoteException e) { + Log.w(TAG, "error in requestCurrentVideoBounds", e); + } + } + }); + } + + /** * Requests the URI of the current channel. */ @CallSuper @@ -1309,6 +1373,10 @@ public abstract class TvInteractiveAppService extends Service { onSetTeletextAppEnabled(enable); } + void sendCurrentVideoBounds(@NonNull Rect bounds) { + onCurrentVideoBounds(bounds); + } + void sendCurrentChannelUri(@Nullable Uri channelUri) { onCurrentChannelUri(channelUri); } diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppView.java b/media/java/android/media/tv/interactive/TvInteractiveAppView.java index 9211a12de0d0..af03bb86d364 100755 --- a/media/java/android/media/tv/interactive/TvInteractiveAppView.java +++ b/media/java/android/media/tv/interactive/TvInteractiveAppView.java @@ -514,6 +514,19 @@ public class TvInteractiveAppView extends ViewGroup { } /** + * Sends current video bounds to related TV interactive app. + * @hide + */ + public void sendCurrentVideoBounds(@NonNull Rect bounds) { + if (DEBUG) { + Log.d(TAG, "sendCurrentVideoBounds"); + } + if (mSession != null) { + mSession.sendCurrentVideoBounds(bounds); + } + } + + /** * Sends current channel URI to related TV interactive app. * * @param channelUri The current channel URI; {@code null} if there is no currently tuned @@ -944,6 +957,16 @@ public class TvInteractiveAppView extends ViewGroup { } /** + * This is called when {@link TvInteractiveAppService.Session#requestCurrentVideoBounds()} + * is called. + * + * @param iAppServiceId The ID of the TV interactive app service bound to this view. + * @hide + */ + public void onRequestCurrentVideoBounds(@NonNull String iAppServiceId) { + } + + /** * This is called when {@link TvInteractiveAppService.Session#requestCurrentChannelUri()} is * called. * @@ -1265,6 +1288,28 @@ public class TvInteractiveAppView extends ViewGroup { } @Override + public void onRequestCurrentVideoBounds(Session session) { + if (DEBUG) { + Log.d(TAG, "onRequestCurrentVideoBounds"); + } + if (this != mSessionCallback) { + Log.w(TAG, "onRequestCurrentVideoBounds - session not created"); + return; + } + synchronized (mCallbackLock) { + if (mCallbackExecutor != null) { + mCallbackExecutor.execute(() -> { + synchronized (mCallbackLock) { + if (mCallback != null) { + mCallback.onRequestCurrentVideoBounds(mIAppServiceId); + } + } + }); + } + } + } + + @Override public void onRequestCurrentChannelUri(Session session) { if (DEBUG) { Log.d(TAG, "onRequestCurrentChannelUri"); diff --git a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java index 50b7fd21cf84..d4f2f2dcbdf8 100644 --- a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java +++ b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java @@ -1336,6 +1336,31 @@ public class TvInteractiveAppManagerService extends SystemService { } @Override + public void sendCurrentVideoBounds(IBinder sessionToken, Rect bounds, int userId) { + if (DEBUG) { + Slogf.d(TAG, "sendCurrentVideoBounds(bounds=%s)", bounds.toString()); + } + final int callingUid = Binder.getCallingUid(); + final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, + userId, "sendCurrentVideoBounds"); + SessionState sessionState = null; + final long identity = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + try { + sessionState = getSessionStateLocked(sessionToken, callingUid, + resolvedUserId); + getSessionLocked(sessionState).sendCurrentVideoBounds(bounds); + } catch (RemoteException | SessionNotFoundException e) { + Slogf.e(TAG, "error in sendCurrentVideoBounds", e); + } + } + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override public void sendCurrentChannelUri(IBinder sessionToken, Uri channelUri, int userId) { if (DEBUG) { Slogf.d(TAG, "sendCurrentChannelUri(channelUri=%s)", channelUri.toString()); @@ -2475,6 +2500,23 @@ public class TvInteractiveAppManagerService extends SystemService { } @Override + public void onRequestCurrentVideoBounds() { + synchronized (mLock) { + if (DEBUG) { + Slogf.d(TAG, "onRequestCurrentVideoBounds"); + } + if (mSessionState.mSession == null || mSessionState.mClient == null) { + return; + } + try { + mSessionState.mClient.onRequestCurrentVideoBounds(mSessionState.mSeq); + } catch (RemoteException e) { + Slogf.e(TAG, "error in onRequestCurrentVideoBounds", e); + } + } + } + + @Override public void onRequestCurrentChannelUri() { synchronized (mLock) { if (DEBUG) { |