# Class CallId

java.lang.Object
com.codename1.call.CallId

public final class CallId extends Object

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.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `static String`
  `format(byte[] bytes)`
  Renders 16 bytes as a canonical identifier.
  `static boolean`
  `isValid(String id)`
  Whether `id` is a canonical identifier: 36 characters, hyphens in the four expected places, hex everywhere else.
  `static String`
  `normalize(String id)`
  Upper-cases a well-formed identifier, or returns null if it is not well-formed.
  `static String`
  `random()`
  A fresh random (version 4) identifier in canonical form.

  ### Methods inherited from class Object

  `clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## 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:
      36 uppercase characters with hyphens

  - ### format

    public static String format(byte[] bytes)
    Renders 16 bytes as a canonical identifier.
    Parameters:
      `bytes` - exactly 16 bytes
    Returns:
      the canonical form
    Throws:
      `IllegalArgumentException` - if `bytes` is not 16 long

  - ### isValid

    public static boolean isValid(String id)
    Whether `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:
      `id` - the candidate, may be null
    Returns:
      true if the shape is right

  - ### 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:
      `id` - the candidate, may be null
    Returns:
      the canonical form, or null if `id` is not an identifier