Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  CallState.java

  Sprache: JAVA
 

package ch.threema.app.voip;

import org.slf4j.Logger;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import androidx.annotation.AnyThread;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;

import static ch.threema.base.utils.LoggingKt.getThreemaLogger;

/**
 * The call state is a combination of the plain state and a call ID.
 * <p>
 * The call state is global, there should not be multiple instances of this.
 * <p>
 * This is a pure data holder, no validation is being done.
 * <p>
 * This class is thread safe.
 */

@AnyThread
public class CallState {
    private static final Logger logger = getThreemaLogger("CallState");

    /**
     * No call is currently active.
     */

    static final int IDLE = 0;

    /**
     * This state only happens on the callee side,
     * before the call was accepted.
     */

    static final int RINGING = 1;

    /**
     * A call was accepted and is being setup.
     */

    static final int INITIALIZING = 2;

    /**
     * A call is currently ongoing.
     */

    static final int CALLING = 3;

    /**
     * A call is being disconnected.
     */

    static final int DISCONNECTING = 4;

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({IDLE, RINGING, INITIALIZING, CALLING, DISCONNECTING})
    @interface State {
    }

    private final AtomicInteger state = new AtomicInteger(IDLE);
    private final AtomicLong callId = new AtomicLong(0);

    /**
     * Whether or not an answer for this call ID has been received yet.
     * <p>
     * This flag is reset when the state transitions to DISCONNECTING or IDLE.
     */

    private volatile boolean answerReceived = false;

    /**
     * The incoming call counter is a transitional variable that is used as long as the call ID has
     * not yet been fully rolled out. It is being used to avoid problems if two calls are using the
     * default call ID "0". The counter is only incremented for incoming calls (in setStateRinging).
     */

    @Deprecated
    private final AtomicLong incomingCallCounter = new AtomicLong(0);

    @Override
    public synchronized String toString() {
        return "CallState{" +
            "state=" + getStateName(this.state.get()) +
            ", callId=" + this.callId.get() +
            '}';
    }

    //region Check / get state

    public boolean isIdle() {
        return this.state.get() == IDLE;
    }

    public synchronized boolean isRinging() {
        return this.state.get() == RINGING;
    }

    public synchronized boolean isInitializing() {
        return this.state.get() == INITIALIZING;
    }

    public synchronized boolean isCalling() {
        return this.state.get() == CALLING;
    }

    public synchronized boolean isDisconnecting() {
        return this.state.get() == DISCONNECTING;
    }

    /**
     * Return the current Call ID.
     * <p>
     * Note: Depending on the use case you might want to use {@link #getStateSnapshot()} instead.
     */

    public long getCallId() {
        return this.callId.get();
    }

    /**
     * Return the incoming call counter.
     */

    @Deprecated
    public long getIncomingCallCounter() {
        return this.incomingCallCounter.get();
    }

    /**
     * Return whether an answer was already received for this call.
     */

    public synchronized boolean answerReceived() {
        return this.answerReceived;
    }

    /**
     * Return an immutable snapshot of the current state.
     * This allows reading the state and the Call ID independently without locking.
     */

    public synchronized @NonNull CallStateSnapshot getStateSnapshot() {
        return new CallStateSnapshot(
            this.state.get(),
            this.callId.get(),
            this.incomingCallCounter.get()
        );
    }

    /**
     * Return the state name for the specified state.
     */

    static @NonNull String getStateName(@State int state) {
        switch (state) {
            case CallState.IDLE:
                return "IDLE";
            case CallState.RINGING:
                return "RINGING";
            case CallState.INITIALIZING:
                return "INITIALIZING";
            case CallState.CALLING:
                return "CALLING";
            case CallState.DISCONNECTING:
                return "DISCONNECTING";
            default:
                return "UNKNOWN";
        }
    }

    //endregion

    //region Set state

    public synchronized void setIdle() {
        this.state.set(IDLE);
        this.callId.set(0);
        this.answerReceived = false;
    }

    public synchronized void setRinging(long callId) {
        final @State int state = this.state.get();
        if (this.state.get() != IDLE) {
            logger.warn("Call state change from {} to RINGING", getStateName(state));
        }
        this.state.set(RINGING);

        if (this.callId.get() != 0) {
            logger.warn("Call ID changed from {} to {}"this.callId, callId);
        }
        this.callId.set(callId);

        this.incomingCallCounter.incrementAndGet();
    }

    public synchronized void setInitializing(long callId) {
        final @State int state = this.state.get();
        if (state != RINGING && state != IDLE) {
            logger.warn("Call state change from {} to INITIALIZING", getStateName(state));
        }
        this.state.set(INITIALIZING);

        final long oldCallId = this.callId.get();
        if (oldCallId != 0 && oldCallId != callId) {
            logger.warn("Call ID changed from {} to {}", oldCallId, callId);
        }
        this.callId.set(callId);
    }

    public synchronized void setAnswerReceived() {
        this.answerReceived = true;
    }

    public synchronized void setCalling(long callId) {
        final @State int state = this.state.get();
        if (state != INITIALIZING) {
            logger.warn("Call state change from {} to CALLING", getStateName(state));
        }
        this.state.set(CALLING);

        final long oldCallId = this.callId.get();
        if (oldCallId != callId) {
            logger.warn("Call ID changed from {} to {}", oldCallId, callId);
        }
        this.callId.set(callId);
    }

    public synchronized void setDisconnecting(long callId) {
        final @State int state = this.state.get();
        if (state != INITIALIZING && state != CALLING) {
            logger.warn("Call state change from {} to DISCONNECTING", getStateName(state));
        }
        this.state.set(DISCONNECTING);

        final long oldCallId = this.callId.get();
        if (oldCallId != callId) {
            logger.warn("Call ID changed from {} to {}", oldCallId, callId);
        }
        this.callId.set(callId);
        this.answerReceived = false;
    }

    //endregion
}

Messung V0.5 in Prozent
C=91 H=95 G=92

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet am  2026-04-27) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge