TIAF: add signing request and result
Detailed call sequence can be found at go/tiaf-use-cases And add INTENT_KEY_COMMAND_TYPE Bug: 224121339 Bug: 225082750 Test: atest testRequestSigning Test: atest testSendSigningResult Change-Id: I32b7e77dc7fc357ce168f486c28c16863bbbb3bf
This commit is contained in:
@@ -26135,6 +26135,7 @@ package android.media.tv.interactive {
|
||||
field public static final String INTENT_KEY_BI_INTERACTIVE_APP_TYPE = "bi_interactive_app_type";
|
||||
field public static final String INTENT_KEY_BI_INTERACTIVE_APP_URI = "bi_interactive_app_uri";
|
||||
field public static final String INTENT_KEY_CHANNEL_URI = "channel_uri";
|
||||
field public static final String INTENT_KEY_COMMAND_TYPE = "command_type";
|
||||
field public static final String INTENT_KEY_INTERACTIVE_APP_SERVICE_ID = "interactive_app_id";
|
||||
field public static final String INTENT_KEY_TV_INPUT_ID = "tv_input_id";
|
||||
field public static final int INTERACTIVE_APP_STATE_ERROR = 3; // 0x3
|
||||
@@ -26209,6 +26210,7 @@ package android.media.tv.interactive {
|
||||
method public abstract boolean onSetSurface(@Nullable android.view.Surface);
|
||||
method public void onSetTeletextAppEnabled(boolean);
|
||||
method public void onSignalStrength(int);
|
||||
method public void onSigningResult(@NonNull String, @NonNull byte[]);
|
||||
method public void onStartInteractiveApp();
|
||||
method public void onStopInteractiveApp();
|
||||
method public void onStreamVolume(float);
|
||||
@@ -26227,6 +26229,7 @@ package android.media.tv.interactive {
|
||||
method @CallSuper public void requestCurrentChannelLcn();
|
||||
method @CallSuper public void requestCurrentChannelUri();
|
||||
method @CallSuper public void requestCurrentTvInputId();
|
||||
method @CallSuper public void requestSigning(@NonNull String, @NonNull String, @NonNull String, @NonNull byte[]);
|
||||
method @CallSuper public void requestStreamVolume();
|
||||
method @CallSuper public void requestTrackInfoList();
|
||||
method @CallSuper public void sendPlaybackCommandRequest(@NonNull String, @Nullable android.os.Bundle);
|
||||
@@ -26268,6 +26271,7 @@ package android.media.tv.interactive {
|
||||
method public void sendCurrentChannelLcn(int);
|
||||
method public void sendCurrentChannelUri(@Nullable android.net.Uri);
|
||||
method public void sendCurrentTvInputId(@Nullable String);
|
||||
method public void sendSigningResult(@NonNull String, @NonNull byte[]);
|
||||
method public void sendStreamVolume(float);
|
||||
method public void sendTrackInfoList(@Nullable java.util.List<android.media.tv.TvTrackInfo>);
|
||||
method public void setCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.interactive.TvInteractiveAppView.TvInteractiveAppCallback);
|
||||
@@ -26276,6 +26280,9 @@ package android.media.tv.interactive {
|
||||
method public int setTvView(@Nullable android.media.tv.TvView);
|
||||
method public void startInteractiveApp();
|
||||
method public void stopInteractiveApp();
|
||||
field public static final String BI_INTERACTIVE_APP_KEY_ALIAS = "alias";
|
||||
field public static final String BI_INTERACTIVE_APP_KEY_CERTIFICATE = "certificate";
|
||||
field public static final String BI_INTERACTIVE_APP_KEY_PRIVATE_KEY = "private_key";
|
||||
}
|
||||
|
||||
public static interface TvInteractiveAppView.OnUnhandledInputEventListener {
|
||||
@@ -26289,6 +26296,7 @@ package android.media.tv.interactive {
|
||||
method public void onRequestCurrentChannelLcn(@NonNull String);
|
||||
method public void onRequestCurrentChannelUri(@NonNull String);
|
||||
method public void onRequestCurrentTvInputId(@NonNull String);
|
||||
method public void onRequestSigning(@NonNull String, @NonNull String, @NonNull String, @NonNull String, @NonNull byte[]);
|
||||
method public void onRequestStreamVolume(@NonNull String);
|
||||
method public void onRequestTrackInfoList(@NonNull String);
|
||||
method public void onSetVideoBounds(@NonNull String, @NonNull android.graphics.Rect);
|
||||
|
||||
@@ -44,5 +44,7 @@ oneway interface ITvInteractiveAppClient {
|
||||
void onRequestStreamVolume(int seq);
|
||||
void onRequestTrackInfoList(int seq);
|
||||
void onRequestCurrentTvInputId(int seq);
|
||||
void onRequestSigning(
|
||||
in String id, in String algorithm, in String alias, in byte[] data, int seq);
|
||||
void onAdRequest(in AdRequest request, int Seq);
|
||||
}
|
||||
|
||||
@@ -50,6 +50,8 @@ interface ITvInteractiveAppManager {
|
||||
void sendStreamVolume(in IBinder sessionToken, float volume, int userId);
|
||||
void sendTrackInfoList(in IBinder sessionToken, in List<TvTrackInfo> tracks, int userId);
|
||||
void sendCurrentTvInputId(in IBinder sessionToken, in String inputId, int userId);
|
||||
void sendSigningResult(in IBinder sessionToken, in String signingId, in byte[] result,
|
||||
int userId);
|
||||
void createSession(in ITvInteractiveAppClient client, in String iAppServiceId, int type,
|
||||
int seq, int userId);
|
||||
void releaseSession(in IBinder sessionToken, int userId);
|
||||
|
||||
@@ -42,6 +42,7 @@ oneway interface ITvInteractiveAppSession {
|
||||
void sendStreamVolume(float volume);
|
||||
void sendTrackInfoList(in List<TvTrackInfo> tracks);
|
||||
void sendCurrentTvInputId(in String inputId);
|
||||
void sendSigningResult(in String signingId, in byte[] result);
|
||||
void release();
|
||||
void notifyTuned(in Uri channelUri);
|
||||
void notifyTrackSelected(int type, in String trackId);
|
||||
|
||||
@@ -43,5 +43,6 @@ oneway interface ITvInteractiveAppSessionCallback {
|
||||
void onRequestStreamVolume();
|
||||
void onRequestTrackInfoList();
|
||||
void onRequestCurrentTvInputId();
|
||||
void onRequestSigning(in String id, in String algorithm, in String alias, in byte[] data);
|
||||
void onAdRequest(in AdRequest request);
|
||||
}
|
||||
|
||||
@@ -249,7 +249,7 @@ public final class TvInteractiveAppManager {
|
||||
*
|
||||
* @see #sendAppLinkCommand(String, Bundle)
|
||||
* @see #ACTION_APP_LINK_COMMAND
|
||||
* @see android.media.tv.interactive.TvInteractiveAppServiceInfo#getId()
|
||||
* @see TvInteractiveAppServiceInfo#getId()
|
||||
*/
|
||||
public static final String INTENT_KEY_INTERACTIVE_APP_SERVICE_ID = "interactive_app_id";
|
||||
|
||||
@@ -285,6 +285,16 @@ public final class TvInteractiveAppManager {
|
||||
*/
|
||||
public static final String INTENT_KEY_BI_INTERACTIVE_APP_URI = "bi_interactive_app_uri";
|
||||
|
||||
/**
|
||||
* Intent key for command type. It's used to send app command to TV app. The value of this key
|
||||
* could vary according to TV apps.
|
||||
* <p>Type: String
|
||||
*
|
||||
* @see #sendAppLinkCommand(String, Bundle)
|
||||
* @see #ACTION_APP_LINK_COMMAND
|
||||
*/
|
||||
public static final String INTENT_KEY_COMMAND_TYPE = "command_type";
|
||||
|
||||
private final ITvInteractiveAppManager mService;
|
||||
private final int mUserId;
|
||||
|
||||
@@ -477,6 +487,19 @@ public final class TvInteractiveAppManager {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestSigning(
|
||||
String id, String algorithm, String alias, byte[] data, int seq) {
|
||||
synchronized (mSessionCallbackRecordMap) {
|
||||
SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
|
||||
if (record == null) {
|
||||
Log.e(TAG, "Callback not found for seq " + seq);
|
||||
return;
|
||||
}
|
||||
record.postRequestSigning(id, algorithm, alias, data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSessionStateChanged(int state, int err, int seq) {
|
||||
synchronized (mSessionCallbackRecordMap) {
|
||||
@@ -1024,6 +1047,18 @@ public final class TvInteractiveAppManager {
|
||||
}
|
||||
}
|
||||
|
||||
void sendSigningResult(@NonNull String signingId, @NonNull byte[] result) {
|
||||
if (mToken == null) {
|
||||
Log.w(TAG, "The session has been already released");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mService.sendSigningResult(mToken, signingId, result, mUserId);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link android.view.Surface} for this session.
|
||||
*
|
||||
@@ -1657,6 +1692,15 @@ public final class TvInteractiveAppManager {
|
||||
});
|
||||
}
|
||||
|
||||
void postRequestSigning(String id, String algorithm, String alias, byte[] data) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mSessionCallback.onRequestSigning(mSession, id, algorithm, alias, data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void postAdRequest(final AdRequest request) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
@@ -1794,11 +1838,26 @@ public final class TvInteractiveAppManager {
|
||||
* called.
|
||||
*
|
||||
* @param session A {@link TvInteractiveAppService.Session} associated with this callback.
|
||||
* @hide
|
||||
*/
|
||||
public void onRequestCurrentTvInputId(Session session) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when
|
||||
* {@link TvInteractiveAppService.Session#requestSigning(String, String, String, byte[])} is
|
||||
* called.
|
||||
*
|
||||
* @param session A {@link TvInteractiveAppService.Session} associated with this callback.
|
||||
* @param signingId the ID to identify the request.
|
||||
* @param algorithm the standard name of the signature algorithm requested, such as
|
||||
* MD5withRSA, SHA256withDSA, etc.
|
||||
* @param alias the alias of the corresponding {@link java.security.KeyStore}.
|
||||
* @param data the original bytes to be signed.
|
||||
*/
|
||||
public void onRequestSigning(
|
||||
Session session, String signingId, String algorithm, String alias, byte[] data) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when {@link TvInteractiveAppService.Session#notifySessionStateChanged} is
|
||||
* called.
|
||||
|
||||
@@ -451,6 +451,17 @@ public abstract class TvInteractiveAppService extends Service {
|
||||
public void onCurrentTvInputId(@Nullable String inputId) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives signing result.
|
||||
* @param signingId the ID to identify the request. It's the same as the corresponding ID in
|
||||
* {@link Session#requestSigning(String, String, String, byte[])}
|
||||
* @param result the signed result.
|
||||
*
|
||||
* @see #requestSigning(String, String, String, byte[])
|
||||
*/
|
||||
public void onSigningResult(@NonNull String signingId, @NonNull byte[] result) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the application sets the surface.
|
||||
*
|
||||
@@ -876,6 +887,47 @@ public abstract class TvInteractiveAppService extends Service {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests signing of the given data.
|
||||
*
|
||||
* <p>This is used when the corresponding server of the broadcast-independent interactive
|
||||
* app requires signing during handshaking, and the interactive app service doesn't have
|
||||
* the built-in private key. The private key is provided by the content providers and
|
||||
* pre-built in the related app, such as TV app.
|
||||
*
|
||||
* @param signingId the ID to identify the request. When a result is received, this ID can
|
||||
* be used to correlate the result with the request.
|
||||
* @param algorithm the standard name of the signature algorithm requested, such as
|
||||
* MD5withRSA, SHA256withDSA, etc. The name is from standards like
|
||||
* FIPS PUB 186-4 and PKCS #1.
|
||||
* @param alias the alias of the corresponding {@link java.security.KeyStore}.
|
||||
* @param data the original bytes to be signed.
|
||||
*
|
||||
* @see #onSigningResult(String, byte[])
|
||||
* @see TvInteractiveAppView#createBiInteractiveApp(Uri, Bundle)
|
||||
* @see TvInteractiveAppView#BI_INTERACTIVE_APP_KEY_ALIAS
|
||||
*/
|
||||
@CallSuper
|
||||
public void requestSigning(@NonNull String signingId, @NonNull String algorithm,
|
||||
@NonNull String alias, @NonNull byte[] data) {
|
||||
executeOrPostRunnableOnMainThread(new Runnable() {
|
||||
@MainThread
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "requestSigning");
|
||||
}
|
||||
if (mSessionCallback != null) {
|
||||
mSessionCallback.onRequestSigning(signingId, algorithm, alias, data);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "error in requestSigning", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an advertisement request to be processed by the related TV input.
|
||||
*
|
||||
@@ -945,6 +997,10 @@ public abstract class TvInteractiveAppService extends Service {
|
||||
onCurrentTvInputId(inputId);
|
||||
}
|
||||
|
||||
void sendSigningResult(String signingId, byte[] result) {
|
||||
onSigningResult(signingId, result);
|
||||
}
|
||||
|
||||
void release() {
|
||||
onRelease();
|
||||
if (mSurface != null) {
|
||||
@@ -1412,6 +1468,11 @@ public abstract class TvInteractiveAppService extends Service {
|
||||
mSessionImpl.sendCurrentTvInputId(inputId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSigningResult(@NonNull String signingId, @NonNull byte[] result) {
|
||||
mSessionImpl.sendSigningResult(signingId, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
mSessionImpl.scheduleMediaViewCleanup();
|
||||
|
||||
@@ -46,6 +46,7 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewRootImpl;
|
||||
|
||||
import java.security.KeyStore;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
@@ -61,6 +62,28 @@ public class TvInteractiveAppView extends ViewGroup {
|
||||
private static final int UNSET_TVVIEW_SUCCESS = 3;
|
||||
private static final int UNSET_TVVIEW_FAIL = 4;
|
||||
|
||||
/**
|
||||
* Used to share client {@link java.security.cert.Certificate} with
|
||||
* {@link TvInteractiveAppService}.
|
||||
* @see #createBiInteractiveApp(Uri, Bundle)
|
||||
* @see java.security.cert.Certificate
|
||||
*/
|
||||
public static final String BI_INTERACTIVE_APP_KEY_CERTIFICATE = "certificate";
|
||||
/**
|
||||
* Used to share the {@link KeyStore} alias with {@link TvInteractiveAppService}.
|
||||
* @see #createBiInteractiveApp(Uri, Bundle)
|
||||
* @see KeyStore#aliases()
|
||||
*/
|
||||
public static final String BI_INTERACTIVE_APP_KEY_ALIAS = "alias";
|
||||
/**
|
||||
* Used to share the {@link java.security.PrivateKey} with {@link TvInteractiveAppService}.
|
||||
* <p>The private key is optional. It is used to encrypt data when necessary.
|
||||
*
|
||||
* @see #createBiInteractiveApp(Uri, Bundle)
|
||||
* @see java.security.PrivateKey
|
||||
*/
|
||||
public static final String BI_INTERACTIVE_APP_KEY_PRIVATE_KEY = "private_key";
|
||||
|
||||
private final TvInteractiveAppManager mTvInteractiveAppManager;
|
||||
private final Handler mHandler = new Handler();
|
||||
private final Object mCallbackLock = new Object();
|
||||
@@ -513,6 +536,27 @@ public class TvInteractiveAppView extends ViewGroup {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends signing result to related TV interactive app.
|
||||
*
|
||||
* <p>This is used when the corresponding server of the broadcast-independent interactive
|
||||
* app requires signing during handshaking, and the interactive app service doesn't have
|
||||
* the built-in private key. The private key is provided by the content providers and
|
||||
* pre-built in the related app, such as TV app.
|
||||
*
|
||||
* @param signingId the ID to identify the request. It's the same as the corresponding ID in
|
||||
* {@link TvInteractiveAppService.Session#requestSigning(String, String, String, byte[])}
|
||||
* @param result the signed result.
|
||||
*/
|
||||
public void sendSigningResult(@NonNull String signingId, @NonNull byte[] result) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "sendSigningResult");
|
||||
}
|
||||
if (mSession != null) {
|
||||
mSession.sendSigningResult(signingId, result);
|
||||
}
|
||||
}
|
||||
|
||||
private void resetInternal() {
|
||||
mSessionCallback = null;
|
||||
if (mSession != null) {
|
||||
@@ -725,6 +769,22 @@ public class TvInteractiveAppView extends ViewGroup {
|
||||
public void onRequestCurrentTvInputId(@NonNull String iAppServiceId) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when
|
||||
* {@link TvInteractiveAppService.Session#requestSigning(String, String, String, byte[])} is
|
||||
* called.
|
||||
*
|
||||
* @param iAppServiceId The ID of the TV interactive app service bound to this view.
|
||||
* @param signingId the ID to identify the request.
|
||||
* @param algorithm the standard name of the signature algorithm requested, such as
|
||||
* MD5withRSA, SHA256withDSA, etc.
|
||||
* @param alias the alias of the corresponding {@link java.security.KeyStore}.
|
||||
* @param data the original bytes to be signed.
|
||||
*/
|
||||
public void onRequestSigning(@NonNull String iAppServiceId, @NonNull String signingId,
|
||||
@NonNull String algorithm, @NonNull String alias, @NonNull byte[] data) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1031,5 +1091,20 @@ public class TvInteractiveAppView extends ViewGroup {
|
||||
mCallback.onRequestCurrentTvInputId(mIAppServiceId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestSigning(
|
||||
Session session, String id, String algorithm, String alias, byte[] data) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "onRequestSigning");
|
||||
}
|
||||
if (this != mSessionCallback) {
|
||||
Log.w(TAG, "onRequestSigning - session not created");
|
||||
return;
|
||||
}
|
||||
if (mCallback != null) {
|
||||
mCallback.onRequestSigning(mIAppServiceId, id, algorithm, alias, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1359,6 +1359,32 @@ public class TvInteractiveAppManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSigningResult(
|
||||
IBinder sessionToken, String signingId, byte[] result, int userId) {
|
||||
if (DEBUG) {
|
||||
Slogf.d(TAG, "sendSigningResult(signingId=%s)", signingId);
|
||||
}
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
|
||||
userId, "sendSigningResult");
|
||||
SessionState sessionState = null;
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
try {
|
||||
sessionState = getSessionStateLocked(sessionToken, callingUid,
|
||||
resolvedUserId);
|
||||
getSessionLocked(sessionState).sendSigningResult(signingId, result);
|
||||
} catch (RemoteException | SessionNotFoundException e) {
|
||||
Slogf.e(TAG, "error in sendSigningResult", e);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSurface(IBinder sessionToken, Surface surface, int userId) {
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
@@ -2220,6 +2246,24 @@ public class TvInteractiveAppManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestSigning(String id, String algorithm, String alias, byte[] data) {
|
||||
synchronized (mLock) {
|
||||
if (DEBUG) {
|
||||
Slogf.d(TAG, "onRequestSigning");
|
||||
}
|
||||
if (mSessionState.mSession == null || mSessionState.mClient == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mSessionState.mClient.onRequestSigning(
|
||||
id, algorithm, alias, data, mSessionState.mSeq);
|
||||
} catch (RemoteException e) {
|
||||
Slogf.e(TAG, "error in onRequestSigning", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdRequest(AdRequest request) {
|
||||
synchronized (mLock) {
|
||||
|
||||
Reference in New Issue
Block a user