Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d7d85eb1 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Tuner APIs: add locks to avoid crashes caused by NPE" into sc-dev

parents 45877fb8 5558cb1c
Loading
Loading
Loading
Loading
+14 −7
Original line number Diff line number Diff line
@@ -148,6 +148,7 @@ public class Lnb implements AutoCloseable {
    LnbCallback mCallback;
    Executor mExecutor;
    Tuner mTuner;
    private final Object mCallbackLock = new Object();


    private native int nativeSetVoltage(int voltage);
@@ -164,22 +165,28 @@ public class Lnb implements AutoCloseable {
    private Lnb() {}

    void setCallback(Executor executor, @Nullable LnbCallback callback, Tuner tuner) {
        synchronized (mCallbackLock) {
            mCallback = callback;
            mExecutor = executor;
            mTuner = tuner;
        }
    }

    private void onEvent(int eventType) {
        synchronized (mCallbackLock) {
            if (mExecutor != null && mCallback != null) {
                mExecutor.execute(() -> mCallback.onEvent(eventType));
            }
        }
    }

    private void onDiseqcMessage(byte[] diseqcMessage) {
        synchronized (mCallbackLock) {
            if (mExecutor != null && mCallback != null) {
                mExecutor.execute(() -> mCallback.onDiseqcMessage(diseqcMessage));
            }
        }
    }

    /* package */ boolean isClosed() {
        synchronized (mLock) {
+138 −85
Original line number Diff line number Diff line
@@ -291,7 +291,7 @@ public class Tuner implements AutoCloseable {
    @Nullable
    private OnTuneEventListener mOnTuneEventListener;
    @Nullable
    private Executor mOnTunerEventExecutor;
    private Executor mOnTuneEventExecutor;
    @Nullable
    private ScanCallback mScanCallback;
    @Nullable
@@ -301,6 +301,10 @@ public class Tuner implements AutoCloseable {
    @Nullable
    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 mFrontendCiCamHandle;
    private Integer mFrontendCiCamId;
@@ -398,19 +402,23 @@ public class Tuner implements AutoCloseable {
     */
    public void setResourceLostListener(@NonNull @CallbackExecutor Executor executor,
            @NonNull OnResourceLostListener listener) {
        synchronized (mOnResourceLostListenerLock) {
            Objects.requireNonNull(executor, "OnResourceLostListener must not be null");
            Objects.requireNonNull(listener, "executor must not be null");
            mOnResourceLostListener = listener;
            mOnResourceLostListenerExecutor = executor;
        }
    }

    /**
     * Removes the listener for resource lost.
     */
    public void clearResourceLostListener() {
        synchronized (mOnResourceLostListenerLock) {
            mOnResourceLostListener = null;
            mOnResourceLostListenerExecutor = null;
        }
    }

    /**
     * Shares the frontend resource with another Tuner instance
@@ -618,11 +626,13 @@ public class Tuner implements AutoCloseable {
                    break;
                }
                case MSG_RESOURCE_LOST: {
                    synchronized (mOnResourceLostListenerLock) {
                        if (mOnResourceLostListener != null
                                && mOnResourceLostListenerExecutor != null) {
                            mOnResourceLostListenerExecutor.execute(
                                    () -> mOnResourceLostListener.onResourceLost(Tuner.this));
                        }
                    }
                    break;
                }
                default:
@@ -652,8 +662,10 @@ public class Tuner implements AutoCloseable {
     */
    public void setOnTuneEventListener(@NonNull @CallbackExecutor Executor executor,
            @NonNull OnTuneEventListener eventListener) {
        synchronized (mOnTuneEventLock) {
            mOnTuneEventListener = eventListener;
        mOnTunerEventExecutor = executor;
            mOnTuneEventExecutor = executor;
        }
    }

    /**
@@ -663,9 +675,10 @@ public class Tuner implements AutoCloseable {
     * @see #setOnTuneEventListener(Executor, OnTuneEventListener)
     */
    public void clearOnTuneEventListener() {
        synchronized (mOnTuneEventLock) {
            mOnTuneEventListener = null;
        mOnTunerEventExecutor = null;

            mOnTuneEventExecutor = null;
        }
    }

    /**
@@ -747,9 +760,9 @@ public class Tuner implements AutoCloseable {
    @Result
    public int scan(@NonNull FrontendSettings settings, @ScanType int scanType,
            @NonNull @CallbackExecutor Executor executor, @NonNull ScanCallback scanCallback) {
        /**
         * Scan can be called again for blink scan if scanCallback and executor are same as before.
         */
        synchronized (mScanCallbackLock) {
            // Scan can be called again for blink scan if scanCallback and executor are same as
            //before.
            if (((mScanCallback != null) && (mScanCallback != scanCallback))
                || ((mScanCallbackExecutor != null) && (mScanCallbackExecutor != executor))) {
                throw new IllegalStateException(
@@ -759,7 +772,8 @@ public class Tuner implements AutoCloseable {
            mFrontendType = settings.getType();
            if (mFrontendType == FrontendSettings.TYPE_DTMB) {
                if (!TunerVersionChecker.checkHigherOrEqualVersionTo(
                    TunerVersionChecker.TUNER_VERSION_1_1, "Scan with DTMB Frontend")) {
                        TunerVersionChecker.TUNER_VERSION_1_1,
                        "Scan with DTMB Frontend")) {
                    return RESULT_UNAVAILABLE;
                }
            }
@@ -774,6 +788,7 @@ public class Tuner implements AutoCloseable {
            }
            return RESULT_UNAVAILABLE;
        }
    }

    /**
     * Stops a previous scanning.
@@ -788,8 +803,8 @@ public class Tuner implements AutoCloseable {
     */
    @Result
    public int cancelScanning() {
        FrameworkStatsLog
                .write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId,
        synchronized (mScanCallbackLock) {
            FrameworkStatsLog.write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId,
                    FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__SCAN_STOPPED);

            int retVal = nativeStopScan();
@@ -797,6 +812,7 @@ public class Tuner implements AutoCloseable {
            mScanCallbackExecutor = null;
            return retVal;
        }
    }

    private boolean requestFrontend() {
        int[] feHandle = new int[1];
@@ -1050,8 +1066,10 @@ public class Tuner implements AutoCloseable {

    private void onFrontendEvent(int eventType) {
        Log.d(TAG, "Got event from tuning. Event type: " + eventType);
        if (mOnTunerEventExecutor != null && mOnTuneEventListener != null) {
            mOnTunerEventExecutor.execute(() -> mOnTuneEventListener.onTuneEvent(eventType));
        synchronized (mOnTuneEventLock) {
            if (mOnTuneEventExecutor != null && mOnTuneEventListener != null) {
                mOnTuneEventExecutor.execute(() -> mOnTuneEventListener.onTuneEvent(eventType));
            }
        }

        Log.d(TAG, "Wrote Stats Log for the events from tuning.");
@@ -1072,116 +1090,151 @@ public class Tuner implements AutoCloseable {

    private void onLocked() {
        Log.d(TAG, "Wrote Stats Log for locked event from scanning.");
        FrameworkStatsLog
                .write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId,
        FrameworkStatsLog.write(
                FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId,
                FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__LOCKED);

        synchronized (mScanCallbackLock) {
            if (mScanCallbackExecutor != null && mScanCallback != null) {
                mScanCallbackExecutor.execute(() -> mScanCallback.onLocked());
            }
        }
    }

    private void onScanStopped() {
        synchronized (mScanCallbackLock) {
            if (mScanCallbackExecutor != null && mScanCallback != null) {
                mScanCallbackExecutor.execute(() -> mScanCallback.onScanStopped());
            }
        }
    }

    private void onProgress(int percent) {
        synchronized (mScanCallbackLock) {
            if (mScanCallbackExecutor != null && mScanCallback != null) {
                mScanCallbackExecutor.execute(() -> mScanCallback.onProgress(percent));
            }
        }
    }

    private void onFrequenciesReport(int[] frequency) {
        synchronized (mScanCallbackLock) {
            if (mScanCallbackExecutor != null && mScanCallback != null) {
                mScanCallbackExecutor.execute(() -> mScanCallback.onFrequenciesReported(frequency));
            }
        }
    }

    private void onSymbolRates(int[] rate) {
        synchronized (mScanCallbackLock) {
            if (mScanCallbackExecutor != null && mScanCallback != null) {
                mScanCallbackExecutor.execute(() -> mScanCallback.onSymbolRatesReported(rate));
            }
        }
    }

    private void onHierarchy(int hierarchy) {
        synchronized (mScanCallbackLock) {
            if (mScanCallbackExecutor != null && mScanCallback != null) {
                mScanCallbackExecutor.execute(() -> mScanCallback.onHierarchyReported(hierarchy));
            }
        }
    }

    private void onSignalType(int signalType) {
        synchronized (mScanCallbackLock) {
            if (mScanCallbackExecutor != null && mScanCallback != null) {
                mScanCallbackExecutor.execute(() -> mScanCallback.onSignalTypeReported(signalType));
            }
        }
    }

    private void onPlpIds(int[] plpIds) {
        synchronized (mScanCallbackLock) {
            if (mScanCallbackExecutor != null && mScanCallback != null) {
                mScanCallbackExecutor.execute(() -> mScanCallback.onPlpIdsReported(plpIds));
            }
        }
    }

    private void onGroupIds(int[] groupIds) {
        synchronized (mScanCallbackLock) {
            if (mScanCallbackExecutor != null && mScanCallback != null) {
                mScanCallbackExecutor.execute(() -> mScanCallback.onGroupIdsReported(groupIds));
            }
        }
    }

    private void onInputStreamIds(int[] inputStreamIds) {
        synchronized (mScanCallbackLock) {
            if (mScanCallbackExecutor != null && mScanCallback != null) {
                mScanCallbackExecutor.execute(
                        () -> mScanCallback.onInputStreamIdsReported(inputStreamIds));
            }
        }
    }

    private void onDvbsStandard(int dvbsStandandard) {
        synchronized (mScanCallbackLock) {
            if (mScanCallbackExecutor != null && mScanCallback != null) {
                mScanCallbackExecutor.execute(
                        () -> mScanCallback.onDvbsStandardReported(dvbsStandandard));
            }
        }
    }

    private void onDvbtStandard(int dvbtStandard) {
        synchronized (mScanCallbackLock) {
            if (mScanCallbackExecutor != null && mScanCallback != null) {
            mScanCallbackExecutor.execute(() -> mScanCallback.onDvbtStandardReported(dvbtStandard));
                mScanCallbackExecutor.execute(
                        () -> mScanCallback.onDvbtStandardReported(dvbtStandard));
            }
        }
    }

    private void onAnalogSifStandard(int sif) {
        synchronized (mScanCallbackLock) {
            if (mScanCallbackExecutor != null && mScanCallback != null) {
                mScanCallbackExecutor.execute(() -> mScanCallback.onAnalogSifStandardReported(sif));
            }
        }
    }

    private void onAtsc3PlpInfos(Atsc3PlpInfo[] atsc3PlpInfos) {
        synchronized (mScanCallbackLock) {
            if (mScanCallbackExecutor != null && mScanCallback != null) {
                mScanCallbackExecutor.execute(
                        () -> mScanCallback.onAtsc3PlpInfosReported(atsc3PlpInfos));
            }
        }
    }

    private void onModulationReported(int modulation) {
        synchronized (mScanCallbackLock) {
            if (mScanCallbackExecutor != null && mScanCallback != null) {
                mScanCallbackExecutor.execute(
                        () -> mScanCallback.onModulationReported(modulation));
            }
        }
    }

    private void onPriorityReported(boolean isHighPriority) {
        synchronized (mScanCallbackLock) {
            if (mScanCallbackExecutor != null && mScanCallback != null) {
                mScanCallbackExecutor.execute(
                        () -> mScanCallback.onPriorityReported(isHighPriority));
            }
        }
    }

    private void onDvbcAnnexReported(int dvbcAnnex) {
        synchronized (mScanCallbackLock) {
            if (mScanCallbackExecutor != null && mScanCallback != null) {
                mScanCallbackExecutor.execute(
                        () -> mScanCallback.onDvbcAnnexReported(dvbcAnnex));
            }
        }
    }

    /**
     * Opens a filter object based on the given types and buffer size.
+9 −4
Original line number Diff line number Diff line
@@ -85,6 +85,7 @@ public class DvrPlayback implements AutoCloseable {
    private static int sInstantId = 0;
    private int mSegmentId = 0;
    private int mUnderflow;
    private final Object mListenerLock = new Object();

    private native int nativeAttachFilter(Filter filter);
    private native int nativeDetachFilter(Filter filter);
@@ -106,18 +107,22 @@ public class DvrPlayback implements AutoCloseable {
    /** @hide */
    public void setListener(
            @NonNull Executor executor, @NonNull OnPlaybackStatusChangedListener listener) {
        synchronized (mListenerLock) {
            mExecutor = executor;
            mListener = listener;
        }
    }

    private void onPlaybackStatusChanged(int status) {
        if (status == PLAYBACK_STATUS_EMPTY) {
            mUnderflow++;
        }
        synchronized (mListenerLock) {
            if (mExecutor != null && mListener != null) {
                mExecutor.execute(() -> mListener.onPlaybackStatusChanged(status));
            }
        }
    }


    /**
+9 −4
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ public class DvrRecorder implements AutoCloseable {
    private int mSegmentId = 0;
    private int mOverflow;
    private Boolean mIsStopped = true;
    private final Object mListenerLock = new Object();

    private native int nativeAttachFilter(Filter filter);
    private native int nativeDetachFilter(Filter filter);
@@ -69,18 +70,22 @@ public class DvrRecorder implements AutoCloseable {
    /** @hide */
    public void setListener(
            @NonNull Executor executor, @NonNull OnRecordStatusChangedListener listener) {
        synchronized (mListenerLock) {
            mExecutor = executor;
            mListener = listener;
        }
    }

    private void onRecordStatusChanged(int status) {
        if (status == Filter.STATUS_OVERFLOW) {
            mOverflow++;
        }
        synchronized (mListenerLock) {
            if (mExecutor != null && mListener != null) {
                mExecutor.execute(() -> mListener.onRecordStatusChanged(status));
            }
        }
    }


    /**
+16 −7
Original line number Diff line number Diff line
@@ -227,6 +227,7 @@ public class Filter implements AutoCloseable {
    private long mNativeContext;
    private FilterCallback mCallback;
    private Executor mExecutor;
    private final Object mCallbackLock = new Object();
    private final long mId;
    private int mMainType;
    private int mSubtype;
@@ -253,16 +254,20 @@ public class Filter implements AutoCloseable {
    }

    private void onFilterStatus(int status) {
        synchronized (mCallbackLock) {
            if (mCallback != null && mExecutor != null) {
                mExecutor.execute(() -> mCallback.onFilterStatusChanged(this, status));
            }
        }
    }

    private void onFilterEvent(FilterEvent[] events) {
        synchronized (mCallbackLock) {
            if (mCallback != null && mExecutor != null) {
                mExecutor.execute(() -> mCallback.onFilterEvent(this, events));
            }
        }
    }

    /** @hide */
    public void setType(@Type int mainType, @Subtype int subtype) {
@@ -272,14 +277,18 @@ public class Filter implements AutoCloseable {

    /** @hide */
    public void setCallback(FilterCallback cb, Executor executor) {
        synchronized (mCallbackLock) {
            mCallback = cb;
            mExecutor = executor;
        }
    }

    /** @hide */
    public FilterCallback getCallback() {
        synchronized (mCallbackLock) {
            return mCallback;
        }
    }

    /**
     * Configures the filter.