Qualcomm 远程信息处理 SDK - 用户指南(10)
4.3.15 配置远程 SIM 卡
此示例应用程序演示了如何使用远程 SIM 配置 API 在 eUICC 上执行 SIM 配置文件管理操作,例如添加配置文件、启用/禁用配置文件、删除配置文件、查询配置文件列表、配置服务器地址和执行内存重置。
- 获取手机工厂、SIM配置文件管理器和卡管理器实例
auto &phoneFactory = telux::tel::PhoneFactory::getInstance();
auto simProfileManager = phoneFactory.getSimProfileManager();
auto cardManager = phoneFactory.getCardManager();
- 检查SIM配置文件子系统是否准备就绪
bool subSystemStatus = simProfileManager->isSubsystemReady();
2.1 如果SIM配置文件管理器子系统未准备好,则等待其准备好
if(!subSystemsStatus) {
std::cout << "SIM profile manager subsystem is not ready" << std::endl;
std::cout << "wait unconditionally for it to be ready " << std::endl;
std::future<bool> f = simProfileManager->onSubsystemReady();
subSystemsStatus = f.get();
}
- 检查卡子系统是否就绪
bool subSystemStatus = cardManager->isSubsystemReady();
3.1 如果卡管理器子系统未准备好,则等待其准备好
if(!subSystemsStatus) {
std::cout << "Card manager subsystem is not ready" << std::endl;
std::cout << "wait unconditionally for it to be ready " << std::endl;
std::future<bool> f = cardManager->onSubsystemReady();
subSystemsStatus = f.get();
}
- 如果 SIM 配置文件和卡管理器子系统无法初始化,则退出应用程序
if(subSystemsStatus) {
std::cout << " *** SIM profile manager subsystem and Card manager ready *** " << std::endl;
} else {
std::cout << " *** ERROR - Unable to initialize SIM profile manager/Card manager subsystem"
<< std::endl;
}
5.实例化并注册RspListener
std::shared_ptr<ISimProfileListener> listener = std::make_shared<RspListener>();
simProfileManager.registerListener(listener);
5.1 用于接收远程 SIM 配置通知的 ISimProfileListener 接口的实现
class RspListener : public telux::tel::ISimProfileListener {
public:
void onDownloadStatus(SlotId slotId, telux::tel::DownloadStatus status,
telux::tel::DownloadErrorCause cause) override {
// Profile download and installation status when add profile operation performed.
}
void onUserDisplayInfo(SlotId slotId, bool userConsentRequired,
telux::tel::PolicyRuleMask mask) override {
// Based on profile policy rules received client can decide to provide user consent
// for download and installation of profile by calling
// ISimProfileManager::provideUserConsent
}
void onConfirmationCodeRequired(SlotId slotId, std::string profileName) override {
// Provide confirmation code for the download and installation of profile by calling
// ISimProfileManager::provideConfirmationCode
}
- 请求eUICC的EID
auto respCb = [&](std::string eid, telux::common::ErrorCode errorCode)
{ eidCallback(eid, errorCode); };
// Implement a callback method to get response for the EID request
void eidCallback(std::string eid, telux::common::ErrorCode error) {
if (error != ErrorCode::SUCCESS) {
std::cout << "requestEid failed with error" << static_cast<int>(error) << std::endl;
return;
}
std::cout << "requestEid succeeded." << std::endl;
}
// Request EID of the eUICC.
auto card = cardManager->getCard(SlotId::DEFAULT_SLOT_ID, &status);
status = card->requestEid(respCb);
- 在eUICC上添加配置文件
auto respCb = [&](telux::common::ErrorCode errorCode) { addProfileCallback(errorCode); };
// Implement a callback method to get response for the add profile request
void addProfileCallback(telux::common::ErrorCode error) {
if (error != ErrorCode::SUCCESS) {
std::cout << "addProfile failed with error" << static_cast<int>(error) << std::endl;
return;
}
std::cout << "addProfile succeeded." << std::endl;
}
// Add/Download profile on the eUICC.
status = simProfileManager->addProfile(SlotId::DEFAULT_SLOT_ID, activationCode,
confirmationCode, isUserConsentSupported, respCb);
7.1 如果下载配置文件需要用户同意,将通过调用 onUserDisplayInfo API 通知客户端注册的监听器
客户端应调用 ISimProfileManager::provideUserConsent API 以便进一步下载配置文件。
void onUserDisplayInfo(SlotId slotId, bool userConsentRequired,
telux::tel::PolicyRuleMask mask) override {
// Based on user info received client can decide to provide user consent for download and
// installation of profile by calling ISimProfileManager::provideUserConsent
}
7.2 如果下载配置文件需要确认码,将通过调用 onConfirmationCodeRequired API 通知客户端注册的监听器
客户端应调用 ISimProfileManager::provideConfirmationCode API 以便进一步下载配置文件。
void onConfirmationCodeRequired(SlotId slotId, std::string profileName) override {
// Provide confirmation code for the download and installation of profile by calling
// ISimProfileManager::provideConfirmationCode
}
7.3 当配置文件下载完成或失败时,客户端会收到下载状态通知
void onDownloadStatus(SlotId slotId, telux::tel::DownloadStatus status,
telux::tel::DownloadErrorCause cause) override {
// Profile download and installation status is recieved here whenever add profile operation
// is performed.
}
- 删除 eUICC 上的配置文件
auto respCb = [&](telux::common::ErrorCode errorCode) { deleteProfileCallback(errorCode); };
// Implement a callback method to get response for the delete profile request
void deleteProfileCallback(telux::common::ErrorCode error) {
if (error != ErrorCode::SUCCESS) {
std::cout << "deleteProfile failed with error" << static_cast<int>(error) << std::endl;
return;
}
std::cout << "deleteProfile succeeded." << std::endl;
}
// Delete profile on the eUICC.
status = simProfileManager->deleteProfile(SlotId::DEFAULT_SLOT_ID, profileId, respCb);
- 在 eUICC 上请求配置文件列表
auto respCb = [&](const std::vector<std::shared_ptr<telux::tel::SimProfile>> &profiles,
telux::common::ErrorCode errorCode) { profileListCallback(profiles, errorCode); };
// Implement a callback method to get response for the request profile list
void profileListCallback(const std::vector<std::shared_ptr<telux::tel::SimProfile>> &profiles,
telux::common::ErrorCode error) {
if (error != ErrorCode::SUCCESS) {
std::cout << "profileList failed with error" << static_cast<int>(error) << std::endl;
return;
}
std::cout << "profileList succeeded." << std::endl;
}
// Get profile list on the eUICC.
status = simProfileManager->requestProfileList(SlotId::DEFAULT_SLOT_ID, respCb);
- 在 eUICC 上启用/禁用配置文件
auto respCb = [&](telux::common::ErrorCode errorCode) { setProfileCallback(errorCode); };
// Implement a callback method to get response for the set profile request
void setProfileCallback(telux::common::ErrorCode error) {
if (error != ErrorCode::SUCCESS) {
std::cout << "setProfile failed with error" << static_cast<int>(error) << std::endl;
return;
}
std::cout << "setProfile succeeded." << std::endl;
}
// Enable/disable profile on the eUICC.
status = simProfileManager->setProfile(SlotId::DEFAULT_SLOT_ID, profileId, enable, respCb);
11.更新个人资料昵称
auto respCb = [&](telux::common::ErrorCode errorCode) { updateNicknameCallback(errorCode); };
// Implement a callback method to get response for update nickname request
void updateNicknameCallback(telux::common::ErrorCode error) {
if (error != ErrorCode::SUCCESS) {
std::cout << "updateNickname failed with error" << static_cast<int>(error) <<
std::endl;
return;
}
std::cout << "updateNickname succeeded." << std::endl;
}
// Update Nickname of the profile
status = simProfileManager->updateNickName(SlotId::DEFAULT_SLOT_ID, profileId, nickname, respCb);
- 在eUICC上设置SMDP+服务器地址
auto respCb = [&](telux::common::ErrorCode errorCode) { setServerAddressCallback(errorCode); };
// Implement a callback method to get response for set server addresss request
void setServerAddressCallback(telux::common::ErrorCode error) {
if (error != ErrorCode::SUCCESS) {
std::cout << "setServerAddress failed with error" << static_cast<int>(error) <<
std::endl;
return;
}
std::cout << "setServerAddress succeeded." << std::endl;
}
// Set SMDP server address on the eUICC
status = simProfileManager->setServerAddress(SlotId::DEFAULT_SLOT_ID, smdpAddress, respCb);
13.从eUICC获取SMDP+和SMDS服务器地址
auto respCb = [&](std::string smdpAddress,
std::string smdsAddress, telux::common::ErrorCode errorCode) {
requestServerAddressCallback(smdpAddress, smdsAddress, errorCode); };
// Implement a callback method to get response for the get server addresss request
void requestServerAddressCallback(std::string smdpAddress,
std::string smdsAddress, telux::common::ErrorCode error) {
if (error != ErrorCode::SUCCESS) {
std::cout << "requestServerAddress failed with error" << static_cast<int>(error) <<
std::endl;
return;
}
std::cout << "requestServerAddress succeeded." << std::endl;
}
// Get SMDP+ and SMDS server address on the eUICC
status = simProfileManager->requestServerAddress(SlotId::DEFAULT_SLOT_ID, respCb);
- eUICC 上的内存重置
auto respCb = [&](telux::common::ErrorCode errorCode) { memoryResetCallback(errorCode); };
// Implement a callback method to get response for the memory reset request
void memoryResetCallback(telux::common::ErrorCode error) {
if (error != ErrorCode::SUCCESS) {
std::cout << "memoryReset failed with error" << static_cast<int>(error) << std::endl;
return;
}
std::cout << "memoryReset succeeded." << std::endl;
}
// Memory reset on the eUICC
status = simProfileManager->memoryReset(SlotId::DEFAULT_SLOT_ID, resetmask, respCb);
4.3.16 远程 SIM 配置应用程序
TelSDK 提供了参考应用程序 rsp_httpd,它有助于探索远程配置 API 的各种功能。
SIM 配置文件管理操作(例如添加配置文件、删除配置文件、启用/禁用配置文件)需要与云进行 HTTP 交互,以将 eUICC 上的配置文件与 SMDP+/SMDS 服务器同步。当调制解调器 LPA/eUICC 需要到达云上的 SMDP+/SMDS 服务器进行 HTTP 事务时,HTTP 请求将发送到远程 SIM 配置服务,即在应用程序处理器上运行的 RSP HTTP 守护程序。RSP HTTP 守护程序代表调制解调器通过在云上运行的 SMDP+/SMDS 服务器执行这些 HTTP 事务。来自云的 HTTP 响应被发送回调制解调器 LPA/eUICC 以采取适当的操作。确保有互联网连接可用于使用 WLAN、WWAN 或以太网执行 HTTP 事务。
- 在设备上运行远程 SIM HTTP 守护程序
# rsp_httpd
使用 -h 选项检查所有支持的选项和使用说明。
4.4 数据
4.4.1 开始/停止蜂窝数据通话
此示例应用程序演示了如何启动或停止蜂窝数据呼叫。
- 实现初始化回调并获取DataFactory实例
可选地,可以通过获取管理器实例来提供初始化回调。当管理器初始化完成时,数据工厂将调用回调。
auto initCb = [&](telux::common::ServiceStatus status) {
std::lock_guard<std::mutex> lock(mtx);
status_ = status;
initCv.notify_all();
};
auto &dataFactory = DataFactory::getInstance();
- 获取DataConnectionManager实例
std::unique_lock<std::mutex> lck(mtx);
dataConnMgr = dataFactory.getDataConnectionManager(slotId, initCb);
3.等待DataConnectionManager初始化完成
initCv.wait(lck);
3.1 检查数据连接管理器初始化状态
如果DataConnectionManager初始化失败,可以通过调用步骤2来完成新的初始化尝试。如果DataConnectionManager初始化成功,则继续执行步骤4
if (status_ == telux::common::ServiceStatus::SERVICE_AVAILABLE) {
// Go to step 4
}
else {
//Go to step 2 for another initialization attempt
}
- 为startDatacall实现DataCallResponseCb回调
void startDataCallResponseCallBack(const std::shared_ptr<telux::data::IDataCall> &dataCall,
telux::common::ErrorCode error) {
std::cout<< "Received callback for startDataCall" << std::endl;
if(error == telux::common::ErrorCode::SUCCESS) {
std::cout<< "Request sent successfully" << std::endl;
} else {
std::cout<< "Request failed with errorCode: " << static_cast<int>(error) << std::endl;
}
}
- 发送带有配置文件 ID、IpFamily 类型以及所需回调方法的开始数据呼叫请求
dataConnectionManager->startDataCall(profileId, telux::data::IpFamilyType::IPV4V6,
startDataCallResponseCallBack);
- startDataCall 响应将调用响应回调
- 为stopDatacall实现DataCallResponseCb回调
void stopDataCallResponseCallBack(const std::shared_ptr<telux::data::IDataCall> &dataCall,
telux::common::ErrorCode error) {
std::cout << "Received callback for stopDataCall" << std::endl;
if(error == telux::common::ErrorCode::SUCCESS) {
std::cout << "Request sent successfully" << std::endl;
} else {
std::cout << "Request failed with errorCode: " << static_cast<int>(error) << std::endl;
}
- 发送带有配置文件 ID、IpFamily 类型以及所需回调方法的停止数据呼叫请求
dataConnectionManager->stopDataCall(profileId, telux::data::IpFamilyType::IPV4V6,
stopDataCallResponseCallBack);
现在,将为 stopDataCall 响应调用响应回调。
4.4.2 获取可用的调制解调器配置文件
此示例应用程序演示了如何请求可用调制解调器配置文件的列表。
- 实现初始化回调并获取DataFactory实例
可选地,可以通过获取管理器实例来提供初始化回调。当管理器初始化完成时,数据工厂将调用回调。
auto initCb = [&](telux::common::ServiceStatus status) {
std::lock_guard<std::mutex> lock(mtx);
status_ = status;
initCv.notify_all();
};
auto &dataFactory = DataFactory::getInstance();
- 获取DataProfileManager实例
std::unique_lock<std::mutex> lck(mtx);
auto dataProfileMgr = dataFactory.getDataProfileManager(slotId, initCb);
3.等待DataProfileManager初始化完成
initCv.wait(lck);
3.1 检查DataProfileManager初始化状态
如果DataProfileManager初始化失败,可以通过调用步骤2来完成新的初始化尝试。如果初始化成功,则继续执行步骤4
if (status == telux::common::ServiceStatus::SERVICE_AVAILABLE) {
// Go to step 4
}
else {
// Go to step 2 for another initialization attempt
}
4.实例化requestProfileList回调
auto dataProfileListCb_ = std::make_shared<DataProfileListCallback>();
4.1 实现IDataProfileListCallback接口来了解requestProfileList的状态
class DataProfileListCallback : public telux::common::IDataProfileListCallback {
virtual void onProfileListResponse(const std::vector<std::shared_ptr<DataProfile>> &profiles,
telux::common::ErrorCode error) override {
std::cout<<"Length of available profiles are "<<profiles.size()<<std::endl;
}
};
- 发送 requestProfileList 以及所需的回调方法
telux::common::Status status = dataProfileMgr->requestProfileList(dataProfileListCb_);
现在,接收 requestProfileList 请求的 DataProfileListCallback 响应。
4.4.3 获取/设置数据过滤模式
此示例应用程序演示了如何获取和设置数据过滤模式。
- 获取DataFactory、DataConnectionManager和DataFilterManager实例
auto &dataFactory = telux::data::DataFactory::getInstance();
auto dataConnMgr_ = dataFactory.getDataConnectionManager();
auto dataFilterMgr_ = dataFactory.getDataFilterManager();
2.等待数据连接管理器和数据过滤管理器子系统初始化
bool dataConnectionSubSystemStatus = dataConnMgr_->isSubsystemReady();
if (!dataConnectionSubSystemStatus) {
std::cout << "Data Connection Manager subsystem is not ready, Please wait" << std::endl;
std::future<bool> f = dataConnMgr_->onSubsystemReady();
// Wait unconditionally for data manager subsystem to be ready
dataConnectionSubSystemStatus = f.get();
}
// Exit the application, if SDK is unable to initialize data manager subsystems
if (!dataConnectionSubSystemStatus) {
std::cout << "ERROR - Unable to initialize subSystem" << std::endl;
return EXIT_FAILURE;
}
bool dataFilterSubSystemStatus = dataFilterMgr_->isReady();
if (!dataFilterSubSystemStatus) {
std::cout << "Data Filter Manager subsystem is not ready, Please wait" << std::endl;
std::future<bool> f = dataFilterMgr_->onReady();
// Wait unconditionally for data filter subsystem to be ready
dataFilterSubSystemStatus = f.get();
}
// Exit the application, if SDK is unable to initialize data manager subsystems
if (!dataFilterSubSystemStatus) {
std::cout << "ERROR - Unable to initialize subSystem" << std::endl;
return EXIT_FAILURE;
}
3.设置数据过滤模式为启用
std::promise<bool> p;
int profileId = 2;
telux::data::IpFamilyType ipFamilyType = telux::data::IpFamilyType::IPV4;
telux::data::DataRestrictMode enableMode;
enableMode.filterAutoExit = telux::data::DataRestrictModeType::DISABLE;
enableMode.filterMode = telux::data::DataRestrictModeType::ENABLE;
auto status = dataFilterMgr_->setDataRestrictMode(enableMode,
[&p](telux::common::ErrorCode error) {
if (error == telux::common::ErrorCode::SUCCESS) {
p.set_value(true);
} else {
std::cout << "Failed to set data filter mode" << std::endl;
p.set_value(false);
}
}, profileId, ipFamilyType);
if(status == telux::common::Status::SUCCESS) {
std::cout << "Set data filter mode Request sent" << std::endl;
} else {
std::cout << "Set data filter mode Request failed" << std::endl;
}
if (p.get_future().get()) {
std::cout << "Set data filter mode succeeded." << std::endl;
}
4.获取数据过滤模式
std::promise<bool> p;
std::string interfaceName = "rmnet_data0";
auto status = dataFilterMgr_->requestDataRestrictMode(interfaceName, configType_,
[&p](telux::data::DataRestrictMode mode, telux::common::ErrorCode error) {
if (error == telux::common::ErrorCode::SUCCESS) {
p.set_value(true);
if (mode.filterMode == DataRestrictModeType::DISABLE) {
std::cout << " DataRestrictMode Disabled" << std::endl;
} else if (mode.filterMode == DataRestrictModeType::ENABLE) {
std::cout << " DataRestrictMode Enabled" << std::endl;
} else {
std::cout << " Invalid DataRestrictMode" << std::endl;
}
} else {
std::cout << "Failed to get data filter mode" << std::endl;
p.set_value(false);
}
});
if(status == telux::common::Status::SUCCESS) {
std::cout << "Get data filter mode Request sent" << std::endl;
} else {
std::cout << "Get data filter mode Request failed" << std::endl;
}
if (p.get_future().get()) {
std::cout << "Get data filter mode succeeded." << std::endl;
}