STREAM_VOICE_CALL

对 AudioManager.STREAM_VOICE_CALL 音频流类型进行分析

hardware/libhardware_legacy/audio/AudioPolicyManagerBase.cpp
frameworks/base/media/java/android/media/AudioManager.java
frameworks/base/media/java/android/media/AudioService.java
frameworks/base/media/java/android/media/AudioSystem.java

通过音频流的类型获取对应的音频策略

AudioPolicyManagerBase.cpp:

AudioPolicyManagerBase::routing_strategy AudioPolicyManagerBase::getStrategy(AudioSystem::stream_type stream) {
    // stream to strategy mapping
    switch (stream) {
    case AudioSystem::VOICE_CALL:
    case AudioSystem::BLUETOOTH_SCO:
        return STRATEGY_PHONE;
    ...
    }
}

可以, voice call的音频策略是 phone

通过音频策略获取到对应的输出设备

AudioPolicyManagerBase.cpp:

audio_devices_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy, bool fromCache) {
    uint32_t device = AUDIO_DEVICE_NONE;
    ... 
    switch (strategy) {
    ... 
    case STRATEGY_PHONE:
        // for phone strategy, we first consider the forced use and then the available devices by order
        // of priority
        switch (mForceUse[AudioSystem::FOR_COMMUNICATION]) { // 判断是否有设置在通讯过程中, 强制使用某种输出设备
        case AudioSystem::FORCE_BT_SCO: // 强制使用蓝牙, 作为输出设备
            if (!isInCall() || strategy != STRATEGY_DTMF) {
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
                if (device) break;
            }
            device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
            if (device) break;
            device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_SCO;
            if (device) break;
            // if SCO device is requested but no SCO device is available, fall back to default case
            // FALL THROUGH

        default:    // FORCE_NONE 没有设置通讯过程中, 强制使用某种输出设备
            // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
            if (mHasA2dp && !isInCall() &&
                    (mForceUse[AudioSystem::FOR_MEDIA] != AudioSystem::FORCE_NO_BT_A2DP) &&
                    (getA2dpOutput() != 0) && !mA2dpSuspended) {
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
                if (device) break;
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
                if (device) break;
            }
            device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
            if (device) break;
            device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_WIRED_HEADSET;
            if (device) break;
            if (mPhoneState != AudioSystem::MODE_IN_CALL) {
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY;
                if (device) break;
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE;
                if (device) break;
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
                if (device) break;
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
                if (device) break;
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
                if (device) break;
            }
			// 没有设置通讯过程中, 音频的输出设备, 则默认使用听筒作为输出设备
            device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_EARPIECE;
            if (device) break;
            device = mDefaultOutputDevice;
            if (device == AUDIO_DEVICE_NONE) {
                ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE");
            }
            break;

        case AudioSystem::FORCE_SPEAKER: // 强制使用扬声器, 作为输出设备
            // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
            // A2DP speaker when forcing to speaker output
            if (mHasA2dp && !isInCall() &&
                    (mForceUse[AudioSystem::FOR_MEDIA] != AudioSystem::FORCE_NO_BT_A2DP) &&
                    (getA2dpOutput() != 0) && !mA2dpSuspended) {
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
                if (device) break;
            }
            if (mPhoneState != AudioSystem::MODE_IN_CALL) {
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY;
                if (device) break;
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE;
                if (device) break;
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
                if (device) break;
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
                if (device) break;
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
                if (device) break;
            }
            device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_SPEAKER;
            if (device) break;
            device = mDefaultOutputDevice;
            if (device == AUDIO_DEVICE_NONE) {
                ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE, FORCE_SPEAKER");
            }
            break;
        }
    break;
	// 关于上面default位置的问题, 如果每个case选择(包括default)最终都有break语句, 则default的位置不影响执行顺序
	// 当每个case选择(包括default)不一定有break语句时, 如果输入不满足其他选择, 最终执行default. 程序会从default处从上向下执行, 直到遇到break语句停止
	// 此处的default位置并不影响执行顺序
	... // 省略
    }
    return device;
}

speech codec

G.711 (也称PCM), 用脉冲编码调制对音频采样,采样率为8k每秒。它利用一个 64Kbps 未压缩通道传输语音讯号。 起压缩率为1:2, 即把16位数据压缩成8位。
G.711 标准下主要有两种压缩算法。一种是µ-law, 北美和日本。另一种是A-law, 欧洲等其他区域

1972 年,为了将 模拟通信转向数字通信执行制定的话音编码标准

这个在通信原理的本科课程中都有介绍过。G.711采用一种称为分组丢失隐藏(PLC)的技术来减少丢包带来的实际影响。有效的信号带宽在静默期间通过语音活动检测(VAD)这一过程被减小。

延迟 0.125 ms
mos 4.1


G.729
也是ITU-T定义的音频编码算法,frame 只有10ms,G.729点到点的时延为25ms,G.729基于CELP模式,用CS-ACELP(Conjugate-Structure Algebraic Code Excited Linear Prediction)方法以8Kbps的波特率对语音进行编码。

G.729采用的是共轭结构的代数码激励线性预测算法(Conjugate Structure Algebraic Code Excited Linear Prediction,CS-ACELP),这是一种基于CELP编码模型的算法。由于G.729编码器能够实现很高的语音质量(MOS分3.9, 这个语音质量算很不错了)和很低的算法延时,被广泛地应用于数据通信的各个领域。

G.729是对8KHz采样16bit量化的线性PCM语音信号进行编码,压缩后数据速率为8Kbps,具备16:1的高压缩率。

延迟 15ms
MOS 3.9

G.729 CS-ACELP 8 3.92


G.723
G.723是ITU-T在1996年制订成型的一种多媒体语音编解码标准。G.723编码器采用LPC合成-分析法和感觉加权误差最小化原理编码。G.723标准可在6.3kbps和5.3kbps两种码率下工作。对激励信号进行量化时,高速率(6.3kbps)编码器的激励信号采用多脉冲最大似然量化(MP­-MLQ),低速率(5.3kbps)编码器的激励信号采用代数码本激励线性预测(ACELP)。其中,高码率算法(6.3kbps)具有较高的重建语音质量,而低码率算法(5.3kbps)的计算复杂度则较低。与一般的低码率语音编码算法一样,这里的G.723标准采用的线性预测的合成分析法也就是我们通常所说的Analysis-by-Synthesis。

G.723.1是一个双速率的语音编码器.
编码器首先对语音信号进行传统电话带宽的滤波(基于G.712),再对语音信号用传统8000-Hz速率进行抽样(基于G.711),并变换成16 bit线性PCM码作为该编码器的输入;
在解码器中对输出进行逆操作来重构语音信号;高速率编码器使用多脉冲最大似然量化(MP-MLQ),低速率编码器使用代数码激励线性预测(ACELP)方法,编码器和解码器都必须支持此两种速率,并能够在帧间对两种速率进行转换;
此系统同样能够对音乐和其他音频信号进行压缩和解压缩,但它对语音信号来说是最优的;采用了执行不连续传输的静音压缩,这就意味着在静音期间的比特流中加入了人为的噪声。除了预留带宽之外,这种技术使发信机的调制解调器保持连续工作,并且避免了载波信号的时通时断。

G.723.1 MP-MLQ 6.3kbps 3.9 MOS
G.723.1 ACELP 5.3kbps 3.65 MOS


G.726

Adaptive Differential Pulse Code Modulation (ADPCM),最为常用的方式是 32 kbit/s,但由于其只是 G.711速率的一半,所以可将网络的可利用空间增加了一倍。G.726具体规定了一个 64 kbpsA-law 或 µ-law PCM 信号是如何被转化为40, 32, 24或16 kbps 的 ADPCM 通道的。在这些通道中,24和16 kbps 的通道被用于数字电路倍增设备(DCME)中的语音传输,而40 kbps 通道则被用于 DCME 中的数据解调信号(尤其是4800 kbps 或更高的调制解调器)。
G.726 encoder 输入一般都是G.711 encoder的输出:64kbps A-law or u-law.其算法实质就是一个ADPCM, 自适应量化算法。


Speex 2.15 /44
Minimizes bandwidth usage by using variable bit rate. It is one of the most preferred codecs used in many VoIP apps.


SILK/ Opus


AMR


GSM


Codec2是一个开源的 语音编解码器, 最低450 bit/s
https://github.com/drowe67/codec2

Codec2的主要开发者是David Rowe ,他同时也是另一个开源语音项目Speex 的开发者。Codec2项目允许在只占用极少带宽的情况下提供通话服务,其算法是基于1980年代的论文,并避开了未过期的专利。


VoLTE使用两种语音编码标准:AMR(或AMR-NB)、AMR-WB。


VoNR使用 EVS


twinkle支持的 codec

G.711 A-law (64 kbps payload, 8 kHz sampling rate)
G.711 μ-law (64 kbps payload, 8 kHz sampling rate)
GSM (13 kbps payload, 8 kHz sampling rate)
Speex narrow band (15.2 kbps payload, 8 kHz sampling rate)
Speex wide band (28 kbps payload, 16 kHz sampling rate)
Speex ultra wide band (36 kbps payload, 32 kHz sampling rate)
iLBC (13.3 or 15.2 kbps payload, 8 kHz sampling rate)
G.726 (16, 24, 32 or 40 kbps payload, 8 kHz sampling rate)


Linphone 自己实现了一个 G.729 编解码器

Bcg729 is an open source implementation of both an encoder and decoder for the ITU G729 Annex A/B speech codec. This library was developed by Belledonne Communications, the company supporting the Linphone project. It was written from scratch and is NOT a derivative work of the ITU reference source code of any kind.

The library is written in C 99, is fully portable, and can be executed on many platforms, including ARM and x86 processors. libbcg729 supports concurrent channel encoding/decoding for multi-call applications such as conferencing.

opus
speex 32k/16k/8k
pcmu
pcma
gsm
g722
g726 40/32/24/16
aal2-g726 32/24/16


参考资料:
https://www.gl.com/voice-codecs.html

https://en.wikipedia.org/wiki/Category:Speech_codecs

Android电话API

接听电话

mTelecomManager =  getSystemService("telecom");
mTelecomManager.acceptRingingCall();  

静音

mAudioManager =  getSystemService("audio");
mAudioManager.setParameters("incall_music_mute=true");

联发科

耳机插上时
Set_SpeechCall_UL_Mute=1
未插耳机时
Set_SpeechCall_UL_Mute=1;rcv_mux=off

对应地,取消静音则是

Set_SpeechCall_UL_Mute=0
或
Set_SpeechCall_UL_Mute=0;rcv_mux=on

请求音频焦点

.requestAudioFocus()

录音

int buf_len = AudioRecord.getMinBufferSize(16000, 16, 2);
audioRecord = new AudioRecord(3, 16000, 16, 2, buf_len);  //  inputSource=3 (AUDIO_SOURCE_VOICE_DOWNLINK)
audioRecord.startRecording();
short[] buf = new short[buf_len];
audioRecord.read(buf, 0, buf_len);

音频源定义

    AUDIO_SOURCE_VOICE_UPLINK = 2,
    AUDIO_SOURCE_VOICE_DOWNLINK = 3,
    AUDIO_SOURCE_VOICE_CALL = 4,

流媒体类型定义

    AUDIO_STREAM_VOICE_CALL       = 0,
    AUDIO_STREAM_SYSTEM           = 1,
    AUDIO_STREAM_RING             = 2,
    AUDIO_STREAM_MUSIC            = 3,

Digest access authentication

https://en.wikipedia.org/wiki/Digest_access_authentication
https://www.w3.org/Protocols/rfc2069/rfc2069

HA1 = MD5(username:realm:password)
HA2 = MD5(method:digestURI)
response = MD5(HA1:nonce:HA2)

或者

HA1 = MD5(username:realm:password)
HA2 = MD5(method:digestURI)
response = MD5(HA1:nonce:nonceCount:cnonce:qop:HA2)

ha1 和 ha1 都是hex string, 作为 response的输入参数

https://raw.githubusercontent.com/jmurley/sip_md5/main/sip_md5.py

SIP基本概念

SIP(Session Initiation Protocol,会话初始协议)是一个用于建立、更改和终止多媒体会话的应用层控制协议,其中的会话可以是IP电话、多媒体会话或多媒体会议。SIP是IETF多媒体数据和控制体系结构的核心协议(最新RFC文档是RFC 3261), SIP用于发起会话,它能控制多个参与者参加的多媒体会话的建立和终结,并能动态调整和修改会话属性,如会话带宽要求、传输的媒体类型(语音、视频和数据等)、媒体的编解码格式、对组播和单播的
支持等。SIP协议基于文本编码,大量借鉴了成熟的HTTP协议。

1. 多媒体会话
多媒体会话(Multimedia Session)是指一组多媒体发送者和接受者,以及从发送者到接受者的数据流。例如一个多媒体会议就是一个多媒体会话。一个会话由一组用户名称、会话ID、网络类型、地址类型以及各个单元的地址来确定

2. 用戶代理
用户代理(UA,User Agent)也称SIP终端,是指支持SIP协议的多媒体会话终端。

UA包括用户代理客户端(UAC,User Agent Client)和用户代理服务器(UAS,User Agent Server)。
一般说的UA均是指二者的总称,因为在一次呼叫中,一个SIP终端既要处理SIP请求,又要发起SIP请求。

用户代理客户端是指在SIP会话建立过程中主动发送会话请求的设备。例如,主叫SIP终端。当代理服务器向被叫终端发送会话请求时, 代理服务器也就扮演 用户代理客户端的角色。

用户代理服务器是指在SIP会话建立过程中接收会话请求的设备。例如,被叫SIP终端。当代理服务器接收主叫终端发送会话请求时, 也就扮演了 用户代理服务器的角色。

3. 代理服务器

————————————————————————————
Agent和Proxy在中文都翻译成代理,在SIP语境,要仔细区分。

把 proxy 翻译成代理,agent 则根据语境翻译成助手(代办)之类会好理解一些(比如office里面的“大眼夹”就是agent,中文叫“office小助手”;苹果的siri, 微软的小娜等也是agent)。

agent 拥有独立思考/行动能力,可以代替你做一些决定。 比如,这是我的管家/律师,合同的事你和他谈。他的决定就是我的决定。 这个得到了授权、可以独立以你的名义完成某个任务、必要时允许他根据情况做出自主决定的,就是 agent

proxy一般原样转发,办理用户交代的事情。

在 翻墙流量 外网web的过程中, 浏览器(browser)就是agent, 它会帮你翻译 html和css, 以非常友好的形式展现内容。它也会理解你的双击,键盘操作,滑动等操作,并将这些操作转换为 http请求 发送给服务器。 它能理解主人的意图,并做出适当的转换。

而 外网的某台 中间服务器,则担当了 proxy的角色, 它基本上原样转发你的 http 请求给 目标服务器 (某些匿名代理服务器,可以让目标服务器
无法觉察你是通过proxy访问的), 再将 http响应原样 返回给你。纯粹的跑腿的角色, 不会帮你转换,思考,甚至代替做出决定。
——————————————————————————————-

代理服务器(Proxy Server)的作用就是传递主叫UA发送的会话请求到被叫UA,然后将被叫UA的响应传递回主叫UA,它相当于主叫UA和被叫UA之间传递会话消息的一座桥梁。

代理服务器在接收到主叫UA的会话请求后,首先要向位置服务器请求查找被叫UA的位置以及主、被叫UA的呼叫策略信息。只有找到被叫UA并且此呼叫是允许的,代理服务器才会向被叫UA发送会话请求。代理服务器一般在SIP会话中都是需要的。

4. 重定向服务器
重定向服务器(Redirect Server)用来指示客户端连接的新地址。比如,主叫UA呼叫被叫UA,当重定向服务器收到主叫UA发送的会话请求消息后,查找被叫UA的位置信息,然后将其返回给主叫UA,使主叫UA重新向该位置发起会话请求。此位置可以是被叫UA的位置,也可以是一个代理服务器的位置。接下来主叫UA如同直接呼叫被叫UA或者向代理服务器呼叫的流程一样。

5. 位置服务器
位置服务器(Location Server)是为代理服务器和重定向服务器等提供UA信息的设备。位置服务器记录了注册服务器接收到的UA的信息。二者可以独立存在,也可以作为逻辑组件存在于同一台服务器上

6. 注册服务器
注册服务器(Registrar Server)接受用户注册,注册的内容(如本地号码等信息)一般是存储在位置服务器上,供后续查询使用。二者都是逻辑组件,一般存在于同一台服务器上。


功能:
1. 确定用户位置:主要利用 SIP终端在注册服务器上的注册信息实现用户定位

2. 确定用户可用性: 确定被叫会话终端是否可以参加此会话。SIP支持多种地址描述和寻址方式,包括SIP-URI(比如sip:123456@192.168.1.11)、Tel-URL(比如tel:+1312000)和SIPS-URI(sips:123456@192.168.1.11)。这样,SIP主叫根据被叫地址,就可以识别出被叫是否在传统电话网上,然后通过一个与传统电话网相连的网关向被叫发起并建立呼叫

3. 确定用户能力: 确定被叫终端可用于参加会话的媒体类型及媒体参数。SIP终端在消息交互过程中携带自身的媒体类型和媒体参数,这使得会话双方都可以明确对方的会话能力

4. 建立会话: 建立主被叫双方的会话。SIP会话双方通过协商媒体类型和媒体参数,最终选择双方都具有的能力建立起会话。

5. 管理会话: 可以更改会话参数或中止会话


SIP消息
SIP消息采用文本方式编码,包括请求消息与响应消息两类。
SIP请求消息包括INVITE ACK OPTIONS BYE CANCEL和REGISTER等。RFC 3261定义的请求消息有以下六种。
INVITE: 用于邀请用户加入一个呼叫。
ACK: 用于对消息进行确认。
OPTIONS: 用于请求协商能力信息。
BYE: 用于释放已建立的呼叫。
CANCEL: 用于释放尚未建立的呼叫。
REGISTER: 用于向SIP注册服务器登记用户位置等信息。

SIP响应消息用于对请求消息进行响应,指示呼叫或注册的成功或失败状态。不同类的响应消息由状态码来区分,状态码包含三位整数,状态码的第一位用于定义响应类型,另外两位用于进一步对响应进行更加详细的说明。


工作流程

1. 登记注册
在完整的SIP系统中,所有的SIP终端作为User Agent都应该向注册服务器登记注册,以告知其位置、会话能力、呼叫策略等信息。
通常,SIP终端开机启动或者配置管理员执行注册操作时,就向注册服务器发送注册请求消息(REGISTER),该消息中携带了所有需要登记的信息。注册服务器收到注册请求消息后向终端发送回应消息,以告知其请求消息已收到。如果注册成功,就再向终端发送“200 OK”消息。

2. 建立呼叫
SIP协议采用Client/Server模型,主要通过UA与代理(proxy)服务器之间的通信来完成用户呼叫的建立过程

3. 重定向呼叫
SIP重定向服务器收到会话请求消息后,不是转发会话请求消息,而是在回应消息中告知被叫SIP终端的地址。主叫终端从而重新直接向被叫终端发送会话请求消息。被叫终端也将直接向主叫终端发送应答消息。


SIP支持的传输协议
SIP是一个应用层的会话协议,可以同时支持各种传输协议:
1) 支持UDP传输: UDP是一个无连接的协议,且不提供可靠性。在UDP上建立SIP连接存在不可靠性。
2) 支持TCP传输: 增加了SIP报文和语音传输的可靠性,通过TCP协议自身的特点为基于SIP的VoIP通信提供了面向连接和可靠的传输。SIP使用TCP传输协议后,SIP协议可以不需要考虑报文丢失和重传问题。
3) SIP支持TLS(Transport Layer Security,传输层安全)传输:SIP支持TCP传输仅仅保证了SIP报文和语音传输的可靠性,而SIP支持TLS传输则保证了SIP报文传输的安全性

TLS本身运行于TCP之上,并且提供了通信双方身份识别和加密SIP报文的一整套安全方案,为应用层协议服务。建立TLS连接时需要认证双方用户的身份,因此用户双方必须有各自合法的数字证书,只有通过认证的用户才可以进行后续的通信。使用TLS传输SIP报文,SIP报文在整个传输过程全部被加密


支持的媒体流协议包括:RTP(Real-time Transport Protocol,实时传输协议)和RTCP(Real-Time Transport Control Protocol,实时传输控制协议)。RTP用于为具有实时特征的数据(如交互音频和视频)提供端到端网络的实时传输服务;RTCP用于实时监控传输质量,并提供拥塞控制和流控制。
RTP和RTCP配合使用,就能以有效的反馈和最小的开销使传输效率更佳。在网络中媒体流是明文传输的,为了保证通信内容的安全性,SRTP协议应运而生。

SRTP(Secure Real-time Transport Protocol,安全RTP协议)通过对RTP/RTCP报文的有效负载进行加密,实现对RTP/RTCP报文的加密、认证以及报文重传保护。

采用SRTP加密媒体流,首先需要协商加密信息,目前仅支持在SDP(Session Description Protocol,会话描述协议)中通过crypto头域进行加密协商。发起方将本端支持的加密属性信息发送给接收方进行协商,协商成功后,接收方返回相应的加密属性信息。会话建立后,双方各自使用自己的密钥加密
RTP/RTCP报文,使用对端的密钥解密对方发送的RTP/RTCP报文。

SDP协商主要包括以下参数信息:
Tag: 加密属性信息标识符,在不同的加密属性必选协商参数行中的tag值必须不同,接收方根据Tag值来决定使用哪一组加密属性
Crypto-Suite : 加密套件,定义加密和认证使用的算法。
Key Parameters : 密钥参数 定义密钥信息,主要包括密钥生成方法和密钥值

terminal capability

在电源协商过程中,终端(手机/modem)会发出一个TERMINAL CAPABILITY命令,用来指示 终端可以提供的最大功率。
在这种情况下,UICC可能会消耗 终端指示的功率,直到断电。

如果在SELECT或者STATUS命令的响应中,指出的应用电源消耗,比在TERMINAL CAPABILITY命令中
表明的终端能提供的最大功率还要高的话, 那么终端应该取消对这个应用的选择。

62 (FCP) 28 
   82 (文件描述符)02        78 21   (MF共享文件...) 
   83 (文件标识符)02      3F 00 
   A5 (专有信息) 0B 
         80   (UICC特性) 01 71  (允许时钟停止,无优先级别,支持电压级别ABC)
         83  (剩余内存) 03      07 EA 1D 
         87    (Supported commands)                  01   01 
         8A  (生命周期)   01   05 (激活)
       8B  (安全特性)03    2F  06 05 
        C6 (PIN状态模板) 09 
        90 (PSDO标签) 01 40 (PSDO值)
        83 01 01 
        83 01 0A 

注意87标签,值为00 表示 TERMINAL CAPABILITY not supported, 01表示 TERMINAL CAPABILITY is supported

如果3F00 MF文件的FCP表明 支持 TERMINAL CAPABILITY, 应该马上发这么一个命令

80 AA 00 00 0F                TERMINAL CAPABILITY
AA 
A9 (Terminal capability constructed Tag)0D 
    83 (Additional Terminal capability indications
related to eUICC)       01   07 
    80 (Terminal power supply)  03   04 3C FF 
    81 (Extended logical channels terminal support)   00 
    82 (Additional interfaces support)   01   01 
90 00 

Terminals supporting eUICC functionality, as defined in GSMA SGP.22 , shall indicate it to the UICC by issuing
the TERMINAL CAPABILITY command with an additional terminal capability indication related to eUICC TLV
object during a new card session before the first application selection.
The terminal capability indications related to eUICC functionality are indicated by tag ’83’ within the constructed TLV
object.


bit0 1 = Local Profile management is supported, 0= Local Profile management is not supported
bit1 1 = Profile Download is supported, 0 = Profile Download is not supported

—————
The eUICC SHALL request the Device to send the Terminal Capability command by setting
the related bit in the file control parameters of the MF.

The Device SHALL report its support of LPA functions using the Terminal Capability
command data defined in ETSI TS 102 221 . This command SHALL be sent before the
SELECT ISD-R command defined in section 5.7.1.

Within the Terminal Capability template (tag ‘A9′), the tag ’83’ is used for indicating the
Device’s support for eUICC related functions.

b1 = Local User Interface in the Device (LUId) supported
b2 = Local Profile Download in the Device (LPDd) supported
b3 = Local Discovery Service in the Device (LDSd) supported
b4 = LUIe based on SCWS supported

postgresql触发器权限

To create or replace a trigger on a table, the user must have the TRIGGER privilege on the table. The user must also have EXECUTE privilege on the trigger function.

要在表上创建或者替换一个触发器,用户必需在该表上有TRIGGER权限。 用户也必须在触发器函数上有EXECUTE权限

查看某用户的表权限
select * from information_schema.table_privileges where grantee='username';

查看某用户的usage权限
select * from information_schema.usage_privileges where grantee='username';

查看某用户在存储过程函数的执行权限
select * from information_schema.routine_privileges where grantee='username';

查看某用户在某表的列上的权限  (比表权限 更细化)
select * from information_schema.column_privileges where grantee='username'; 

查看当前用户能够访问的数据类型
select * from information_schema.data_type_privileges ; 

CREATE FUNCTION defines a new function. CREATE OR REPLACE FUNCTION will either create a new function, or replace an existing definition. To be able to define a function, the user must have the USAGE privilege on the language.
CREATE FUNCTION定义一个新函数。 CREATE OR REPLACE FUNCTION 创建一个新函数 或者 替换已经存在的定义。
为了能够定义一个函数, 用户必须有 创建函数所使用的语言的 USAGE 权限。

Linux shell获取网卡IPv6地址

0. 通过googel的dns服务器,获取出口的IPV6地址

dig -6 TXT +short o-o.myaddr.l.google.com @ns1.google.com | sed 's|"||g'
或者
dig @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \"

通过查询一个 特殊地址( o-o.myaddr.l.google.com ) 的txt记录

或者通过一个http服务

curl http://icanhazip.com
或者
curl -s ipv6.icanhazip.com
或者
curl api64.ipify.org
或者
curl 'https://api64.ipify.org?format=json'
或
curl 6.ipw.cn 

1. 通过查询本机的路由表

ip route get 2001:4860:4860::8888 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'

sed命令解释

sed            # the sed executable located via $PATH
-n             # no output unless explicitly requested
'              # begin the command space
/src/          # regex match the string 'src'
{              # begin a block of commands **
s/             # begin a substitution (match)
  .*src *      # match anything leading up to and including src and any number of spaces
  \([^ ]*\)    # define a group containing any number of non spaces
  .*           # match any trailing characters (which will begin with a space because of the previous rule).
/              # begin the substitution replacement
  \1           # reference the content in the first defined group
/              # end the substitution
p              # print (explicitly, remember) the result
;              # designate the end of the command
q              # quit
}              # end the block of commands
'              # end the command space

或者用awk也可以

ip route get 2001:4860:4860::8888 |  awk '{gsub(".*src",""); print $1; exit}'

或者让ip命令输出json

ip -6 -j route get 2001:4860:4860::8888 

prefsrc的值,就是

或者

ip route get 2001:4860:4860::8888 | grep src| sed 's/.*src \(.*\)$/\1/g'

2. 用ip 命令获取地址 global类型地址

ip -6 a show scope global  up | egrep  -o '([0-9a-f:]+:+)+[0-9a-f]+'  -m 1

只匹配第1个地址

3. 删除路由器上 deprecated 的地址

 ip -6  addr  show   dev br-lan | grep deprecated  | sed 's/.*inet6 \(.*\)$/\1/g'


ip -6  addr  show   dev   enp1s0    | sed -n '/deprecated/{s/.*inet6 *\([^ ]*\).*/\1/p;q}'
ip -6  addr  show   dev   enp1s0    | grep deprecated  | egrep  -o '([0-9a-f:]+:+)+[0-9a-f]+'  -m 1



ip -6 addr del        ....       dev br-lan

ISIM初始化

如果终端想要参与IMS操作,应该在UICC激活之后。
如果在EF_DIR(2F00)中列出了ISIM应用,终端应该“按DF名字选择”ISIM应用。
=====================
ISIM不得表明任何语言偏好。它应该使用UICC上激活的其他应用使用语言。或者 使用 MF目录下的EF_PL文件中指定的语言。
如果终端不支持EF_PL中指定的语言,那么终端应该使用它自己内部的默认的语言。
然后,终端应该运行用户验证过程。如果这个过程没有被成功执行, ISIM应该用初始化应该停止。
终端执行 管理信息请求。如果这些过程被成功直接性, ISIM会话应该开始, 否在会话不应该开始。
在预先的过程被成功执行后, 终端应该运行下面的过程:
1) IMPI 请求
2) IMPU 请求
3) SIP 域名请求
4) ISIM 服务表 请求,如果不存在6F07(IST)文件,那么应该假定不存在任何可用 ist定义的服务
5)P-CSCF地址请求
在初始化完成后, 应该发送一个特殊的STATUS命令,来表明 ISIM成功初始化, 可以开始ISIM会话了。

The Terminal uses the AUTHENTICATE command in GBA security context (Bootstrapping Mode) (see 7.1.1). The
response is sent to the Terminal.
After a successful GBA_U Procedure, the Terminal shall update the B-TID field and the Key Life Time field in
EFGBABP.

The Terminal shall first read EFGBABP. The Terminal then uses the AUTHENTICATE command in GBA security
context (NAF Derivation Mode) (see 7.1.1). The response is sent to the Terminal.
===================
SM-over-IP
Requirement:Service n°8 “available”.
Request:the ME performs the reading procedure with EFPSISMSC.
Update:The ME performs the updating procedure with EFPSISMSC.
=============
The function can be used in several different contexts:
-an IMS AKA security context during the procedure for authenticating the ISIM to its HN and vice versa when
IMS AKA authentication data are available. The function shall be used whenever an IMS context shall be
established, i.e. when the terminal receives a challenge from the IMS. A cipher key and an integrity key are
calculated. For the execution of the command the ISIM uses the subscriber authentication key K, which is stored
in the ISIM.
-a HTTP Digest security context, when HTTP Digest authentication data are available. Digest authentication
operations are described in IETF RFC 2617 [26].
-a GBA_U security context, when a GBA bootstrapping procedure is requested. In this context the function is
used in two different modes:
a) Bootstrapping Mode: during the procedure for mutual authenticating of the ISIM and the Bootstrapping
Server Function (BSF) and for deriving Bootstrapped key material from the AKA run.
b) NAF Derivation Mode: during the procedure for deriving Network Application Function (NAF) specific keys
from previous bootstrapped key material.

a Local Key Establishment security context, when a Local Key Establishment procedure is requested.

The function is related to a particular ISIM and shall not be executable unless the ISIM application has been selected
and activated, and the current directory is the ISIM ADF or any subdirectory under this ADF and a successful PIN
verification procedure has been performed (see clause 5).

=============
IMS AKA security context
The ISIM first computes the anonymity key AK = f5K (RAND) and retrieves the sequence number
SQN = (SQN ⊕ AK) ⊕ AK.
Then the ISIM computes XMAC = f1K (SQN || RAND || AMF) and compares this with the MAC which is included in
AUTN. If they are different, the ISIM abandons the function.
Next the ISIM verifies that the received sequence number SQN is previously unused. If it is unused and its value is
lower than SQNMS, it shall still be accepted if it is among the last 32 sequence numbers generated. A possible
verification method is described in TS 33.102 [4].
NOTE:
This implies that the ISIM has to keep a list of the last used sequence numbers and the length of the list is
at least 32 entries.

If the ISIM detects the sequence numbers to be invalid, this is considered as a synchronisation failure and the ISIM
abandons the function. In this case the command response is AUTS, where:
-AUTS = Conc(SQNMS ) || MACS;
-Conc(SQNMS) = SQNMS ⊕ f5*K(RAND) is the concealed value of the counter SQNMS in the ISIM; and
-MACS = f1*K(SQNMS || RAND || AMF) where:
-RAND is the random value received in the current user authentication request;
the AMF assumes a dummy value of all zeroes so that it does not need to be transmitted in clear in the
resynchronisation message.
If the sequence number is considered in the correct range, the ISIM computes RES = f2K (RAND), the cipher key
CK = f3K (RAND) and the integrity key IK = f4K (RAND) and includes these in the command response. Note that if
this is more efficient, RES, CK and IK could also be computed earlier at any time after receiving RAND.
The use of AMF is HN specific and while processing the command, the content of the AMF has to be interpreted in the
appropriate manner. The AMF may e.g. be used for support of multiple algorithms or keys or for changing the size of
lists, see TS 33.102 [4].
====================

GBA security context (Bootstrapping Mode)
ISIM operations in GBA security context are supported if service n°2 is “available”.
The ISIM receives the RAND and AUTN*. The ISIM first computes the anonymity key AK = f5K (RAND) and
retrieves the sequence number SQN = (SQN ⊕ AK) ⊕ AK.
The ISIM calculates IK = f4K (RAND) and MAC (by performing the MAC modification function described in
TS 33.220 [25]). Then the ISIM computes XMAC = f1K (SQN || RAND || AMF) and compares this with the MAC
previously produced. If they are different, the ISIM abandons the function.
Then the ISIM performs the remaining checking of AUTN* as in IMS security context. If the ISIM detects the sequence
numbers to be invalid, this is considered as a synchronisation failure and the ISIM abandons the function. In this case
the command response is AUTS, which is computed as in ISIM security context.
If the sequence number is considered in the correct range, the ISIM computes RES = f2K (RAND) and the cipher key
CK = f3K (RAND).
The ISIM then derives and stores GBA_U bootstrapped key material from CK, IK values. The ISIM also stores RAND
in the RAND field of EFGBABP
The ISIM stores GBA_U bootstrapped key material from only one bootstrapping procedure. The previous bootstrapped
key material, if present, shall be replaced by the new one. This key material is linked with the data contained in EFGBABP
: RAND, which is updated by the ISIM and B-TID, which shall be further updated by the ME.
=======================

6F02    SFI=02  IMS Private user identity    '8000FF...FF'
6F03         SFI=05   Home Network Domain Name      '8000FF...FF'
6F04         SFI=04  IMS public user identity       '8000FF...FF'
6FAD    SFI=03       Administrative Data     全0
6F06    SFI=06  Access Rule Reference     有些基带,也把 SFI=0x17 也映射到这个文件
6FD5    GBA Bootstrapping parameters     'FF...FF'   推荐存在  ---为全FF
6F07    SFI=07   ISIM Service Table
6F09    P-CSCF address----在t-mobile中为全FF
6F3C    Short messages
6F42    SMS parametrers
6F43                          02 FF
6F47     UICC IARI             00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

6FD7    GBA NAF List               'FF...FF'----全FF
6FDD    NAF Key Centre Address      'FF...FF'
6FE5     Public Service Identity of the SM-SC
6FE7   UICC IARI--------------------------全 FF
6FF7   From Preferred        '00'
6FF8   IMSConfigData
6FFC   XCAP Configuration Data--------可以不存在
6FFA   WebRTC URI
6FFE   MuD and MiD Configuration Data

Generic Bootstrapping Architecture (GBA) is a technology that enables the authentication of a user. This authentication is possible if the user owns a valid identity on an HLR (Home Location Register) or on an HSS (Home Subscriber Server).

3GPP TS 33.220

The user authentication is instantiated by a shared secret, one in the smartcard, for example a SIM card inside the mobile phone and the other is on the HLR/HSS.

GBA authenticates by making a network component challenge the smartcard and verify that the answer is the one predicted by the HLR/HSS.

Instead of asking the service provider to trust the BSF and relying on it for every authentication request, the BSF establishes a shared secret between the simcard card and the service provider. This shared secret is limited in time and for a specific domain.

运营商短消息中心

北京移动 +8613800100500

移动物联网 +8613800100569

河北移动 +8613800311500

马来u-mobile +60 18 100 0108

756D6F62696C65(umobile)

FFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF07910681010001F8FFFFFFFFFFFFFF

菲律宾 globe +63 91 7000 0130

534D532043656E747265 (SMS Centre)

FFFFFDFFFFFFFFFFFFFFFFFFFFFFFF0791361907001003FFFFFFFFFFFFFF

泰国AIS +66 92 301 0900

FFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF07916629030109F0FFFFFFFFFFFFFF

新加坡 Starhub +65 9854 1000

FFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF06915689450100FFFFFFFFFFFFFFFF

美国Ultramobile +1 206 313 0004

FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1FFFFFFFFFFFFFFFFFFFFFFFF07912160130300F4FFFFFFFF0000FF

美国 T-Mobile +1 206 313 0004

542D4D6F62696C65(T-Mobile)

FFFFFFFFFFFFFFFFF1FFFFFFFFFFFFFFFFFFFFFFFF07912160130300F4FFFFFFFF0000FF

AID

泰国 AIS

61174F10

A0000000871002FF45FF018906030000

5003414953

菲律宾 Globe

61184F10

A0000000871002FF86FF0789FFFFFFFF

50045553494DFFFFFFFFFFFFFFFFFFFFFFFFFFFF

新加坡 Starhub

61184F10

A0000000871002FF86FF0289060100FF

50045553494DFFFFFFFFFFFFFFFFFFFFFFFFFFFF

马来西亚u-mobile

611E4F0F

A0000000871002FF60FF0189B00001

500B55204D6F62696C65203347FFFFFFFF

确实比较罕见, AID长度为F而不是10

ultamobile

61184F10

A0000000871002FFFFFFFF8906190000

50045553494DFFFFFFFFFFFFFFFFFFFFFFFF

61184F10

A0000000871004FFFFFFFF8907030000

50044953494DFFFFFFFFFFFFFFFFFFFFFFFF

61174F0C

A000000063504B43532D3135

5007504B4353233135FFFFFFFFFFFFFFFFFFFFFFFFFF

t-mobile

61184F10

A0000000871002FFFFFFFF8906190000

50045553494DFFFFFFFFFFFFFFFFFFFFFFFF

61184F10

A0000000871004FFFFFFFF8907030000

50044953494DFFFFFFFFFFFFFFFFFFFFFFFF

61174F0C

A000000063504B43532D3135

5007504B4353233135FFFFFFFFFFFFFFFFFFFFFFFFFF

ultra-mobile是t-mobile的MVNO, 卡片文件基本上是一样的