Merge "Tuner APIs: add locks to avoid crashes caused by NPE" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
d7d85eb143
@@ -148,6 +148,7 @@ public class Lnb implements AutoCloseable {
|
|||||||
LnbCallback mCallback;
|
LnbCallback mCallback;
|
||||||
Executor mExecutor;
|
Executor mExecutor;
|
||||||
Tuner mTuner;
|
Tuner mTuner;
|
||||||
|
private final Object mCallbackLock = new Object();
|
||||||
|
|
||||||
|
|
||||||
private native int nativeSetVoltage(int voltage);
|
private native int nativeSetVoltage(int voltage);
|
||||||
@@ -164,22 +165,28 @@ public class Lnb implements AutoCloseable {
|
|||||||
private Lnb() {}
|
private Lnb() {}
|
||||||
|
|
||||||
void setCallback(Executor executor, @Nullable LnbCallback callback, Tuner tuner) {
|
void setCallback(Executor executor, @Nullable LnbCallback callback, Tuner tuner) {
|
||||||
|
synchronized (mCallbackLock) {
|
||||||
mCallback = callback;
|
mCallback = callback;
|
||||||
mExecutor = executor;
|
mExecutor = executor;
|
||||||
mTuner = tuner;
|
mTuner = tuner;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onEvent(int eventType) {
|
private void onEvent(int eventType) {
|
||||||
|
synchronized (mCallbackLock) {
|
||||||
if (mExecutor != null && mCallback != null) {
|
if (mExecutor != null && mCallback != null) {
|
||||||
mExecutor.execute(() -> mCallback.onEvent(eventType));
|
mExecutor.execute(() -> mCallback.onEvent(eventType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onDiseqcMessage(byte[] diseqcMessage) {
|
private void onDiseqcMessage(byte[] diseqcMessage) {
|
||||||
|
synchronized (mCallbackLock) {
|
||||||
if (mExecutor != null && mCallback != null) {
|
if (mExecutor != null && mCallback != null) {
|
||||||
mExecutor.execute(() -> mCallback.onDiseqcMessage(diseqcMessage));
|
mExecutor.execute(() -> mCallback.onDiseqcMessage(diseqcMessage));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* package */ boolean isClosed() {
|
/* package */ boolean isClosed() {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
|
|||||||
@@ -291,7 +291,7 @@ public class Tuner implements AutoCloseable {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private OnTuneEventListener mOnTuneEventListener;
|
private OnTuneEventListener mOnTuneEventListener;
|
||||||
@Nullable
|
@Nullable
|
||||||
private Executor mOnTunerEventExecutor;
|
private Executor mOnTuneEventExecutor;
|
||||||
@Nullable
|
@Nullable
|
||||||
private ScanCallback mScanCallback;
|
private ScanCallback mScanCallback;
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -301,6 +301,10 @@ public class Tuner implements AutoCloseable {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private Executor mOnResourceLostListenerExecutor;
|
private Executor mOnResourceLostListenerExecutor;
|
||||||
|
|
||||||
|
private final Object mOnTuneEventLock = new Object();
|
||||||
|
private final Object mScanCallbackLock = new Object();
|
||||||
|
private final Object mOnResourceLostListenerLock = new Object();
|
||||||
|
|
||||||
private Integer mDemuxHandle;
|
private Integer mDemuxHandle;
|
||||||
private Integer mFrontendCiCamHandle;
|
private Integer mFrontendCiCamHandle;
|
||||||
private Integer mFrontendCiCamId;
|
private Integer mFrontendCiCamId;
|
||||||
@@ -398,19 +402,23 @@ public class Tuner implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
public void setResourceLostListener(@NonNull @CallbackExecutor Executor executor,
|
public void setResourceLostListener(@NonNull @CallbackExecutor Executor executor,
|
||||||
@NonNull OnResourceLostListener listener) {
|
@NonNull OnResourceLostListener listener) {
|
||||||
|
synchronized (mOnResourceLostListenerLock) {
|
||||||
Objects.requireNonNull(executor, "OnResourceLostListener must not be null");
|
Objects.requireNonNull(executor, "OnResourceLostListener must not be null");
|
||||||
Objects.requireNonNull(listener, "executor must not be null");
|
Objects.requireNonNull(listener, "executor must not be null");
|
||||||
mOnResourceLostListener = listener;
|
mOnResourceLostListener = listener;
|
||||||
mOnResourceLostListenerExecutor = executor;
|
mOnResourceLostListenerExecutor = executor;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the listener for resource lost.
|
* Removes the listener for resource lost.
|
||||||
*/
|
*/
|
||||||
public void clearResourceLostListener() {
|
public void clearResourceLostListener() {
|
||||||
|
synchronized (mOnResourceLostListenerLock) {
|
||||||
mOnResourceLostListener = null;
|
mOnResourceLostListener = null;
|
||||||
mOnResourceLostListenerExecutor = null;
|
mOnResourceLostListenerExecutor = null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shares the frontend resource with another Tuner instance
|
* Shares the frontend resource with another Tuner instance
|
||||||
@@ -618,11 +626,13 @@ public class Tuner implements AutoCloseable {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MSG_RESOURCE_LOST: {
|
case MSG_RESOURCE_LOST: {
|
||||||
|
synchronized (mOnResourceLostListenerLock) {
|
||||||
if (mOnResourceLostListener != null
|
if (mOnResourceLostListener != null
|
||||||
&& mOnResourceLostListenerExecutor != null) {
|
&& mOnResourceLostListenerExecutor != null) {
|
||||||
mOnResourceLostListenerExecutor.execute(
|
mOnResourceLostListenerExecutor.execute(
|
||||||
() -> mOnResourceLostListener.onResourceLost(Tuner.this));
|
() -> mOnResourceLostListener.onResourceLost(Tuner.this));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -652,8 +662,10 @@ public class Tuner implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
public void setOnTuneEventListener(@NonNull @CallbackExecutor Executor executor,
|
public void setOnTuneEventListener(@NonNull @CallbackExecutor Executor executor,
|
||||||
@NonNull OnTuneEventListener eventListener) {
|
@NonNull OnTuneEventListener eventListener) {
|
||||||
|
synchronized (mOnTuneEventLock) {
|
||||||
mOnTuneEventListener = eventListener;
|
mOnTuneEventListener = eventListener;
|
||||||
mOnTunerEventExecutor = executor;
|
mOnTuneEventExecutor = executor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -663,9 +675,10 @@ public class Tuner implements AutoCloseable {
|
|||||||
* @see #setOnTuneEventListener(Executor, OnTuneEventListener)
|
* @see #setOnTuneEventListener(Executor, OnTuneEventListener)
|
||||||
*/
|
*/
|
||||||
public void clearOnTuneEventListener() {
|
public void clearOnTuneEventListener() {
|
||||||
|
synchronized (mOnTuneEventLock) {
|
||||||
mOnTuneEventListener = null;
|
mOnTuneEventListener = null;
|
||||||
mOnTunerEventExecutor = null;
|
mOnTuneEventExecutor = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -747,9 +760,9 @@ public class Tuner implements AutoCloseable {
|
|||||||
@Result
|
@Result
|
||||||
public int scan(@NonNull FrontendSettings settings, @ScanType int scanType,
|
public int scan(@NonNull FrontendSettings settings, @ScanType int scanType,
|
||||||
@NonNull @CallbackExecutor Executor executor, @NonNull ScanCallback scanCallback) {
|
@NonNull @CallbackExecutor Executor executor, @NonNull ScanCallback scanCallback) {
|
||||||
/**
|
synchronized (mScanCallbackLock) {
|
||||||
* Scan can be called again for blink scan if scanCallback and executor are same as before.
|
// Scan can be called again for blink scan if scanCallback and executor are same as
|
||||||
*/
|
//before.
|
||||||
if (((mScanCallback != null) && (mScanCallback != scanCallback))
|
if (((mScanCallback != null) && (mScanCallback != scanCallback))
|
||||||
|| ((mScanCallbackExecutor != null) && (mScanCallbackExecutor != executor))) {
|
|| ((mScanCallbackExecutor != null) && (mScanCallbackExecutor != executor))) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
@@ -759,7 +772,8 @@ public class Tuner implements AutoCloseable {
|
|||||||
mFrontendType = settings.getType();
|
mFrontendType = settings.getType();
|
||||||
if (mFrontendType == FrontendSettings.TYPE_DTMB) {
|
if (mFrontendType == FrontendSettings.TYPE_DTMB) {
|
||||||
if (!TunerVersionChecker.checkHigherOrEqualVersionTo(
|
if (!TunerVersionChecker.checkHigherOrEqualVersionTo(
|
||||||
TunerVersionChecker.TUNER_VERSION_1_1, "Scan with DTMB Frontend")) {
|
TunerVersionChecker.TUNER_VERSION_1_1,
|
||||||
|
"Scan with DTMB Frontend")) {
|
||||||
return RESULT_UNAVAILABLE;
|
return RESULT_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -774,6 +788,7 @@ public class Tuner implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
return RESULT_UNAVAILABLE;
|
return RESULT_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops a previous scanning.
|
* Stops a previous scanning.
|
||||||
@@ -788,8 +803,8 @@ public class Tuner implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
@Result
|
@Result
|
||||||
public int cancelScanning() {
|
public int cancelScanning() {
|
||||||
FrameworkStatsLog
|
synchronized (mScanCallbackLock) {
|
||||||
.write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId,
|
FrameworkStatsLog.write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId,
|
||||||
FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__SCAN_STOPPED);
|
FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__SCAN_STOPPED);
|
||||||
|
|
||||||
int retVal = nativeStopScan();
|
int retVal = nativeStopScan();
|
||||||
@@ -797,6 +812,7 @@ public class Tuner implements AutoCloseable {
|
|||||||
mScanCallbackExecutor = null;
|
mScanCallbackExecutor = null;
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean requestFrontend() {
|
private boolean requestFrontend() {
|
||||||
int[] feHandle = new int[1];
|
int[] feHandle = new int[1];
|
||||||
@@ -1050,8 +1066,10 @@ public class Tuner implements AutoCloseable {
|
|||||||
|
|
||||||
private void onFrontendEvent(int eventType) {
|
private void onFrontendEvent(int eventType) {
|
||||||
Log.d(TAG, "Got event from tuning. Event type: " + eventType);
|
Log.d(TAG, "Got event from tuning. Event type: " + eventType);
|
||||||
if (mOnTunerEventExecutor != null && mOnTuneEventListener != null) {
|
synchronized (mOnTuneEventLock) {
|
||||||
mOnTunerEventExecutor.execute(() -> mOnTuneEventListener.onTuneEvent(eventType));
|
if (mOnTuneEventExecutor != null && mOnTuneEventListener != null) {
|
||||||
|
mOnTuneEventExecutor.execute(() -> mOnTuneEventListener.onTuneEvent(eventType));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d(TAG, "Wrote Stats Log for the events from tuning.");
|
Log.d(TAG, "Wrote Stats Log for the events from tuning.");
|
||||||
@@ -1072,116 +1090,151 @@ public class Tuner implements AutoCloseable {
|
|||||||
|
|
||||||
private void onLocked() {
|
private void onLocked() {
|
||||||
Log.d(TAG, "Wrote Stats Log for locked event from scanning.");
|
Log.d(TAG, "Wrote Stats Log for locked event from scanning.");
|
||||||
FrameworkStatsLog
|
FrameworkStatsLog.write(
|
||||||
.write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId,
|
FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId,
|
||||||
FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__LOCKED);
|
FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__LOCKED);
|
||||||
|
|
||||||
|
synchronized (mScanCallbackLock) {
|
||||||
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
||||||
mScanCallbackExecutor.execute(() -> mScanCallback.onLocked());
|
mScanCallbackExecutor.execute(() -> mScanCallback.onLocked());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onScanStopped() {
|
private void onScanStopped() {
|
||||||
|
synchronized (mScanCallbackLock) {
|
||||||
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
||||||
mScanCallbackExecutor.execute(() -> mScanCallback.onScanStopped());
|
mScanCallbackExecutor.execute(() -> mScanCallback.onScanStopped());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onProgress(int percent) {
|
private void onProgress(int percent) {
|
||||||
|
synchronized (mScanCallbackLock) {
|
||||||
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
||||||
mScanCallbackExecutor.execute(() -> mScanCallback.onProgress(percent));
|
mScanCallbackExecutor.execute(() -> mScanCallback.onProgress(percent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onFrequenciesReport(int[] frequency) {
|
private void onFrequenciesReport(int[] frequency) {
|
||||||
|
synchronized (mScanCallbackLock) {
|
||||||
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
||||||
mScanCallbackExecutor.execute(() -> mScanCallback.onFrequenciesReported(frequency));
|
mScanCallbackExecutor.execute(() -> mScanCallback.onFrequenciesReported(frequency));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onSymbolRates(int[] rate) {
|
private void onSymbolRates(int[] rate) {
|
||||||
|
synchronized (mScanCallbackLock) {
|
||||||
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
||||||
mScanCallbackExecutor.execute(() -> mScanCallback.onSymbolRatesReported(rate));
|
mScanCallbackExecutor.execute(() -> mScanCallback.onSymbolRatesReported(rate));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onHierarchy(int hierarchy) {
|
private void onHierarchy(int hierarchy) {
|
||||||
|
synchronized (mScanCallbackLock) {
|
||||||
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
||||||
mScanCallbackExecutor.execute(() -> mScanCallback.onHierarchyReported(hierarchy));
|
mScanCallbackExecutor.execute(() -> mScanCallback.onHierarchyReported(hierarchy));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onSignalType(int signalType) {
|
private void onSignalType(int signalType) {
|
||||||
|
synchronized (mScanCallbackLock) {
|
||||||
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
||||||
mScanCallbackExecutor.execute(() -> mScanCallback.onSignalTypeReported(signalType));
|
mScanCallbackExecutor.execute(() -> mScanCallback.onSignalTypeReported(signalType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onPlpIds(int[] plpIds) {
|
private void onPlpIds(int[] plpIds) {
|
||||||
|
synchronized (mScanCallbackLock) {
|
||||||
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
||||||
mScanCallbackExecutor.execute(() -> mScanCallback.onPlpIdsReported(plpIds));
|
mScanCallbackExecutor.execute(() -> mScanCallback.onPlpIdsReported(plpIds));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onGroupIds(int[] groupIds) {
|
private void onGroupIds(int[] groupIds) {
|
||||||
|
synchronized (mScanCallbackLock) {
|
||||||
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
||||||
mScanCallbackExecutor.execute(() -> mScanCallback.onGroupIdsReported(groupIds));
|
mScanCallbackExecutor.execute(() -> mScanCallback.onGroupIdsReported(groupIds));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onInputStreamIds(int[] inputStreamIds) {
|
private void onInputStreamIds(int[] inputStreamIds) {
|
||||||
|
synchronized (mScanCallbackLock) {
|
||||||
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
||||||
mScanCallbackExecutor.execute(
|
mScanCallbackExecutor.execute(
|
||||||
() -> mScanCallback.onInputStreamIdsReported(inputStreamIds));
|
() -> mScanCallback.onInputStreamIdsReported(inputStreamIds));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onDvbsStandard(int dvbsStandandard) {
|
private void onDvbsStandard(int dvbsStandandard) {
|
||||||
|
synchronized (mScanCallbackLock) {
|
||||||
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
||||||
mScanCallbackExecutor.execute(
|
mScanCallbackExecutor.execute(
|
||||||
() -> mScanCallback.onDvbsStandardReported(dvbsStandandard));
|
() -> mScanCallback.onDvbsStandardReported(dvbsStandandard));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onDvbtStandard(int dvbtStandard) {
|
private void onDvbtStandard(int dvbtStandard) {
|
||||||
|
synchronized (mScanCallbackLock) {
|
||||||
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
||||||
mScanCallbackExecutor.execute(() -> mScanCallback.onDvbtStandardReported(dvbtStandard));
|
mScanCallbackExecutor.execute(
|
||||||
|
() -> mScanCallback.onDvbtStandardReported(dvbtStandard));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onAnalogSifStandard(int sif) {
|
private void onAnalogSifStandard(int sif) {
|
||||||
|
synchronized (mScanCallbackLock) {
|
||||||
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
||||||
mScanCallbackExecutor.execute(() -> mScanCallback.onAnalogSifStandardReported(sif));
|
mScanCallbackExecutor.execute(() -> mScanCallback.onAnalogSifStandardReported(sif));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onAtsc3PlpInfos(Atsc3PlpInfo[] atsc3PlpInfos) {
|
private void onAtsc3PlpInfos(Atsc3PlpInfo[] atsc3PlpInfos) {
|
||||||
|
synchronized (mScanCallbackLock) {
|
||||||
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
||||||
mScanCallbackExecutor.execute(
|
mScanCallbackExecutor.execute(
|
||||||
() -> mScanCallback.onAtsc3PlpInfosReported(atsc3PlpInfos));
|
() -> mScanCallback.onAtsc3PlpInfosReported(atsc3PlpInfos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onModulationReported(int modulation) {
|
private void onModulationReported(int modulation) {
|
||||||
|
synchronized (mScanCallbackLock) {
|
||||||
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
||||||
mScanCallbackExecutor.execute(
|
mScanCallbackExecutor.execute(
|
||||||
() -> mScanCallback.onModulationReported(modulation));
|
() -> mScanCallback.onModulationReported(modulation));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onPriorityReported(boolean isHighPriority) {
|
private void onPriorityReported(boolean isHighPriority) {
|
||||||
|
synchronized (mScanCallbackLock) {
|
||||||
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
||||||
mScanCallbackExecutor.execute(
|
mScanCallbackExecutor.execute(
|
||||||
() -> mScanCallback.onPriorityReported(isHighPriority));
|
() -> mScanCallback.onPriorityReported(isHighPriority));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onDvbcAnnexReported(int dvbcAnnex) {
|
private void onDvbcAnnexReported(int dvbcAnnex) {
|
||||||
|
synchronized (mScanCallbackLock) {
|
||||||
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
if (mScanCallbackExecutor != null && mScanCallback != null) {
|
||||||
mScanCallbackExecutor.execute(
|
mScanCallbackExecutor.execute(
|
||||||
() -> mScanCallback.onDvbcAnnexReported(dvbcAnnex));
|
() -> mScanCallback.onDvbcAnnexReported(dvbcAnnex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens a filter object based on the given types and buffer size.
|
* Opens a filter object based on the given types and buffer size.
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ public class DvrPlayback implements AutoCloseable {
|
|||||||
private static int sInstantId = 0;
|
private static int sInstantId = 0;
|
||||||
private int mSegmentId = 0;
|
private int mSegmentId = 0;
|
||||||
private int mUnderflow;
|
private int mUnderflow;
|
||||||
|
private final Object mListenerLock = new Object();
|
||||||
|
|
||||||
private native int nativeAttachFilter(Filter filter);
|
private native int nativeAttachFilter(Filter filter);
|
||||||
private native int nativeDetachFilter(Filter filter);
|
private native int nativeDetachFilter(Filter filter);
|
||||||
@@ -106,18 +107,22 @@ public class DvrPlayback implements AutoCloseable {
|
|||||||
/** @hide */
|
/** @hide */
|
||||||
public void setListener(
|
public void setListener(
|
||||||
@NonNull Executor executor, @NonNull OnPlaybackStatusChangedListener listener) {
|
@NonNull Executor executor, @NonNull OnPlaybackStatusChangedListener listener) {
|
||||||
|
synchronized (mListenerLock) {
|
||||||
mExecutor = executor;
|
mExecutor = executor;
|
||||||
mListener = listener;
|
mListener = listener;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onPlaybackStatusChanged(int status) {
|
private void onPlaybackStatusChanged(int status) {
|
||||||
if (status == PLAYBACK_STATUS_EMPTY) {
|
if (status == PLAYBACK_STATUS_EMPTY) {
|
||||||
mUnderflow++;
|
mUnderflow++;
|
||||||
}
|
}
|
||||||
|
synchronized (mListenerLock) {
|
||||||
if (mExecutor != null && mListener != null) {
|
if (mExecutor != null && mListener != null) {
|
||||||
mExecutor.execute(() -> mListener.onPlaybackStatusChanged(status));
|
mExecutor.execute(() -> mListener.onPlaybackStatusChanged(status));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ public class DvrRecorder implements AutoCloseable {
|
|||||||
private int mSegmentId = 0;
|
private int mSegmentId = 0;
|
||||||
private int mOverflow;
|
private int mOverflow;
|
||||||
private Boolean mIsStopped = true;
|
private Boolean mIsStopped = true;
|
||||||
|
private final Object mListenerLock = new Object();
|
||||||
|
|
||||||
private native int nativeAttachFilter(Filter filter);
|
private native int nativeAttachFilter(Filter filter);
|
||||||
private native int nativeDetachFilter(Filter filter);
|
private native int nativeDetachFilter(Filter filter);
|
||||||
@@ -69,18 +70,22 @@ public class DvrRecorder implements AutoCloseable {
|
|||||||
/** @hide */
|
/** @hide */
|
||||||
public void setListener(
|
public void setListener(
|
||||||
@NonNull Executor executor, @NonNull OnRecordStatusChangedListener listener) {
|
@NonNull Executor executor, @NonNull OnRecordStatusChangedListener listener) {
|
||||||
|
synchronized (mListenerLock) {
|
||||||
mExecutor = executor;
|
mExecutor = executor;
|
||||||
mListener = listener;
|
mListener = listener;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onRecordStatusChanged(int status) {
|
private void onRecordStatusChanged(int status) {
|
||||||
if (status == Filter.STATUS_OVERFLOW) {
|
if (status == Filter.STATUS_OVERFLOW) {
|
||||||
mOverflow++;
|
mOverflow++;
|
||||||
}
|
}
|
||||||
|
synchronized (mListenerLock) {
|
||||||
if (mExecutor != null && mListener != null) {
|
if (mExecutor != null && mListener != null) {
|
||||||
mExecutor.execute(() -> mListener.onRecordStatusChanged(status));
|
mExecutor.execute(() -> mListener.onRecordStatusChanged(status));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -227,6 +227,7 @@ public class Filter implements AutoCloseable {
|
|||||||
private long mNativeContext;
|
private long mNativeContext;
|
||||||
private FilterCallback mCallback;
|
private FilterCallback mCallback;
|
||||||
private Executor mExecutor;
|
private Executor mExecutor;
|
||||||
|
private final Object mCallbackLock = new Object();
|
||||||
private final long mId;
|
private final long mId;
|
||||||
private int mMainType;
|
private int mMainType;
|
||||||
private int mSubtype;
|
private int mSubtype;
|
||||||
@@ -253,16 +254,20 @@ public class Filter implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onFilterStatus(int status) {
|
private void onFilterStatus(int status) {
|
||||||
|
synchronized (mCallbackLock) {
|
||||||
if (mCallback != null && mExecutor != null) {
|
if (mCallback != null && mExecutor != null) {
|
||||||
mExecutor.execute(() -> mCallback.onFilterStatusChanged(this, status));
|
mExecutor.execute(() -> mCallback.onFilterStatusChanged(this, status));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onFilterEvent(FilterEvent[] events) {
|
private void onFilterEvent(FilterEvent[] events) {
|
||||||
|
synchronized (mCallbackLock) {
|
||||||
if (mCallback != null && mExecutor != null) {
|
if (mCallback != null && mExecutor != null) {
|
||||||
mExecutor.execute(() -> mCallback.onFilterEvent(this, events));
|
mExecutor.execute(() -> mCallback.onFilterEvent(this, events));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public void setType(@Type int mainType, @Subtype int subtype) {
|
public void setType(@Type int mainType, @Subtype int subtype) {
|
||||||
@@ -272,14 +277,18 @@ public class Filter implements AutoCloseable {
|
|||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public void setCallback(FilterCallback cb, Executor executor) {
|
public void setCallback(FilterCallback cb, Executor executor) {
|
||||||
|
synchronized (mCallbackLock) {
|
||||||
mCallback = cb;
|
mCallback = cb;
|
||||||
mExecutor = executor;
|
mExecutor = executor;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public FilterCallback getCallback() {
|
public FilterCallback getCallback() {
|
||||||
|
synchronized (mCallbackLock) {
|
||||||
return mCallback;
|
return mCallback;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the filter.
|
* Configures the filter.
|
||||||
|
|||||||
Reference in New Issue
Block a user