private void onUpdateIccAvailability() { if (mUiccController == null) { return; } UiccCardApplication newUiccApplication = getUiccCardApplication(); UiccCardApplication app = mUiccApplication.get(); if (app != newUiccApplication) { if (app != null) { Rlog.d(TAG, "Removing stale icc objects."); if (mIccRecords.get() != null) { mIccRecords.get().unregisterForNewSms(this); } mIccRecords.set(null); mUiccApplication.set(null); } if (newUiccApplication != null) { Rlog.d(TAG, "New Uicc application found"); mUiccApplication.set(newUiccApplication); mIccRecords.set(newUiccApplication.getIccRecords()); if (mIccRecords.get() != null) { mIccRecords.get().registerForNewSms(this, EVENT_NEW_ICC_SMS, null); } } } }
/* Sets the default subscription. If only one phone instance is active that * subscription is set as default subscription. If both phone instances * are active the first instance "0" is set as default subscription */ public static void setDefaultSubscription(int subId) { SystemProperties.set(PROPERTY_DEFAULT_SUBSCRIPTION, Integer.toString(subId)); int phoneId = SubscriptionController.getInstance().getPhoneId(subId); synchronized (sLockProxyPhones) { // Set the default phone in base class if (phoneId >= 0 && phoneId < sProxyPhones.length) { sProxyPhone = sProxyPhones[phoneId]; sCommandsInterface = sCommandsInterfaces[phoneId]; sMadeDefaults = true; } } // Update MCC MNC device configuration information String defaultMccMnc = TelephonyManager.getDefault().getSimOperatorNumericForPhone(phoneId); if (DBG) Rlog.d(LOG_TAG, "update mccmnc=" + defaultMccMnc); MccTable.updateMccMncConfiguration(sContext, defaultMccMnc, false); // Broadcast an Intent for default sub change Intent intent = new Intent(TelephonyIntents.ACTION_DEFAULT_SUBSCRIPTION_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); SubscriptionManager.putPhoneIdAndSubIdExtra(intent, phoneId); Rlog.d( LOG_TAG, "setDefaultSubscription : " + subId + " Broadcasting Default Subscription Changed..."); sContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); }
/** * Returns the tpdu from the pdu * * @return the tpdu for the message. * @hide */ public byte[] getTpdu(String format) { Rlog.d(LOG_TAG, "call getTpdu with format: " + format); byte[] pdu = this.getPdu(); if (format.equals(FORMAT_3GPP)) { if (pdu == null) { Rlog.d(LOG_TAG, "pdu is null"); return null; } int smsc_len = (pdu[0] & 0xff) + 1; int tpdu_len = pdu.length - smsc_len; byte[] tpdu = new byte[tpdu_len]; try { System.arraycopy(pdu, smsc_len, tpdu, 0, tpdu.length); return tpdu; } catch (ArrayIndexOutOfBoundsException e) { Rlog.e(LOG_TAG, "Out of boudns"); return null; } } else if (format.equals(FORMAT_3GPP2)) { return pdu; } return super.getTpdu(); }
/** * Set audio parameter "wb_amr" for HD-Voice (Wideband AMR). * * @param state: 0 = unsupported, 1 = supported. REQUIRED FOR JF FAMILY THIS SETS THE INFORMATION * CRASHES WITHOUT THIS FUNCTION part of the new csd binary */ private void setWbAmr(int state) { if (state == 1) { Rlog.d(RILJ_LOG_TAG, "setWbAmr(): setting audio parameter - wb_amr=on"); mAudioManager.setParameters("wide_voice_enable=true"); } else if (state == 0) { Rlog.d(RILJ_LOG_TAG, "setWbAmr(): setting audio parameter - wb_amr=off"); mAudioManager.setParameters("wide_voice_enable=false"); } }
private void loadSpnOverrides() { FileReader spnReader; File spnFile = new File(Environment.getRootDirectory(), PARTNER_SPN_OVERRIDE_PATH); File oemSpnFile = new File(Environment.getOemDirectory(), OEM_SPN_OVERRIDE_PATH); if (oemSpnFile.exists()) { // OEM image exist SPN xml, get the timestamp from OEM & System image for comparison. long oemSpnTime = oemSpnFile.lastModified(); long sysSpnTime = spnFile.lastModified(); Rlog.d(LOG_TAG, "SPN Timestamp: oemTime = " + oemSpnTime + " sysTime = " + sysSpnTime); // To get the newer version of SPN from OEM image if (oemSpnTime > sysSpnTime) { Rlog.d(LOG_TAG, "SPN in OEM image is newer than System image"); spnFile = oemSpnFile; } } else { // No SPN in OEM image, so load it from system image. Rlog.d( LOG_TAG, "No SPN in OEM image = " + oemSpnFile.getPath() + " Load SPN from system image"); } try { spnReader = new FileReader(spnFile); } catch (FileNotFoundException e) { Rlog.w(LOG_TAG, "Can not open " + spnFile.getAbsolutePath()); return; } try { XmlPullParser parser = Xml.newPullParser(); parser.setInput(spnReader); XmlUtils.beginDocument(parser, "spnOverrides"); while (true) { XmlUtils.nextElement(parser); String name = parser.getName(); if (!"spnOverride".equals(name)) { break; } String numeric = parser.getAttributeValue(null, "numeric"); String data = parser.getAttributeValue(null, "spn"); mCarrierSpnMap.put(numeric, data); } spnReader.close(); } catch (XmlPullParserException e) { Rlog.w(LOG_TAG, "Exception in spn-conf parser " + e); } catch (IOException e) { Rlog.w(LOG_TAG, "Exception in spn-conf parser " + e); } }
/** * Create an SmsMessage from a raw PDU. * * @param pdu raw data for creating short message * @param simId SIM ID */ public static GeminiSmsMessage createFromPdu(byte[] pdu, int simId) { String format = GeminiSmsMessage.getSmsFormat(simId); Rlog.d(LOG_TAG, "create SmsMessage from pdu with format " + format); SmsMessage sms = createFromPdu(pdu, format); if (sms != null) { return new GeminiSmsMessage(sms, simId); } else { Rlog.d(LOG_TAG, "fail to create SmsMessage from pdu"); return null; } }
private void readFromParcel(Parcel in) { dialogSize = in.readInt(); Rlog.d(TAG, "readFromParcel size = " + dialogSize); if (dialogSize < 0) { return; } callInfo = new ArrayList<String[]>(); for (int i = 0; i < dialogSize; i++) { String[] info = new String[INDEX_MAX]; info = in.createStringArray(); // read each string[] callInfo.add(info); } Rlog.d(TAG, "readFromParcel - " + toString()); }
private void parseSmsDeliver(PduParser p, int firstByte) { mReplyPathPresent = (firstByte & 0x80) == 0x80; mOriginatingAddress = p.getAddress(); if (mOriginatingAddress != null) { if (VDBG) Rlog.v(LOG_TAG, "SMS originating address: " + mOriginatingAddress.address); } // TP-Protocol-Identifier (TP-PID) // TS 23.040 9.2.3.9 mProtocolIdentifier = p.getByte(); // TP-Data-Coding-Scheme // see TS 23.038 mDataCodingScheme = p.getByte(); if (VDBG) { Rlog.v( LOG_TAG, "SMS TP-PID:" + mProtocolIdentifier + " data coding scheme: " + mDataCodingScheme); } mScTimeMillis = p.getSCTimestampMillis(); if (VDBG) Rlog.d(LOG_TAG, "SMS SC timestamp: " + mScTimeMillis); boolean hasUserDataHeader = (firstByte & 0x40) == 0x40; parseUserData(p, hasUserDataHeader); }
// Workaround for Samsung CDMA "ring of death" bug: // // Symptom: As soon as the phone receives notice of an incoming call, an // audible "old fashioned ring" is emitted through the earpiece and // persists through the duration of the call, or until reboot if the call // isn't answered. // // Background: The CDMA telephony stack implements a number of "signal info // tones" that are locally generated by ToneGenerator and mixed into the // voice call path in response to radio RIL_UNSOL_CDMA_INFO_REC requests. // One of these tones, IS95_CONST_IR_SIG_IS54B_L, is requested by the // radio just prior to notice of an incoming call when the voice call // path is muted. CallNotifier is responsible for stopping all signal // tones (by "playing" the TONE_CDMA_SIGNAL_OFF tone) upon receipt of a // "new ringing connection", prior to unmuting the voice call path. // // Problem: CallNotifier's incoming call path is designed to minimize // latency to notify users of incoming calls ASAP. Thus, // SignalInfoTonePlayer requests are handled asynchronously by spawning a // one-shot thread for each. Unfortunately the ToneGenerator API does // not provide a mechanism to specify an ordering on requests, and thus, // unexpected thread interleaving may result in ToneGenerator processing // them in the opposite order that CallNotifier intended. In this case, // playing the "signal off" tone first, followed by playing the "old // fashioned ring" indefinitely. // // Solution: An API change to ToneGenerator is required to enable // SignalInfoTonePlayer to impose an ordering on requests (i.e., drop any // request that's older than the most recent observed). Such a change, // or another appropriate fix should be implemented in AOSP first. // // Workaround: Intercept RIL_UNSOL_CDMA_INFO_REC requests from the radio, // check for a signal info record matching IS95_CONST_IR_SIG_IS54B_L, and // drop it so it's never seen by CallNotifier. If other signal tones are // observed to cause this problem, they should be dropped here as well. @Override protected void notifyRegistrantsCdmaInfoRec(CdmaInformationRecords infoRec) { final int response = RIL_UNSOL_CDMA_INFO_REC; if (infoRec.record instanceof CdmaSignalInfoRec) { CdmaSignalInfoRec sir = (CdmaSignalInfoRec) infoRec.record; if (sir != null && sir.isPresent && sir.signalType == SignalToneUtil.IS95_CONST_IR_SIGNAL_IS54B && sir.alertPitch == SignalToneUtil.IS95_CONST_IR_ALERT_MED && sir.signal == SignalToneUtil.IS95_CONST_IR_SIG_IS54B_L) { Rlog.d( RILJ_LOG_TAG, "Dropping \"" + responseToString(response) + " " + retToString(response, sir) + "\" to prevent \"ring of death\" bug."); return; } } super.notifyRegistrantsCdmaInfoRec(infoRec); }
/** * dialogIds Will have following information - dialogIds[INDEX_DIALOG_ID] - Holds Unique DialogId * dialogIds[INDEX_NUMBER] - Holds number/uri dialogIds[INDEX_ISPULLABLE] - Pullable/NonPullable * (true, false) dialogIds[INDEX_CALLTYPE] - CallType CallType - volteactive, volteheld, vttxrx, * vttx, vtrx, vtheld dialogIds[INDEX_DIRECTION] - Direction of the call (Originator/recipent) */ public QtiViceInfo(List<String[]> dialogIds) { if (dialogIds != null) { callInfo = new ArrayList<String[]>(); dialogSize = dialogIds.size(); callInfo = dialogIds; Rlog.d(TAG, "QtiViceInfo const = " + toString()); } }
/** Process a MMI PUK code */ void processCode() { try { if (isPinPukCommand()) { // TODO: This is the same as the code in GsmMmiCode.java, // MmiCode should be an abstract or base class and this and // other common variables and code should be promoted. // sia = old PIN or PUK // sib = new PIN // sic = new PIN String oldPinOrPuk = mSia; String newPinOrPuk = mSib; int pinLen = newPinOrPuk.length(); if (isRegister()) { if (!newPinOrPuk.equals(mSic)) { // password mismatch; return error handlePasswordError(com.android.internal.R.string.mismatchPin); } else if (pinLen < 4 || pinLen > 8) { // invalid length handlePasswordError(com.android.internal.R.string.invalidPin); } else if (mSc.equals(SC_PIN) && mUiccApplication != null && mUiccApplication.getState() == AppState.APPSTATE_PUK) { // Sim is puk-locked handlePasswordError(com.android.internal.R.string.needPuk); } else if (mUiccApplication != null) { Rlog.d(LOG_TAG, "process mmi service code using UiccApp sc=" + mSc); // We have an app and the pre-checks are OK if (mSc.equals(SC_PIN)) { mUiccApplication.changeIccLockPassword( oldPinOrPuk, newPinOrPuk, obtainMessage(EVENT_SET_COMPLETE, this)); } else if (mSc.equals(SC_PIN2)) { mUiccApplication.changeIccFdnPassword( oldPinOrPuk, newPinOrPuk, obtainMessage(EVENT_SET_COMPLETE, this)); } else if (mSc.equals(SC_PUK)) { mUiccApplication.supplyPuk( oldPinOrPuk, newPinOrPuk, obtainMessage(EVENT_SET_COMPLETE, this)); } else if (mSc.equals(SC_PUK2)) { mUiccApplication.supplyPuk2( oldPinOrPuk, newPinOrPuk, obtainMessage(EVENT_SET_COMPLETE, this)); } else { throw new RuntimeException("Unsupported service code=" + mSc); } } else { throw new RuntimeException("No application mUiccApplicaiton is null"); } } else { throw new RuntimeException("Ivalid register/action=" + mAction); } } } catch (RuntimeException exc) { mState = State.FAILED; mMessage = mContext.getText(com.android.internal.R.string.mmiError); mPhone.onMMIDone(this); } }
@Override protected void processUnsolicited(Parcel p) { Object ret; int dataPosition = p.dataPosition(); // save off position within the Parcel int response = p.readInt(); switch (response) { case RIL_UNSOL_RIL_CONNECTED: // Fix for NV/RUIM setting on CDMA SIM devices // skip getcdmascriptionsource as if qualcomm handles it in the ril binary ret = responseInts(p); setRadioPower(false, null); setPreferredNetworkType(mPreferredNetworkType, null); int cdmaSubscription = Settings.Global.getInt( mContext.getContentResolver(), Settings.Global.CDMA_SUBSCRIPTION_MODE, -1); if (cdmaSubscription != -1) { setCdmaSubscriptionSource(mCdmaSubscription, null); } setCellInfoListRate(Integer.MAX_VALUE, null); notifyRegistrantsRilConnectionChanged(((int[]) ret)[0]); break; case RIL_UNSOL_NITZ_TIME_RECEIVED: handleNitzTimeReceived(p); break; // SAMSUNG STATES case SamsungExynos4RIL.RIL_UNSOL_AM: ret = responseString(p); String amString = (String) ret; Rlog.d(RILJ_LOG_TAG, "Executing AM: " + amString); try { Runtime.getRuntime().exec("am " + amString); } catch (IOException e) { e.printStackTrace(); Rlog.e(RILJ_LOG_TAG, "am " + amString + " could not be executed."); } break; case SamsungExynos4RIL.RIL_UNSOL_RESPONSE_HANDOVER: ret = responseVoid(p); break; case 1036: ret = responseVoid(p); break; case SamsungExynos4RIL.RIL_UNSOL_WB_AMR_STATE: ret = responseInts(p); setWbAmr(((int[]) ret)[0]); break; default: // Rewind the Parcel p.setDataPosition(dataPosition); // Forward responses that we are not overriding to the super class super.processUnsolicited(p); return; } }
/** {@inheritDoc} */ @Override protected void sendSms(SmsTracker tracker) { HashMap<String, Object> map = tracker.mData; byte pdu[] = (byte[]) map.get("pdu"); if (tracker.mRetryCount > 0) { Rlog.d( TAG, "sendSms: " + " mRetryCount=" + tracker.mRetryCount + " mMessageRef=" + tracker.mMessageRef + " SS=" + mPhone.getServiceState().getState()); // per TS 23.040 Section 9.2.3.6: If TP-MTI SMS-SUBMIT (0x01) type // TP-RD (bit 2) is 1 for retry // and TP-MR is set to previously failed sms TP-MR if (((0x01 & pdu[0]) == 0x01)) { pdu[0] |= 0x04; // TP-RD pdu[1] = (byte) tracker.mMessageRef; // TP-MR } } Rlog.d( TAG, "sendSms: " + " isIms()=" + isIms() + " mRetryCount=" + tracker.mRetryCount + " mImsRetry=" + tracker.mImsRetry + " mMessageRef=" + tracker.mMessageRef + " SS=" + mPhone.getServiceState().getState()); sendSmsByPstn(tracker); }
public GsmSMSDispatcher( PhoneBase phone, SmsUsageMonitor usageMonitor, ImsSMSDispatcher imsSMSDispatcher, GsmInboundSmsHandler gsmInboundSmsHandler) { super(phone, usageMonitor, imsSMSDispatcher); mCi.setOnSmsStatus(this, EVENT_NEW_SMS_STATUS_REPORT, null); mCi.setOnSmsOnSim(this, EVENT_SMS_ON_ICC, null); mGsmInboundSmsHandler = gsmInboundSmsHandler; mUiccController = UiccController.getInstance(); mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null); Rlog.d(TAG, "GsmSMSDispatcher created"); }
/** The contents of the /proc/cmdline file */ private static String getProcCmdLine() { String cmdline = ""; FileInputStream is = null; try { is = new FileInputStream("/proc/cmdline"); byte[] buffer = new byte[2048]; int count = is.read(buffer); if (count > 0) { cmdline = new String(buffer, 0, count); } } catch (IOException e) { Rlog.d(TAG, "No /proc/cmdline exception=" + e); } finally { if (is != null) { try { is.close(); } catch (IOException e) { } } } Rlog.d(TAG, "/proc/cmdline=" + cmdline); return cmdline; }
// TODO: Fix when we "properly" have TelephonyDevController/SubscriptionController .. public static int calculatePreferredNetworkType(Context context, int phoneSubId) { int networkType = android.provider.Settings.Global.getInt( context.getContentResolver(), android.provider.Settings.Global.PREFERRED_NETWORK_MODE + phoneSubId, RILConstants.PREFERRED_NETWORK_MODE); Rlog.d( LOG_TAG, "calculatePreferredNetworkType: phoneSubId = " + phoneSubId + " networkType = " + networkType); return networkType; }
/* Returns User SMS Prompt property, enabled or not */ public static boolean isSMSPromptEnabled() { boolean prompt = false; int value = 0; try { value = Settings.Global.getInt( sContext.getContentResolver(), Settings.Global.MULTI_SIM_SMS_PROMPT); } catch (SettingNotFoundException snfe) { Rlog.e(LOG_TAG, "Settings Exception Reading Dual Sim SMS Prompt Values"); } prompt = (value == 0) ? false : true; Rlog.d(LOG_TAG, "SMS Prompt option:" + prompt); return prompt; }
protected void updatePhoneObject() { if (mPhoneBase .getContext() .getResources() .getBoolean(com.android.internal.R.bool.config_switch_phone_on_voice_reg_state_change)) { // If the phone is not registered on a network, no need to update. boolean isRegistered = mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE || mSS.getVoiceRegState() == ServiceState.STATE_EMERGENCY_ONLY; if (!isRegistered) { Rlog.d(LOG_TAG, "updatePhoneObject: Ignore update"); return; } mPhoneBase.updatePhoneObject(mSS.getRilVoiceRadioTechnology()); } }
/** * Create the beginning of a SUBMIT PDU. This is the part of the SUBMIT PDU that is common to the * two versions of {@link #getSubmitPdu}, one of which takes a byte array and the other of which * takes a <code>String</code>. * * @param scAddress Service Centre address. null == use default * @param destinationAddress the address of the destination for the message * @param mtiByte * @param ret <code>SubmitPdu</code> containing the encoded SC address, if applicable, and the * encoded message */ private static ByteArrayOutputStream getSubmitPduHead( String scAddress, String destinationAddress, byte mtiByte, boolean statusReportRequested, SubmitPdu ret) { ByteArrayOutputStream bo = new ByteArrayOutputStream(MAX_USER_DATA_BYTES + 40); // SMSC address with length octet, or 0 if (scAddress == null) { ret.encodedScAddress = null; } else { ret.encodedScAddress = PhoneNumberUtils.networkPortionToCalledPartyBCDWithLength(scAddress); } // TP-Message-Type-Indicator (and friends) if (statusReportRequested) { // Set TP-Status-Report-Request bit. mtiByte |= 0x20; if (VDBG) Rlog.d(LOG_TAG, "SMS status report requested"); } bo.write(mtiByte); // space for TP-Message-Reference bo.write(0); byte[] daBytes; daBytes = PhoneNumberUtils.networkPortionToCalledPartyBCD(destinationAddress); // destination address length in BCD digits, ignoring TON byte and pad // TODO Should be better. bo.write((daBytes.length - 1) * 2 - ((daBytes[daBytes.length - 1] & 0xf0) == 0xf0 ? 1 : 0)); // destination address bo.write(daBytes, 0, daBytes.length); // TP-Protocol-Identifier bo.write(0); return bo; }
/** {@inheritDoc} */ @Override protected void sendText( String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, Uri messageUri, String callingPkg, int priority, boolean isExpectMore, int validityPeriod) { SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(scAddr, destAddr, text, (deliveryIntent != null), validityPeriod); if (pdu != null) { HashMap map = getSmsTrackerMap(destAddr, scAddr, text, pdu); SmsTracker tracker = getSmsTracker( map, sentIntent, deliveryIntent, getFormat(), messageUri, isExpectMore, text /*fullMessageText*/, true /*isText*/, validityPeriod); String carrierPackage = getCarrierAppPackageName(); if (carrierPackage != null) { Rlog.d(TAG, "Found carrier package."); TextSmsSender smsSender = new TextSmsSender(tracker); smsSender.sendSmsByCarrierApp(carrierPackage, new SmsSenderCallback(smsSender)); } else { Rlog.v(TAG, "No carrier package."); sendRawPdu(tracker); } } else { Rlog.e(TAG, "GsmSMSDispatcher.sendText(): getSubmitPdu() returned null"); } }
private void smsLock() { // Do not send a new SMS until the response for the previous SMS has been received // * for the error case where the response never comes back, time out after // 30 seconds and just try the next SEND_SMS synchronized (mSMSLock) { long timeoutTime = SystemClock.elapsedRealtime() + SEND_SMS_TIMEOUT_IN_MS; long waitTimeLeft = SEND_SMS_TIMEOUT_IN_MS; while (mIsSendingSMS && (waitTimeLeft > 0)) { Rlog.d(RILJ_LOG_TAG, "sendSMS() waiting for response of previous SEND_SMS"); try { mSMSLock.wait(waitTimeLeft); } catch (InterruptedException ex) { // ignore the interrupt and rewait for the remainder } waitTimeLeft = timeoutTime - SystemClock.elapsedRealtime(); } if (waitTimeLeft <= 0) { Rlog.e(RILJ_LOG_TAG, "sendSms() timed out waiting for response of previous CDMA_SEND_SMS"); } mIsSendingSMS = true; } }
public String toString() { if (callInfo != null) { Rlog.d(TAG, "mCallInfo size = " + dialogSize); StringBuilder sb = new StringBuilder(); for (int i = 0; i < dialogSize; i++) { String[] callinfo = callInfo.get(i); sb.append("QtiViceInfo :"); sb.append("DialogId - "); sb.append(callinfo[INDEX_DIALOG_ID]); sb.append("Number - "); sb.append(callinfo[INDEX_NUMBER]); sb.append("IsPullable - "); sb.append(callinfo[INDEX_ISPULLABLE]); sb.append("CallType - "); sb.append(callinfo[INDEX_CALLTYPE]); sb.append("Direction - "); sb.append(callinfo[INDEX_DIRECTION]); } return sb.toString(); } return null; }
/** * TS 27.005 3.1, <pdu> definition "In the case of SMS: 3GPP TS 24.011 [6] SC address * followed by 3GPP TS 23.040 [3] TPDU in hexadecimal format: ME/TA converts each octet of TP data * unit into two IRA character long hex number (e.g. octet with integer value 42 is presented to * TE as two characters 2A (IRA 50 and 65))" ...in the case of cell broadcast, something else... */ private void parsePdu(byte[] pdu) { mPdu = pdu; // Rlog.d(LOG_TAG, "raw sms message:"); // Rlog.d(LOG_TAG, s); PduParser p = new PduParser(pdu); mScAddress = p.getSCAddress(); if (mScAddress != null) { if (VDBG) Rlog.d(LOG_TAG, "SMS SC address: " + mScAddress); } // TODO(mkf) support reply path, user data header indicator // TP-Message-Type-Indicator // 9.2.3 int firstByte = p.getByte(); mMti = firstByte & 0x3; switch (mMti) { // TP-Message-Type-Indicator // 9.2.3 case 0: case 3: // GSM 03.40 9.2.3.1: MTI == 3 is Reserved. // This should be processed in the same way as MTI == 0 (Deliver) parseSmsDeliver(p, firstByte); break; case 1: parseSmsSubmit(p, firstByte); break; case 2: parseSmsStatusReport(p, firstByte); break; default: // TODO(mkf) the rest of these throw new RuntimeException("Unsupported message type"); } }
/** {@inheritDoc} */ @Override protected void sendData( String destAddr, String scAddr, int destPort, int origPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) { SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu( scAddr, destAddr, destPort, origPort, data, (deliveryIntent != null)); if (pdu != null) { HashMap map = getSmsTrackerMap(destAddr, scAddr, destPort, origPort, data, pdu); SmsTracker tracker = getSmsTracker( map, sentIntent, deliveryIntent, getFormat(), null /*messageUri*/, false /*isExpectMore*/, null /*fullMessageText*/, false /*isText*/); String carrierPackage = getCarrierAppPackageName(); if (carrierPackage != null) { Rlog.d(TAG, "Found carrier package."); DataSmsSender smsSender = new DataSmsSender(tracker); smsSender.sendSmsByCarrierApp(carrierPackage, new SmsSenderCallback(smsSender)); } else { Rlog.v(TAG, "No carrier package."); sendRawPdu(tracker); } } else { Rlog.e(TAG, "GsmSMSDispatcher.sendData(): getSubmitPdu() returned null"); } }
@Override protected RadioState getRadioStateFromInt(int stateInt) { if (!oldRilState) super.getRadioStateFromInt(stateInt); RadioState state; /* RIL_RadioState ril.h */ switch (stateInt) { case 0: state = RadioState.RADIO_OFF; break; case 1: case 2: state = RadioState.RADIO_UNAVAILABLE; break; case 4: // When SIM is PIN-unlocked, RIL doesn't respond with RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED. // We notify the system here. Rlog.d(RILJ_LOG_TAG, "SIM is PIN-unlocked now"); if (mIccStatusChangedRegistrants != null) { mIccStatusChangedRegistrants.notifyRegistrants(); } case 3: case 5: case 6: case 7: case 8: case 9: case 10: case 13: state = RadioState.RADIO_ON; break; default: throw new RuntimeException("Unrecognized RIL_RadioState: " + stateInt); } return state; }
public static Phone getPhone(int phoneId) { Phone phone; String dbgInfo = ""; synchronized (sLockProxyPhones) { if (!sMadeDefaults) { throw new IllegalStateException("Default phones haven't been made yet!"); // CAF_MSIM FIXME need to introduce default phone id ? } else if (phoneId == SubscriptionManager.DEFAULT_PHONE_INDEX) { if (DBG) dbgInfo = "phoneId == DEFAULT_PHONE_ID return sProxyPhone"; phone = sProxyPhone; } else { if (DBG) dbgInfo = "phoneId != DEFAULT_PHONE_ID return sProxyPhones[phoneId]"; phone = (((phoneId >= 0) && (phoneId < TelephonyManager.getDefault().getPhoneCount())) ? sProxyPhones[phoneId] : null); } if (DBG) { Rlog.d(LOG_TAG, "getPhone:- " + dbgInfo + " phoneId=" + phoneId + " phone=" + phone); } return phone; } }
/** * Parse and return the SC address prepended to SMS messages coming via the TS 27.005 / AT * interface. Returns null on invalid address */ String getSCAddress() { int len; String ret; // length of SC Address len = getByte(); if (len == 0) { // no SC address ret = null; } else { // SC address try { ret = PhoneNumberUtils.calledPartyBCDToString(mPdu, mCur, len); } catch (RuntimeException tr) { Rlog.d(LOG_TAG, "invalid SC address: ", tr); ret = null; } } mCur += len; return ret; }
/** * Return if the current radio is LTE on CDMA. This is a tri-state return value as for a period of * time the mode may be unknown. * * @return {@link PhoneConstants#LTE_ON_CDMA_UNKNOWN}, {@link PhoneConstants#LTE_ON_CDMA_FALSE} or * {@link PhoneConstants#LTE_ON_CDMA_TRUE} * @hide */ public static int getLteOnCdmaModeStatic() { int retVal; int curVal; String productType = ""; curVal = SystemProperties.getInt( TelephonyProperties.PROPERTY_LTE_ON_CDMA_DEVICE, PhoneConstants.LTE_ON_CDMA_UNKNOWN); retVal = curVal; if (retVal == PhoneConstants.LTE_ON_CDMA_UNKNOWN) { Matcher matcher = sProductTypePattern.matcher(sKernelCmdLine); if (matcher.find()) { productType = matcher.group(1); if (sLteOnCdmaProductType.equals(productType)) { retVal = PhoneConstants.LTE_ON_CDMA_TRUE; } else { retVal = PhoneConstants.LTE_ON_CDMA_FALSE; } } else { retVal = PhoneConstants.LTE_ON_CDMA_FALSE; } } Rlog.d( TAG, "getLteOnCdmaMode=" + retVal + " curVal=" + curVal + " product_type='" + productType + "' lteOnCdmaProductType='" + sLteOnCdmaProductType + "'"); return retVal; }
protected void log(String msg) { Rlog.d(LOG_TAG, "[GsmCallTracker] " + msg); }
protected synchronized void handlePollCalls(AsyncResult ar) { List polledCalls; if (ar.exception == null) { polledCalls = (List) ar.result; } else if (isCommandExceptionRadioNotAvailable(ar.exception)) { // just a dummy empty ArrayList to cause the loop // to hang up all the calls polledCalls = new ArrayList(); } else { // Radio probably wasn't ready--try again in a bit // But don't keep polling if the channel is closed pollCallsAfterDelay(); return; } Connection newRinging = null; // or waiting boolean hasNonHangupStateChanged = false; // Any change besides // a dropped connection boolean needsPollDelay = false; boolean unknownConnectionAppeared = false; for (int i = 0, curDC = 0, dcSize = polledCalls.size(); i < connections.length; i++) { GsmConnection conn = connections[i]; DriverCall dc = null; // polledCall list is sparse if (curDC < dcSize) { dc = (DriverCall) polledCalls.get(curDC); if (dc.index == i + 1) { curDC++; } else { dc = null; } } if (DBG_POLL) log("poll: conn[i=" + i + "]=" + conn + ", dc=" + dc); if (conn == null && dc != null) { // Connection appeared in CLCC response that we don't know about if (pendingMO != null && pendingMO.compareTo(dc)) { if (DBG_POLL) log("poll: pendingMO=" + pendingMO); // It's our pending mobile originating call connections[i] = pendingMO; pendingMO.index = i; pendingMO.update(dc); pendingMO = null; // Someone has already asked to hangup this call if (hangupPendingMO) { hangupPendingMO = false; try { if (Phone.DEBUG_PHONE) log("poll: hangupPendingMO, hangup conn " + i); hangup(connections[i]); } catch (CallStateException ex) { Rlog.e(LOG_TAG, "unexpected error on hangup"); } // Do not continue processing this poll // Wait for hangup and repoll return; } } else { connections[i] = new GsmConnection(phone.getContext(), dc, this, i); // it's a ringing call if (connections[i].getCall() == ringingCall) { newRinging = connections[i]; } else { // Something strange happened: a call appeared // which is neither a ringing call or one we created. // Either we've crashed and re-attached to an existing // call, or something else (eg, SIM) initiated the call. Rlog.i(LOG_TAG, "Phantom call appeared " + dc); // If it's a connected call, set the connect time so that // it's non-zero. It may not be accurate, but at least // it won't appear as a Missed Call. if (dc.state != DriverCall.State.ALERTING && dc.state != DriverCall.State.DIALING) { connections[i].onConnectedInOrOut(); if (dc.state == DriverCall.State.HOLDING) { // We've transitioned into HOLDING connections[i].onStartedHolding(); } } unknownConnectionAppeared = true; } } hasNonHangupStateChanged = true; } else if (conn != null && dc == null) { // Connection missing in CLCC response that we were // tracking. droppedDuringPoll.add(conn); // Dropped connections are removed from the CallTracker // list but kept in the GsmCall list connections[i] = null; } else if (conn != null && dc != null && !conn.compareTo(dc)) { // Connection in CLCC response does not match what // we were tracking. Assume dropped call and new call droppedDuringPoll.add(conn); connections[i] = new GsmConnection(phone.getContext(), dc, this, i); if (connections[i].getCall() == ringingCall) { newRinging = connections[i]; } // else something strange happened hasNonHangupStateChanged = true; } else if (conn != null && dc != null) { /* implicit conn.compareTo(dc) */ boolean changed; changed = conn.update(dc); hasNonHangupStateChanged = hasNonHangupStateChanged || changed; } if (REPEAT_POLLING) { if (dc != null) { // FIXME with RIL, we should not need this anymore if ((dc.state == DriverCall.State.DIALING /*&& cm.getOption(cm.OPTION_POLL_DIALING)*/ ) || (dc.state == DriverCall.State.ALERTING /*&& cm.getOption(cm.OPTION_POLL_ALERTING)*/ ) || (dc.state == DriverCall.State.INCOMING /*&& cm.getOption(cm.OPTION_POLL_INCOMING)*/ ) || (dc.state == DriverCall.State.WAITING /*&& cm.getOption(cm.OPTION_POLL_WAITING)*/ )) { // Sometimes there's no unsolicited notification // for state transitions needsPollDelay = true; } } } } // This is the first poll after an ATD. // We expect the pending call to appear in the list // If it does not, we land here if (pendingMO != null) { Rlog.d(LOG_TAG, "Pending MO dropped before poll fg state:" + foregroundCall.getState()); droppedDuringPoll.add(pendingMO); pendingMO = null; hangupPendingMO = false; } if (newRinging != null) { phone.notifyNewRingingConnection(newRinging); } // clear the "local hangup" and "missed/rejected call" // cases from the "dropped during poll" list // These cases need no "last call fail" reason for (int i = droppedDuringPoll.size() - 1; i >= 0; i--) { GsmConnection conn = droppedDuringPoll.get(i); if (conn.isIncoming() && conn.getConnectTime() == 0) { // Missed or rejected call Connection.DisconnectCause cause; if (conn.cause == Connection.DisconnectCause.LOCAL) { cause = Connection.DisconnectCause.INCOMING_REJECTED; } else { cause = Connection.DisconnectCause.INCOMING_MISSED; } if (Phone.DEBUG_PHONE) { log("missed/rejected call, conn.cause=" + conn.cause); log("setting cause to " + cause); } droppedDuringPoll.remove(i); conn.onDisconnect(cause); } else if (conn.cause == Connection.DisconnectCause.LOCAL) { // Local hangup droppedDuringPoll.remove(i); conn.onDisconnect(Connection.DisconnectCause.LOCAL); } else if (conn.cause == Connection.DisconnectCause.INVALID_NUMBER) { droppedDuringPoll.remove(i); conn.onDisconnect(Connection.DisconnectCause.INVALID_NUMBER); } } // Any non-local disconnects: determine cause if (droppedDuringPoll.size() > 0) { cm.getLastCallFailCause(obtainNoPollCompleteMessage(EVENT_GET_LAST_CALL_FAIL_CAUSE)); } if (needsPollDelay) { pollCallsAfterDelay(); } // Cases when we can no longer keep disconnected Connection's // with their previous calls // 1) the phone has started to ring // 2) A Call/Connection object has changed state... // we may have switched or held or answered (but not hung up) if (newRinging != null || hasNonHangupStateChanged) { internalClearDisconnected(); } updatePhoneState(); if (unknownConnectionAppeared) { phone.notifyUnknownConnection(); } if (hasNonHangupStateChanged || newRinging != null) { phone.notifyPreciseCallStateChanged(); } // dumpState(); }