blob: 77c2e615a9bc5696e84e20e1672d04775bad88a9 [file] [log] [blame]
/*
* Copyright (c) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "RILC"
#include <android/hardware/radio/1.1/IRadio.h>
#include <android/hardware/radio/1.1/IRadioResponse.h>
#include <android/hardware/radio/1.1/IRadioIndication.h>
#include <android/hardware/radio/1.1/types.h>
#include <android/hardware/radio/deprecated/1.0/IOemHook.h>
#include <hwbinder/IPCThreadState.h>
#include <hwbinder/ProcessState.h>
#include <telephony/ril.h>
#include <telephony/ril_mnc.h>
#include <telephony/ril_mcc.h>
#include <ril_service.h>
#include <hidl/HidlTransportSupport.h>
#include <utils/SystemClock.h>
#include <inttypes.h>
#define INVALID_HEX_CHAR 16
using namespace android::hardware::radio;
using namespace android::hardware::radio::V1_0;
using namespace android::hardware::radio::deprecated::V1_0;
using ::android::hardware::configureRpcThreadpool;
using ::android::hardware::joinRpcThreadpool;
using ::android::hardware::Return;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_array;
using ::android::hardware::Void;
using android::CommandInfo;
using android::RequestInfo;
using android::requestToString;
using android::sp;
#define BOOL_TO_INT(x) (x ? 1 : 0)
#define ATOI_NULL_HANDLED(x) (x ? atoi(x) : -1)
#define ATOI_NULL_HANDLED_DEF(x, defaultVal) (x ? atoi(x) : defaultVal)
#if defined(ANDROID_MULTI_SIM)
#define CALL_ONREQUEST(a, b, c, d, e) \
s_vendorFunctions->onRequest((a), (b), (c), (d), ((RIL_SOCKET_ID)(e)))
#define CALL_ONSTATEREQUEST(a) s_vendorFunctions->onStateRequest((RIL_SOCKET_ID)(a))
#else
#define CALL_ONREQUEST(a, b, c, d, e) s_vendorFunctions->onRequest((a), (b), (c), (d))
#define CALL_ONSTATEREQUEST(a) s_vendorFunctions->onStateRequest()
#endif
#ifdef OEM_HOOK_DISABLED
constexpr bool kOemHookEnabled = false;
#else
constexpr bool kOemHookEnabled = true;
#endif
RIL_RadioFunctions *s_vendorFunctions = NULL;
static CommandInfo *s_commands;
struct RadioImpl;
struct OemHookImpl;
#if (SIM_COUNT >= 2)
sp<RadioImpl> radioService[SIM_COUNT];
sp<OemHookImpl> oemHookService[SIM_COUNT];
int64_t nitzTimeReceived[SIM_COUNT];
// counter used for synchronization. It is incremented every time response callbacks are updated.
volatile int32_t mCounterRadio[SIM_COUNT];
volatile int32_t mCounterOemHook[SIM_COUNT];
#else
sp<RadioImpl> radioService[1];
sp<OemHookImpl> oemHookService[1];
int64_t nitzTimeReceived[1];
// counter used for synchronization. It is incremented every time response callbacks are updated.
volatile int32_t mCounterRadio[1];
volatile int32_t mCounterOemHook[1];
#endif
static pthread_rwlock_t radioServiceRwlock = PTHREAD_RWLOCK_INITIALIZER;
#if (SIM_COUNT >= 2)
static pthread_rwlock_t radioServiceRwlock2 = PTHREAD_RWLOCK_INITIALIZER;
#if (SIM_COUNT >= 3)
static pthread_rwlock_t radioServiceRwlock3 = PTHREAD_RWLOCK_INITIALIZER;
#if (SIM_COUNT >= 4)
static pthread_rwlock_t radioServiceRwlock4 = PTHREAD_RWLOCK_INITIALIZER;
#endif
#endif
#endif
void convertRilHardwareConfigListToHal(void *response, size_t responseLen,
hidl_vec<HardwareConfig>& records);
void convertRilRadioCapabilityToHal(void *response, size_t responseLen, RadioCapability& rc);
void convertRilLceDataInfoToHal(void *response, size_t responseLen, LceDataInfo& lce);
void convertRilSignalStrengthToHal(void *response, size_t responseLen,
SignalStrength& signalStrength);
void convertRilDataCallToHal(RIL_Data_Call_Response_v11 *dcResponse,
SetupDataCallResult& dcResult);
void convertRilDataCallListToHal(void *response, size_t responseLen,
hidl_vec<SetupDataCallResult>& dcResultList);
void convertRilCellInfoListToHal(void *response, size_t responseLen, hidl_vec<CellInfo>& records);
struct RadioImpl : public V1_1::IRadio {
int32_t mSlotId;
sp<IRadioResponse> mRadioResponse;
sp<IRadioIndication> mRadioIndication;
sp<V1_1::IRadioResponse> mRadioResponseV1_1;
sp<V1_1::IRadioIndication> mRadioIndicationV1_1;
Return<void> setResponseFunctions(
const ::android::sp<IRadioResponse>& radioResponse,
const ::android::sp<IRadioIndication>& radioIndication);
Return<void> getIccCardStatus(int32_t serial);
Return<void> supplyIccPinForApp(int32_t serial, const hidl_string& pin,
const hidl_string& aid);
Return<void> supplyIccPukForApp(int32_t serial, const hidl_string& puk,
const hidl_string& pin, const hidl_string& aid);
Return<void> supplyIccPin2ForApp(int32_t serial,
const hidl_string& pin2,
const hidl_string& aid);
Return<void> supplyIccPuk2ForApp(int32_t serial, const hidl_string& puk2,
const hidl_string& pin2, const hidl_string& aid);
Return<void> changeIccPinForApp(int32_t serial, const hidl_string& oldPin,
const hidl_string& newPin, const hidl_string& aid);
Return<void> changeIccPin2ForApp(int32_t serial, const hidl_string& oldPin2,
const hidl_string& newPin2, const hidl_string& aid);
Return<void> supplyNetworkDepersonalization(int32_t serial, const hidl_string& netPin);
Return<void> getCurrentCalls(int32_t serial);
Return<void> dial(int32_t serial, const Dial& dialInfo);
Return<void> getImsiForApp(int32_t serial,
const ::android::hardware::hidl_string& aid);
Return<void> hangup(int32_t serial, int32_t gsmIndex);
Return<void> hangupWaitingOrBackground(int32_t serial);
Return<void> hangupForegroundResumeBackground(int32_t serial);
Return<void> switchWaitingOrHoldingAndActive(int32_t serial);
Return<void> conference(int32_t serial);
Return<void> rejectCall(int32_t serial);
Return<void> getLastCallFailCause(int32_t serial);
Return<void> getSignalStrength(int32_t serial);
Return<void> getVoiceRegistrationState(int32_t serial);
Return<void> getDataRegistrationState(int32_t serial);
Return<void> getOperator(int32_t serial);
Return<void> setRadioPower(int32_t serial, bool on);
Return<void> sendDtmf(int32_t serial,
const ::android::hardware::hidl_string& s);
Return<void> sendSms(int32_t serial, const GsmSmsMessage& message);
Return<void> sendSMSExpectMore(int32_t serial, const GsmSmsMessage& message);
Return<void> setupDataCall(int32_t serial,
RadioTechnology radioTechnology,
const DataProfileInfo& profileInfo,
bool modemCognitive,
bool roamingAllowed,
bool isRoaming);
Return<void> iccIOForApp(int32_t serial,
const IccIo& iccIo);
Return<void> sendUssd(int32_t serial,
const ::android::hardware::hidl_string& ussd);
Return<void> cancelPendingUssd(int32_t serial);
Return<void> getClir(int32_t serial);
Return<void> setClir(int32_t serial, int32_t status);
Return<void> getCallForwardStatus(int32_t serial,
const CallForwardInfo& callInfo);
Return<void> setCallForward(int32_t serial,
const CallForwardInfo& callInfo);
Return<void> getCallWaiting(int32_t serial, int32_t serviceClass);
Return<void> setCallWaiting(int32_t serial, bool enable, int32_t serviceClass);
Return<void> acknowledgeLastIncomingGsmSms(int32_t serial,
bool success, SmsAcknowledgeFailCause cause);
Return<void> acceptCall(int32_t serial);
Return<void> deactivateDataCall(int32_t serial,
int32_t cid, bool reasonRadioShutDown);
Return<void> getFacilityLockForApp(int32_t serial,
const ::android::hardware::hidl_string& facility,
const ::android::hardware::hidl_string& password,
int32_t serviceClass,
const ::android::hardware::hidl_string& appId);
Return<void> setFacilityLockForApp(int32_t serial,
const ::android::hardware::hidl_string& facility,
bool lockState,
const ::android::hardware::hidl_string& password,
int32_t serviceClass,
const ::android::hardware::hidl_string& appId);
Return<void> setBarringPassword(int32_t serial,
const ::android::hardware::hidl_string& facility,
const ::android::hardware::hidl_string& oldPassword,
const ::android::hardware::hidl_string& newPassword);
Return<void> getNetworkSelectionMode(int32_t serial);
Return<void> setNetworkSelectionModeAutomatic(int32_t serial);
Return<void> setNetworkSelectionModeManual(int32_t serial,
const ::android::hardware::hidl_string& operatorNumeric);
Return<void> getAvailableNetworks(int32_t serial);
Return<void> startNetworkScan(int32_t serial, const V1_1::NetworkScanRequest& request);
Return<void> stopNetworkScan(int32_t serial);
Return<void> startDtmf(int32_t serial,
const ::android::hardware::hidl_string& s);
Return<void> stopDtmf(int32_t serial);
Return<void> getBasebandVersion(int32_t serial);
Return<void> separateConnection(int32_t serial, int32_t gsmIndex);
Return<void> setMute(int32_t serial, bool enable);
Return<void> getMute(int32_t serial);
Return<void> getClip(int32_t serial);
Return<void> getDataCallList(int32_t serial);
Return<void> setSuppServiceNotifications(int32_t serial, bool enable);
Return<void> writeSmsToSim(int32_t serial,
const SmsWriteArgs& smsWriteArgs);
Return<void> deleteSmsOnSim(int32_t serial, int32_t index);
Return<void> setBandMode(int32_t serial, RadioBandMode mode);
Return<void> getAvailableBandModes(int32_t serial);
Return<void> sendEnvelope(int32_t serial,
const ::android::hardware::hidl_string& command);
Return<void> sendTerminalResponseToSim(int32_t serial,
const ::android::hardware::hidl_string& commandResponse);
Return<void> handleStkCallSetupRequestFromSim(int32_t serial, bool accept);
Return<void> explicitCallTransfer(int32_t serial);
Return<void> setPreferredNetworkType(int32_t serial, PreferredNetworkType nwType);
Return<void> getPreferredNetworkType(int32_t serial);
Return<void> getNeighboringCids(int32_t serial);
Return<void> setLocationUpdates(int32_t serial, bool enable);
Return<void> setCdmaSubscriptionSource(int32_t serial,
CdmaSubscriptionSource cdmaSub);
Return<void> setCdmaRoamingPreference(int32_t serial, CdmaRoamingType type);
Return<void> getCdmaRoamingPreference(int32_t serial);
Return<void> setTTYMode(int32_t serial, TtyMode mode);
Return<void> getTTYMode(int32_t serial);
Return<void> setPreferredVoicePrivacy(int32_t serial, bool enable);
Return<void> getPreferredVoicePrivacy(int32_t serial);
Return<void> sendCDMAFeatureCode(int32_t serial,
const ::android::hardware::hidl_string& featureCode);
Return<void> sendBurstDtmf(int32_t serial,
const ::android::hardware::hidl_string& dtmf,
int32_t on,
int32_t off);
Return<void> sendCdmaSms(int32_t serial, const CdmaSmsMessage& sms);
Return<void> acknowledgeLastIncomingCdmaSms(int32_t serial,
const CdmaSmsAck& smsAck);
Return<void> getGsmBroadcastConfig(int32_t serial);
Return<void> setGsmBroadcastConfig(int32_t serial,
const hidl_vec<GsmBroadcastSmsConfigInfo>& configInfo);
Return<void> setGsmBroadcastActivation(int32_t serial, bool activate);
Return<void> getCdmaBroadcastConfig(int32_t serial);
Return<void> setCdmaBroadcastConfig(int32_t serial,
const hidl_vec<CdmaBroadcastSmsConfigInfo>& configInfo);
Return<void> setCdmaBroadcastActivation(int32_t serial, bool activate);
Return<void> getCDMASubscription(int32_t serial);
Return<void> writeSmsToRuim(int32_t serial, const CdmaSmsWriteArgs& cdmaSms);
Return<void> deleteSmsOnRuim(int32_t serial, int32_t index);
Return<void> getDeviceIdentity(int32_t serial);
Return<void> exitEmergencyCallbackMode(int32_t serial);
Return<void> getSmscAddress(int32_t serial);
Return<void> setSmscAddress(int32_t serial,
const ::android::hardware::hidl_string& smsc);
Return<void> reportSmsMemoryStatus(int32_t serial, bool available);
Return<void> reportStkServiceIsRunning(int32_t serial);
Return<void> getCdmaSubscriptionSource(int32_t serial);
Return<void> requestIsimAuthentication(int32_t serial,
const ::android::hardware::hidl_string& challenge);
Return<void> acknowledgeIncomingGsmSmsWithPdu(int32_t serial,
bool success,
const ::android::hardware::hidl_string& ackPdu);
Return<void> sendEnvelopeWithStatus(int32_t serial,
const ::android::hardware::hidl_string& contents);
Return<void> getVoiceRadioTechnology(int32_t serial);
Return<void> getCellInfoList(int32_t serial);
Return<void> setCellInfoListRate(int32_t serial, int32_t rate);
Return<void> setInitialAttachApn(int32_t serial, const DataProfileInfo& dataProfileInfo,
bool modemCognitive, bool isRoaming);
Return<void> getImsRegistrationState(int32_t serial);
Return<void> sendImsSms(int32_t serial, const ImsSmsMessage& message);
Return<void> iccTransmitApduBasicChannel(int32_t serial, const SimApdu& message);
Return<void> iccOpenLogicalChannel(int32_t serial,
const ::android::hardware::hidl_string& aid, int32_t p2);
Return<void> iccCloseLogicalChannel(int32_t serial, int32_t channelId);
Return<void> iccTransmitApduLogicalChannel(int32_t serial, const SimApdu& message);
Return<void> nvReadItem(int32_t serial, NvItem itemId);
Return<void> nvWriteItem(int32_t serial, const NvWriteItem& item);
Return<void> nvWriteCdmaPrl(int32_t serial,
const ::android::hardware::hidl_vec<uint8_t>& prl);
Return<void> nvResetConfig(int32_t serial, ResetNvType resetType);
Return<void> setUiccSubscription(int32_t serial, const SelectUiccSub& uiccSub);
Return<void> setDataAllowed(int32_t serial, bool allow);
Return<void> getHardwareConfig(int32_t serial);
Return<void> requestIccSimAuthentication(int32_t serial,
int32_t authContext,
const ::android::hardware::hidl_string& authData,
const ::android::hardware::hidl_string& aid);
Return<void> setDataProfile(int32_t serial,
const ::android::hardware::hidl_vec<DataProfileInfo>& profiles, bool isRoaming);
Return<void> requestShutdown(int32_t serial);
Return<void> getRadioCapability(int32_t serial);
Return<void> setRadioCapability(int32_t serial, const RadioCapability& rc);
Return<void> startLceService(int32_t serial, int32_t reportInterval, bool pullMode);
Return<void> stopLceService(int32_t serial);
Return<void> pullLceData(int32_t serial);
Return<void> getModemActivityInfo(int32_t serial);
Return<void> setAllowedCarriers(int32_t serial,
bool allAllowed,
const CarrierRestrictions& carriers);
Return<void> getAllowedCarriers(int32_t serial);
Return<void> sendDeviceState(int32_t serial, DeviceStateType deviceStateType, bool state);
Return<void> setIndicationFilter(int32_t serial, int32_t indicationFilter);
Return<void> startKeepalive(int32_t serial, const V1_1::KeepaliveRequest& keepalive);
Return<void> stopKeepalive(int32_t serial, int32_t sessionHandle);
Return<void> setSimCardPower(int32_t serial, bool powerUp);
Return<void> setSimCardPower_1_1(int32_t serial,
const V1_1::CardPowerState state);
Return<void> responseAcknowledgement();
Return<void> setCarrierInfoForImsiEncryption(int32_t serial,
const V1_1::ImsiEncryptionInfo& message);
void checkReturnStatus(Return<void>& ret);
};
struct OemHookImpl : public IOemHook {
int32_t mSlotId;
sp<IOemHookResponse> mOemHookResponse;
sp<IOemHookIndication> mOemHookIndication;
Return<void> setResponseFunctions(
const ::android::sp<IOemHookResponse>& oemHookResponse,
const ::android::sp<IOemHookIndication>& oemHookIndication);
Return<void> sendRequestRaw(int32_t serial,
const ::android::hardware::hidl_vec<uint8_t>& data);
Return<void> sendRequestStrings(int32_t serial,
const ::android::hardware::hidl_vec<::android::hardware::hidl_string>& data);
};
void memsetAndFreeStrings(int numPointers, ...) {
va_list ap;
va_start(ap, numPointers);
for (int i = 0; i < numPointers; i++) {
char *ptr = va_arg(ap, char *);
if (ptr) {
#ifdef MEMSET_FREED
#define MAX_STRING_LENGTH 4096
memset(ptr, 0, strnlen(ptr, MAX_STRING_LENGTH));
#endif
free(ptr);
}
}
va_end(ap);
}
void sendErrorResponse(RequestInfo *pRI, RIL_Errno err) {
pRI->pCI->responseFunction((int) pRI->socket_id,
(int) RadioResponseType::SOLICITED, pRI->token, err, NULL, 0);
}
/**
* Copies over src to dest. If memory allocation fails, responseFunction() is called for the
* request with error RIL_E_NO_MEMORY. The size() method is used to determine the size of the
* destination buffer into which the HIDL string is copied. If there is a discrepancy between
* the string length reported by the size() method, and the length of the string returned by
* the c_str() method, the function will return false indicating a failure.
*
* Returns true on success, and false on failure.
*/
bool copyHidlStringToRil(char **dest, const hidl_string &src, RequestInfo *pRI, bool allowEmpty) {
size_t len = src.size();
if (len == 0 && !allowEmpty) {
*dest = NULL;
return true;
}
*dest = (char *) calloc(len + 1, sizeof(char));
if (*dest == NULL) {
RLOGE("Memory allocation failed for request %s", requestToString(pRI->pCI->requestNumber));
sendErrorResponse(pRI, RIL_E_NO_MEMORY);
return false;
}
if (strlcpy(*dest, src.c_str(), len + 1) >= (len + 1)) {
RLOGE("Copy of the HIDL string has been truncated, as "
"the string length reported by size() does not "
"match the length of string returned by c_str().");
free(*dest);
*dest = NULL;
sendErrorResponse(pRI, RIL_E_INTERNAL_ERR);
return false;
}
return true;
}
bool copyHidlStringToRil(char **dest, const hidl_string &src, RequestInfo *pRI) {
return copyHidlStringToRil(dest, src, pRI, false);
}
hidl_string convertCharPtrToHidlString(const char *ptr) {
hidl_string ret;
if (ptr != NULL) {
// TODO: replace this with strnlen
ret.setToExternal(ptr, strlen(ptr));
}
return ret;
}
bool dispatchVoid(int serial, int slotId, int request) {
RequestInfo *pRI = android::addRequestToList(serial, slotId, request);
if (pRI == NULL) {
return false;
}
CALL_ONREQUEST(request, NULL, 0, pRI, slotId);
return true;
}
bool dispatchString(int serial, int slotId, int request, const char * str) {
RequestInfo *pRI = android::addRequestToList(serial, slotId, request);
if (pRI == NULL) {
return false;
}
char *pString;
if (!copyHidlStringToRil(&pString, str, pRI)) {
return false;
}
CALL_ONREQUEST(request, pString, sizeof(char *), pRI, slotId);
memsetAndFreeStrings(1, pString);
return true;
}
bool dispatchStrings(int serial, int slotId, int request, bool allowEmpty, int countStrings, ...) {
RequestInfo *pRI = android::addRequestToList(serial, slotId, request);
if (pRI == NULL) {
return false;
}
char **pStrings;
pStrings = (char **)calloc(countStrings, sizeof(char *));
if (pStrings == NULL) {
RLOGE("Memory allocation failed for request %s", requestToString(request));
sendErrorResponse(pRI, RIL_E_NO_MEMORY);
return false;
}
va_list ap;
va_start(ap, countStrings);
for (int i = 0; i < countStrings; i++) {
const char* str = va_arg(ap, const char *);
if (!copyHidlStringToRil(&pStrings[i], hidl_string(str), pRI, allowEmpty)) {
va_end(ap);
for (int j = 0; j < i; j++) {
memsetAndFreeStrings(1, pStrings[j]);
}
free(pStrings);
return false;
}
}
va_end(ap);
CALL_ONREQUEST(request, pStrings, countStrings * sizeof(char *), pRI, slotId);
if (pStrings != NULL) {
for (int i = 0 ; i < countStrings ; i++) {
memsetAndFreeStrings(1, pStrings[i]);
}
#ifdef MEMSET_FREED
memset(pStrings, 0, countStrings * sizeof(char *));
#endif
free(pStrings);
}
return true;
}
bool dispatchStrings(int serial, int slotId, int request, const hidl_vec<hidl_string>& data) {
RequestInfo *pRI = android::addRequestToList(serial, slotId, request);
if (pRI == NULL) {
return false;
}
int countStrings = data.size();
char **pStrings;
pStrings = (char **)calloc(countStrings, sizeof(char *));
if (pStrings == NULL) {
RLOGE("Memory allocation failed for request %s", requestToString(request));
sendErrorResponse(pRI, RIL_E_NO_MEMORY);
return false;
}
for (int i = 0; i < countStrings; i++) {
if (!copyHidlStringToRil(&pStrings[i], data[i], pRI)) {
for (int j = 0; j < i; j++) {
memsetAndFreeStrings(1, pStrings[j]);
}
free(pStrings);
return false;
}
}
CALL_ONREQUEST(request, pStrings, countStrings * sizeof(char *), pRI, slotId);
if (pStrings != NULL) {
for (int i = 0 ; i < countStrings ; i++) {
memsetAndFreeStrings(1, pStrings[i]);
}
#ifdef MEMSET_FREED
memset(pStrings, 0, countStrings * sizeof(char *));
#endif
free(pStrings);
}
return true;
}
bool dispatchInts(int serial, int slotId, int request, int countInts, ...) {
RequestInfo *pRI = android::addRequestToList(serial, slotId, request);
if (pRI == NULL) {
return false;
}
int *pInts = (int *)calloc(countInts, sizeof(int));
if (pInts == NULL) {
RLOGE("Memory allocation failed for request %s", requestToString(request));
sendErrorResponse(pRI, RIL_E_NO_MEMORY);
return false;
}
va_list ap;
va_start(ap, countInts);
for (int i = 0; i < countInts; i++) {
pInts[i] = va_arg(ap, int);
}
va_end(ap);
CALL_ONREQUEST(request, pInts, countInts * sizeof(int), pRI, slotId);
if (pInts != NULL) {
#ifdef MEMSET_FREED
memset(pInts, 0, countInts * sizeof(int));
#endif
free(pInts);
}
return true;
}
bool dispatchCallForwardStatus(int serial, int slotId, int request,
const CallForwardInfo& callInfo) {
RequestInfo *pRI = android::addRequestToList(serial, slotId, request);
if (pRI == NULL) {
return false;
}
RIL_CallForwardInfo cf;
cf.status = (int) callInfo.status;
cf.reason = callInfo.reason;
cf.serviceClass = callInfo.serviceClass;
cf.toa = callInfo.toa;
cf.timeSeconds = callInfo.timeSeconds;
if (!copyHidlStringToRil(&cf.number, callInfo.number, pRI)) {
return false;
}
CALL_ONREQUEST(request, &cf, sizeof(cf), pRI, slotId);
memsetAndFreeStrings(1, cf.number);
return true;
}
bool dispatchRaw(int serial, int slotId, int request, const hidl_vec<uint8_t>& rawBytes) {
RequestInfo *pRI = android::addRequestToList(serial, slotId, request);
if (pRI == NULL) {
return false;
}
const uint8_t *uData = rawBytes.data();
CALL_ONREQUEST(request, (void *) uData, rawBytes.size(), pRI, slotId);
return true;
}
bool dispatchIccApdu(int serial, int slotId, int request, const SimApdu& message) {
RequestInfo *pRI = android::addRequestToList(serial, slotId, request);
if (pRI == NULL) {
return false;
}
RIL_SIM_APDU apdu = {};
apdu.sessionid = message.sessionId;
apdu.cla = message.cla;
apdu.instruction = message.instruction;
apdu.p1 = message.p1;
apdu.p2 = message.p2;
apdu.p3 = message.p3;
if (!copyHidlStringToRil(&apdu.data, message.data, pRI)) {
return false;
}
CALL_ONREQUEST(request, &apdu, sizeof(apdu), pRI, slotId);
memsetAndFreeStrings(1, apdu.data);
return true;
}
void checkReturnStatus(int32_t slotId, Return<void>& ret, bool isRadioService) {
if (ret.isOk() == false) {
RLOGE("checkReturnStatus: unable to call response/indication callback");
// Remote process hosting the callbacks must be dead. Reset the callback objects;
// there's no other recovery to be done here. When the client process is back up, it will
// call setResponseFunctions()
// Caller should already hold rdlock, release that first
// note the current counter to avoid overwriting updates made by another thread before
// write lock is acquired.
int counter = isRadioService ? mCounterRadio[slotId] : mCounterOemHook[slotId];
pthread_rwlock_t *radioServiceRwlockPtr = radio::getRadioServiceRwlock(slotId);
int ret = pthread_rwlock_unlock(radioServiceRwlockPtr);
assert(ret == 0);
// acquire wrlock
ret = pthread_rwlock_wrlock(radioServiceRwlockPtr);
assert(ret == 0);
// make sure the counter value has not changed
if (counter == (isRadioService ? mCounterRadio[slotId] : mCounterOemHook[slotId])) {
if (isRadioService) {
radioService[slotId]->mRadioResponse = NULL;
radioService[slotId]->mRadioIndication = NULL;
radioService[slotId]->mRadioResponseV1_1 = NULL;
radioService[slotId]->mRadioIndicationV1_1 = NULL;
} else {
oemHookService[slotId]->mOemHookResponse = NULL;
oemHookService[slotId]->mOemHookIndication = NULL;
}
isRadioService ? mCounterRadio[slotId]++ : mCounterOemHook[slotId]++;
} else {
RLOGE("checkReturnStatus: not resetting responseFunctions as they likely "
"got updated on another thread");
}
// release wrlock
ret = pthread_rwlock_unlock(radioServiceRwlockPtr);
assert(ret == 0);
// Reacquire rdlock
ret = pthread_rwlock_rdlock(radioServiceRwlockPtr);
assert(ret == 0);
}
}
void RadioImpl::checkReturnStatus(Return<void>& ret) {
::checkReturnStatus(mSlotId, ret, true);
}
Return<void> RadioImpl::setResponseFunctions(
const ::android::sp<IRadioResponse>& radioResponseParam,
const ::android::sp<IRadioIndication>& radioIndicationParam) {
RLOGD("setResponseFunctions");
pthread_rwlock_t *radioServiceRwlockPtr = radio::getRadioServiceRwlock(mSlotId);
int ret = pthread_rwlock_wrlock(radioServiceRwlockPtr);
assert(ret == 0);
mRadioResponse = radioResponseParam;
mRadioIndication = radioIndicationParam;
mRadioResponseV1_1 = V1_1::IRadioResponse::castFrom(mRadioResponse).withDefault(nullptr);
mRadioIndicationV1_1 = V1_1::IRadioIndication::castFrom(mRadioIndication).withDefault(nullptr);
if (mRadioResponseV1_1 == nullptr || mRadioIndicationV1_1 == nullptr) {
mRadioResponseV1_1 = nullptr;
mRadioIndicationV1_1 = nullptr;
}
mCounterRadio[mSlotId]++;
ret = pthread_rwlock_unlock(radioServiceRwlockPtr);
assert(ret == 0);
// client is connected. Send initial indications.
android::onNewCommandConnect((RIL_SOCKET_ID) mSlotId);
return Void();
}
Return<void> RadioImpl::getIccCardStatus(int32_t serial) {
#if VDBG
RLOGD("getIccCardStatus: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_SIM_STATUS);
return Void();
}
Return<void> RadioImpl::supplyIccPinForApp(int32_t serial, const hidl_string& pin,
const hidl_string& aid) {
#if VDBG
RLOGD("supplyIccPinForApp: serial %d", serial);
#endif
dispatchStrings(serial, mSlotId, RIL_REQUEST_ENTER_SIM_PIN, true,
2, pin.c_str(), aid.c_str());
return Void();
}
Return<void> RadioImpl::supplyIccPukForApp(int32_t serial, const hidl_string& puk,
const hidl_string& pin, const hidl_string& aid) {
#if VDBG
RLOGD("supplyIccPukForApp: serial %d", serial);
#endif
dispatchStrings(serial, mSlotId, RIL_REQUEST_ENTER_SIM_PUK, true,
3, puk.c_str(), pin.c_str(), aid.c_str());
return Void();
}
Return<void> RadioImpl::supplyIccPin2ForApp(int32_t serial, const hidl_string& pin2,
const hidl_string& aid) {
#if VDBG
RLOGD("supplyIccPin2ForApp: serial %d", serial);
#endif
dispatchStrings(serial, mSlotId, RIL_REQUEST_ENTER_SIM_PIN2, true,
2, pin2.c_str(), aid.c_str());
return Void();
}
Return<void> RadioImpl::supplyIccPuk2ForApp(int32_t serial, const hidl_string& puk2,
const hidl_string& pin2, const hidl_string& aid) {
#if VDBG
RLOGD("supplyIccPuk2ForApp: serial %d", serial);
#endif
dispatchStrings(serial, mSlotId, RIL_REQUEST_ENTER_SIM_PUK2, true,
3, puk2.c_str(), pin2.c_str(), aid.c_str());
return Void();
}
Return<void> RadioImpl::changeIccPinForApp(int32_t serial, const hidl_string& oldPin,
const hidl_string& newPin, const hidl_string& aid) {
#if VDBG
RLOGD("changeIccPinForApp: serial %d", serial);
#endif
dispatchStrings(serial, mSlotId, RIL_REQUEST_CHANGE_SIM_PIN, true,
3, oldPin.c_str(), newPin.c_str(), aid.c_str());
return Void();
}
Return<void> RadioImpl::changeIccPin2ForApp(int32_t serial, const hidl_string& oldPin2,
const hidl_string& newPin2, const hidl_string& aid) {
#if VDBG
RLOGD("changeIccPin2ForApp: serial %d", serial);
#endif
dispatchStrings(serial, mSlotId, RIL_REQUEST_CHANGE_SIM_PIN2, true,
3, oldPin2.c_str(), newPin2.c_str(), aid.c_str());
return Void();
}
Return<void> RadioImpl::supplyNetworkDepersonalization(int32_t serial,
const hidl_string& netPin) {
#if VDBG
RLOGD("supplyNetworkDepersonalization: serial %d", serial);
#endif
dispatchStrings(serial, mSlotId, RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION, true,
1, netPin.c_str());
return Void();
}
Return<void> RadioImpl::getCurrentCalls(int32_t serial) {
#if VDBG
RLOGD("getCurrentCalls: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_CURRENT_CALLS);
return Void();
}
Return<void> RadioImpl::dial(int32_t serial, const Dial& dialInfo) {
#if VDBG
RLOGD("dial: serial %d", serial);
#endif
RequestInfo *pRI = android::addRequestToList(serial, mSlotId, RIL_REQUEST_DIAL);
if (pRI == NULL) {
return Void();
}
RIL_Dial dial = {};
RIL_UUS_Info uusInfo = {};
int32_t sizeOfDial = sizeof(dial);
if (!copyHidlStringToRil(&dial.address, dialInfo.address, pRI)) {
return Void();
}
dial.clir = (int) dialInfo.clir;
if (dialInfo.uusInfo.size() != 0) {
uusInfo.uusType = (RIL_UUS_Type) dialInfo.uusInfo[0].uusType;
uusInfo.uusDcs = (RIL_UUS_DCS) dialInfo.uusInfo[0].uusDcs;
if (dialInfo.uusInfo[0].uusData.size() == 0) {
uusInfo.uusData = NULL;
uusInfo.uusLength = 0;
} else {
if (!copyHidlStringToRil(&uusInfo.uusData, dialInfo.uusInfo[0].uusData, pRI)) {
memsetAndFreeStrings(1, dial.address);
return Void();
}
uusInfo.uusLength = dialInfo.uusInfo[0].uusData.size();
}
dial.uusInfo = &uusInfo;
}
CALL_ONREQUEST(RIL_REQUEST_DIAL, &dial, sizeOfDial, pRI, mSlotId);
memsetAndFreeStrings(2, dial.address, uusInfo.uusData);
return Void();
}
Return<void> RadioImpl::getImsiForApp(int32_t serial, const hidl_string& aid) {
#if VDBG
RLOGD("getImsiForApp: serial %d", serial);
#endif
dispatchStrings(serial, mSlotId, RIL_REQUEST_GET_IMSI, false,
1, aid.c_str());
return Void();
}
Return<void> RadioImpl::hangup(int32_t serial, int32_t gsmIndex) {
#if VDBG
RLOGD("hangup: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_HANGUP, 1, gsmIndex);
return Void();
}
Return<void> RadioImpl::hangupWaitingOrBackground(int32_t serial) {
#if VDBG
RLOGD("hangupWaitingOrBackground: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND);
return Void();
}
Return<void> RadioImpl::hangupForegroundResumeBackground(int32_t serial) {
#if VDBG
RLOGD("hangupForegroundResumeBackground: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND);
return Void();
}
Return<void> RadioImpl::switchWaitingOrHoldingAndActive(int32_t serial) {
#if VDBG
RLOGD("switchWaitingOrHoldingAndActive: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE);
return Void();
}
Return<void> RadioImpl::conference(int32_t serial) {
#if VDBG
RLOGD("conference: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_CONFERENCE);
return Void();
}
Return<void> RadioImpl::rejectCall(int32_t serial) {
#if VDBG
RLOGD("rejectCall: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_UDUB);
return Void();
}
Return<void> RadioImpl::getLastCallFailCause(int32_t serial) {
#if VDBG
RLOGD("getLastCallFailCause: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_LAST_CALL_FAIL_CAUSE);
return Void();
}
Return<void> RadioImpl::getSignalStrength(int32_t serial) {
#if VDBG
RLOGD("getSignalStrength: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_SIGNAL_STRENGTH);
return Void();
}
Return<void> RadioImpl::getVoiceRegistrationState(int32_t serial) {
#if VDBG
RLOGD("getVoiceRegistrationState: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_VOICE_REGISTRATION_STATE);
return Void();
}
Return<void> RadioImpl::getDataRegistrationState(int32_t serial) {
#if VDBG
RLOGD("getDataRegistrationState: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_DATA_REGISTRATION_STATE);
return Void();
}
Return<void> RadioImpl::getOperator(int32_t serial) {
#if VDBG
RLOGD("getOperator: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_OPERATOR);
return Void();
}
Return<void> RadioImpl::setRadioPower(int32_t serial, bool on) {
RLOGD("setRadioPower: serial %d on %d", serial, on);
dispatchInts(serial, mSlotId, RIL_REQUEST_RADIO_POWER, 1, BOOL_TO_INT(on));
return Void();
}
Return<void> RadioImpl::sendDtmf(int32_t serial, const hidl_string& s) {
#if VDBG
RLOGD("sendDtmf: serial %d", serial);
#endif
dispatchString(serial, mSlotId, RIL_REQUEST_DTMF, s.c_str());
return Void();
}
Return<void> RadioImpl::sendSms(int32_t serial, const GsmSmsMessage& message) {
#if VDBG
RLOGD("sendSms: serial %d", serial);
#endif
dispatchStrings(serial, mSlotId, RIL_REQUEST_SEND_SMS, false,
2, message.smscPdu.c_str(), message.pdu.c_str());
return Void();
}
Return<void> RadioImpl::sendSMSExpectMore(int32_t serial, const GsmSmsMessage& message) {
#if VDBG
RLOGD("sendSMSExpectMore: serial %d", serial);
#endif
dispatchStrings(serial, mSlotId, RIL_REQUEST_SEND_SMS_EXPECT_MORE, false,
2, message.smscPdu.c_str(), message.pdu.c_str());
return Void();
}
static bool convertMvnoTypeToString(MvnoType type, char *&str) {
switch (type) {
case MvnoType::IMSI:
str = (char *)"imsi";
return true;
case MvnoType::GID:
str = (char *)"gid";
return true;
case MvnoType::SPN:
str = (char *)"spn";
return true;
case MvnoType::NONE:
str = (char *)"";
return true;
}
return false;
}
Return<void> RadioImpl::setupDataCall(int32_t serial, RadioTechnology radioTechnology,
const DataProfileInfo& dataProfileInfo, bool modemCognitive,
bool roamingAllowed, bool isRoaming) {
#if VDBG
RLOGD("setupDataCall: serial %d", serial);
#endif
if (s_vendorFunctions->version >= 4 && s_vendorFunctions->version <= 14) {
const hidl_string &protocol =
(isRoaming ? dataProfileInfo.roamingProtocol : dataProfileInfo.protocol);
dispatchStrings(serial, mSlotId, RIL_REQUEST_SETUP_DATA_CALL, true, 7,
std::to_string((int) radioTechnology + 2).c_str(),
std::to_string((int) dataProfileInfo.profileId).c_str(),
dataProfileInfo.apn.c_str(),
dataProfileInfo.user.c_str(),
dataProfileInfo.password.c_str(),
std::to_string((int) dataProfileInfo.authType).c_str(),
protocol.c_str());
} else if (s_vendorFunctions->version >= 15) {
char *mvnoTypeStr = NULL;
if (!convertMvnoTypeToString(dataProfileInfo.mvnoType, mvnoTypeStr)) {
RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
RIL_REQUEST_SETUP_DATA_CALL);
if (pRI != NULL) {
sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
}
return Void();
}
dispatchStrings(serial, mSlotId, RIL_REQUEST_SETUP_DATA_CALL, true, 15,
std::to_string((int) radioTechnology + 2).c_str(),
std::to_string((int) dataProfileInfo.profileId).c_str(),
dataProfileInfo.apn.c_str(),
dataProfileInfo.user.c_str(),
dataProfileInfo.password.c_str(),
std::to_string((int) dataProfileInfo.authType).c_str(),
dataProfileInfo.protocol.c_str(),
dataProfileInfo.roamingProtocol.c_str(),
std::to_string(dataProfileInfo.supportedApnTypesBitmap).c_str(),
std::to_string(dataProfileInfo.bearerBitmap).c_str(),
modemCognitive ? "1" : "0",
std::to_string(dataProfileInfo.mtu).c_str(),
mvnoTypeStr,
dataProfileInfo.mvnoMatchData.c_str(),
roamingAllowed ? "1" : "0");
} else {
RLOGE("Unsupported RIL version %d, min version expected 4", s_vendorFunctions->version);
RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
RIL_REQUEST_SETUP_DATA_CALL);
if (pRI != NULL) {
sendErrorResponse(pRI, RIL_E_REQUEST_NOT_SUPPORTED);
}
}
return Void();
}
Return<void> RadioImpl::iccIOForApp(int32_t serial, const IccIo& iccIo) {
#if VDBG
RLOGD("iccIOForApp: serial %d", serial);
#endif
RequestInfo *pRI = android::addRequestToList(serial, mSlotId, RIL_REQUEST_SIM_IO);
if (pRI == NULL) {
return Void();
}
RIL_SIM_IO_v6 rilIccIo = {};
rilIccIo.command = iccIo.command;
rilIccIo.fileid = iccIo.fileId;
if (!copyHidlStringToRil(&rilIccIo.path, iccIo.path, pRI)) {
return Void();
}
rilIccIo.p1 = iccIo.p1;
rilIccIo.p2 = iccIo.p2;
rilIccIo.p3 = iccIo.p3;
if (!copyHidlStringToRil(&rilIccIo.data, iccIo.data, pRI)) {
memsetAndFreeStrings(1, rilIccIo.path);
return Void();
}
if (!copyHidlStringToRil(&rilIccIo.pin2, iccIo.pin2, pRI)) {
memsetAndFreeStrings(2, rilIccIo.path, rilIccIo.data);
return Void();
}
if (!copyHidlStringToRil(&rilIccIo.aidPtr, iccIo.aid, pRI)) {
memsetAndFreeStrings(3, rilIccIo.path, rilIccIo.data, rilIccIo.pin2);
return Void();
}
CALL_ONREQUEST(RIL_REQUEST_SIM_IO, &rilIccIo, sizeof(rilIccIo), pRI, mSlotId);
memsetAndFreeStrings(4, rilIccIo.path, rilIccIo.data, rilIccIo.pin2, rilIccIo.aidPtr);
return Void();
}
Return<void> RadioImpl::sendUssd(int32_t serial, const hidl_string& ussd) {
#if VDBG
RLOGD("sendUssd: serial %d", serial);
#endif
dispatchString(serial, mSlotId, RIL_REQUEST_SEND_USSD, ussd.c_str());
return Void();
}
Return<void> RadioImpl::cancelPendingUssd(int32_t serial) {
#if VDBG
RLOGD("cancelPendingUssd: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_CANCEL_USSD);
return Void();
}
Return<void> RadioImpl::getClir(int32_t serial) {
#if VDBG
RLOGD("getClir: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_CLIR);
return Void();
}
Return<void> RadioImpl::setClir(int32_t serial, int32_t status) {
#if VDBG
RLOGD("setClir: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_SET_CLIR, 1, status);
return Void();
}
Return<void> RadioImpl::getCallForwardStatus(int32_t serial, const CallForwardInfo& callInfo) {
#if VDBG
RLOGD("getCallForwardStatus: serial %d", serial);
#endif
dispatchCallForwardStatus(serial, mSlotId, RIL_REQUEST_QUERY_CALL_FORWARD_STATUS,
callInfo);
return Void();
}
Return<void> RadioImpl::setCallForward(int32_t serial, const CallForwardInfo& callInfo) {
#if VDBG
RLOGD("setCallForward: serial %d", serial);
#endif
dispatchCallForwardStatus(serial, mSlotId, RIL_REQUEST_SET_CALL_FORWARD,
callInfo);
return Void();
}
Return<void> RadioImpl::getCallWaiting(int32_t serial, int32_t serviceClass) {
#if VDBG
RLOGD("getCallWaiting: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_QUERY_CALL_WAITING, 1, serviceClass);
return Void();
}
Return<void> RadioImpl::setCallWaiting(int32_t serial, bool enable, int32_t serviceClass) {
#if VDBG
RLOGD("setCallWaiting: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_SET_CALL_WAITING, 2, BOOL_TO_INT(enable),
serviceClass);
return Void();
}
Return<void> RadioImpl::acknowledgeLastIncomingGsmSms(int32_t serial,
bool success, SmsAcknowledgeFailCause cause) {
#if VDBG
RLOGD("acknowledgeLastIncomingGsmSms: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_SMS_ACKNOWLEDGE, 2, BOOL_TO_INT(success),
cause);
return Void();
}
Return<void> RadioImpl::acceptCall(int32_t serial) {
#if VDBG
RLOGD("acceptCall: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_ANSWER);
return Void();
}
Return<void> RadioImpl::deactivateDataCall(int32_t serial,
int32_t cid, bool reasonRadioShutDown) {
#if VDBG
RLOGD("deactivateDataCall: serial %d", serial);
#endif
dispatchStrings(serial, mSlotId, RIL_REQUEST_DEACTIVATE_DATA_CALL, false,
2, (std::to_string(cid)).c_str(), reasonRadioShutDown ? "1" : "0");
return Void();
}
Return<void> RadioImpl::getFacilityLockForApp(int32_t serial, const hidl_string& facility,
const hidl_string& password, int32_t serviceClass,
const hidl_string& appId) {
#if VDBG
RLOGD("getFacilityLockForApp: serial %d", serial);
#endif
dispatchStrings(serial, mSlotId, RIL_REQUEST_QUERY_FACILITY_LOCK, true,
4, facility.c_str(), password.c_str(),
(std::to_string(serviceClass)).c_str(), appId.c_str());
return Void();
}
Return<void> RadioImpl::setFacilityLockForApp(int32_t serial, const hidl_string& facility,
bool lockState, const hidl_string& password,
int32_t serviceClass, const hidl_string& appId) {
#if VDBG
RLOGD("setFacilityLockForApp: serial %d", serial);
#endif
dispatchStrings(serial, mSlotId, RIL_REQUEST_SET_FACILITY_LOCK, true,
5, facility.c_str(), lockState ? "1" : "0", password.c_str(),
(std::to_string(serviceClass)).c_str(), appId.c_str() );
return Void();
}
Return<void> RadioImpl::setBarringPassword(int32_t serial, const hidl_string& facility,
const hidl_string& oldPassword,
const hidl_string& newPassword) {
#if VDBG
RLOGD("setBarringPassword: serial %d", serial);
#endif
dispatchStrings(serial, mSlotId, RIL_REQUEST_CHANGE_BARRING_PASSWORD, true,
3, facility.c_str(), oldPassword.c_str(), newPassword.c_str());
return Void();
}
Return<void> RadioImpl::getNetworkSelectionMode(int32_t serial) {
#if VDBG
RLOGD("getNetworkSelectionMode: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE);
return Void();
}
Return<void> RadioImpl::setNetworkSelectionModeAutomatic(int32_t serial) {
#if VDBG
RLOGD("setNetworkSelectionModeAutomatic: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC);
return Void();
}
Return<void> RadioImpl::setNetworkSelectionModeManual(int32_t serial,
const hidl_string& operatorNumeric) {
#if VDBG
RLOGD("setNetworkSelectionModeManual: serial %d", serial);
#endif
dispatchString(serial, mSlotId, RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL,
operatorNumeric.c_str());
return Void();
}
Return<void> RadioImpl::getAvailableNetworks(int32_t serial) {
#if VDBG
RLOGD("getAvailableNetworks: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_QUERY_AVAILABLE_NETWORKS);
return Void();
}
Return<void> RadioImpl::startNetworkScan(int32_t serial, const V1_1::NetworkScanRequest& request) {
#if VDBG
RLOGD("startNetworkScan: serial %d", serial);
#endif
RequestInfo *pRI = android::addRequestToList(serial, mSlotId, RIL_REQUEST_START_NETWORK_SCAN);
if (pRI == NULL) {
return Void();
}
if (request.specifiers.size() > MAX_RADIO_ACCESS_NETWORKS) {
sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
return Void();
}
RIL_NetworkScanRequest scan_request = {};
scan_request.type = (RIL_ScanType) request.type;
scan_request.interval = request.interval;
scan_request.specifiers_length = request.specifiers.size();
for (size_t i = 0; i < request.specifiers.size(); ++i) {
if (request.specifiers[i].geranBands.size() > MAX_BANDS ||
request.specifiers[i].utranBands.size() > MAX_BANDS ||
request.specifiers[i].eutranBands.size() > MAX_BANDS ||
request.specifiers[i].channels.size() > MAX_CHANNELS) {
sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
return Void();
}
const V1_1::RadioAccessSpecifier& ras_from =
request.specifiers[i];
RIL_RadioAccessSpecifier& ras_to = scan_request.specifiers[i];
ras_to.radio_access_network = (RIL_RadioAccessNetworks) ras_from.radioAccessNetwork;
ras_to.channels_length = ras_from.channels.size();
std::copy(ras_from.channels.begin(), ras_from.channels.end(), ras_to.channels);
const std::vector<uint32_t> * bands = nullptr;
switch (request.specifiers[i].radioAccessNetwork) {
case V1_1::RadioAccessNetworks::GERAN:
ras_to.bands_length = ras_from.geranBands.size();
bands = (std::vector<uint32_t> *) &ras_from.geranBands;
break;
case V1_1::RadioAccessNetworks::UTRAN:
ras_to.bands_length = ras_from.utranBands.size();
bands = (std::vector<uint32_t> *) &ras_from.utranBands;
break;
case V1_1::RadioAccessNetworks::EUTRAN:
ras_to.bands_length = ras_from.eutranBands.size();
bands = (std::vector<uint32_t> *) &ras_from.eutranBands;
break;
default:
sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
return Void();
}
// safe to copy to geran_bands because it's a union member
for (size_t idx = 0; idx < ras_to.bands_length; ++idx) {
ras_to.bands.geran_bands[idx] = (RIL_GeranBands) (*bands)[idx];
}
}
CALL_ONREQUEST(RIL_REQUEST_START_NETWORK_SCAN, &scan_request, sizeof(scan_request), pRI,
mSlotId);
return Void();
}
Return<void> RadioImpl::stopNetworkScan(int32_t serial) {
#if VDBG
RLOGD("stopNetworkScan: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_STOP_NETWORK_SCAN);
return Void();
}
Return<void> RadioImpl::startDtmf(int32_t serial, const hidl_string& s) {
#if VDBG
RLOGD("startDtmf: serial %d", serial);
#endif
dispatchString(serial, mSlotId, RIL_REQUEST_DTMF_START,
s.c_str());
return Void();
}
Return<void> RadioImpl::stopDtmf(int32_t serial) {
#if VDBG
RLOGD("stopDtmf: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_DTMF_STOP);
return Void();
}
Return<void> RadioImpl::getBasebandVersion(int32_t serial) {
#if VDBG
RLOGD("getBasebandVersion: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_BASEBAND_VERSION);
return Void();
}
Return<void> RadioImpl::separateConnection(int32_t serial, int32_t gsmIndex) {
#if VDBG
RLOGD("separateConnection: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_SEPARATE_CONNECTION, 1, gsmIndex);
return Void();
}
Return<void> RadioImpl::setMute(int32_t serial, bool enable) {
#if VDBG
RLOGD("setMute: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_SET_MUTE, 1, BOOL_TO_INT(enable));
return Void();
}
Return<void> RadioImpl::getMute(int32_t serial) {
#if VDBG
RLOGD("getMute: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_MUTE);
return Void();
}
Return<void> RadioImpl::getClip(int32_t serial) {
#if VDBG
RLOGD("getClip: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_QUERY_CLIP);
return Void();
}
Return<void> RadioImpl::getDataCallList(int32_t serial) {
#if VDBG
RLOGD("getDataCallList: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_DATA_CALL_LIST);
return Void();
}
Return<void> RadioImpl::setSuppServiceNotifications(int32_t serial, bool enable) {
#if VDBG
RLOGD("setSuppServiceNotifications: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION, 1,
BOOL_TO_INT(enable));
return Void();
}
Return<void> RadioImpl::writeSmsToSim(int32_t serial, const SmsWriteArgs& smsWriteArgs) {
#if VDBG
RLOGD("writeSmsToSim: serial %d", serial);
#endif
RequestInfo *pRI = android::addRequestToList(serial, mSlotId, RIL_REQUEST_WRITE_SMS_TO_SIM);
if (pRI == NULL) {
return Void();
}
RIL_SMS_WriteArgs args;
args.status = (int) smsWriteArgs.status;
if (!copyHidlStringToRil(&args.pdu, smsWriteArgs.pdu, pRI)) {
return Void();
}
if (!copyHidlStringToRil(&args.smsc, smsWriteArgs.smsc, pRI)) {
memsetAndFreeStrings(1, args.pdu);
return Void();
}
CALL_ONREQUEST(RIL_REQUEST_WRITE_SMS_TO_SIM, &args, sizeof(args), pRI, mSlotId);
memsetAndFreeStrings(2, args.smsc, args.pdu);
return Void();
}
Return<void> RadioImpl::deleteSmsOnSim(int32_t serial, int32_t index) {
#if VDBG
RLOGD("deleteSmsOnSim: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_DELETE_SMS_ON_SIM, 1, index);
return Void();
}
Return<void> RadioImpl::setBandMode(int32_t serial, RadioBandMode mode) {
#if VDBG
RLOGD("setBandMode: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_SET_BAND_MODE, 1, mode);
return Void();
}
Return<void> RadioImpl::getAvailableBandModes(int32_t serial) {
#if VDBG
RLOGD("getAvailableBandModes: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE);
return Void();
}
Return<void> RadioImpl::sendEnvelope(int32_t serial, const hidl_string& command) {
#if VDBG
RLOGD("sendEnvelope: serial %d", serial);
#endif
dispatchString(serial, mSlotId, RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND,
command.c_str());
return Void();
}
Return<void> RadioImpl::sendTerminalResponseToSim(int32_t serial,
const hidl_string& commandResponse) {
#if VDBG
RLOGD("sendTerminalResponseToSim: serial %d", serial);
#endif
dispatchString(serial, mSlotId, RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE,
commandResponse.c_str());
return Void();
}
Return<void> RadioImpl::handleStkCallSetupRequestFromSim(int32_t serial, bool accept) {
#if VDBG
RLOGD("handleStkCallSetupRequestFromSim: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM,
1, BOOL_TO_INT(accept));
return Void();
}
Return<void> RadioImpl::explicitCallTransfer(int32_t serial) {
#if VDBG
RLOGD("explicitCallTransfer: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_EXPLICIT_CALL_TRANSFER);
return Void();
}
Return<void> RadioImpl::setPreferredNetworkType(int32_t serial, PreferredNetworkType nwType) {
#if VDBG
RLOGD("setPreferredNetworkType: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, 1, nwType);
return Void();
}
Return<void> RadioImpl::getPreferredNetworkType(int32_t serial) {
#if VDBG
RLOGD("getPreferredNetworkType: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE);
return Void();
}
Return<void> RadioImpl::getNeighboringCids(int32_t serial) {
#if VDBG
RLOGD("getNeighboringCids: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_NEIGHBORING_CELL_IDS);
return Void();
}
Return<void> RadioImpl::setLocationUpdates(int32_t serial, bool enable) {
#if VDBG
RLOGD("setLocationUpdates: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_SET_LOCATION_UPDATES, 1, BOOL_TO_INT(enable));
return Void();
}
Return<void> RadioImpl::setCdmaSubscriptionSource(int32_t serial, CdmaSubscriptionSource cdmaSub) {
#if VDBG
RLOGD("setCdmaSubscriptionSource: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE, 1, cdmaSub);
return Void();
}
Return<void> RadioImpl::setCdmaRoamingPreference(int32_t serial, CdmaRoamingType type) {
#if VDBG
RLOGD("setCdmaRoamingPreference: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE, 1, type);
return Void();
}
Return<void> RadioImpl::getCdmaRoamingPreference(int32_t serial) {
#if VDBG
RLOGD("getCdmaRoamingPreference: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE);
return Void();
}
Return<void> RadioImpl::setTTYMode(int32_t serial, TtyMode mode) {
#if VDBG
RLOGD("setTTYMode: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_SET_TTY_MODE, 1, mode);
return Void();
}
Return<void> RadioImpl::getTTYMode(int32_t serial) {
#if VDBG
RLOGD("getTTYMode: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_QUERY_TTY_MODE);
return Void();
}
Return<void> RadioImpl::setPreferredVoicePrivacy(int32_t serial, bool enable) {
#if VDBG
RLOGD("setPreferredVoicePrivacy: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE,
1, BOOL_TO_INT(enable));
return Void();
}
Return<void> RadioImpl::getPreferredVoicePrivacy(int32_t serial) {
#if VDBG
RLOGD("getPreferredVoicePrivacy: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE);
return Void();
}
Return<void> RadioImpl::sendCDMAFeatureCode(int32_t serial, const hidl_string& featureCode) {
#if VDBG
RLOGD("sendCDMAFeatureCode: serial %d", serial);
#endif
dispatchString(serial, mSlotId, RIL_REQUEST_CDMA_FLASH,
featureCode.c_str());
return Void();
}
Return<void> RadioImpl::sendBurstDtmf(int32_t serial, const hidl_string& dtmf, int32_t on,
int32_t off) {
#if VDBG
RLOGD("sendBurstDtmf: serial %d", serial);
#endif
dispatchStrings(serial, mSlotId, RIL_REQUEST_CDMA_BURST_DTMF, false,
3, dtmf.c_str(), (std::to_string(on)).c_str(),
(std::to_string(off)).c_str());
return Void();
}
void constructCdmaSms(RIL_CDMA_SMS_Message &rcsm, const CdmaSmsMessage& sms) {
rcsm.uTeleserviceID = sms.teleserviceId;
rcsm.bIsServicePresent = BOOL_TO_INT(sms.isServicePresent);
rcsm.uServicecategory = sms.serviceCategory;
rcsm.sAddress.digit_mode = (RIL_CDMA_SMS_DigitMode) sms.address.digitMode;
rcsm.sAddress.number_mode = (RIL_CDMA_SMS_NumberMode) sms.address.numberMode;
rcsm.sAddress.number_type = (RIL_CDMA_SMS_NumberType) sms.address.numberType;
rcsm.sAddress.number_plan = (RIL_CDMA_SMS_NumberPlan) sms.address.numberPlan;
rcsm.sAddress.number_of_digits = sms.address.digits.size();
int digitLimit= MIN((rcsm.sAddress.number_of_digits), RIL_CDMA_SMS_ADDRESS_MAX);
for (int i = 0; i < digitLimit; i++) {
rcsm.sAddress.digits[i] = sms.address.digits[i];
}
rcsm.sSubAddress.subaddressType = (RIL_CDMA_SMS_SubaddressType) sms.subAddress.subaddressType;
rcsm.sSubAddress.odd = BOOL_TO_INT(sms.subAddress.odd);
rcsm.sSubAddress.number_of_digits = sms.subAddress.digits.size();
digitLimit= MIN((rcsm.sSubAddress.number_of_digits), RIL_CDMA_SMS_SUBADDRESS_MAX);
for (int i = 0; i < digitLimit; i++) {
rcsm.sSubAddress.digits[i] = sms.subAddress.digits[i];
}
rcsm.uBearerDataLen = sms.bearerData.size();
digitLimit= MIN((rcsm.uBearerDataLen), RIL_CDMA_SMS_BEARER_DATA_MAX);
for (int i = 0; i < digitLimit; i++) {
rcsm.aBearerData[i] = sms.bearerData[i];
}
}
Return<void> RadioImpl::sendCdmaSms(int32_t serial, const CdmaSmsMessage& sms) {
#if VDBG
RLOGD("sendCdmaSms: serial %d", serial);
#endif
RequestInfo *pRI = android::addRequestToList(serial, mSlotId, RIL_REQUEST_CDMA_SEND_SMS);
if (pRI == NULL) {
return Void();
}
RIL_CDMA_SMS_Message rcsm = {};
constructCdmaSms(rcsm, sms);
CALL_ONREQUEST(pRI->pCI->requestNumber, &rcsm, sizeof(rcsm), pRI, mSlotId);
return Void();
}
Return<void> RadioImpl::acknowledgeLastIncomingCdmaSms(int32_t serial, const CdmaSmsAck& smsAck) {
#if VDBG
RLOGD("acknowledgeLastIncomingCdmaSms: serial %d", serial);
#endif
RequestInfo *pRI = android::addRequestToList(serial, mSlotId, RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE);
if (pRI == NULL) {
return Void();
}
RIL_CDMA_SMS_Ack rcsa = {};
rcsa.uErrorClass = (RIL_CDMA_SMS_ErrorClass) smsAck.errorClass;
rcsa.uSMSCauseCode = smsAck.smsCauseCode;
CALL_ONREQUEST(pRI->pCI->requestNumber, &rcsa, sizeof(rcsa), pRI, mSlotId);
return Void();
}
Return<void> RadioImpl::getGsmBroadcastConfig(int32_t serial) {
#if VDBG
RLOGD("getGsmBroadcastConfig: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG);
return Void();
}
Return<void> RadioImpl::setGsmBroadcastConfig(int32_t serial,
const hidl_vec<GsmBroadcastSmsConfigInfo>&
configInfo) {
#if VDBG
RLOGD("setGsmBroadcastConfig: serial %d", serial);
#endif
RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG);
if (pRI == NULL) {
return Void();
}
uint32_t num = configInfo.size();
if (num > MAX_BROADCAST_SMS_CONFIG_INFO) {
RLOGE("setGsmBroadcastConfig: Invalid configInfo length %s",
requestToString(pRI->pCI->requestNumber));
sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
return Void();
}
auto gsmBci = new RIL_GSM_BroadcastSmsConfigInfo[num];
if (gsmBci == nullptr) {
sendErrorResponse(pRI, RIL_E_NO_MEMORY);
return Void();
}
std::vector<RIL_GSM_BroadcastSmsConfigInfo*> gsmBciPtrs(num);
for (uint32_t i = 0 ; i < num ; i++ ) {
gsmBciPtrs[i] = &gsmBci[i];
gsmBci[i].fromServiceId = configInfo[i].fromServiceId;
gsmBci[i].toServiceId = configInfo[i].toServiceId;
gsmBci[i].fromCodeScheme = configInfo[i].fromCodeScheme;
gsmBci[i].toCodeScheme = configInfo[i].toCodeScheme;
gsmBci[i].selected = BOOL_TO_INT(configInfo[i].selected);
}
CALL_ONREQUEST(pRI->pCI->requestNumber, gsmBciPtrs.data(),
num * sizeof(RIL_GSM_BroadcastSmsConfigInfo *), pRI, mSlotId);
delete []gsmBci;
return Void();
}
Return<void> RadioImpl::setGsmBroadcastActivation(int32_t serial, bool activate) {
#if VDBG
RLOGD("setGsmBroadcastActivation: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_GSM_SMS_BROADCAST_ACTIVATION,
1, BOOL_TO_INT(!activate));
return Void();
}
Return<void> RadioImpl::getCdmaBroadcastConfig(int32_t serial) {
#if VDBG
RLOGD("getCdmaBroadcastConfig: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_CDMA_GET_BROADCAST_SMS_CONFIG);
return Void();
}
Return<void> RadioImpl::setCdmaBroadcastConfig(int32_t serial,
const hidl_vec<CdmaBroadcastSmsConfigInfo>&
configInfo) {
#if VDBG
RLOGD("setCdmaBroadcastConfig: serial %d", serial);
#endif
RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
RIL_REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG);
if (pRI == NULL) {
return Void();
}
uint32_t num = configInfo.size();
if (num > MAX_BROADCAST_SMS_CONFIG_INFO) {
RLOGE("setCdmaBroadcastConfig: Invalid configInfo length %s",
requestToString(pRI->pCI->requestNumber));
sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
return Void();
}
auto cdmaBci = new RIL_CDMA_BroadcastSmsConfigInfo[num];
if (cdmaBci == nullptr) {
sendErrorResponse(pRI, RIL_E_NO_MEMORY);
return Void();
}
std::vector<RIL_CDMA_BroadcastSmsConfigInfo*> cdmaBciPtrs(num);
for (uint32_t i = 0 ; i < num ; i++ ) {
cdmaBciPtrs[i] = &cdmaBci[i];
cdmaBci[i].service_category = configInfo[i].serviceCategory;
cdmaBci[i].language = configInfo[i].language;
cdmaBci[i].selected = BOOL_TO_INT(configInfo[i].selected);
}
CALL_ONREQUEST(pRI->pCI->requestNumber, cdmaBciPtrs.data(),
num * sizeof(RIL_CDMA_BroadcastSmsConfigInfo *), pRI, mSlotId);
delete []cdmaBci;
return Void();
}
Return<void> RadioImpl::setCdmaBroadcastActivation(int32_t serial, bool activate) {
#if VDBG
RLOGD("setCdmaBroadcastActivation: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_CDMA_SMS_BROADCAST_ACTIVATION,
1, BOOL_TO_INT(!activate));
return Void();
}
Return<void> RadioImpl::getCDMASubscription(int32_t serial) {
#if VDBG
RLOGD("getCDMASubscription: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_CDMA_SUBSCRIPTION);
return Void();
}
Return<void> RadioImpl::writeSmsToRuim(int32_t serial, const CdmaSmsWriteArgs& cdmaSms) {
#if VDBG
RLOGD("writeSmsToRuim: serial %d", serial);
#endif
RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM);
if (pRI == NULL) {
return Void();
}
RIL_CDMA_SMS_WriteArgs rcsw = {};
rcsw.status = (int) cdmaSms.status;
constructCdmaSms(rcsw.message, cdmaSms.message);
CALL_ONREQUEST(pRI->pCI->requestNumber, &rcsw, sizeof(rcsw), pRI, mSlotId);
return Void();
}
Return<void> RadioImpl::deleteSmsOnRuim(int32_t serial, int32_t index) {
#if VDBG
RLOGD("deleteSmsOnRuim: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM, 1, index);
return Void();
}
Return<void> RadioImpl::getDeviceIdentity(int32_t serial) {
#if VDBG
RLOGD("getDeviceIdentity: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_DEVICE_IDENTITY);
return Void();
}
Return<void> RadioImpl::exitEmergencyCallbackMode(int32_t serial) {
#if VDBG
RLOGD("exitEmergencyCallbackMode: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE);
return Void();
}
Return<void> RadioImpl::getSmscAddress(int32_t serial) {
#if VDBG
RLOGD("getSmscAddress: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_SMSC_ADDRESS);
return Void();
}
Return<void> RadioImpl::setSmscAddress(int32_t serial, const hidl_string& smsc) {
#if VDBG
RLOGD("setSmscAddress: serial %d", serial);
#endif
dispatchString(serial, mSlotId, RIL_REQUEST_SET_SMSC_ADDRESS,
smsc.c_str());
return Void();
}
Return<void> RadioImpl::reportSmsMemoryStatus(int32_t serial, bool available) {
#if VDBG
RLOGD("reportSmsMemoryStatus: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_REPORT_SMS_MEMORY_STATUS, 1,
BOOL_TO_INT(available));
return Void();
}
Return<void> RadioImpl::reportStkServiceIsRunning(int32_t serial) {
#if VDBG
RLOGD("reportStkServiceIsRunning: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING);
return Void();
}
Return<void> RadioImpl::getCdmaSubscriptionSource(int32_t serial) {
#if VDBG
RLOGD("getCdmaSubscriptionSource: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE);
return Void();
}
Return<void> RadioImpl::requestIsimAuthentication(int32_t serial, const hidl_string& challenge) {
#if VDBG
RLOGD("requestIsimAuthentication: serial %d", serial);
#endif
dispatchString(serial, mSlotId, RIL_REQUEST_ISIM_AUTHENTICATION,
challenge.c_str());
return Void();
}
Return<void> RadioImpl::acknowledgeIncomingGsmSmsWithPdu(int32_t serial, bool success,
const hidl_string& ackPdu) {
#if VDBG
RLOGD("acknowledgeIncomingGsmSmsWithPdu: serial %d", serial);
#endif
dispatchStrings(serial, mSlotId, RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU, false,
2, success ? "1" : "0", ackPdu.c_str());
return Void();
}
Return<void> RadioImpl::sendEnvelopeWithStatus(int32_t serial, const hidl_string& contents) {
#if VDBG
RLOGD("sendEnvelopeWithStatus: serial %d", serial);
#endif
dispatchString(serial, mSlotId, RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS,
contents.c_str());
return Void();
}
Return<void> RadioImpl::getVoiceRadioTechnology(int32_t serial) {
#if VDBG
RLOGD("getVoiceRadioTechnology: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_VOICE_RADIO_TECH);
return Void();
}
Return<void> RadioImpl::getCellInfoList(int32_t serial) {
#if VDBG
RLOGD("getCellInfoList: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_CELL_INFO_LIST);
return Void();
}
Return<void> RadioImpl::setCellInfoListRate(int32_t serial, int32_t rate) {
#if VDBG
RLOGD("setCellInfoListRate: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE, 1, rate);
return Void();
}
Return<void> RadioImpl::setInitialAttachApn(int32_t serial, const DataProfileInfo& dataProfileInfo,
bool modemCognitive, bool isRoaming) {
#if VDBG
RLOGD("setInitialAttachApn: serial %d", serial);
#endif
RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
RIL_REQUEST_SET_INITIAL_ATTACH_APN);
if (pRI == NULL) {
return Void();
}
if (s_vendorFunctions->version <= 14) {
RIL_InitialAttachApn iaa = {};
if (!copyHidlStringToRil(&iaa.apn, dataProfileInfo.apn, pRI, true)) {
return Void();
}
const hidl_string &protocol =
(isRoaming ? dataProfileInfo.roamingProtocol : dataProfileInfo.protocol);
if (!copyHidlStringToRil(&iaa.protocol, protocol, pRI)) {
memsetAndFreeStrings(1, iaa.apn);
return Void();
}
iaa.authtype = (int) dataProfileInfo.authType;
if (!copyHidlStringToRil(&iaa.username, dataProfileInfo.user, pRI)) {
memsetAndFreeStrings(2, iaa.apn, iaa.protocol);
return Void();
}
if (!copyHidlStringToRil(&iaa.password, dataProfileInfo.password, pRI)) {
memsetAndFreeStrings(3, iaa.apn, iaa.protocol, iaa.username);
return Void();
}
CALL_ONREQUEST(RIL_REQUEST_SET_INITIAL_ATTACH_APN, &iaa, sizeof(iaa), pRI, mSlotId);
memsetAndFreeStrings(4, iaa.apn, iaa.protocol, iaa.username, iaa.password);
} else {
RIL_InitialAttachApn_v15 iaa = {};
if (!copyHidlStringToRil(&iaa.apn, dataProfileInfo.apn, pRI, true)) {
return Void();
}
if (!copyHidlStringToRil(&iaa.protocol, dataProfileInfo.protocol, pRI)) {
memsetAndFreeStrings(1, iaa.apn);
return Void();
}
if (!copyHidlStringToRil(&iaa.roamingProtocol, dataProfileInfo.roamingProtocol, pRI)) {
memsetAndFreeStrings(2, iaa.apn, iaa.protocol);
return Void();
}
iaa.authtype = (int) dataProfileInfo.authType;
if (!copyHidlStringToRil(&iaa.username, dataProfileInfo.user, pRI)) {
memsetAndFreeStrings(3, iaa.apn, iaa.protocol, iaa.roamingProtocol);
return Void();
}
if (!copyHidlStringToRil(&iaa.password, dataProfileInfo.password, pRI)) {
memsetAndFreeStrings(4, iaa.apn, iaa.protocol, iaa.roamingProtocol, iaa.username);
return Void();
}
iaa.supportedTypesBitmask = dataProfileInfo.supportedApnTypesBitmap;
iaa.bearerBitmask = dataProfileInfo.bearerBitmap;
iaa.modemCognitive = BOOL_TO_INT(modemCognitive);
iaa.mtu = dataProfileInfo.mtu;
if (!convertMvnoTypeToString(dataProfileInfo.mvnoType, iaa.mvnoType)) {
sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
memsetAndFreeStrings(5, iaa.apn, iaa.protocol, iaa.roamingProtocol, iaa.username,
iaa.password);
return Void();
}
if (!copyHidlStringToRil(&iaa.mvnoMatchData, dataProfileInfo.mvnoMatchData, pRI)) {
memsetAndFreeStrings(5, iaa.apn, iaa.protocol, iaa.roamingProtocol, iaa.username,
iaa.password);
return Void();
}
CALL_ONREQUEST(RIL_REQUEST_SET_INITIAL_ATTACH_APN, &iaa, sizeof(iaa), pRI, mSlotId);
memsetAndFreeStrings(6, iaa.apn, iaa.protocol, iaa.roamingProtocol, iaa.username,
iaa.password, iaa.mvnoMatchData);
}
return Void();
}
Return<void> RadioImpl::getImsRegistrationState(int32_t serial) {
#if VDBG
RLOGD("getImsRegistrationState: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_IMS_REGISTRATION_STATE);
return Void();
}
bool dispatchImsGsmSms(const ImsSmsMessage& message, RequestInfo *pRI) {
RIL_IMS_SMS_Message rism = {};
char **pStrings;
int countStrings = 2;
int dataLen = sizeof(char *) * countStrings;
rism.tech = RADIO_TECH_3GPP;
rism.retry = BOOL_TO_INT(message.retry);
rism.messageRef = message.messageRef;
if (message.gsmMessage.size() != 1) {
RLOGE("dispatchImsGsmSms: Invalid len %s", requestToString(pRI->pCI->requestNumber));
sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
return false;
}
pStrings = (char **)calloc(countStrings, sizeof(char *));
if (pStrings == NULL) {
RLOGE("dispatchImsGsmSms: Memory allocation failed for request %s",
requestToString(pRI->pCI->requestNumber));
sendErrorResponse(pRI, RIL_E_NO_MEMORY);
return false;
}
if (!copyHidlStringToRil(&pStrings[0], message.gsmMessage[0].smscPdu, pRI)) {
#ifdef MEMSET_FREED
memset(pStrings, 0, dataLen);
#endif
free(pStrings);
return false;
}
if (!copyHidlStringToRil(&pStrings[1], message.gsmMessage[0].pdu, pRI)) {
memsetAndFreeStrings(1, pStrings[0]);
#ifdef MEMSET_FREED
memset(pStrings, 0, dataLen);
#endif
free(pStrings);
return false;
}
rism.message.gsmMessage = pStrings;
CALL_ONREQUEST(pRI->pCI->requestNumber, &rism, sizeof(RIL_RadioTechnologyFamily) +
sizeof(uint8_t) + sizeof(int32_t) + dataLen, pRI, pRI->socket_id);
for (int i = 0 ; i < countStrings ; i++) {
memsetAndFreeStrings(1, pStrings[i]);
}
#ifdef MEMSET_FREED
memset(pStrings, 0, dataLen);
#endif
free(pStrings);
return true;
}
struct ImsCdmaSms {
RIL_IMS_SMS_Message imsSms;
RIL_CDMA_SMS_Message cdmaSms;
};
bool dispatchImsCdmaSms(const ImsSmsMessage& message, RequestInfo *pRI) {
ImsCdmaSms temp = {};
if (message.cdmaMessage.size() != 1) {
RLOGE("dispatchImsCdmaSms: Invalid len %s", requestToString(pRI->pCI->requestNumber));
sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
return false;
}
temp.imsSms.tech = RADIO_TECH_3GPP2;
temp.imsSms.retry = BOOL_TO_INT(message.retry);
temp.imsSms.messageRef = message.messageRef;
temp.imsSms.message.cdmaMessage = &temp.cdmaSms;
constructCdmaSms(temp.cdmaSms, message.cdmaMessage[0]);
// Vendor code expects payload length to include actual msg payload
// (sizeof(RIL_CDMA_SMS_Message)) instead of (RIL_CDMA_SMS_Message *) + size of other fields in
// RIL_IMS_SMS_Message
int payloadLen = sizeof(RIL_RadioTechnologyFamily) + sizeof(uint8_t) + sizeof(int32_t)
+ sizeof(RIL_CDMA_SMS_Message);
CALL_ONREQUEST(pRI->pCI->requestNumber, &temp.imsSms, payloadLen, pRI, pRI->socket_id);
return true;
}
Return<void> RadioImpl::sendImsSms(int32_t serial, const ImsSmsMessage& message) {
#if VDBG
RLOGD("sendImsSms: serial %d", serial);
#endif
RequestInfo *pRI = android::addRequestToList(serial, mSlotId, RIL_REQUEST_IMS_SEND_SMS);
if (pRI == NULL) {
return Void();
}
if (RadioTechnologyFamily::THREE_GPP == message.tech) {
dispatchImsGsmSms(message, pRI);
} else if (RadioTechnologyFamily::THREE_GPP2 == message.tech) {
dispatchImsCdmaSms(message, pRI);
} else {
RLOGE("sendImsSms: Invalid radio tech %s",
requestToString(pRI->pCI->requestNumber));
sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
}
return Void();
}
Return<void> RadioImpl::iccTransmitApduBasicChannel(int32_t serial, const SimApdu& message) {
#if VDBG
RLOGD("iccTransmitApduBasicChannel: serial %d", serial);
#endif
dispatchIccApdu(serial, mSlotId, RIL_REQUEST_SIM_TRANSMIT_APDU_BASIC, message);
return Void();
}
Return<void> RadioImpl::iccOpenLogicalChannel(int32_t serial, const hidl_string& aid, int32_t p2) {
#if VDBG
RLOGD("iccOpenLogicalChannel: serial %d", serial);
#endif
if (s_vendorFunctions->version < 15) {
dispatchString(serial, mSlotId, RIL_REQUEST_SIM_OPEN_CHANNEL, aid.c_str());
} else {
RequestInfo *pRI = android::addRequestToList(serial, mSlotId, RIL_REQUEST_SIM_OPEN_CHANNEL);
if (pRI == NULL) {
return Void();
}
RIL_OpenChannelParams params = {};
params.p2 = p2;
if (!copyHidlStringToRil(&params.aidPtr, aid, pRI)) {
return Void();
}
CALL_ONREQUEST(pRI->pCI->requestNumber, &params, sizeof(params), pRI, mSlotId);
memsetAndFreeStrings(1, params.aidPtr);
}
return Void();
}
Return<void> RadioImpl::iccCloseLogicalChannel(int32_t serial, int32_t channelId) {
#if VDBG
RLOGD("iccCloseLogicalChannel: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_SIM_CLOSE_CHANNEL, 1, channelId);
return Void();
}
Return<void> RadioImpl::iccTransmitApduLogicalChannel(int32_t serial, const SimApdu& message) {
#if VDBG
RLOGD("iccTransmitApduLogicalChannel: serial %d", serial);
#endif
dispatchIccApdu(serial, mSlotId, RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL, message);
return Void();
}
Return<void> RadioImpl::nvReadItem(int32_t serial, NvItem itemId) {
#if VDBG
RLOGD("nvReadItem: serial %d", serial);
#endif
RequestInfo *pRI = android::addRequestToList(serial, mSlotId, RIL_REQUEST_NV_READ_ITEM);
if (pRI == NULL) {
return Void();
}
RIL_NV_ReadItem nvri = {};
nvri.itemID = (RIL_NV_Item) itemId;
CALL_ONREQUEST(pRI->pCI->requestNumber, &nvri, sizeof(nvri), pRI, mSlotId);
return Void();
}
Return<void> RadioImpl::nvWriteItem(int32_t serial, const NvWriteItem& item) {
#if VDBG
RLOGD("nvWriteItem: serial %d", serial);
#endif
RequestInfo *pRI = android::addRequestToList(serial, mSlotId, RIL_REQUEST_NV_WRITE_ITEM);
if (pRI == NULL) {
return Void();
}
RIL_NV_WriteItem nvwi = {};
nvwi.itemID = (RIL_NV_Item) item.itemId;
if (!copyHidlStringToRil(&nvwi.value, item.value, pRI)) {
return Void();
}
CALL_ONREQUEST(pRI->pCI->requestNumber, &nvwi, sizeof(nvwi), pRI, mSlotId);
memsetAndFreeStrings(1, nvwi.value);
return Void();
}
Return<void> RadioImpl::nvWriteCdmaPrl(int32_t serial, const hidl_vec<uint8_t>& prl) {
#if VDBG
RLOGD("nvWriteCdmaPrl: serial %d", serial);
#endif
dispatchRaw(serial, mSlotId, RIL_REQUEST_NV_WRITE_CDMA_PRL, prl);
return Void();
}
Return<void> RadioImpl::nvResetConfig(int32_t serial, ResetNvType resetType) {
int rilResetType = -1;
#if VDBG
RLOGD("nvResetConfig: serial %d", serial);
#endif
/* Convert ResetNvType to RIL.h values
* RIL_REQUEST_NV_RESET_CONFIG
* 1 - reload all NV items
* 2 - erase NV reset (SCRTN)
* 3 - factory reset (RTN)
*/
switch(resetType) {
case ResetNvType::RELOAD:
rilResetType = 1;
break;
case ResetNvType::ERASE:
rilResetType = 2;
break;
case ResetNvType::FACTORY_RESET:
rilResetType = 3;
break;
}
dispatchInts(serial, mSlotId, RIL_REQUEST_NV_RESET_CONFIG, 1, rilResetType);
return Void();
}
Return<void> RadioImpl::setUiccSubscription(int32_t serial, const SelectUiccSub& uiccSub) {
#if VDBG
RLOGD("setUiccSubscription: serial %d", serial);
#endif
RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
RIL_REQUEST_SET_UICC_SUBSCRIPTION);
if (pRI == NULL) {
return Void();
}
RIL_SelectUiccSub rilUiccSub = {};
rilUiccSub.slot = uiccSub.slot;
rilUiccSub.app_index = uiccSub.appIndex;
rilUiccSub.sub_type = (RIL_SubscriptionType) uiccSub.subType;
rilUiccSub.act_status = (RIL_UiccSubActStatus) uiccSub.actStatus;
CALL_ONREQUEST(pRI->pCI->requestNumber, &rilUiccSub, sizeof(rilUiccSub), pRI, mSlotId);
return Void();
}
Return<void> RadioImpl::setDataAllowed(int32_t serial, bool allow) {
#if VDBG
RLOGD("setDataAllowed: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_ALLOW_DATA, 1, BOOL_TO_INT(allow));
return Void();
}
Return<void> RadioImpl::getHardwareConfig(int32_t serial) {
#if VDBG
RLOGD("getHardwareConfig: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_HARDWARE_CONFIG);
return Void();
}
Return<void> RadioImpl::requestIccSimAuthentication(int32_t serial, int32_t authContext,
const hidl_string& authData, const hidl_string& aid) {
#if VDBG
RLOGD("requestIccSimAuthentication: serial %d", serial);
#endif
RequestInfo *pRI = android::addRequestToList(serial, mSlotId, RIL_REQUEST_SIM_AUTHENTICATION);
if (pRI == NULL) {
return Void();
}
RIL_SimAuthentication pf = {};
pf.authContext = authContext;
if (!copyHidlStringToRil(&pf.authData, authData, pRI)) {
return Void();
}
if (!copyHidlStringToRil(&pf.aid, aid, pRI)) {
memsetAndFreeStrings(1, pf.authData);
return Void();
}
CALL_ONREQUEST(pRI->pCI->requestNumber, &pf, sizeof(pf), pRI, mSlotId);
memsetAndFreeStrings(2, pf.authData, pf.aid);
return Void();
}
/**
* @param numProfiles number of data profile
* @param dataProfiles the pointer to the actual data profiles. The acceptable type is
RIL_DataProfileInfo or RIL_DataProfileInfo_v15.
* @param dataProfilePtrs the pointer to the pointers that point to each data profile structure
* @param numfields number of string-type member in the data profile structure
* @param ... the variadic parameters are pointers to each string-type member
**/
template <typename T>
void freeSetDataProfileData(int numProfiles, T *dataProfiles, T **dataProfilePtrs,
int numfields, ...) {
va_list args;
va_start(args, numfields);
// Iterate through each string-type field that need to be free.
for (int i = 0; i < numfields; i++) {
// Iterate through each data profile and free that specific string-type field.
// The type 'char *T::*' is a type of pointer to a 'char *' member inside T structure.
char *T::*ptr = va_arg(args, char *T::*);
for (int j = 0; j < numProfiles; j++) {
memsetAndFreeStrings(1, dataProfiles[j].*ptr);
}
}
va_end(args);
#ifdef MEMSET_FREED
memset(dataProfiles, 0, numProfiles * sizeof(T));
memset(dataProfilePtrs, 0, numProfiles * sizeof(T *));
#endif
free(dataProfiles);
free(dataProfilePtrs);
}
Return<void> RadioImpl::setDataProfile(int32_t serial, const hidl_vec<DataProfileInfo>& profiles,
bool isRoaming) {
#if VDBG
RLOGD("setDataProfile: serial %d", serial);
#endif
RequestInfo *pRI = android::addRequestToList(serial, mSlotId, RIL_REQUEST_SET_DATA_PROFILE);
if (pRI == NULL) {
return Void();
}
size_t num = profiles.size();
bool success = false;
if (s_vendorFunctions->version <= 14) {
RIL_DataProfileInfo *dataProfiles =
(RIL_DataProfileInfo *) calloc(num, sizeof(RIL_DataProfileInfo));
if (dataProfiles == NULL) {
RLOGE("Memory allocation failed for request %s",
requestToString(pRI->pCI->requestNumber));
sendErrorResponse(pRI, RIL_E_NO_MEMORY);
return Void();
}
RIL_DataProfileInfo **dataProfilePtrs =
(RIL_DataProfileInfo **) calloc(num, sizeof(RIL_DataProfileInfo *));
if (dataProfilePtrs == NULL) {
RLOGE("Memory allocation failed for request %s",
requestToString(pRI->pCI->requestNumber));
free(dataProfiles);
sendErrorResponse(pRI, RIL_E_NO_MEMORY);
return Void();
}
for (size_t i = 0; i < num; i++) {
dataProfilePtrs[i] = &dataProfiles[i];
success = copyHidlStringToRil(&dataProfiles[i].apn, profiles[i].apn, pRI, true);
const hidl_string &protocol =
(isRoaming ? profiles[i].roamingProtocol : profiles[i].protocol);
if (success && !copyHidlStringToRil(&dataProfiles[i].protocol, protocol, pRI, true)) {
success = false;
}
if (success && !copyHidlStringToRil(&dataProfiles[i].user, profiles[i].user, pRI,
true)) {
success = false;
}
if (success && !copyHidlStringToRil(&dataProfiles[i].password, profiles[i].password,
pRI, true)) {
success = false;
}
if (!success) {
freeSetDataProfileData(num, dataProfiles, dataProfilePtrs, 4,
&RIL_DataProfileInfo::apn, &RIL_DataProfileInfo::protocol,
&RIL_DataProfileInfo::user, &RIL_DataProfileInfo::password);
return Void();
}
dataProfiles[i].profileId = (RIL_DataProfile) profiles[i].profileId;
dataProfiles[i].authType = (int) profiles[i].authType;
dataProfiles[i].type = (int) profiles[i].type;
dataProfiles[i].maxConnsTime = profiles[i].maxConnsTime;
dataProfiles[i].maxConns = profiles[i].maxConns;
dataProfiles[i].waitTime = profiles[i].waitTime;
dataProfiles[i].enabled = BOOL_TO_INT(profiles[i].enabled);
}
CALL_ONREQUEST(RIL_REQUEST_SET_DATA_PROFILE, dataProfilePtrs,
num * sizeof(RIL_DataProfileInfo *), pRI, mSlotId);
freeSetDataProfileData(num, dataProfiles, dataProfilePtrs, 4,
&RIL_DataProfileInfo::apn, &RIL_DataProfileInfo::protocol,
&RIL_DataProfileInfo::user, &RIL_DataProfileInfo::password);
} else {
RIL_DataProfileInfo_v15 *dataP