Framework support cas@1.2

Test: Manual
bug: 141783130
Change-Id: I62d42ad51444b8d58282f5d6992ba6f2169dd6d3
This commit is contained in:
Henry Fang 2019-12-27 16:50:20 -08:00
parent 658b4ca415
commit 43cab92abe
7 changed files with 560 additions and 61 deletions

View File

@ -326,8 +326,9 @@ java_library {
"framework-protos",
"game-driver-protos",
"android.hidl.base-V1.0-java",
"android.hardware.cas-V1.1-java",
"android.hardware.cas-V1.0-java",
"android.hardware.cas-V1.1-java",
"android.hardware.cas-V1.2-java",
"android.hardware.contexthub-V1.0-java",
"android.hardware.gnss-V1.0-java",
"android.hardware.health-V1.0-java-constants",

View File

@ -24793,11 +24793,13 @@ package android.media {
public final class MediaCas implements java.lang.AutoCloseable {
ctor public MediaCas(int) throws android.media.MediaCasException.UnsupportedCasException;
ctor public MediaCas(int, @Nullable String, int) throws android.media.MediaCasException.UnsupportedCasException;
method public void close();
method public static android.media.MediaCas.PluginDescriptor[] enumeratePlugins();
method protected void finalize();
method public static boolean isSystemIdSupported(int);
method public android.media.MediaCas.Session openSession() throws android.media.MediaCasException;
method @Nullable public android.media.MediaCas.Session openSession(int, int) throws android.media.MediaCasException;
method public void processEmm(@NonNull byte[], int, int) throws android.media.MediaCasException;
method public void processEmm(@NonNull byte[]) throws android.media.MediaCasException;
method public void provision(@NonNull String) throws android.media.MediaCasException;
@ -24805,10 +24807,32 @@ package android.media {
method public void sendEvent(int, int, @Nullable byte[]) throws android.media.MediaCasException;
method public void setEventListener(@Nullable android.media.MediaCas.EventListener, @Nullable android.os.Handler);
method public void setPrivateData(@NonNull byte[]) throws android.media.MediaCasException;
field public static final int PLUGIN_STATUS_PHYSICAL_MODULE_CHANGED = 0; // 0x0
field public static final int PLUGIN_STATUS_SESSION_NUMBER_CHANGED = 1; // 0x1
field public static final int SCRAMBLING_MODE_AES128 = 9; // 0x9
field public static final int SCRAMBLING_MODE_AES_ECB = 10; // 0xa
field public static final int SCRAMBLING_MODE_AES_SCTE52 = 11; // 0xb
field public static final int SCRAMBLING_MODE_DVB_CISSA_V1 = 6; // 0x6
field public static final int SCRAMBLING_MODE_DVB_CSA1 = 1; // 0x1
field public static final int SCRAMBLING_MODE_DVB_CSA2 = 2; // 0x2
field public static final int SCRAMBLING_MODE_DVB_CSA3_ENHANCE = 5; // 0x5
field public static final int SCRAMBLING_MODE_DVB_CSA3_MINIMAL = 4; // 0x4
field public static final int SCRAMBLING_MODE_DVB_CSA3_STANDARD = 3; // 0x3
field public static final int SCRAMBLING_MODE_DVB_IDSA = 7; // 0x7
field public static final int SCRAMBLING_MODE_MULTI2 = 8; // 0x8
field public static final int SCRAMBLING_MODE_RESERVED = 0; // 0x0
field public static final int SCRAMBLING_MODE_TDES_ECB = 12; // 0xc
field public static final int SCRAMBLING_MODE_TDES_SCTE52 = 13; // 0xd
field public static final int SESSION_USAGE_LIVE = 0; // 0x0
field public static final int SESSION_USAGE_PLAYBACK = 1; // 0x1
field public static final int SESSION_USAGE_RECORD = 2; // 0x2
field public static final int SESSION_USAGE_TIMESHIFT = 3; // 0x3
}
public static interface MediaCas.EventListener {
method public void onEvent(@NonNull android.media.MediaCas, int, int, @Nullable byte[]);
method public default void onPluginStatusUpdate(@NonNull android.media.MediaCas, int, int);
method public default void onResourceLost(@NonNull android.media.MediaCas);
method public default void onSessionEvent(@NonNull android.media.MediaCas, @NonNull android.media.MediaCas.Session, int, int, @Nullable byte[]);
}
@ -24819,6 +24843,7 @@ package android.media {
public final class MediaCas.Session implements java.lang.AutoCloseable {
method public void close();
method @NonNull public byte[] getSessionId();
method public void processEcm(@NonNull byte[], int, int) throws android.media.MediaCasException;
method public void processEcm(@NonNull byte[]) throws android.media.MediaCasException;
method public void sendSessionEvent(int, int, @Nullable byte[]) throws android.media.MediaCasException;
@ -24831,6 +24856,9 @@ package android.media {
public static final class MediaCasException.DeniedByServerException extends android.media.MediaCasException {
}
public static final class MediaCasException.InsufficientResourceException extends android.media.MediaCasException {
}
public static final class MediaCasException.NotProvisionedException extends android.media.MediaCasException {
}
@ -28817,6 +28845,19 @@ package android.media.tv {
field public static final int TIME_SHIFT_STATUS_UNSUPPORTED = 1; // 0x1
field public static final int VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY = 4; // 0x4
field public static final int VIDEO_UNAVAILABLE_REASON_BUFFERING = 3; // 0x3
field public static final int VIDEO_UNAVAILABLE_REASON_CAS_BLACKOUT = 16; // 0x10
field public static final int VIDEO_UNAVAILABLE_REASON_CAS_CARD_INVALID = 15; // 0xf
field public static final int VIDEO_UNAVAILABLE_REASON_CAS_CARD_MUTE = 14; // 0xe
field public static final int VIDEO_UNAVAILABLE_REASON_CAS_INSUFFICIENT_OUTPUT_PROTECTION = 7; // 0x7
field public static final int VIDEO_UNAVAILABLE_REASON_CAS_LICENSE_EXPIRED = 10; // 0xa
field public static final int VIDEO_UNAVAILABLE_REASON_CAS_NEED_ACTIVATION = 11; // 0xb
field public static final int VIDEO_UNAVAILABLE_REASON_CAS_NEED_PAIRING = 12; // 0xc
field public static final int VIDEO_UNAVAILABLE_REASON_CAS_NO_CARD = 13; // 0xd
field public static final int VIDEO_UNAVAILABLE_REASON_CAS_PVR_RECORDING_NOT_ALLOWED = 8; // 0x8
field public static final int VIDEO_UNAVAILABLE_REASON_CAS_REBOOTING = 17; // 0x11
field public static final int VIDEO_UNAVAILABLE_REASON_CAS_UNKNOWN = 18; // 0x12
field public static final int VIDEO_UNAVAILABLE_REASON_INSUFFICIENT_RESOURCE = 6; // 0x6
field public static final int VIDEO_UNAVAILABLE_REASON_NOT_CONNECTED = 5; // 0x5
field public static final int VIDEO_UNAVAILABLE_REASON_TUNING = 1; // 0x1
field public static final int VIDEO_UNAVAILABLE_REASON_UNKNOWN = 0; // 0x0
field public static final int VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL = 2; // 0x2
@ -28838,6 +28879,11 @@ package android.media.tv {
method @Nullable public android.media.tv.TvInputService.RecordingSession onCreateRecordingSession(@NonNull String, @NonNull String);
method @Nullable public abstract android.media.tv.TvInputService.Session onCreateSession(String);
method @Nullable public android.media.tv.TvInputService.Session onCreateSession(@NonNull String, @NonNull String);
field public static final int PRIORITY_HINT_USE_CASE_TYPE_BACKGROUND = 100; // 0x64
field public static final int PRIORITY_HINT_USE_CASE_TYPE_LIVE = 400; // 0x190
field public static final int PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK = 300; // 0x12c
field public static final int PRIORITY_HINT_USE_CASE_TYPE_RECORD = 500; // 0x1f4
field public static final int PRIORITY_HINT_USE_CASE_TYPE_SCAN = 200; // 0xc8
field public static final String SERVICE_INTERFACE = "android.media.tv.TvInputService";
field public static final String SERVICE_META_DATA = "android.media.tv.input";
}

View File

@ -16,13 +16,15 @@
package android.media;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.hardware.cas.V1_0.HidlCasPluginDescriptor;
import android.hardware.cas.V1_0.ICas;
import android.hardware.cas.V1_0.IMediaCasService;
import android.hardware.cas.V1_1.ICasListener;
import android.hardware.cas.V1_2.ICasListener;
import android.media.MediaCasException.*;
import android.media.tv.TvInputService.PriorityHintUseCaseType;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
@ -34,6 +36,8 @@ import android.os.RemoteException;
import android.util.Log;
import android.util.Singleton;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
/**
@ -100,28 +104,185 @@ public final class MediaCas implements AutoCloseable {
private static final String TAG = "MediaCas";
private ICas mICas;
private android.hardware.cas.V1_1.ICas mICasV11;
private android.hardware.cas.V1_2.ICas mICasV12;
private EventListener mListener;
private HandlerThread mHandlerThread;
private EventHandler mEventHandler;
private @PriorityHintUseCaseType int mPriorityHint;
private String mTvInputServiceSessionId;
/**
* Scrambling modes used to open cas sessions.
*
* @hide
*/
@IntDef(prefix = "SCRAMBLING_MODE_",
value = {SCRAMBLING_MODE_RESERVED, SCRAMBLING_MODE_DVB_CSA1, SCRAMBLING_MODE_DVB_CSA2,
SCRAMBLING_MODE_DVB_CSA3_STANDARD,
SCRAMBLING_MODE_DVB_CSA3_MINIMAL, SCRAMBLING_MODE_DVB_CSA3_ENHANCE,
SCRAMBLING_MODE_DVB_CISSA_V1, SCRAMBLING_MODE_DVB_IDSA,
SCRAMBLING_MODE_MULTI2, SCRAMBLING_MODE_AES128, SCRAMBLING_MODE_AES_ECB,
SCRAMBLING_MODE_AES_SCTE52, SCRAMBLING_MODE_TDES_ECB, SCRAMBLING_MODE_TDES_SCTE52})
@Retention(RetentionPolicy.SOURCE)
public @interface ScramblingMode {}
/**
* DVB (Digital Video Broadcasting) reserved mode.
*/
public static final int SCRAMBLING_MODE_RESERVED =
android.hardware.cas.V1_2.ScramblingMode.RESERVED;
/**
* DVB (Digital Video Broadcasting) Common Scrambling Algorithm (CSA) 1.
*/
public static final int SCRAMBLING_MODE_DVB_CSA1 =
android.hardware.cas.V1_2.ScramblingMode.DVB_CSA1;
/**
* DVB CSA 2.
*/
public static final int SCRAMBLING_MODE_DVB_CSA2 =
android.hardware.cas.V1_2.ScramblingMode.DVB_CSA2;
/**
* DVB CSA 3 in standard mode.
*/
public static final int SCRAMBLING_MODE_DVB_CSA3_STANDARD =
android.hardware.cas.V1_2.ScramblingMode.DVB_CSA3_STANDARD;
/**
* DVB CSA 3 in minimally enhanced mode.
*/
public static final int SCRAMBLING_MODE_DVB_CSA3_MINIMAL =
android.hardware.cas.V1_2.ScramblingMode.DVB_CSA3_MINIMAL;
/**
* DVB CSA 3 in fully enhanced mode.
*/
public static final int SCRAMBLING_MODE_DVB_CSA3_ENHANCE =
android.hardware.cas.V1_2.ScramblingMode.DVB_CSA3_ENHANCE;
/**
* DVB Common IPTV Software-oriented Scrambling Algorithm (CISSA) Version 1.
*/
public static final int SCRAMBLING_MODE_DVB_CISSA_V1 =
android.hardware.cas.V1_2.ScramblingMode.DVB_CISSA_V1;
/**
* ATIS-0800006 IIF Default Scrambling Algorithm (IDSA).
*/
public static final int SCRAMBLING_MODE_DVB_IDSA =
android.hardware.cas.V1_2.ScramblingMode.DVB_IDSA;
/**
* A symmetric key algorithm.
*/
public static final int SCRAMBLING_MODE_MULTI2 =
android.hardware.cas.V1_2.ScramblingMode.MULTI2;
/**
* Advanced Encryption System (AES) 128-bit Encryption mode.
*/
public static final int SCRAMBLING_MODE_AES128 =
android.hardware.cas.V1_2.ScramblingMode.AES128;
/**
* Advanced Encryption System (AES) Electronic Code Book (ECB) mode.
*/
public static final int SCRAMBLING_MODE_AES_ECB =
android.hardware.cas.V1_2.ScramblingMode.AES_ECB;
/**
* Advanced Encryption System (AES) Society of Cable Telecommunications Engineers (SCTE) 52
* mode.
*/
public static final int SCRAMBLING_MODE_AES_SCTE52 =
android.hardware.cas.V1_2.ScramblingMode.AES_SCTE52;
/**
* Triple Data Encryption Algorithm (TDES) Electronic Code Book (ECB) mode.
*/
public static final int SCRAMBLING_MODE_TDES_ECB =
android.hardware.cas.V1_2.ScramblingMode.TDES_ECB;
/**
* Triple Data Encryption Algorithm (TDES) Society of Cable Telecommunications Engineers (SCTE)
* 52 mode.
*/
public static final int SCRAMBLING_MODE_TDES_SCTE52 =
android.hardware.cas.V1_2.ScramblingMode.TDES_SCTE52;
/**
* Usages used to open cas sessions.
*
* @hide
*/
@IntDef(prefix = "SESSION_USAGE_",
value = {SESSION_USAGE_LIVE, SESSION_USAGE_PLAYBACK, SESSION_USAGE_RECORD,
SESSION_USAGE_TIMESHIFT})
@Retention(RetentionPolicy.SOURCE)
public @interface SessionUsage {}
/**
* Cas session is used to descramble live streams.
*/
public static final int SESSION_USAGE_LIVE = android.hardware.cas.V1_2.SessionIntent.LIVE;
/**
* Cas session is used to descramble recoreded streams.
*/
public static final int SESSION_USAGE_PLAYBACK =
android.hardware.cas.V1_2.SessionIntent.PLAYBACK;
/**
* Cas session is used to descramble live streams and encrypt local recorded content
*/
public static final int SESSION_USAGE_RECORD = android.hardware.cas.V1_2.SessionIntent.RECORD;
/**
* Cas session is used to descramble live streams , encrypt local recorded content and playback
* local encrypted content.
*/
public static final int SESSION_USAGE_TIMESHIFT =
android.hardware.cas.V1_2.SessionIntent.TIMESHIFT;
/**
* Plugin status events sent from cas system.
*
* @hide
*/
@IntDef(prefix = "PLUGIN_STATUS_",
value = {PLUGIN_STATUS_PHYSICAL_MODULE_CHANGED, PLUGIN_STATUS_SESSION_NUMBER_CHANGED})
@Retention(RetentionPolicy.SOURCE)
public @interface PluginStatus {}
/**
* The event to indicate that the status of CAS system is changed by the removal or insertion of
* physical CAS modules.
*/
public static final int PLUGIN_STATUS_PHYSICAL_MODULE_CHANGED =
android.hardware.cas.V1_2.StatusEvent.PLUGIN_PHYSICAL_MODULE_CHANGED;
/**
* The event to indicate that the number of CAS system's session is changed.
*/
public static final int PLUGIN_STATUS_SESSION_NUMBER_CHANGED =
android.hardware.cas.V1_2.StatusEvent.PLUGIN_SESSION_NUMBER_CHANGED;
private static final Singleton<IMediaCasService> sService = new Singleton<IMediaCasService>() {
@Override
protected IMediaCasService create() {
try {
Log.d(TAG, "Tried to get cas@1.1 service");
android.hardware.cas.V1_1.IMediaCasService serviceV11 =
android.hardware.cas.V1_1.IMediaCasService.getService(true /*wait*/);
if (serviceV11 != null) {
return serviceV11;
}
} catch (Exception eV1_1) {
try {
Log.d(TAG, "Tried to get cas@1.0 service");
return IMediaCasService.getService(true /*wait*/);
} catch (Exception eV1_0) {
Log.d(TAG, "Failed to get cas@1.0 service");
Log.d(TAG, "Trying to get cas@1.2 service");
android.hardware.cas.V1_2.IMediaCasService serviceV12 =
android.hardware.cas.V1_2.IMediaCasService.getService(true /*wait*/);
if (serviceV12 != null) {
return serviceV12;
}
} catch (Exception eV1_2) {
Log.d(TAG, "Failed to get cas@1.2 service");
}
try {
Log.d(TAG, "Trying to get cas@1.1 service");
android.hardware.cas.V1_1.IMediaCasService serviceV11 =
android.hardware.cas.V1_1.IMediaCasService.getService(true /*wait*/);
if (serviceV11 != null) {
return serviceV11;
}
} catch (Exception eV1_1) {
Log.d(TAG, "Failed to get cas@1.1 service");
}
try {
Log.d(TAG, "Trying to get cas@1.0 service");
return IMediaCasService.getService(true /*wait*/);
} catch (Exception eV1_0) {
Log.d(TAG, "Failed to get cas@1.0 service");
}
return null;
}
};
@ -139,6 +300,7 @@ public final class MediaCas implements AutoCloseable {
private void cleanupAndRethrowIllegalState() {
mICas = null;
mICasV11 = null;
mICasV12 = null;
throw new IllegalStateException();
}
@ -146,6 +308,8 @@ public final class MediaCas implements AutoCloseable {
private static final int MSG_CAS_EVENT = 0;
private static final int MSG_CAS_SESSION_EVENT = 1;
private static final int MSG_CAS_STATUS_EVENT = 2;
private static final int MSG_CAS_RESOURCE_LOST = 3;
private static final String SESSION_KEY = "sessionId";
private static final String DATA_KEY = "data";
@ -164,6 +328,10 @@ public final class MediaCas implements AutoCloseable {
mListener.onSessionEvent(MediaCas.this,
createFromSessionId(sessionId), msg.arg1, msg.arg2,
bundle.getByteArray(DATA_KEY));
} else if (msg.what == MSG_CAS_STATUS_EVENT) {
mListener.onPluginStatusUpdate(MediaCas.this, msg.arg1, msg.arg2);
} else if (msg.what == MSG_CAS_RESOURCE_LOST) {
mListener.onResourceLost(MediaCas.this);
}
}
}
@ -189,6 +357,12 @@ public final class MediaCas implements AutoCloseable {
msg.setData(bundle);
mEventHandler.sendMessage(msg);
}
@Override
public void onStatusUpdate(byte status, int arg)
throws RemoteException {
mEventHandler.sendMessage(mEventHandler.obtainMessage(
EventHandler.MSG_CAS_STATUS_EVENT, status, arg));
}
};
/**
* Describe a CAS plugin with its CA_system_ID and string name.
@ -257,7 +431,7 @@ public final class MediaCas implements AutoCloseable {
final ArrayList<Byte> mSessionId;
Session(@NonNull ArrayList<Byte> sessionId) {
mSessionId = sessionId;
mSessionId = new ArrayList<Byte>(sessionId);
}
/**
@ -363,6 +537,19 @@ public final class MediaCas implements AutoCloseable {
}
}
/**
* Get Session Id.
*
* @return session Id of the session.
*
* @throws IllegalStateException if the MediaCas instance is not valid.
*/
@NonNull
public byte[] getSessionId() {
validateInternalStates();
return toBytes(mSessionId);
}
/**
* Close the session.
*
@ -445,14 +632,23 @@ public final class MediaCas implements AutoCloseable {
public MediaCas(int CA_system_id) throws UnsupportedCasException {
try {
IMediaCasService service = getService();
android.hardware.cas.V1_1.IMediaCasService serviceV11 =
android.hardware.cas.V1_2.IMediaCasService serviceV12 =
android.hardware.cas.V1_2.IMediaCasService.castFrom(service);
if (serviceV12 == null) {
android.hardware.cas.V1_1.IMediaCasService serviceV11 =
android.hardware.cas.V1_1.IMediaCasService.castFrom(service);
if (serviceV11 == null) {
Log.d(TAG, "Used cas@1_0 interface to create plugin");
mICas = service.createPlugin(CA_system_id, mBinder);
if (serviceV11 == null) {
Log.d(TAG, "Used cas@1_0 interface to create plugin");
mICas = service.createPlugin(CA_system_id, mBinder);
} else {
Log.d(TAG, "Used cas@1.1 interface to create plugin");
mICas = mICasV11 = serviceV11.createPluginExt(CA_system_id, mBinder);
}
} else {
Log.d(TAG, "Used cas@1.1 interface to create plugin");
mICas = mICasV11 = serviceV11.createPluginExt(CA_system_id, mBinder);
Log.d(TAG, "Used cas@1.2 interface to create plugin");
mICas = mICasV11 = mICasV12 =
android.hardware.cas.V1_2.ICas
.castFrom(serviceV12.createPluginExt(CA_system_id, mBinder));
}
} catch(Exception e) {
Log.e(TAG, "Failed to create plugin: " + e);
@ -465,6 +661,24 @@ public final class MediaCas implements AutoCloseable {
}
}
/**
* Instantiate a CA system of the specified system id.
*
* @param casSystemId The system id of the CA system.
* @param tvInputServiceSessionId The Id of the session opened in TV Input Service (TIS)
* {@link android.media.tv.TvInputService#onCreateSession(String, String)}
* @param priorityHint priority hint from the use case type for new created CAS system.
*
* @throws UnsupportedCasException if the device does not support the
* specified CA system.
*/
public MediaCas(int casSystemId, @Nullable String tvInputServiceSessionId,
@PriorityHintUseCaseType int priorityHint) throws UnsupportedCasException {
this(casSystemId);
mPriorityHint = priorityHint;
mTvInputServiceSessionId = tvInputServiceSessionId;
}
IHwBinder getBinder() {
validateInternalStates();
@ -476,6 +690,7 @@ public final class MediaCas implements AutoCloseable {
* to receives scheme-specific notifications from a MediaCas instance.
*/
public interface EventListener {
/**
* Notify the listener of a scheme-specific event from the CA system.
*
@ -501,6 +716,27 @@ public final class MediaCas implements AutoCloseable {
int event, int arg, @Nullable byte[] data) {
Log.d(TAG, "Received MediaCas Session event");
}
/**
* Notify the listener that the cas plugin status is updated.
*
* @param mediaCas the MediaCas object to receive this event.
* @param status the plugin status which is updated.
* @param arg an integer whose meaning is specific to the status to be updated.
*/
default void onPluginStatusUpdate(@NonNull MediaCas mediaCas, @PluginStatus int status,
int arg) {
Log.d(TAG, "Received MediaCas Plugin Status event");
}
/**
* Notify the listener that the session resources was lost.
*
* @param mediaCas the MediaCas object to receive this event.
*/
default void onResourceLost(@NonNull MediaCas mediaCas) {
Log.d(TAG, "Received MediaCas Resource Reclaim event");
}
}
/**
@ -563,6 +799,20 @@ public final class MediaCas implements AutoCloseable {
mSession = createFromSessionId(sessionId);
}
}
private class OpenSession_1_2_Callback implements
android.hardware.cas.V1_2.ICas.openSession_1_2Callback {
public Session mSession;
public int mStatus;
@Override
public void onValues(int status, ArrayList<Byte> sessionId) {
mStatus = status;
mSession = createFromSessionId(sessionId);
}
}
/**
* Open a session to descramble one or more streams scrambled by the
* conditional access system.
@ -587,6 +837,40 @@ public final class MediaCas implements AutoCloseable {
return null;
}
/**
* Open a session with usage and scrambling information, so that descrambler can be configured
* to descramble one or more streams scrambled by the conditional access system.
*
* @param sessionUsage used for the created session.
* @param scramblingMode used for the created session.
*
* @return session the newly opened session.
*
* @throws IllegalStateException if the MediaCas instance is not valid.
* @throws MediaCasException for CAS-specific errors.
* @throws MediaCasStateException for CAS-specific state exceptions.
*/
@Nullable
public Session openSession(@SessionUsage int sessionUsage, @ScramblingMode int scramblingMode)
throws MediaCasException {
validateInternalStates();
if (mICasV12 == null) {
Log.d(TAG, "Open Session with scrambling mode is only supported by cas@1.2+ interface");
throw new UnsupportedCasException("Open Session with scrambling mode is not supported");
}
try {
OpenSession_1_2_Callback cb = new OpenSession_1_2_Callback();
mICasV12.openSession_1_2(sessionUsage, scramblingMode, cb);
MediaCasException.throwExceptionIfNeeded(cb.mStatus);
return cb.mSession;
} catch (RemoteException e) {
cleanupAndRethrowIllegalState();
}
return null;
}
/**
* Send a received EMM packet to the CA system.
*

View File

@ -16,7 +16,7 @@
package android.media;
import android.hardware.cas.V1_0.Status;
import android.hardware.cas.V1_2.Status;
/**
* Base class for MediaCas exceptions
@ -85,4 +85,15 @@ public class MediaCasException extends Exception {
super(detailMessage);
}
}
/**
* Exception thrown when an operation on a MediaCas object is attempted
* and hardware resources are not sufficient to allocate, due to client's lower priority.
*/
public static final class InsufficientResourceException extends MediaCasException {
/** @hide */
public InsufficientResourceException(String detailMessage) {
super(detailMessage);
}
}
}

View File

@ -18,8 +18,7 @@ package android.media;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.hardware.cas.V1_0.Status;
import android.hardware.cas.V1_2.Status;
/**
* Base class for MediaCas runtime exceptions
@ -48,39 +47,60 @@ public class MediaCasStateException extends IllegalStateException {
String diagnosticInfo = "";
switch (err) {
case Status.ERROR_CAS_UNKNOWN:
diagnosticInfo = "General CAS error";
break;
case Status.ERROR_CAS_NO_LICENSE:
diagnosticInfo = "No license";
break;
case Status.ERROR_CAS_LICENSE_EXPIRED:
diagnosticInfo = "License expired";
break;
case Status.ERROR_CAS_SESSION_NOT_OPENED:
diagnosticInfo = "Session not opened";
break;
case Status.ERROR_CAS_CANNOT_HANDLE:
diagnosticInfo = "Unsupported scheme or data format";
break;
case Status.ERROR_CAS_INVALID_STATE:
diagnosticInfo = "Invalid CAS state";
break;
case Status.ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION:
diagnosticInfo = "Insufficient output protection";
break;
case Status.ERROR_CAS_TAMPER_DETECTED:
diagnosticInfo = "Tamper detected";
break;
case Status.ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED:
diagnosticInfo = "Not initialized";
break;
case Status.ERROR_CAS_DECRYPT:
diagnosticInfo = "Decrypt error";
break;
default:
diagnosticInfo = "Unknown CAS state exception";
break;
case Status.ERROR_CAS_UNKNOWN:
diagnosticInfo = "General CAS error";
break;
case Status.ERROR_CAS_NO_LICENSE:
diagnosticInfo = "No license";
break;
case Status.ERROR_CAS_LICENSE_EXPIRED:
diagnosticInfo = "License expired";
break;
case Status.ERROR_CAS_SESSION_NOT_OPENED:
diagnosticInfo = "Session not opened";
break;
case Status.ERROR_CAS_CANNOT_HANDLE:
diagnosticInfo = "Unsupported scheme or data format";
break;
case Status.ERROR_CAS_INVALID_STATE:
diagnosticInfo = "Invalid CAS state";
break;
case Status.ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION:
diagnosticInfo = "Insufficient output protection";
break;
case Status.ERROR_CAS_TAMPER_DETECTED:
diagnosticInfo = "Tamper detected";
break;
case Status.ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED:
diagnosticInfo = "Not initialized";
break;
case Status.ERROR_CAS_DECRYPT:
diagnosticInfo = "Decrypt error";
break;
case Status.ERROR_CAS_NEED_ACTIVATION:
diagnosticInfo = "Need Activation";
break;
case Status.ERROR_CAS_NEED_PAIRING:
diagnosticInfo = "Need Pairing";
break;
case Status.ERROR_CAS_NO_CARD:
diagnosticInfo = "No Card";
break;
case Status.ERROR_CAS_CARD_MUTE:
diagnosticInfo = "Card Muted";
break;
case Status.ERROR_CAS_CARD_INVALID:
diagnosticInfo = "Card Invalid";
break;
case Status.ERROR_CAS_BLACKOUT:
diagnosticInfo = "Blackout";
break;
case Status.ERROR_CAS_REBOOTING:
diagnosticInfo = "Rebooting";
break;
default:
diagnosticInfo = "Unknown CAS state exception";
break;
}
throw new MediaCasStateException(err, msg,
String.format("%s (err=%d)", diagnosticInfo, err));

View File

@ -110,12 +110,20 @@ public final class TvInputManager {
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef({VIDEO_UNAVAILABLE_REASON_UNKNOWN, VIDEO_UNAVAILABLE_REASON_TUNING,
VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL, VIDEO_UNAVAILABLE_REASON_BUFFERING,
VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY})
VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL, VIDEO_UNAVAILABLE_REASON_BUFFERING,
VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY, VIDEO_UNAVAILABLE_REASON_INSUFFICIENT_RESOURCE,
VIDEO_UNAVAILABLE_REASON_CAS_INSUFFICIENT_OUTPUT_PROTECTION,
VIDEO_UNAVAILABLE_REASON_CAS_PVR_RECORDING_NOT_ALLOWED,
VIDEO_UNAVAILABLE_REASON_CAS_PVR_RECORDING_NOT_ALLOWED,
VIDEO_UNAVAILABLE_REASON_CAS_NO_LICENSE, VIDEO_UNAVAILABLE_REASON_CAS_LICENSE_EXPIRED,
VIDEO_UNAVAILABLE_REASON_CAS_NEED_ACTIVATION, VIDEO_UNAVAILABLE_REASON_CAS_NEED_PAIRING,
VIDEO_UNAVAILABLE_REASON_CAS_NO_CARD, VIDEO_UNAVAILABLE_REASON_CAS_CARD_MUTE,
VIDEO_UNAVAILABLE_REASON_CAS_CARD_INVALID, VIDEO_UNAVAILABLE_REASON_CAS_BLACKOUT,
VIDEO_UNAVAILABLE_REASON_CAS_REBOOTING, VIDEO_UNAVAILABLE_REASON_CAS_UNKNOWN})
public @interface VideoUnavailableReason {}
static final int VIDEO_UNAVAILABLE_REASON_START = 0;
static final int VIDEO_UNAVAILABLE_REASON_END = 5;
static final int VIDEO_UNAVAILABLE_REASON_END = 18;
/**
* Reason for {@link TvInputService.Session#notifyVideoUnavailable(int)} and
@ -151,9 +159,88 @@ public final class TvInputManager {
* Reason for {@link TvInputService.Session#notifyVideoUnavailable(int)} and
* {@link TvView.TvInputCallback#onVideoUnavailable(String, int)}: Video is unavailable because
* the source is not physically connected, for example the HDMI cable is not connected.
*/
public static final int VIDEO_UNAVAILABLE_REASON_NOT_CONNECTED = 5;
/**
* Reason for {@link TvInputService.Session#notifyVideoUnavailable(int)} and
* {@link TvView.TvInputCallback#onVideoUnavailable(String, int)}: Video is unavailable because
* the resource is not enough to meet requirement.
*/
public static final int VIDEO_UNAVAILABLE_REASON_INSUFFICIENT_RESOURCE = 6;
/**
* Reason for {@link TvInputService.Session#notifyVideoUnavailable(int)} and
* {@link TvView.TvInputCallback#onVideoUnavailable(String, int)}: Video is unavailable because
* the output protection level enabled on the device is not sufficient to meet the requirements
* in the license policy.
*/
public static final int VIDEO_UNAVAILABLE_REASON_CAS_INSUFFICIENT_OUTPUT_PROTECTION = 7;
/**
* Reason for {@link TvInputService.Session#notifyVideoUnavailable(int)} and
* {@link TvView.TvInputCallback#onVideoUnavailable(String, int)}: Video is unavailable because
* the PVR record is not allowed by the license policy.
*/
public static final int VIDEO_UNAVAILABLE_REASON_CAS_PVR_RECORDING_NOT_ALLOWED = 8;
/**
* Reason for {@link TvInputService.Session#notifyVideoUnavailable(int)} and
* {@link TvView.TvInputCallback#onVideoUnavailable(String, int)}: Video is unavailable because
* no license keys have been provided.
* @hide
*/
public static final int VIDEO_UNAVAILABLE_REASON_NOT_CONNECTED = VIDEO_UNAVAILABLE_REASON_END;
public static final int VIDEO_UNAVAILABLE_REASON_CAS_NO_LICENSE = 9;
/**
* Reason for {@link TvInputService.Session#notifyVideoUnavailable(int)} and
* {@link TvView.TvInputCallback#onVideoUnavailable(String, int)}: Video is unavailable because
* Using a license in whhich the keys have expired.
*/
public static final int VIDEO_UNAVAILABLE_REASON_CAS_LICENSE_EXPIRED = 10;
/**
* Reason for {@link TvInputService.Session#notifyVideoUnavailable(int)} and
* {@link TvView.TvInputCallback#onVideoUnavailable(String, int)}: Video is unavailable because
* the device need be activated.
*/
public static final int VIDEO_UNAVAILABLE_REASON_CAS_NEED_ACTIVATION = 11;
/**
* Reason for {@link TvInputService.Session#notifyVideoUnavailable(int)} and
* {@link TvView.TvInputCallback#onVideoUnavailable(String, int)}: Video is unavailable because
* the device need be paired.
*/
public static final int VIDEO_UNAVAILABLE_REASON_CAS_NEED_PAIRING = 12;
/**
* Reason for {@link TvInputService.Session#notifyVideoUnavailable(int)} and
* {@link TvView.TvInputCallback#onVideoUnavailable(String, int)}: Video is unavailable because
* smart card is missed.
*/
public static final int VIDEO_UNAVAILABLE_REASON_CAS_NO_CARD = 13;
/**
* Reason for {@link TvInputService.Session#notifyVideoUnavailable(int)} and
* {@link TvView.TvInputCallback#onVideoUnavailable(String, int)}: Video is unavailable because
* smart card is muted.
*/
public static final int VIDEO_UNAVAILABLE_REASON_CAS_CARD_MUTE = 14;
/**
* Reason for {@link TvInputService.Session#notifyVideoUnavailable(int)} and
* {@link TvView.TvInputCallback#onVideoUnavailable(String, int)}: Video is unavailable because
* smart card is invalid.
*/
public static final int VIDEO_UNAVAILABLE_REASON_CAS_CARD_INVALID = 15;
/**
* Reason for {@link TvInputService.Session#notifyVideoUnavailable(int)} and
* {@link TvView.TvInputCallback#onVideoUnavailable(String, int)}: Video is unavailable because
* of a geographical blackout.
*/
public static final int VIDEO_UNAVAILABLE_REASON_CAS_BLACKOUT = 16;
/**
* Reason for {@link TvInputService.Session#notifyVideoUnavailable(int)} and
* {@link TvView.TvInputCallback#onVideoUnavailable(String, int)}: Video is unavailable because
* CAS system is rebooting.
*/
public static final int VIDEO_UNAVAILABLE_REASON_CAS_REBOOTING = 17;
/**
* Reason for {@link TvInputService.Session#notifyVideoUnavailable(int)} and
* {@link TvView.TvInputCallback#onVideoUnavailable(String, int)}: Video is unavailable because
* of unknown CAS error.
*/
public static final int VIDEO_UNAVAILABLE_REASON_CAS_UNKNOWN = VIDEO_UNAVAILABLE_REASON_END;
/** @hide */
@Retention(RetentionPolicy.SOURCE)

View File

@ -17,6 +17,7 @@
package android.media.tv;
import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
@ -58,6 +59,8 @@ import android.widget.FrameLayout;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
@ -95,6 +98,53 @@ public abstract class TvInputService extends Service {
*/
public static final String SERVICE_META_DATA = "android.media.tv.input";
/**
* Prioirity hint from use case types.
*
* @hide
*/
@IntDef(prefix = "PRIORITY_HINT_USE_CASE_TYPE_",
value = {PRIORITY_HINT_USE_CASE_TYPE_BACKGROUND, PRIORITY_HINT_USE_CASE_TYPE_SCAN,
PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK, PRIORITY_HINT_USE_CASE_TYPE_LIVE,
PRIORITY_HINT_USE_CASE_TYPE_RECORD})
@Retention(RetentionPolicy.SOURCE)
public @interface PriorityHintUseCaseType {}
/**
* Use case of priority hint for {@link android.media.MediaCas#MediaCas(int, String , int)}:
* Background.
* TODO Link: Tuner#Tuner(Context, string, int).
*/
public static final int PRIORITY_HINT_USE_CASE_TYPE_BACKGROUND = 100;
/**
* Use case of priority hint for {@link android.media.MediaCas#MediaCas(int, String , int)}:
* Scan.
* TODO Link: Tuner#Tuner(Context, string, int).
*/
public static final int PRIORITY_HINT_USE_CASE_TYPE_SCAN = 200;
/**
* Use case of priority hint for {@link android.media.MediaCas#MediaCas(int, String , int)}:
* Playback.
* TODO Link: Tuner#Tuner(Context, string, int).
*/
public static final int PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK = 300;
/**
* Use case of priority hint for {@link android.media.MediaCas#MediaCas(int, String , int)}:
* Live.
* TODO Link: Tuner#Tuner(Context, string, int).
*/
public static final int PRIORITY_HINT_USE_CASE_TYPE_LIVE = 400;
/**
* Use case of priority hint for {@link android.media.MediaCas#MediaCas(int, String , int)}:
* Record.
* TODO Link: Tuner#Tuner(Context, string, int).
*/
public static final int PRIORITY_HINT_USE_CASE_TYPE_RECORD = 500;
/**
* Handler instance to handle request from TV Input Manager Service. Should be run in the main
* looper to be synchronously run with {@code Session.mHandler}.