public final class CallId
- Object
- CallId
Canonical form of the identifier that names one call everywhere: in this API, in CallKit, in Telecom, and in the VoIP push payload a server sends.
It is an RFC 4122 identifier written as 36 characters, uppercase, with
hyphens – 6B29FC40-CA47-1067-B31D-00DD010662DA. The case is fixed
rather than ignored because the identifier is compared as a string on
every hop, including by a server that did not come from this API, and
“compare case-insensitively everywhere” is a rule that only has to be
forgotten once.
Who allocates one
- For a call this app places or learns about over its own connection,
this app allocates with
random(). - For a call that arrives as a VoIP push, the sending server
allocates and the identifier travels in the payload, because on iOS
the call must be reported to the system before any of this app’s code
runs. See
VoipPush.
Either way the same identifier must be used by both ends for the whole life of the call, or the two sides will disagree about which call an action refers to.
This class is not instantiated; it holds the format and the generator.
Methods
public static String random() | A fresh random (version 4) identifier in canonical form. |
public static String format(byte[] bytes) | Renders 16 bytes as a canonical identifier. |
public static boolean isValid(String id) | Whether id is a canonical identifier: 36 characters, hyphens in the four expected places, hex everywhere else. |
public static String normalize(String id) | Upper-cases a well-formed identifier, or returns null if it is not well-formed. |
Inherited methods
Method details
random
public static String random()A fresh random (version 4) identifier in canonical form.
From SecureRandom, deliberately, and NOT
from java.util.Random. The device runtime’s Random is
this(System.currentTimeMillis()) over a 48-bit LCG – see
vm/JavaAPI/src/java/util/Random.java – so two processes that reach
this class in the same millisecond produce the same sequence of
identifiers, and it is the SEED that collides rather than the 122
random bits, which is a far smaller space than the format suggests.
A call id is not decoration: it is the key CallKit and Telecom hold
the session under and the token the app’s server routes signalling
by, so two calls sharing one aliases them – CallKit answers a
duplicate report with CallUUIDAlreadyExists, and a server hands the
wrong session an answer or an end.
Every port that supports calling implements secureRandomBytes, so this does not narrow which PLATFORMS the API works on – but it does require the runtime to be up, because the bytes come through the implementation. That is true wherever application code runs and is NOT true in a platform service the OS starts on its own: Android’s CN1ConnectionService can be created by Telecom in a process with no Display, and it mints its own id there rather than calling this. A port adding a similar entry point has to do the same.
Returns
format
public static String format(byte[] bytes)Parameters
bytesbyte[]- exactly 16 bytes
Returns
Throws
IllegalArgumentException- if
bytesis not 16 long
isValid
public static boolean isValid(String id)id is a canonical identifier: 36 characters, hyphens in the
four expected places, hex everywhere else. Case is not checked
here – use normalize(String) to both check and fix the case.Parameters
idString- the candidate, may be null
Returns
normalize
public static String normalize(String id)Upper-cases a well-formed identifier, or returns null if it is not well-formed.
Ports call this on the way in, so a lowercase identifier from a
server payload is accepted and stored canonically rather than
becoming a call nothing can later find. A null return is the
signal to answer CallError.INVALID_ID; this never throws, because
the value routinely comes from off the device.
Parameters
idString- the candidate, may be null
Returns
id is not an identifier