diff --git a/core/api/current.txt b/core/api/current.txt index d03ab96fbf461..c7b8d32f77a98 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -26205,6 +26205,7 @@ package android.media.tv.interactive { method public void onCurrentChannelUri(@Nullable android.net.Uri); method public void onCurrentTvInputId(@Nullable String); method public void onDestroyBiInteractiveAppRequest(@NonNull String); + method public void onError(@NonNull String, @NonNull android.os.Bundle); method public boolean onGenericMotionEvent(@NonNull android.view.MotionEvent); method public boolean onKeyDown(int, @NonNull android.view.KeyEvent); method public boolean onKeyLongPress(int, @NonNull android.view.KeyEvent); @@ -26266,6 +26267,7 @@ package android.media.tv.interactive { method public void destroyBiInteractiveApp(@NonNull String); method public boolean dispatchUnhandledInputEvent(@NonNull android.view.InputEvent); method @Nullable public android.media.tv.interactive.TvInteractiveAppView.OnUnhandledInputEventListener getOnUnhandledInputEventListener(); + method public void notifyError(@NonNull String, @NonNull android.os.Bundle); method public void onAttachedToWindow(); method public void onDetachedFromWindow(); method public void onLayout(boolean, int, int, int, int); @@ -26292,6 +26294,7 @@ package android.media.tv.interactive { field public static final String BI_INTERACTIVE_APP_KEY_HTTP_ADDITIONAL_HEADERS = "http_additional_headers"; field public static final String BI_INTERACTIVE_APP_KEY_HTTP_USER_AGENT = "http_user_agent"; field public static final String BI_INTERACTIVE_APP_KEY_PRIVATE_KEY = "private_key"; + field public static final String ERROR_KEY_METHOD_NAME = "method_name"; } public static interface TvInteractiveAppView.OnUnhandledInputEventListener { diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl index 9ff564ea37376..c8c695f07b20d 100644 --- a/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl +++ b/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl @@ -51,6 +51,7 @@ interface ITvInteractiveAppManager { void sendCurrentTvInputId(in IBinder sessionToken, in String inputId, int userId); void sendSigningResult(in IBinder sessionToken, in String signingId, in byte[] result, int userId); + void notifyError(in IBinder sessionToken, in String errMsg, in Bundle params, int userId); void createSession(in ITvInteractiveAppClient client, in String iAppServiceId, int type, int seq, int userId); void releaseSession(in IBinder sessionToken, int userId); diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl index e14b2bb18ea61..818c28717ec21 100644 --- a/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl +++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl @@ -43,6 +43,7 @@ oneway interface ITvInteractiveAppSession { void sendTrackInfoList(in List tracks); void sendCurrentTvInputId(in String inputId); void sendSigningResult(in String signingId, in byte[] result); + void notifyError(in String errMsg, in Bundle params); void release(); void notifyTuned(in Uri channelUri); void notifyTrackSelected(int type, in String trackId); diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java index d3cbcdc9a255f..43d4605209dca 100755 --- a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java +++ b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java @@ -1047,6 +1047,18 @@ public final class TvInteractiveAppManager { } } + void notifyError(@NonNull String errMsg, @NonNull Bundle params) { + if (mToken == null) { + Log.w(TAG, "The session has been already released"); + return; + } + try { + mService.notifyError(mToken, errMsg, params, mUserId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Sets the {@link android.view.Surface} for this session. * diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppService.java b/media/java/android/media/tv/interactive/TvInteractiveAppService.java index b103b10363038..54700b6594f8d 100755 --- a/media/java/android/media/tv/interactive/TvInteractiveAppService.java +++ b/media/java/android/media/tv/interactive/TvInteractiveAppService.java @@ -39,6 +39,7 @@ import android.media.tv.TvInputInfo; import android.media.tv.TvInputManager; import android.media.tv.TvTrackInfo; import android.media.tv.TvView; +import android.media.tv.interactive.TvInteractiveAppView.TvInteractiveAppCallback; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; @@ -465,6 +466,20 @@ public abstract class TvInteractiveAppService extends Service { public void onSigningResult(@NonNull String signingId, @NonNull byte[] result) { } + /** + * Called when the application sends information of an error. + * + * @param errMsg the message of the error. + * @param params additional parameters of the error. For example, the signingId of {@link + * TvInteractiveAppCallback#onRequestSigning(String, String, String, String, byte[])} + * can be included to identify the related signing request, and the method name + * "onRequestSigning" can also be added to the params. + * + * @see TvInteractiveAppView#ERROR_KEY_METHOD_NAME + */ + public void onError(@NonNull String errMsg, @NonNull Bundle params) { + } + /** * Called when the application sets the surface. * @@ -1004,6 +1019,10 @@ public abstract class TvInteractiveAppService extends Service { onSigningResult(signingId, result); } + void notifyError(String errMsg, Bundle params) { + onError(errMsg, params); + } + void release() { onRelease(); if (mSurface != null) { @@ -1476,6 +1495,11 @@ public abstract class TvInteractiveAppService extends Service { mSessionImpl.sendSigningResult(signingId, result); } + @Override + public void notifyError(@NonNull String errMsg, @NonNull Bundle params) { + mSessionImpl.notifyError(errMsg, params); + } + @Override public void release() { mSessionImpl.scheduleMediaViewCleanup(); diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppView.java b/media/java/android/media/tv/interactive/TvInteractiveAppView.java index 1df757b2d9d72..9f6556062f532 100755 --- a/media/java/android/media/tv/interactive/TvInteractiveAppView.java +++ b/media/java/android/media/tv/interactive/TvInteractiveAppView.java @@ -97,6 +97,13 @@ public class TvInteractiveAppView extends ViewGroup { */ public static final String BI_INTERACTIVE_APP_KEY_HTTP_USER_AGENT = "http_user_agent"; + /** + * The name of the method where the error happened, if applicable. For example, if there is an + * error during signing, the request name is "onRequestSigning". + * @see #notifyError(String, Bundle) + */ + public static final String ERROR_KEY_METHOD_NAME = "method_name"; + private final TvInteractiveAppManager mTvInteractiveAppManager; private final Handler mHandler = new Handler(); private final Object mCallbackLock = new Object(); @@ -590,6 +597,26 @@ public class TvInteractiveAppView extends ViewGroup { } } + /** + * Notifies the corresponding {@link TvInteractiveAppService} when there is an error. + * + * @param errMsg the message of the error. + * @param params additional parameters of the error. For example, the signingId of {@link + * TvInteractiveAppCallback#onRequestSigning(String, String, String, String, byte[])} can be + * included to identify the related signing request, and the method name "onRequestSigning" + * can also be added to the params. + * + * @see #ERROR_KEY_METHOD_NAME + */ + public void notifyError(@NonNull String errMsg, @NonNull Bundle params) { + if (DEBUG) { + Log.d(TAG, "notifyError msg=" + errMsg + "; params=" + params); + } + if (mSession != null) { + mSession.notifyError(errMsg, params); + } + } + private void resetInternal() { mSessionCallback = null; if (mSession != null) { 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 672458bef4a7f..c524bc48a332e 100644 --- a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java +++ b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java @@ -1349,6 +1349,31 @@ public class TvInteractiveAppManagerService extends SystemService { } } + @Override + public void notifyError(IBinder sessionToken, String errMsg, Bundle params, int userId) { + if (DEBUG) { + Slogf.d(TAG, "notifyError(errMsg=%s)", errMsg); + } + final int callingUid = Binder.getCallingUid(); + final int resolvedUserId = + resolveCallingUserId(Binder.getCallingPid(), callingUid, userId, "notifyError"); + SessionState sessionState = null; + final long identity = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + try { + sessionState = + getSessionStateLocked(sessionToken, callingUid, resolvedUserId); + getSessionLocked(sessionState).notifyError(errMsg, params); + } catch (RemoteException | SessionNotFoundException e) { + Slogf.e(TAG, "error in notifyError", e); + } + } + } finally { + Binder.restoreCallingIdentity(identity); + } + } + @Override public void setSurface(IBinder sessionToken, Surface surface, int userId) { final int callingUid = Binder.getCallingUid();