Merge "TIAF: Interactive App to DTV Channel flow"

This commit is contained in:
Yixiao Luo
2021-12-16 00:26:55 +00:00
committed by Android (Google) Code Review
6 changed files with 154 additions and 3 deletions

View File

@@ -15,9 +15,9 @@
*/
package android.media.tv.interactive;
import android.media.tv.BroadcastInfoRequest;
import android.media.tv.BroadcastInfoRequest;
import android.os.Bundle;
import android.view.InputChannel;
/**
@@ -31,4 +31,5 @@ oneway interface ITvIAppClient {
void onLayoutSurface(int left, int top, int right, int bottom, int seq);
void onBroadcastInfoRequest(in BroadcastInfoRequest request, int seq);
void onSessionStateChanged(int state, int seq);
}
void onCommandRequest(in String cmdType, in Bundle parameters, int seq);
}

View File

@@ -19,6 +19,7 @@ package android.media.tv.interactive;
import android.media.tv.BroadcastInfoRequest;
import android.media.tv.interactive.ITvIAppSession;
import android.media.tv.BroadcastInfoRequest;
import android.os.Bundle;
/**
* Helper interface for ITvIAppSession to allow TvIAppService to notify the system service when
@@ -30,4 +31,5 @@ oneway interface ITvIAppSessionCallback {
void onLayoutSurface(int left, int top, int right, int bottom);
void onBroadcastInfoRequest(in BroadcastInfoRequest request);
void onSessionStateChanged(int state);
}
void onCommandRequest(in String cmdType, in Bundle parameters);
}

View File

@@ -243,6 +243,19 @@ public final class TvIAppManager {
}
}
@Override
public void onCommandRequest(@TvIAppService.IAppServiceCommandType String cmdType,
Bundle parameters, int seq) {
synchronized (mSessionCallbackRecordMap) {
SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
if (record == null) {
Log.e(TAG, "Callback not found for seq " + seq);
return;
}
record.postCommandRequest(cmdType, parameters);
}
}
@Override
public void onSessionStateChanged(int state, int seq) {
synchronized (mSessionCallbackRecordMap) {
@@ -1046,6 +1059,16 @@ public final class TvIAppManager {
});
}
void postCommandRequest(final @TvIAppService.IAppServiceCommandType String cmdType,
final Bundle parameters) {
mHandler.post(new Runnable() {
@Override
public void run() {
mSessionCallback.onCommandRequest(mSession, cmdType, parameters);
}
});
}
void postSessionStateChanged(int state) {
mHandler.post(new Runnable() {
@Override
@@ -1092,6 +1115,17 @@ public final class TvIAppManager {
public void onLayoutSurface(Session session, int left, int top, int right, int bottom) {
}
/**
* This is called when {@link TvIAppService.Session#requestCommand} is called.
*
* @param session A {@link TvIAppManager.Session} associated with this callback.
* @param cmdType type of the command.
* @param parameters parameters of the command.
*/
public void onCommandRequest(Session session,
@TvIAppService.IAppServiceCommandType String cmdType, Bundle parameters) {
}
/**
* This is called when {@link TvIAppService.Session#notifySessionStateChanged} is called.
*

View File

@@ -19,6 +19,7 @@ package android.media.tv.interactive;
import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringDef;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.Service;
@@ -53,6 +54,8 @@ import android.widget.FrameLayout;
import com.android.internal.os.SomeArgs;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
@@ -83,6 +86,28 @@ public abstract class TvIAppService extends Service {
*/
public static final String SERVICE_META_DATA = "android.media.tv.interactive.app";
/** @hide */
@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_STOP,
IAPP_SERVICE_COMMAND_TYPE_SETSTREAMVOLUME
})
public @interface IAppServiceCommandType {}
/** @hide */
public static final String IAPP_SERVICE_COMMAND_TYPE_TUNE = "Tune";
/** @hide */
public static final String IAPP_SERVICE_COMMAND_TYPE_TUNENEXT = "TuneNext";
/** @hide */
public static final String IAPP_SERVICE_COMMAND_TYPE_TUNEPREV = "TunePrevious";
/** @hide */
public static final String IAPP_SERVICE_COMMAND_TYPE_STOP = "Stop";
/** @hide */
public static final String IAPP_SERVICE_COMMAND_TYPE_SETSTREAMVOLUME = "setStreamVolume";
private final Handler mServiceHandler = new ServiceHandler();
private final RemoteCallbackList<ITvIAppServiceCallback> mCallbacks =
new RemoteCallbackList<>();
@@ -443,6 +468,31 @@ public abstract class TvIAppService extends Service {
});
}
/**
* requests a specific command to be processed by the related TV input.
* @param cmdType type of the specific command
* @param parameters parameters of the specific command
*/
public void requestCommand(@IAppServiceCommandType String cmdType, Bundle parameters) {
executeOrPostRunnableOnMainThread(new Runnable() {
@MainThread
@Override
public void run() {
try {
if (DEBUG) {
Log.d(TAG, "requestCommand (cmdType=" + cmdType + ", parameters="
+ parameters.toString() + ")");
}
if (mSessionCallback != null) {
mSessionCallback.onCommandRequest(cmdType, parameters);
}
} catch (RemoteException e) {
Log.w(TAG, "error in requestCommand", e);
}
}
});
}
void startIApp() {
onStartIApp();
}

View File

@@ -26,6 +26,7 @@ import android.media.tv.TvInputManager;
import android.media.tv.TvView;
import android.media.tv.interactive.TvIAppManager.Session;
import android.media.tv.interactive.TvIAppManager.SessionCallback;
import android.os.Bundle;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
@@ -53,6 +54,7 @@ public class TvIAppView extends ViewGroup {
private final Handler mHandler = new Handler();
private Session mSession;
private MySessionCallback mSessionCallback;
private TvIAppCallback mCallback;
private SurfaceView mSurfaceView;
private Surface mSurface;
@@ -123,6 +125,16 @@ public class TvIAppView extends ViewGroup {
mTvIAppManager = (TvIAppManager) getContext().getSystemService("tv_interactive_app");
}
/**
* Sets the callback to be invoked when an event is dispatched to this TvIAppView.
*
* @param callback The callback to receive events. A value of {@code null} removes the existing
* callback.
*/
public void setCallback(@Nullable TvIAppCallback callback) {
mCallback = callback;
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
@@ -322,6 +334,23 @@ public class TvIAppView extends ViewGroup {
return UNSET_TVVIEW_SUCCESS;
}
/**
* Callback used to receive various status updates on the {@link TvIAppView}.
*/
public abstract static class TvIAppCallback {
/**
* This is called when a command is requested to be processed by the related TV input.
*
* @param iAppServiceId The ID of the TV interactive app service bound to this view.
* @param cmdType type of the command
* @param parameters parameters of the command
*/
public void onCommandRequest(String iAppServiceId,
@TvIAppService.IAppServiceCommandType String cmdType, Bundle parameters) {
}
}
private class MySessionCallback extends SessionCallback {
final String mIAppServiceId;
int mType;
@@ -395,5 +424,21 @@ public class TvIAppView extends ViewGroup {
mUseRequestedSurfaceLayout = true;
requestLayout();
}
@Override
public void onCommandRequest(Session session,
@TvIAppService.IAppServiceCommandType String cmdType, Bundle parameters) {
if (DEBUG) {
Log.d(TAG, "onCommandRequest (cmdType=" + cmdType + ", parameters="
+ parameters.toString() + ")");
}
if (this != mSessionCallback) {
Log.w(TAG, "onCommandRequest - session not created");
return;
}
if (mCallback != null) {
mCallback.onCommandRequest(mIAppServiceId, cmdType, parameters);
}
}
}
}

View File

@@ -1548,6 +1548,25 @@ public class TvIAppManagerService extends SystemService {
}
}
@Override
public void onCommandRequest(@TvIAppService.IAppServiceCommandType String cmdType,
Bundle parameters) {
synchronized (mLock) {
if (DEBUG) {
Slogf.d(TAG, "onCommandRequest (cmdType=" + cmdType + ", parameters="
+ parameters.toString() + ")");
}
if (mSessionState.mSession == null || mSessionState.mClient == null) {
return;
}
try {
mSessionState.mClient.onCommandRequest(cmdType, parameters, mSessionState.mSeq);
} catch (RemoteException e) {
Slogf.e(TAG, "error in onCommandRequest", e);
}
}
}
@Override
public void onSessionStateChanged(int state) {
synchronized (mLock) {