Merge "Tuner JNI: descrambler" into rvc-dev am: c1f78e8c20
Change-Id: Ib0f52eab3337689e42c5a2df322aa204bd712aae
This commit is contained in:
@@ -52,8 +52,12 @@ public class Descrambler implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
public static final int PID_TYPE_MMTP = 2;
|
public static final int PID_TYPE_MMTP = 2;
|
||||||
|
|
||||||
|
private static final String TAG = "Descrambler";
|
||||||
|
|
||||||
|
|
||||||
private long mNativeContext;
|
private long mNativeContext;
|
||||||
|
private boolean mIsClosed = false;
|
||||||
|
private final Object mLock = new Object();
|
||||||
|
|
||||||
private native int nativeAddPid(int pidType, int pid, Filter filter);
|
private native int nativeAddPid(int pidType, int pid, Filter filter);
|
||||||
private native int nativeRemovePid(int pidType, int pid, Filter filter);
|
private native int nativeRemovePid(int pidType, int pid, Filter filter);
|
||||||
@@ -80,7 +84,10 @@ public class Descrambler implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
@Result
|
@Result
|
||||||
public int addPid(@PidType int pidType, int pid, @Nullable Filter filter) {
|
public int addPid(@PidType int pidType, int pid, @Nullable Filter filter) {
|
||||||
return nativeAddPid(pidType, pid, filter);
|
synchronized (mLock) {
|
||||||
|
TunerUtils.checkResourceState(TAG, mIsClosed);
|
||||||
|
return nativeAddPid(pidType, pid, filter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -95,7 +102,10 @@ public class Descrambler implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
@Result
|
@Result
|
||||||
public int removePid(@PidType int pidType, int pid, @Nullable Filter filter) {
|
public int removePid(@PidType int pidType, int pid, @Nullable Filter filter) {
|
||||||
return nativeRemovePid(pidType, pid, filter);
|
synchronized (mLock) {
|
||||||
|
TunerUtils.checkResourceState(TAG, mIsClosed);
|
||||||
|
return nativeRemovePid(pidType, pid, filter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -109,8 +119,11 @@ public class Descrambler implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
@Result
|
@Result
|
||||||
public int setKeyToken(@NonNull byte[] keyToken) {
|
public int setKeyToken(@NonNull byte[] keyToken) {
|
||||||
Objects.requireNonNull(keyToken, "key token must not be null");
|
synchronized (mLock) {
|
||||||
return nativeSetKeyToken(keyToken);
|
TunerUtils.checkResourceState(TAG, mIsClosed);
|
||||||
|
Objects.requireNonNull(keyToken, "key token must not be null");
|
||||||
|
return nativeSetKeyToken(keyToken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -118,7 +131,17 @@ public class Descrambler implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
nativeClose();
|
synchronized (mLock) {
|
||||||
|
if (mIsClosed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int res = nativeClose();
|
||||||
|
if (res != Tuner.RESULT_SUCCESS) {
|
||||||
|
TunerUtils.throwExceptionForResult(res, "Failed to close descrambler");
|
||||||
|
} else {
|
||||||
|
mIsClosed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,9 +143,12 @@ public class Lnb implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
public static final int EVENT_TYPE_LNB_OVERLOAD = Constants.LnbEventType.LNB_OVERLOAD;
|
public static final int EVENT_TYPE_LNB_OVERLOAD = Constants.LnbEventType.LNB_OVERLOAD;
|
||||||
|
|
||||||
|
private static final String TAG = "Lnb";
|
||||||
|
|
||||||
int mId;
|
int mId;
|
||||||
LnbCallback mCallback;
|
LnbCallback mCallback;
|
||||||
Executor mExecutor;
|
Executor mExecutor;
|
||||||
|
Tuner mTuner;
|
||||||
|
|
||||||
|
|
||||||
private native int nativeSetVoltage(int voltage);
|
private native int nativeSetVoltage(int voltage);
|
||||||
@@ -156,13 +159,17 @@ public class Lnb implements AutoCloseable {
|
|||||||
|
|
||||||
private long mNativeContext;
|
private long mNativeContext;
|
||||||
|
|
||||||
|
private Boolean mIsClosed = false;
|
||||||
|
private final Object mLock = new Object();
|
||||||
|
|
||||||
private Lnb(int id) {
|
private Lnb(int id) {
|
||||||
mId = id;
|
mId = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCallback(Executor executor, @Nullable LnbCallback callback) {
|
void setCallback(Executor executor, @Nullable LnbCallback callback, Tuner tuner) {
|
||||||
mCallback = callback;
|
mCallback = callback;
|
||||||
mExecutor = executor;
|
mExecutor = executor;
|
||||||
|
mTuner = tuner;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onEvent(int eventType) {
|
private void onEvent(int eventType) {
|
||||||
@@ -177,6 +184,12 @@ public class Lnb implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* package */ boolean isClosed() {
|
||||||
|
synchronized (mLock) {
|
||||||
|
return mIsClosed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the LNB's power voltage.
|
* Sets the LNB's power voltage.
|
||||||
*
|
*
|
||||||
@@ -185,7 +198,10 @@ public class Lnb implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
@Result
|
@Result
|
||||||
public int setVoltage(@Voltage int voltage) {
|
public int setVoltage(@Voltage int voltage) {
|
||||||
return nativeSetVoltage(voltage);
|
synchronized (mLock) {
|
||||||
|
TunerUtils.checkResourceState(TAG, mIsClosed);
|
||||||
|
return nativeSetVoltage(voltage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -196,7 +212,10 @@ public class Lnb implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
@Result
|
@Result
|
||||||
public int setTone(@Tone int tone) {
|
public int setTone(@Tone int tone) {
|
||||||
return nativeSetTone(tone);
|
synchronized (mLock) {
|
||||||
|
TunerUtils.checkResourceState(TAG, mIsClosed);
|
||||||
|
return nativeSetTone(tone);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -207,7 +226,10 @@ public class Lnb implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
@Result
|
@Result
|
||||||
public int setSatellitePosition(@Position int position) {
|
public int setSatellitePosition(@Position int position) {
|
||||||
return nativeSetSatellitePosition(position);
|
synchronized (mLock) {
|
||||||
|
TunerUtils.checkResourceState(TAG, mIsClosed);
|
||||||
|
return nativeSetSatellitePosition(position);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -222,16 +244,27 @@ public class Lnb implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
@Result
|
@Result
|
||||||
public int sendDiseqcMessage(@NonNull byte[] message) {
|
public int sendDiseqcMessage(@NonNull byte[] message) {
|
||||||
return nativeSendDiseqcMessage(message);
|
synchronized (mLock) {
|
||||||
|
TunerUtils.checkResourceState(TAG, mIsClosed);
|
||||||
|
return nativeSendDiseqcMessage(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Releases the LNB instance.
|
* Releases the LNB instance.
|
||||||
*/
|
*/
|
||||||
public void close() {
|
public void close() {
|
||||||
int res = nativeClose();
|
synchronized (mLock) {
|
||||||
if (res != Tuner.RESULT_SUCCESS) {
|
if (mIsClosed) {
|
||||||
TunerUtils.throwExceptionForResult(res, "Failed to close LNB");
|
return;
|
||||||
|
}
|
||||||
|
int res = nativeClose();
|
||||||
|
if (res != Tuner.RESULT_SUCCESS) {
|
||||||
|
TunerUtils.throwExceptionForResult(res, "Failed to close LNB");
|
||||||
|
} else {
|
||||||
|
mIsClosed = true;
|
||||||
|
mTuner.releaseLnb();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,10 @@ import android.util.Log;
|
|||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
@@ -222,8 +225,8 @@ public class Tuner implements AutoCloseable {
|
|||||||
private Executor mOnResourceLostListenerExecutor;
|
private Executor mOnResourceLostListenerExecutor;
|
||||||
|
|
||||||
private Integer mDemuxHandle;
|
private Integer mDemuxHandle;
|
||||||
private Integer mDescramblerHandle;
|
private Map<Integer, Descrambler> mDescramblers = new HashMap<>();
|
||||||
private Descrambler mDescrambler;
|
private List<Filter> mFilters = new ArrayList<>();
|
||||||
|
|
||||||
private final TunerResourceManager.ResourcesReclaimListener mResourceListener =
|
private final TunerResourceManager.ResourcesReclaimListener mResourceListener =
|
||||||
new TunerResourceManager.ResourcesReclaimListener() {
|
new TunerResourceManager.ResourcesReclaimListener() {
|
||||||
@@ -356,9 +359,20 @@ public class Tuner implements AutoCloseable {
|
|||||||
mFrontend = null;
|
mFrontend = null;
|
||||||
}
|
}
|
||||||
if (mLnb != null) {
|
if (mLnb != null) {
|
||||||
mTunerResourceManager.releaseLnb(mLnbHandle, mClientId);
|
releaseLnb();
|
||||||
mLnb = null;
|
}
|
||||||
mLnbHandle = null;
|
if (!mDescramblers.isEmpty()) {
|
||||||
|
for (Map.Entry<Integer, Descrambler> d : mDescramblers.entrySet()) {
|
||||||
|
d.getValue().close();
|
||||||
|
mTunerResourceManager.releaseDescrambler(d.getKey(), mClientId);
|
||||||
|
}
|
||||||
|
mDescramblers.clear();
|
||||||
|
}
|
||||||
|
if (!mFilters.isEmpty()) {
|
||||||
|
for (Filter f : mFilters) {
|
||||||
|
f.close();
|
||||||
|
}
|
||||||
|
mFilters.clear();
|
||||||
}
|
}
|
||||||
TunerUtils.throwExceptionForResult(nativeClose(), "failed to close tuner");
|
TunerUtils.throwExceptionForResult(nativeClose(), "failed to close tuner");
|
||||||
}
|
}
|
||||||
@@ -857,6 +871,7 @@ public class Tuner implements AutoCloseable {
|
|||||||
if (mHandler == null) {
|
if (mHandler == null) {
|
||||||
mHandler = createEventHandler();
|
mHandler = createEventHandler();
|
||||||
}
|
}
|
||||||
|
mFilters.add(filter);
|
||||||
}
|
}
|
||||||
return filter;
|
return filter;
|
||||||
}
|
}
|
||||||
@@ -875,9 +890,11 @@ public class Tuner implements AutoCloseable {
|
|||||||
public Lnb openLnb(@CallbackExecutor @NonNull Executor executor, @NonNull LnbCallback cb) {
|
public Lnb openLnb(@CallbackExecutor @NonNull Executor executor, @NonNull LnbCallback cb) {
|
||||||
Objects.requireNonNull(executor, "executor must not be null");
|
Objects.requireNonNull(executor, "executor must not be null");
|
||||||
Objects.requireNonNull(cb, "LnbCallback must not be null");
|
Objects.requireNonNull(cb, "LnbCallback must not be null");
|
||||||
checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_LNB);
|
|
||||||
if (mLnb != null) {
|
if (mLnb != null) {
|
||||||
mLnb.setCallback(executor, cb);
|
return mLnb;
|
||||||
|
}
|
||||||
|
if (checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_LNB) && mLnb != null) {
|
||||||
|
mLnb.setCallback(executor, cb, this);
|
||||||
}
|
}
|
||||||
return mLnb;
|
return mLnb;
|
||||||
}
|
}
|
||||||
@@ -897,9 +914,14 @@ public class Tuner implements AutoCloseable {
|
|||||||
Objects.requireNonNull(name, "LNB name must not be null");
|
Objects.requireNonNull(name, "LNB name must not be null");
|
||||||
Objects.requireNonNull(executor, "executor must not be null");
|
Objects.requireNonNull(executor, "executor must not be null");
|
||||||
Objects.requireNonNull(cb, "LnbCallback must not be null");
|
Objects.requireNonNull(cb, "LnbCallback must not be null");
|
||||||
mLnb = nativeOpenLnbByName(name);
|
Lnb newLnb = nativeOpenLnbByName(name);
|
||||||
if (mLnb != null) {
|
if (newLnb != null) {
|
||||||
mLnb.setCallback(executor, cb);
|
if (mLnb != null) {
|
||||||
|
mLnb.close();
|
||||||
|
mLnbHandle = null;
|
||||||
|
}
|
||||||
|
mLnb = newLnb;
|
||||||
|
mLnb.setCallback(executor, cb, this);
|
||||||
}
|
}
|
||||||
return mLnb;
|
return mLnb;
|
||||||
}
|
}
|
||||||
@@ -934,8 +956,7 @@ public class Tuner implements AutoCloseable {
|
|||||||
@RequiresPermission(android.Manifest.permission.ACCESS_TV_DESCRAMBLER)
|
@RequiresPermission(android.Manifest.permission.ACCESS_TV_DESCRAMBLER)
|
||||||
@Nullable
|
@Nullable
|
||||||
public Descrambler openDescrambler() {
|
public Descrambler openDescrambler() {
|
||||||
checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_DESCRAMBLER);
|
return requestDescrambler();
|
||||||
return mDescrambler;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -995,15 +1016,21 @@ public class Tuner implements AutoCloseable {
|
|||||||
return granted;
|
return granted;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean requestDescrambler() {
|
private Descrambler requestDescrambler() {
|
||||||
int[] descramblerHandle = new int[1];
|
int[] descramblerHandle = new int[1];
|
||||||
TunerDescramblerRequest request = new TunerDescramblerRequest(mClientId);
|
TunerDescramblerRequest request = new TunerDescramblerRequest(mClientId);
|
||||||
boolean granted = mTunerResourceManager.requestDescrambler(request, descramblerHandle);
|
boolean granted = mTunerResourceManager.requestDescrambler(request, descramblerHandle);
|
||||||
if (granted) {
|
if (!granted) {
|
||||||
mDescramblerHandle = descramblerHandle[0];
|
return null;
|
||||||
mDescrambler = nativeOpenDescramblerByHandle(mDescramblerHandle);
|
|
||||||
}
|
}
|
||||||
return granted;
|
int handle = descramblerHandle[0];
|
||||||
|
Descrambler descrambler = nativeOpenDescramblerByHandle(handle);
|
||||||
|
if (descrambler != null) {
|
||||||
|
mDescramblers.put(handle, descrambler);
|
||||||
|
} else {
|
||||||
|
mTunerResourceManager.releaseDescrambler(handle, mClientId);
|
||||||
|
}
|
||||||
|
return descrambler;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkResource(int resourceType) {
|
private boolean checkResource(int resourceType) {
|
||||||
@@ -1015,7 +1042,7 @@ public class Tuner implements AutoCloseable {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TunerResourceManager.TUNER_RESOURCE_TYPE_LNB: {
|
case TunerResourceManager.TUNER_RESOURCE_TYPE_LNB: {
|
||||||
if (mLnbHandle == null && !requestLnb()) {
|
if (mLnb == null && !requestLnb()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1026,13 +1053,15 @@ public class Tuner implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TunerResourceManager.TUNER_RESOURCE_TYPE_DESCRAMBLER: {
|
default:
|
||||||
if (mDescramblerHandle == null && !requestDescrambler()) {
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* package */ void releaseLnb() {
|
||||||
|
mTunerResourceManager.releaseLnb(mLnbHandle, mClientId);
|
||||||
|
mLnbHandle = null;
|
||||||
|
mLnb = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,5 +157,16 @@ public final class TunerUtils {
|
|||||||
throw new RuntimeException("Unexpected result " + r + ". " + msg);
|
throw new RuntimeException("Unexpected result " + r + ". " + msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the state of a resource instance.
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException if the resource has already been closed.
|
||||||
|
*/
|
||||||
|
public static void checkResourceState(String name, boolean closed) {
|
||||||
|
if (closed) {
|
||||||
|
throw new IllegalStateException(name + " has been closed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private TunerUtils() {}
|
private TunerUtils() {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,6 +180,8 @@ public class Filter implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
public static final int STATUS_OVERFLOW = Constants.DemuxFilterStatus.OVERFLOW;
|
public static final int STATUS_OVERFLOW = Constants.DemuxFilterStatus.OVERFLOW;
|
||||||
|
|
||||||
|
private static final String TAG = "Filter";
|
||||||
|
|
||||||
private long mNativeContext;
|
private long mNativeContext;
|
||||||
private FilterCallback mCallback;
|
private FilterCallback mCallback;
|
||||||
private Executor mExecutor;
|
private Executor mExecutor;
|
||||||
@@ -188,6 +190,8 @@ public class Filter implements AutoCloseable {
|
|||||||
private int mSubtype;
|
private int mSubtype;
|
||||||
private Filter mSource;
|
private Filter mSource;
|
||||||
private boolean mStarted;
|
private boolean mStarted;
|
||||||
|
private boolean mIsClosed = false;
|
||||||
|
private final Object mLock = new Object();
|
||||||
|
|
||||||
private native int nativeConfigureFilter(
|
private native int nativeConfigureFilter(
|
||||||
int type, int subType, FilterConfiguration settings);
|
int type, int subType, FilterConfiguration settings);
|
||||||
@@ -244,21 +248,27 @@ public class Filter implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
@Result
|
@Result
|
||||||
public int configure(@NonNull FilterConfiguration config) {
|
public int configure(@NonNull FilterConfiguration config) {
|
||||||
Settings s = config.getSettings();
|
synchronized (mLock) {
|
||||||
int subType = (s == null) ? mSubtype : s.getType();
|
TunerUtils.checkResourceState(TAG, mIsClosed);
|
||||||
if (mMainType != config.getType() || mSubtype != subType) {
|
Settings s = config.getSettings();
|
||||||
throw new IllegalArgumentException("Invalid filter config. filter main type="
|
int subType = (s == null) ? mSubtype : s.getType();
|
||||||
+ mMainType + ", filter subtype=" + mSubtype + ". config main type="
|
if (mMainType != config.getType() || mSubtype != subType) {
|
||||||
+ config.getType() + ", config subtype=" + subType);
|
throw new IllegalArgumentException("Invalid filter config. filter main type="
|
||||||
|
+ mMainType + ", filter subtype=" + mSubtype + ". config main type="
|
||||||
|
+ config.getType() + ", config subtype=" + subType);
|
||||||
|
}
|
||||||
|
return nativeConfigureFilter(config.getType(), subType, config);
|
||||||
}
|
}
|
||||||
return nativeConfigureFilter(config.getType(), subType, config);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the filter Id.
|
* Gets the filter Id.
|
||||||
*/
|
*/
|
||||||
public int getId() {
|
public int getId() {
|
||||||
return nativeGetId();
|
synchronized (mLock) {
|
||||||
|
TunerUtils.checkResourceState(TAG, mIsClosed);
|
||||||
|
return nativeGetId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -276,14 +286,17 @@ public class Filter implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
@Result
|
@Result
|
||||||
public int setDataSource(@Nullable Filter source) {
|
public int setDataSource(@Nullable Filter source) {
|
||||||
if (mSource != null) {
|
synchronized (mLock) {
|
||||||
throw new IllegalStateException("Data source is existing");
|
TunerUtils.checkResourceState(TAG, mIsClosed);
|
||||||
|
if (mSource != null) {
|
||||||
|
throw new IllegalStateException("Data source is existing");
|
||||||
|
}
|
||||||
|
int res = nativeSetDataSource(source);
|
||||||
|
if (res == Tuner.RESULT_SUCCESS) {
|
||||||
|
mSource = source;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
int res = nativeSetDataSource(source);
|
|
||||||
if (res == Tuner.RESULT_SUCCESS) {
|
|
||||||
mSource = source;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -295,7 +308,10 @@ public class Filter implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
@Result
|
@Result
|
||||||
public int start() {
|
public int start() {
|
||||||
return nativeStartFilter();
|
synchronized (mLock) {
|
||||||
|
TunerUtils.checkResourceState(TAG, mIsClosed);
|
||||||
|
return nativeStartFilter();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -308,7 +324,10 @@ public class Filter implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
@Result
|
@Result
|
||||||
public int stop() {
|
public int stop() {
|
||||||
return nativeStopFilter();
|
synchronized (mLock) {
|
||||||
|
TunerUtils.checkResourceState(TAG, mIsClosed);
|
||||||
|
return nativeStopFilter();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -321,7 +340,10 @@ public class Filter implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
@Result
|
@Result
|
||||||
public int flush() {
|
public int flush() {
|
||||||
return nativeFlushFilter();
|
synchronized (mLock) {
|
||||||
|
TunerUtils.checkResourceState(TAG, mIsClosed);
|
||||||
|
return nativeFlushFilter();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -333,8 +355,11 @@ public class Filter implements AutoCloseable {
|
|||||||
* @return the number of bytes read.
|
* @return the number of bytes read.
|
||||||
*/
|
*/
|
||||||
public int read(@NonNull byte[] buffer, @BytesLong long offset, @BytesLong long size) {
|
public int read(@NonNull byte[] buffer, @BytesLong long offset, @BytesLong long size) {
|
||||||
size = Math.min(size, buffer.length - offset);
|
synchronized (mLock) {
|
||||||
return nativeRead(buffer, offset, size);
|
TunerUtils.checkResourceState(TAG, mIsClosed);
|
||||||
|
size = Math.min(size, buffer.length - offset);
|
||||||
|
return nativeRead(buffer, offset, size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -342,9 +367,16 @@ public class Filter implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
int res = nativeClose();
|
synchronized (mLock) {
|
||||||
if (res != Tuner.RESULT_SUCCESS) {
|
if (mIsClosed) {
|
||||||
TunerUtils.throwExceptionForResult(res, "Failed to close filter.");
|
return;
|
||||||
|
}
|
||||||
|
int res = nativeClose();
|
||||||
|
if (res != Tuner.RESULT_SUCCESS) {
|
||||||
|
TunerUtils.throwExceptionForResult(res, "Failed to close filter.");
|
||||||
|
} else {
|
||||||
|
mIsClosed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1368,24 +1368,27 @@ int JTuner::disconnectCiCam() {
|
|||||||
|
|
||||||
jobject JTuner::openDescrambler() {
|
jobject JTuner::openDescrambler() {
|
||||||
ALOGD("JTuner::openDescrambler");
|
ALOGD("JTuner::openDescrambler");
|
||||||
if (mTuner == nullptr) {
|
if (mTuner == nullptr || mDemux == nullptr) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
sp<IDescrambler> descramblerSp;
|
sp<IDescrambler> descramblerSp;
|
||||||
mTuner->openDescrambler([&](Result, const sp<IDescrambler>& descrambler) {
|
Result res;
|
||||||
|
mTuner->openDescrambler([&](Result r, const sp<IDescrambler>& descrambler) {
|
||||||
|
res = r;
|
||||||
descramblerSp = descrambler;
|
descramblerSp = descrambler;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (descramblerSp == NULL) {
|
if (res != Result::SUCCESS || descramblerSp == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
descramblerSp->setDemuxSource(mDemuxId);
|
||||||
|
|
||||||
JNIEnv *env = AndroidRuntime::getJNIEnv();
|
JNIEnv *env = AndroidRuntime::getJNIEnv();
|
||||||
jobject descramblerObj =
|
jobject descramblerObj =
|
||||||
env->NewObject(
|
env->NewObject(
|
||||||
env->FindClass("android/media/tv/tuner/Descrambler"),
|
env->FindClass("android/media/tv/tuner/Descrambler"),
|
||||||
gFields.descramblerInitID,
|
gFields.descramblerInitID);
|
||||||
mObject);
|
|
||||||
|
|
||||||
descramblerSp->incStrong(descramblerObj);
|
descramblerSp->incStrong(descramblerObj);
|
||||||
env->SetLongField(descramblerObj, gFields.descramblerContext, (jlong)descramblerSp.get());
|
env->SetLongField(descramblerObj, gFields.descramblerContext, (jlong)descramblerSp.get());
|
||||||
@@ -1402,11 +1405,13 @@ jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) {
|
|||||||
|
|
||||||
sp<IFilter> iFilterSp;
|
sp<IFilter> iFilterSp;
|
||||||
sp<FilterCallback> callback = new FilterCallback();
|
sp<FilterCallback> callback = new FilterCallback();
|
||||||
|
Result res;
|
||||||
mDemux->openFilter(type, bufferSize, callback,
|
mDemux->openFilter(type, bufferSize, callback,
|
||||||
[&](Result, const sp<IFilter>& filter) {
|
[&](Result r, const sp<IFilter>& filter) {
|
||||||
iFilterSp = filter;
|
iFilterSp = filter;
|
||||||
|
res = r;
|
||||||
});
|
});
|
||||||
if (iFilterSp == NULL) {
|
if (res != Result::SUCCESS || iFilterSp == NULL) {
|
||||||
ALOGD("Failed to open filter, type = %d", type.mainType);
|
ALOGD("Failed to open filter, type = %d", type.mainType);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -2355,8 +2360,7 @@ static void android_media_tv_Tuner_native_init(JNIEnv *env) {
|
|||||||
|
|
||||||
jclass descramblerClazz = env->FindClass("android/media/tv/tuner/Descrambler");
|
jclass descramblerClazz = env->FindClass("android/media/tv/tuner/Descrambler");
|
||||||
gFields.descramblerContext = env->GetFieldID(descramblerClazz, "mNativeContext", "J");
|
gFields.descramblerContext = env->GetFieldID(descramblerClazz, "mNativeContext", "J");
|
||||||
gFields.descramblerInitID =
|
gFields.descramblerInitID = env->GetMethodID(descramblerClazz, "<init>", "()V");
|
||||||
env->GetMethodID(descramblerClazz, "<init>", "()V");
|
|
||||||
|
|
||||||
jclass dvrRecorderClazz = env->FindClass("android/media/tv/tuner/dvr/DvrRecorder");
|
jclass dvrRecorderClazz = env->FindClass("android/media/tv/tuner/dvr/DvrRecorder");
|
||||||
gFields.dvrRecorderContext = env->GetFieldID(dvrRecorderClazz, "mNativeContext", "J");
|
gFields.dvrRecorderContext = env->GetFieldID(dvrRecorderClazz, "mNativeContext", "J");
|
||||||
@@ -2905,7 +2909,7 @@ static jint android_media_tv_Tuner_configure_filter(
|
|||||||
sp<IFilter> iFilterSp = filterSp->getIFilter();
|
sp<IFilter> iFilterSp = filterSp->getIFilter();
|
||||||
if (iFilterSp == NULL) {
|
if (iFilterSp == NULL) {
|
||||||
ALOGD("Failed to configure filter: filter not found");
|
ALOGD("Failed to configure filter: filter not found");
|
||||||
return (int)Result::INVALID_STATE;
|
return (jint) Result::NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
DemuxFilterSettings filterSettings = getFilterConfiguration(env, type, subtype, settings);
|
DemuxFilterSettings filterSettings = getFilterConfiguration(env, type, subtype, settings);
|
||||||
Result res = iFilterSp->configure(filterSettings);
|
Result res = iFilterSp->configure(filterSettings);
|
||||||
@@ -2936,7 +2940,7 @@ static jint android_media_tv_Tuner_get_filter_id(JNIEnv* env, jobject filter) {
|
|||||||
sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
|
sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
|
||||||
if (iFilterSp == NULL) {
|
if (iFilterSp == NULL) {
|
||||||
ALOGD("Failed to get filter ID: filter not found");
|
ALOGD("Failed to get filter ID: filter not found");
|
||||||
return (int) Result::INVALID_STATE;
|
return (int) Result::NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
Result res;
|
Result res;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
@@ -2956,7 +2960,7 @@ static jint android_media_tv_Tuner_set_filter_data_source(
|
|||||||
sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
|
sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
|
||||||
if (iFilterSp == NULL) {
|
if (iFilterSp == NULL) {
|
||||||
ALOGD("Failed to set filter data source: filter not found");
|
ALOGD("Failed to set filter data source: filter not found");
|
||||||
return (jint) Result::INVALID_STATE;
|
return (jint) Result::NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
Result r;
|
Result r;
|
||||||
if (srcFilter == NULL) {
|
if (srcFilter == NULL) {
|
||||||
@@ -2965,7 +2969,7 @@ static jint android_media_tv_Tuner_set_filter_data_source(
|
|||||||
sp<IFilter> srcSp = getFilter(env, srcFilter)->getIFilter();
|
sp<IFilter> srcSp = getFilter(env, srcFilter)->getIFilter();
|
||||||
if (iFilterSp == NULL) {
|
if (iFilterSp == NULL) {
|
||||||
ALOGD("Failed to set filter data source: src filter not found");
|
ALOGD("Failed to set filter data source: src filter not found");
|
||||||
return (jint) Result::INVALID_STATE;
|
return (jint) Result::INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
r = iFilterSp->setDataSource(srcSp);
|
r = iFilterSp->setDataSource(srcSp);
|
||||||
}
|
}
|
||||||
@@ -2976,7 +2980,7 @@ static jint android_media_tv_Tuner_start_filter(JNIEnv *env, jobject filter) {
|
|||||||
sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
|
sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
|
||||||
if (iFilterSp == NULL) {
|
if (iFilterSp == NULL) {
|
||||||
ALOGD("Failed to start filter: filter not found");
|
ALOGD("Failed to start filter: filter not found");
|
||||||
return (jint) Result::INVALID_STATE;
|
return (jint) Result::NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
Result r = iFilterSp->start();
|
Result r = iFilterSp->start();
|
||||||
return (jint) r;
|
return (jint) r;
|
||||||
@@ -2986,7 +2990,7 @@ static jint android_media_tv_Tuner_stop_filter(JNIEnv *env, jobject filter) {
|
|||||||
sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
|
sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
|
||||||
if (iFilterSp == NULL) {
|
if (iFilterSp == NULL) {
|
||||||
ALOGD("Failed to stop filter: filter not found");
|
ALOGD("Failed to stop filter: filter not found");
|
||||||
return (jint) Result::INVALID_STATE;
|
return (jint) Result::NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
Result r = iFilterSp->stop();
|
Result r = iFilterSp->stop();
|
||||||
return (jint) r;
|
return (jint) r;
|
||||||
@@ -2996,7 +3000,7 @@ static jint android_media_tv_Tuner_flush_filter(JNIEnv *env, jobject filter) {
|
|||||||
sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
|
sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
|
||||||
if (iFilterSp == NULL) {
|
if (iFilterSp == NULL) {
|
||||||
ALOGD("Failed to flush filter: filter not found");
|
ALOGD("Failed to flush filter: filter not found");
|
||||||
return (jint) Result::INVALID_STATE;
|
return (jint) Result::NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
Result r = iFilterSp->flush();
|
Result r = iFilterSp->flush();
|
||||||
return (jint) r;
|
return (jint) r;
|
||||||
@@ -3016,7 +3020,7 @@ static jint android_media_tv_Tuner_close_filter(JNIEnv *env, jobject filter) {
|
|||||||
sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
|
sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
|
||||||
if (iFilterSp == NULL) {
|
if (iFilterSp == NULL) {
|
||||||
ALOGD("Failed to close filter: filter not found");
|
ALOGD("Failed to close filter: filter not found");
|
||||||
return (jint) Result::INVALID_STATE;
|
return (jint) Result::NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
Result r = iFilterSp->close();
|
Result r = iFilterSp->close();
|
||||||
return (jint) r;
|
return (jint) r;
|
||||||
@@ -3121,34 +3125,51 @@ static jobject android_media_tv_Tuner_open_descrambler(JNIEnv *env, jobject thiz
|
|||||||
return tuner->openDescrambler();
|
return tuner->openDescrambler();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int android_media_tv_Tuner_add_pid(
|
static jint android_media_tv_Tuner_descrambler_add_pid(
|
||||||
JNIEnv *env, jobject descrambler, jint pidType, jint pid, jobject filter) {
|
JNIEnv *env, jobject descrambler, jint pidType, jint pid, jobject filter) {
|
||||||
sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler);
|
sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler);
|
||||||
if (descramblerSp == NULL) {
|
if (descramblerSp == NULL) {
|
||||||
return false;
|
return (jint) Result::NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
|
sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
|
||||||
Result result = descramblerSp->addPid(getDemuxPid((int)pidType, (int)pid), iFilterSp);
|
Result result = descramblerSp->addPid(getDemuxPid((int)pidType, (int)pid), iFilterSp);
|
||||||
return (int)result;
|
return (jint) result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int android_media_tv_Tuner_remove_pid(
|
static jint android_media_tv_Tuner_descrambler_remove_pid(
|
||||||
JNIEnv *env, jobject descrambler, jint pidType, jint pid, jobject filter) {
|
JNIEnv *env, jobject descrambler, jint pidType, jint pid, jobject filter) {
|
||||||
sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler);
|
sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler);
|
||||||
if (descramblerSp == NULL) {
|
if (descramblerSp == NULL) {
|
||||||
return false;
|
return (jint) Result::NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
|
sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
|
||||||
Result result = descramblerSp->removePid(getDemuxPid((int)pidType, (int)pid), iFilterSp);
|
Result result = descramblerSp->removePid(getDemuxPid((int)pidType, (int)pid), iFilterSp);
|
||||||
return (int)result;
|
return (jint) result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int android_media_tv_Tuner_set_key_token(JNIEnv, jobject, jbyteArray) {
|
static jint android_media_tv_Tuner_descrambler_set_key_token(
|
||||||
return 0;
|
JNIEnv* env, jobject descrambler, jbyteArray keyToken) {
|
||||||
|
sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler);
|
||||||
|
if (descramblerSp == NULL) {
|
||||||
|
return (jint) Result::NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
int size = env->GetArrayLength(keyToken);
|
||||||
|
std::vector<uint8_t> v(size);
|
||||||
|
env->GetByteArrayRegion(keyToken, 0, size, reinterpret_cast<jbyte*>(&v[0]));
|
||||||
|
Result result = descramblerSp->setKeyToken(v);
|
||||||
|
return (jint) result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int android_media_tv_Tuner_close_descrambler(JNIEnv, jobject) {
|
static jint android_media_tv_Tuner_close_descrambler(JNIEnv* env, jobject descrambler) {
|
||||||
return 0;
|
sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler);
|
||||||
|
if (descramblerSp == NULL) {
|
||||||
|
return (jint) Result::NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
Result r = descramblerSp->close();
|
||||||
|
if (r == Result::SUCCESS) {
|
||||||
|
descramblerSp->decStrong(descrambler);
|
||||||
|
}
|
||||||
|
return (jint) r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static jobject android_media_tv_Tuner_open_dvr_recorder(
|
static jobject android_media_tv_Tuner_open_dvr_recorder(
|
||||||
@@ -3533,10 +3554,10 @@ static const JNINativeMethod gTimeFilterMethods[] = {
|
|||||||
|
|
||||||
static const JNINativeMethod gDescramblerMethods[] = {
|
static const JNINativeMethod gDescramblerMethods[] = {
|
||||||
{ "nativeAddPid", "(IILandroid/media/tv/tuner/filter/Filter;)I",
|
{ "nativeAddPid", "(IILandroid/media/tv/tuner/filter/Filter;)I",
|
||||||
(void *)android_media_tv_Tuner_add_pid },
|
(void *)android_media_tv_Tuner_descrambler_add_pid },
|
||||||
{ "nativeRemovePid", "(IILandroid/media/tv/tuner/filter/Filter;)I",
|
{ "nativeRemovePid", "(IILandroid/media/tv/tuner/filter/Filter;)I",
|
||||||
(void *)android_media_tv_Tuner_remove_pid },
|
(void *)android_media_tv_Tuner_descrambler_remove_pid },
|
||||||
{ "nativeSetKeyToken", "([B)I", (void *)android_media_tv_Tuner_set_key_token },
|
{ "nativeSetKeyToken", "([B)I", (void *)android_media_tv_Tuner_descrambler_set_key_token },
|
||||||
{ "nativeClose", "()I", (void *)android_media_tv_Tuner_close_descrambler },
|
{ "nativeClose", "()I", (void *)android_media_tv_Tuner_close_descrambler },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user