Extend TIAF APIs

1. get current video bounds
2. timeline selector
3. playback command stop modes
4. extend table request / response

Bug: 264934231
Test: mmm
Change-Id: Id1f8b18e264495c37ebf841326e0e5b4ff534287
This commit is contained in:
shubang
2023-01-09 15:41:19 -08:00
committed by Shubang Lu
parent c28af28dfb
commit d931e912b4
12 changed files with 347 additions and 2 deletions

View File

@@ -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>() {

View File

@@ -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);
mTableUri = tableUri;
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);
}
/**
@@ -75,6 +110,30 @@ public final class TableResponse extends BroadcastInfoResponse implements Parcel
return mTableUri;
}
/**
* 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
@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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();

View File

@@ -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;
@@ -354,6 +359,12 @@ public class ITvInteractiveAppSessionWrapper
mCaller.obtainMessageO(DO_SET_TELETEXT_APP_ENABLED, enable));
}
@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(

View File

@@ -444,6 +444,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) {
@@ -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
@@ -2118,6 +2151,15 @@ public final class TvInteractiveAppManager {
public void onSetVideoBounds(Session session, Rect rect) {
}
/**
* 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.

View File

@@ -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
@@ -497,6 +530,13 @@ public abstract class TvInteractiveAppService extends Service {
public void onSetTeletextAppEnabled(boolean enable) {
}
/**
* Receives current video bounds.
* @hide
*/
public void onCurrentVideoBounds(@NonNull Rect bounds) {
}
/**
* Receives current channel URI.
*/
@@ -982,6 +1022,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.
*/
@@ -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);
}

View File

@@ -513,6 +513,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.
*
@@ -943,6 +956,16 @@ public class TvInteractiveAppView extends ViewGroup {
public void onSetVideoBounds(@NonNull String iAppServiceId, @NonNull Rect rect) {
}
/**
* 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.
@@ -1264,6 +1287,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) {

View File

@@ -1335,6 +1335,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) {
@@ -2474,6 +2499,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) {