Merge "Added data service manager"
diff --git a/proto/telephony.proto b/proto/telephony.proto
index 700c961..7d2e84b 100644
--- a/proto/telephony.proto
+++ b/proto/telephony.proto
@@ -760,6 +760,8 @@
DEACTIVATE_REASON_RADIO_OFF = 2;
DEACTIVATE_REASON_PDP_RESET = 3;
+
+ DEACTIVATE_REASON_HANDOVER = 4;
}
}
diff --git a/src/java/com/android/internal/telephony/CommandsInterface.java b/src/java/com/android/internal/telephony/CommandsInterface.java
index ab12091..aa3ee43 100644
--- a/src/java/com/android/internal/telephony/CommandsInterface.java
+++ b/src/java/com/android/internal/telephony/CommandsInterface.java
@@ -17,6 +17,7 @@
package com.android.internal.telephony;
import android.net.KeepalivePacketData;
+import android.net.LinkProperties;
import android.os.Handler;
import android.os.Message;
import android.os.WorkSource;
@@ -1625,22 +1626,27 @@
/**
* Setup a packet data connection On successful completion, the result
- * message will return a {@link com.android.internal.telephony.dataconnection.DataCallResponse}
- * object containing the connection information.
+ * message will return a SetupDataResult object containing the connection information.
*
- * @param radioTechnology
- * Radio technology to use. Values is one of RIL_RADIO_TECHNOLOGY_*
+ * @param accessNetworkType
+ * Access network to use. Values is one of AccessNetworkConstants.AccessNetworkType.
* @param dataProfile
* Data profile for data call setup
* @param isRoaming
* Device is roaming or not
* @param allowRoaming
* Flag indicating data roaming is enabled or not
+ * @param reason
+ * The reason for data setup
+ * @param linkProperties
+ * If the reason is for handover, this indicates the link properties of the existing
+ * data connection
* @param result
* Callback message
*/
- void setupDataCall(int radioTechnology, DataProfile dataProfile, boolean isRoaming,
- boolean allowRoaming, Message result);
+ void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
+ boolean allowRoaming, int reason, LinkProperties linkProperties,
+ Message result);
/**
* Deactivate packet data connection
diff --git a/src/java/com/android/internal/telephony/DriverCall.java b/src/java/com/android/internal/telephony/DriverCall.java
index a923d8f..96e1556 100644
--- a/src/java/com/android/internal/telephony/DriverCall.java
+++ b/src/java/com/android/internal/telephony/DriverCall.java
@@ -37,6 +37,30 @@
// statements that use this enum
}
+ /**
+ * Audio information
+ */
+ /** Unspecified audio codec */
+ public static final int AUDIO_QUALITY_UNSPECIFIED = 0;
+ /** AMR (Narrowband) audio codec */
+ public static final int AUDIO_QUALITY_AMR = 1;
+ /** AMR (Wideband) audio codec */
+ public static final int AUDIO_QUALITY_AMR_WB = 2;
+ /** GSM Enhanced Full-Rate audio codec */
+ public static final int AUDIO_QUALITY_GSM_EFR = 3;
+ /** GSM Full-Rate audio codec */
+ public static final int AUDIO_QUALITY_GSM_FR = 4;
+ /** GSM Half-Rate audio codec */
+ public static final int AUDIO_QUALITY_GSM_HR = 5;
+ /** Enhanced Variable rate codec */
+ public static final int AUDIO_QUALITY_EVRC = 6;
+ /** Enhanced Variable rate codec revision B */
+ public static final int AUDIO_QUALITY_EVRC_B = 7;
+ /** Enhanced Variable rate codec (Wideband) */
+ public static final int AUDIO_QUALITY_EVRC_WB = 8;
+ /** Enhanced Variable rate codec (Narrowband) */
+ public static final int AUDIO_QUALITY_EVRC_NW = 9;
+
public int index;
public boolean isMT;
public State state; // May be null if unavail
@@ -50,6 +74,7 @@
public String name;
public int namePresentation;
public UUSInfo uusInfo;
+ public int audioQuality = AUDIO_QUALITY_UNSPECIFIED;
/** returns null on error */
static DriverCall
@@ -113,7 +138,8 @@
+ (isVoice ? "voc" : "nonvoc") + ","
+ (isVoicePrivacy ? "evp" : "noevp") + ","
/*+ "number=" + number */ + ",cli=" + numberPresentation + ","
- /*+ "name="+ name */ + "," + namePresentation;
+ /*+ "name="+ name */ + "," + namePresentation + ","
+ + "audioQuality=" + audioQuality;
}
public static State
diff --git a/src/java/com/android/internal/telephony/GsmCdmaConnection.java b/src/java/com/android/internal/telephony/GsmCdmaConnection.java
index a8d79cf..42157f1 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaConnection.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaConnection.java
@@ -141,6 +141,8 @@
mParent.attach(this, dc);
fetchDtmfToneDelay(phone);
+
+ setAudioQuality(getAudioQualityFromDC(dc.audioQuality));
}
/** This is an MO call, created when dialing */
@@ -635,6 +637,17 @@
}
}
+ int newAudioQuality = getAudioQualityFromDC(dc.audioQuality);
+ if (getAudioQuality() != newAudioQuality) {
+ if (Phone.DEBUG_PHONE) {
+ log("update: audioQuality # changed!: "
+ + (newAudioQuality == Connection.AUDIO_QUALITY_HIGH_DEFINITION
+ ? "high" : "standard"));
+ }
+ setAudioQuality(newAudioQuality);
+ changed = true;
+ }
+
// A null cnapName should be the same as ""
if (TextUtils.isEmpty(dc.name)) {
if (!TextUtils.isEmpty(mCnapName)) {
@@ -927,6 +940,16 @@
}
}
+ private int getAudioQualityFromDC(int audioQuality) {
+ switch (audioQuality) {
+ case DriverCall.AUDIO_QUALITY_AMR_WB:
+ case DriverCall.AUDIO_QUALITY_EVRC_NW:
+ return Connection.AUDIO_QUALITY_HIGH_DEFINITION;
+ default:
+ return Connection.AUDIO_QUALITY_STANDARD;
+ }
+ }
+
/**
* Set post dial state and acquire wake lock while switching to "started" or "pause"
* state, the wake lock will be released if state switches out of "started" or "pause"
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index fc3caa1..0c51dca 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -1767,6 +1767,57 @@
}
@Override
+ public void getCallBarring(String facility, String password, Message onComplete,
+ int serviceClass) {
+ if (isPhoneTypeGsm()) {
+ Phone imsPhone = mImsPhone;
+ if ((imsPhone != null)
+ && ((imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)
+ || imsPhone.isUtEnabled())) {
+ imsPhone.getCallBarring(facility, password, onComplete, serviceClass);
+ return;
+ }
+ mCi.queryFacilityLock(facility, password, serviceClass, onComplete);
+ } else {
+ loge("getCallBarringOption: not possible in CDMA");
+ }
+ }
+
+ @Override
+ public void setCallBarring(String facility, boolean lockState, String password,
+ Message onComplete, int serviceClass) {
+ if (isPhoneTypeGsm()) {
+ Phone imsPhone = mImsPhone;
+ if ((imsPhone != null)
+ && ((imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)
+ || imsPhone.isUtEnabled())) {
+ imsPhone.setCallBarring(facility, lockState, password, onComplete, serviceClass);
+ return;
+ }
+ mCi.setFacilityLock(facility, lockState, password, serviceClass, onComplete);
+ } else {
+ loge("setCallBarringOption: not possible in CDMA");
+ }
+ }
+
+ /**
+ * Changes access code used for call barring
+ *
+ * @param facility is one of CB_FACILTY_*
+ * @param oldPwd is old password
+ * @param newPwd is new password
+ * @param onComplete is callback message when the action is completed.
+ */
+ public void changeCallBarringPassword(String facility, String oldPwd, String newPwd,
+ Message onComplete) {
+ if (isPhoneTypeGsm()) {
+ mCi.changeBarringPassword(facility, oldPwd, newPwd, onComplete);
+ } else {
+ loge("changeCallBarringPassword: not possible in CDMA");
+ }
+ }
+
+ @Override
public void getOutgoingCallerIdDisplay(Message onComplete) {
if (isPhoneTypeGsm()) {
Phone imsPhone = mImsPhone;
diff --git a/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java b/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
index 0fc08c6..c3ae1b0 100644
--- a/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
+++ b/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
@@ -83,7 +83,7 @@
final protected Context mContext;
final protected AppOpsManager mAppOps;
final private UserManager mUserManager;
- protected SMSDispatcher mDispatcher;
+ protected SmsDispatchersController mDispatchersController;
protected Handler mHandler = new Handler() {
@Override
@@ -131,7 +131,7 @@
mContext = phone.getContext();
mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- mDispatcher = new ImsSMSDispatcher(phone,
+ mDispatchersController = new SmsDispatchersController(phone,
phone.mSmsStorageMonitor, phone.mSmsUsageMonitor);
}
@@ -170,7 +170,7 @@
protected void updatePhoneObject(Phone phone) {
mPhone = phone;
- mDispatcher.updatePhoneObject(phone);
+ mDispatchersController.updatePhoneObject(phone);
}
protected void enforceReceiveAndSend(String message) {
@@ -379,7 +379,8 @@
return;
}
destAddr = filterDestAddress(destAddr);
- mDispatcher.sendData(destAddr, scAddr, destPort, data, sentIntent, deliveryIntent);
+ mDispatchersController.sendData(destAddr, scAddr, destPort, data, sentIntent,
+ deliveryIntent);
}
/**
@@ -451,7 +452,7 @@
enforcePrivilegedAppPermissions();
}
destAddr = filterDestAddress(destAddr);
- mDispatcher.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent,
+ mDispatchersController.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent,
null/*messageUri*/, callingPackage, persistMessageForNonDefaultSmsApp);
}
@@ -472,7 +473,17 @@
"\n format=" + format +
"\n receivedIntent=" + receivedIntent);
}
- mDispatcher.injectSmsPdu(pdu, format, receivedIntent);
+ mDispatchersController.injectSmsPdu(pdu, format,
+ result -> {
+ if (receivedIntent != null) {
+ try {
+ receivedIntent.send(result);
+ } catch (PendingIntent.CanceledException e) {
+ Rlog.d(LOG_TAG, "receivedIntent cancelled.");
+ }
+ }
+ }
+ );
}
/**
@@ -546,7 +557,7 @@
singleDeliveryIntent = deliveryIntents.get(i);
}
- mDispatcher.sendText(destAddr, scAddr, singlePart,
+ mDispatchersController.sendText(destAddr, scAddr, singlePart,
singleSentIntent, singleDeliveryIntent,
null/*messageUri*/, callingPackage,
persistMessageForNonDefaultSmsApp);
@@ -554,19 +565,19 @@
return;
}
- mDispatcher.sendMultipartText(destAddr, scAddr, (ArrayList<String>) parts,
+ mDispatchersController.sendMultipartText(destAddr, scAddr, (ArrayList<String>) parts,
(ArrayList<PendingIntent>) sentIntents, (ArrayList<PendingIntent>) deliveryIntents,
null/*messageUri*/, callingPackage, persistMessageForNonDefaultSmsApp);
}
public int getPremiumSmsPermission(String packageName) {
- return mDispatcher.getPremiumSmsPermission(packageName);
+ return mDispatchersController.getPremiumSmsPermission(packageName);
}
public void setPremiumSmsPermission(String packageName, int permission) {
- mDispatcher.setPremiumSmsPermission(packageName, permission);
+ mDispatchersController.setPremiumSmsPermission(packageName, permission);
}
/**
@@ -919,11 +930,11 @@
}
public boolean isImsSmsSupported() {
- return mDispatcher.isIms();
+ return mDispatchersController.isIms();
}
public String getImsSmsFormat() {
- return mDispatcher.getImsSmsFormat();
+ return mDispatchersController.getImsSmsFormat();
}
public void sendStoredText(String callingPkg, Uri messageUri, String scAddress,
@@ -951,7 +962,7 @@
return;
}
textAndAddress[1] = filterDestAddress(textAndAddress[1]);
- mDispatcher.sendText(textAndAddress[1], scAddress, textAndAddress[0],
+ mDispatchersController.sendText(textAndAddress[1], scAddress, textAndAddress[0],
sentIntent, deliveryIntent, messageUri, callingPkg,
true /* persistMessageForNonDefaultSmsApp */);
}
@@ -1007,14 +1018,14 @@
singleDeliveryIntent = deliveryIntents.get(i);
}
- mDispatcher.sendText(textAndAddress[1], scAddress, singlePart,
+ mDispatchersController.sendText(textAndAddress[1], scAddress, singlePart,
singleSentIntent, singleDeliveryIntent, messageUri, callingPkg,
true /* persistMessageForNonDefaultSmsApp */);
}
return;
}
- mDispatcher.sendMultipartText(
+ mDispatchersController.sendMultipartText(
textAndAddress[1], // destAddress
scAddress,
parts,
diff --git a/src/java/com/android/internal/telephony/ImsSMSDispatcher.java b/src/java/com/android/internal/telephony/ImsSMSDispatcher.java
deleted file mode 100644
index 4d8f62c..0000000
--- a/src/java/com/android/internal/telephony/ImsSMSDispatcher.java
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * Copyright (C) 2006 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.
- */
-
-package com.android.internal.telephony;
-
-import static android.telephony.SmsManager.RESULT_ERROR_GENERIC_FAILURE;
-import android.app.PendingIntent;
-import android.app.PendingIntent.CanceledException;
-import android.net.Uri;
-import android.os.AsyncResult;
-import android.os.Message;
-import android.provider.Telephony.Sms.Intents;
-import android.telephony.Rlog;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.cdma.CdmaInboundSmsHandler;
-import com.android.internal.telephony.cdma.CdmaSMSDispatcher;
-import com.android.internal.telephony.gsm.GsmInboundSmsHandler;
-import com.android.internal.telephony.gsm.GsmSMSDispatcher;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-
-public class ImsSMSDispatcher extends SMSDispatcher {
- private static final String TAG = "RIL_ImsSms";
-
- private SMSDispatcher mCdmaDispatcher;
- private SMSDispatcher mGsmDispatcher;
-
- private GsmInboundSmsHandler mGsmInboundSmsHandler;
- private CdmaInboundSmsHandler mCdmaInboundSmsHandler;
-
-
- /** true if IMS is registered and sms is supported, false otherwise.*/
- private boolean mIms = false;
- private String mImsSmsFormat = SmsConstants.FORMAT_UNKNOWN;
-
- public ImsSMSDispatcher(Phone phone, SmsStorageMonitor storageMonitor,
- SmsUsageMonitor usageMonitor) {
- super(phone, usageMonitor, null);
- Rlog.d(TAG, "ImsSMSDispatcher created");
-
- // Create dispatchers, inbound SMS handlers and
- // broadcast undelivered messages in raw table.
- mCdmaDispatcher = new CdmaSMSDispatcher(phone, usageMonitor, this);
- mGsmInboundSmsHandler = GsmInboundSmsHandler.makeInboundSmsHandler(phone.getContext(),
- storageMonitor, phone);
- mCdmaInboundSmsHandler = CdmaInboundSmsHandler.makeInboundSmsHandler(phone.getContext(),
- storageMonitor, phone, (CdmaSMSDispatcher) mCdmaDispatcher);
- mGsmDispatcher = new GsmSMSDispatcher(phone, usageMonitor, this, mGsmInboundSmsHandler);
- SmsBroadcastUndelivered.initialize(phone.getContext(),
- mGsmInboundSmsHandler, mCdmaInboundSmsHandler);
- InboundSmsHandler.registerNewMessageNotificationActionHandler(phone.getContext());
-
- mCi.registerForOn(this, EVENT_RADIO_ON, null);
- mCi.registerForImsNetworkStateChanged(this, EVENT_IMS_STATE_CHANGED, null);
- }
-
- /* Updates the phone object when there is a change */
- @Override
- protected void updatePhoneObject(Phone phone) {
- Rlog.d(TAG, "In IMS updatePhoneObject ");
- super.updatePhoneObject(phone);
- mCdmaDispatcher.updatePhoneObject(phone);
- mGsmDispatcher.updatePhoneObject(phone);
- mGsmInboundSmsHandler.updatePhoneObject(phone);
- mCdmaInboundSmsHandler.updatePhoneObject(phone);
- }
-
- public void dispose() {
- mCi.unregisterForOn(this);
- mCi.unregisterForImsNetworkStateChanged(this);
- mGsmDispatcher.dispose();
- mCdmaDispatcher.dispose();
- mGsmInboundSmsHandler.dispose();
- mCdmaInboundSmsHandler.dispose();
- }
-
- /**
- * Handles events coming from the phone stack. Overridden from handler.
- *
- * @param msg the message to handle
- */
- @Override
- public void handleMessage(Message msg) {
- AsyncResult ar;
-
- switch (msg.what) {
- case EVENT_RADIO_ON:
- case EVENT_IMS_STATE_CHANGED: // received unsol
- mCi.getImsRegistrationState(this.obtainMessage(EVENT_IMS_STATE_DONE));
- break;
-
- case EVENT_IMS_STATE_DONE:
- ar = (AsyncResult) msg.obj;
-
- if (ar.exception == null) {
- updateImsInfo(ar);
- } else {
- Rlog.e(TAG, "IMS State query failed with exp "
- + ar.exception);
- }
- break;
-
- default:
- super.handleMessage(msg);
- }
- }
-
- private void setImsSmsFormat(int format) {
- // valid format?
- switch (format) {
- case PhoneConstants.PHONE_TYPE_GSM:
- mImsSmsFormat = "3gpp";
- break;
- case PhoneConstants.PHONE_TYPE_CDMA:
- mImsSmsFormat = "3gpp2";
- break;
- default:
- mImsSmsFormat = "unknown";
- break;
- }
- }
-
- private void updateImsInfo(AsyncResult ar) {
- int[] responseArray = (int[])ar.result;
-
- mIms = false;
- if (responseArray[0] == 1) { // IMS is registered
- Rlog.d(TAG, "IMS is registered!");
- mIms = true;
- } else {
- Rlog.d(TAG, "IMS is NOT registered!");
- }
-
- setImsSmsFormat(responseArray[1]);
-
- if (("unknown".equals(mImsSmsFormat))) {
- Rlog.e(TAG, "IMS format was unknown!");
- // failed to retrieve valid IMS SMS format info, set IMS to unregistered
- mIms = false;
- }
- }
-
- @Override
- public void sendData(String destAddr, String scAddr, int destPort,
- byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
- if (isCdmaMo()) {
- mCdmaDispatcher.sendData(destAddr, scAddr, destPort,
- data, sentIntent, deliveryIntent);
- } else {
- mGsmDispatcher.sendData(destAddr, scAddr, destPort,
- data, sentIntent, deliveryIntent);
- }
- }
-
- @Override
- public void sendMultipartText(String destAddr, String scAddr,
- ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,
- ArrayList<PendingIntent> deliveryIntents, Uri messageUri, String callingPkg,
- boolean persistMessage) {
- if (isCdmaMo()) {
- mCdmaDispatcher.sendMultipartText(destAddr, scAddr,
- parts, sentIntents, deliveryIntents, messageUri, callingPkg, persistMessage);
- } else {
- mGsmDispatcher.sendMultipartText(destAddr, scAddr,
- parts, sentIntents, deliveryIntents, messageUri, callingPkg, persistMessage);
- }
- }
-
- @Override
- protected void sendSms(SmsTracker tracker) {
- // sendSms is a helper function to other send functions, sendText/Data...
- // it is not part of ISms.stub
- Rlog.e(TAG, "sendSms should never be called from here!");
- }
-
- @Override
- protected void sendSmsByPstn(SmsTracker tracker) {
- // This function should be defined in Gsm/CdmaDispatcher.
- Rlog.e(TAG, "sendSmsByPstn should never be called from here!");
- }
-
- @Override
- public void sendText(String destAddr, String scAddr, String text, PendingIntent sentIntent,
- PendingIntent deliveryIntent, Uri messageUri, String callingPkg,
- boolean persistMessage) {
- Rlog.d(TAG, "sendText");
- if (isCdmaMo()) {
- mCdmaDispatcher.sendText(destAddr, scAddr,
- text, sentIntent, deliveryIntent, messageUri, callingPkg, persistMessage);
- } else {
- mGsmDispatcher.sendText(destAddr, scAddr,
- text, sentIntent, deliveryIntent, messageUri, callingPkg, persistMessage);
- }
- }
-
- @VisibleForTesting
- @Override
- public void injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent) {
- Rlog.d(TAG, "ImsSMSDispatcher:injectSmsPdu");
- try {
- // TODO We need to decide whether we should allow injecting GSM(3gpp)
- // SMS pdus when the phone is camping on CDMA(3gpp2) network and vice versa.
- android.telephony.SmsMessage msg =
- android.telephony.SmsMessage.createFromPdu(pdu, format);
-
- // Only class 1 SMS are allowed to be injected.
- if (msg == null ||
- msg.getMessageClass() != android.telephony.SmsMessage.MessageClass.CLASS_1) {
- if (msg == null) {
- Rlog.e(TAG, "injectSmsPdu: createFromPdu returned null");
- }
- if (receivedIntent != null) {
- receivedIntent.send(Intents.RESULT_SMS_GENERIC_ERROR);
- }
- return;
- }
-
- AsyncResult ar = new AsyncResult(receivedIntent, msg, null);
-
- if (format.equals(SmsConstants.FORMAT_3GPP)) {
- Rlog.i(TAG, "ImsSMSDispatcher:injectSmsText Sending msg=" + msg +
- ", format=" + format + "to mGsmInboundSmsHandler");
- mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_INJECT_SMS, ar);
- } else if (format.equals(SmsConstants.FORMAT_3GPP2)) {
- Rlog.i(TAG, "ImsSMSDispatcher:injectSmsText Sending msg=" + msg +
- ", format=" + format + "to mCdmaInboundSmsHandler");
- mCdmaInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_INJECT_SMS, ar);
- } else {
- // Invalid pdu format.
- Rlog.e(TAG, "Invalid pdu format: " + format);
- if (receivedIntent != null)
- receivedIntent.send(Intents.RESULT_SMS_GENERIC_ERROR);
- }
- } catch (Exception e) {
- Rlog.e(TAG, "injectSmsPdu failed: ", e);
- try {
- if (receivedIntent != null)
- receivedIntent.send(Intents.RESULT_SMS_GENERIC_ERROR);
- } catch (CanceledException ex) {}
- }
- }
-
- @Override
- public void sendRetrySms(SmsTracker tracker) {
- String oldFormat = tracker.mFormat;
-
- // newFormat will be based on voice technology
- String newFormat =
- (PhoneConstants.PHONE_TYPE_CDMA == mPhone.getPhoneType()) ?
- mCdmaDispatcher.getFormat() :
- mGsmDispatcher.getFormat();
-
- // was previously sent sms format match with voice tech?
- if (oldFormat.equals(newFormat)) {
- if (isCdmaFormat(newFormat)) {
- Rlog.d(TAG, "old format matched new format (cdma)");
- mCdmaDispatcher.sendSms(tracker);
- return;
- } else {
- Rlog.d(TAG, "old format matched new format (gsm)");
- mGsmDispatcher.sendSms(tracker);
- return;
- }
- }
-
- // format didn't match, need to re-encode.
- HashMap map = tracker.getData();
-
- // to re-encode, fields needed are: scAddr, destAddr, and
- // text if originally sent as sendText or
- // data and destPort if originally sent as sendData.
- if (!( map.containsKey("scAddr") && map.containsKey("destAddr") &&
- ( map.containsKey("text") ||
- (map.containsKey("data") && map.containsKey("destPort"))))) {
- // should never come here...
- Rlog.e(TAG, "sendRetrySms failed to re-encode per missing fields!");
- tracker.onFailed(mContext, RESULT_ERROR_GENERIC_FAILURE, 0/*errorCode*/);
- return;
- }
- String scAddr = (String)map.get("scAddr");
- String destAddr = (String)map.get("destAddr");
-
- SmsMessageBase.SubmitPduBase pdu = null;
- // figure out from tracker if this was sendText/Data
- if (map.containsKey("text")) {
- Rlog.d(TAG, "sms failed was text");
- String text = (String)map.get("text");
-
- if (isCdmaFormat(newFormat)) {
- Rlog.d(TAG, "old format (gsm) ==> new format (cdma)");
- pdu = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(
- scAddr, destAddr, text, (tracker.mDeliveryIntent != null), null);
- } else {
- Rlog.d(TAG, "old format (cdma) ==> new format (gsm)");
- pdu = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(
- scAddr, destAddr, text, (tracker.mDeliveryIntent != null), null);
- }
- } else if (map.containsKey("data")) {
- Rlog.d(TAG, "sms failed was data");
- byte[] data = (byte[])map.get("data");
- Integer destPort = (Integer)map.get("destPort");
-
- if (isCdmaFormat(newFormat)) {
- Rlog.d(TAG, "old format (gsm) ==> new format (cdma)");
- pdu = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(
- scAddr, destAddr, destPort.intValue(), data,
- (tracker.mDeliveryIntent != null));
- } else {
- Rlog.d(TAG, "old format (cdma) ==> new format (gsm)");
- pdu = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(
- scAddr, destAddr, destPort.intValue(), data,
- (tracker.mDeliveryIntent != null));
- }
- }
-
- // replace old smsc and pdu with newly encoded ones
- map.put("smsc", pdu.encodedScAddress);
- map.put("pdu", pdu.encodedMessage);
-
- SMSDispatcher dispatcher = (isCdmaFormat(newFormat)) ?
- mCdmaDispatcher : mGsmDispatcher;
-
- tracker.mFormat = dispatcher.getFormat();
- dispatcher.sendSms(tracker);
- }
-
- @Override
- protected void sendSubmitPdu(SmsTracker tracker) {
- sendRawPdu(tracker);
- }
-
- @Override
- protected String getFormat() {
- // this function should be defined in Gsm/CdmaDispatcher.
- Rlog.e(TAG, "getFormat should never be called from here!");
- return "unknown";
- }
-
- @Override
- protected GsmAlphabet.TextEncodingDetails calculateLength(
- CharSequence messageBody, boolean use7bitOnly) {
- Rlog.e(TAG, "Error! Not implemented for IMS.");
- return null;
- }
-
- @Override
- protected SmsTracker getNewSubmitPduTracker(String destinationAddress, String scAddress,
- String message, SmsHeader smsHeader, int format, PendingIntent sentIntent,
- PendingIntent deliveryIntent, boolean lastPart,
- AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri,
- String fullMessageText) {
- Rlog.e(TAG, "Error! Not implemented for IMS.");
- return null;
- }
-
- @Override
- public boolean isIms() {
- return mIms;
- }
-
- @Override
- public String getImsSmsFormat() {
- return mImsSmsFormat;
- }
-
- /**
- * Determines whether or not to use CDMA format for MO SMS.
- * If SMS over IMS is supported, then format is based on IMS SMS format,
- * otherwise format is based on current phone type.
- *
- * @return true if Cdma format should be used for MO SMS, false otherwise.
- */
- private boolean isCdmaMo() {
- if (!isIms()) {
- // IMS is not registered, use Voice technology to determine SMS format.
- return (PhoneConstants.PHONE_TYPE_CDMA == mPhone.getPhoneType());
- }
- // IMS is registered with SMS support
- return isCdmaFormat(mImsSmsFormat);
- }
-
- /**
- * Determines whether or not format given is CDMA format.
- *
- * @param format
- * @return true if format given is CDMA format, false otherwise.
- */
- private boolean isCdmaFormat(String format) {
- return (mCdmaDispatcher.getFormat().equals(format));
- }
-}
diff --git a/src/java/com/android/internal/telephony/ImsSmsDispatcher.java b/src/java/com/android/internal/telephony/ImsSmsDispatcher.java
new file mode 100644
index 0000000..ac629f8
--- /dev/null
+++ b/src/java/com/android/internal/telephony/ImsSmsDispatcher.java
@@ -0,0 +1,396 @@
+/*
+ * Copyright (C) 2018 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
+ */
+
+package com.android.internal.telephony;
+
+import android.app.Activity;
+import android.os.RemoteException;
+import android.os.Message;
+import android.app.PendingIntent;
+import android.app.PendingIntent.CanceledException;
+import android.provider.Telephony.Sms;
+import android.content.Intent;
+import android.telephony.Rlog;
+
+import com.android.ims.ImsException;
+import com.android.ims.ImsManager;
+import com.android.ims.ImsServiceProxy;
+import com.android.ims.internal.IImsSmsListener;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
+import com.android.internal.telephony.util.SMSDispatcherUtil;
+import com.android.internal.telephony.gsm.SmsMessage;
+
+import android.telephony.ims.internal.feature.ImsFeature;
+import android.telephony.ims.internal.feature.MmTelFeature;
+import android.telephony.ims.internal.stub.SmsImplBase;
+import android.telephony.ims.internal.stub.SmsImplBase.SendStatusResult;
+import android.telephony.ims.internal.stub.SmsImplBase.StatusReportResult;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.provider.Telephony.Sms.Intents;
+import android.util.Pair;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Responsible for communications with {@link com.android.ims.ImsManager} to send/receive messages
+ * over IMS.
+ */
+public class ImsSmsDispatcher extends SMSDispatcher {
+ // Initial condition for ims connection retry.
+ private static final int IMS_RETRY_STARTING_TIMEOUT_MS = 500; // ms
+ // Ceiling bitshift amount for service query timeout, calculated as:
+ // 2^mImsServiceRetryCount * IMS_RETRY_STARTING_TIMEOUT_MS, where
+ // mImsServiceRetryCount ∊ [0, CEILING_SERVICE_RETRY_COUNT].
+ private static final int CEILING_SERVICE_RETRY_COUNT = 6;
+
+ @VisibleForTesting
+ public Map<Integer, SmsTracker> mTrackers = new ConcurrentHashMap<>();
+ @VisibleForTesting
+ public AtomicInteger mNextToken = new AtomicInteger();
+ private final Object mLock = new Object();
+ private volatile boolean mIsSmsCapable;
+ private volatile boolean mIsImsServiceUp;
+ private volatile boolean mIsRegistered;
+ private volatile int mImsServiceRetryCount;
+
+ /**
+ * Default implementation of interface that calculates the ImsService retry timeout.
+ * Override-able for testing.
+ */
+ private IRetryTimeout mRetryTimeout = () -> {
+ int timeout = (1 << mImsServiceRetryCount) * IMS_RETRY_STARTING_TIMEOUT_MS;
+ if (mImsServiceRetryCount <= CEILING_SERVICE_RETRY_COUNT) {
+ mImsServiceRetryCount++;
+ }
+ return timeout;
+ };
+
+ /**
+ * Listen to the IMS service state change
+ *
+ */
+ private ImsRegistrationImplBase.Callback mRegistrationCallback =
+ new ImsRegistrationImplBase.Callback() {
+ @Override
+ public void onRegistered(
+ @ImsRegistrationImplBase.ImsRegistrationTech int imsRadioTech) {
+ Rlog.d(TAG, "onImsConnected imsRadioTech=" + imsRadioTech);
+ synchronized (mLock) {
+ mIsRegistered = true;
+ }
+ }
+
+ @Override
+ public void onRegistering(
+ @ImsRegistrationImplBase.ImsRegistrationTech int imsRadioTech) {
+ Rlog.d(TAG, "onImsProgressing imsRadioTech=" + imsRadioTech);
+ synchronized (mLock) {
+ mIsRegistered = false;
+ }
+ }
+
+ @Override
+ public void onDeregistered(com.android.ims.ImsReasonInfo info) {
+ Rlog.d(TAG, "onImsDisconnected imsReasonInfo=" + info);
+ synchronized (mLock) {
+ mIsRegistered = false;
+ }
+ }
+ };
+
+ private ImsFeature.CapabilityCallback mCapabilityCallback =
+ new ImsFeature.CapabilityCallback() {
+ @Override
+ public void onCapabilitiesStatusChanged(ImsFeature.Capabilities config) {
+ synchronized (mLock) {
+ mIsSmsCapable = config.isCapable(
+ MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_SMS);
+ }
+ }
+ };
+
+ // Callback fires when ImsManager MMTel Feature changes state
+ private ImsServiceProxy.IFeatureUpdate mNotifyStatusChangedCallback =
+ new ImsServiceProxy.IFeatureUpdate() {
+ @Override
+ public void notifyStateChanged() {
+ try {
+ int status = getImsManager().getImsServiceStatus();
+ Rlog.d(TAG, "Status Changed: " + status);
+ switch (status) {
+ case android.telephony.ims.feature.ImsFeature.STATE_READY: {
+ synchronized (mLock) {
+ setListeners();
+ mIsImsServiceUp = true;
+ }
+ break;
+ }
+ case android.telephony.ims.feature.ImsFeature.STATE_INITIALIZING:
+ // fall through
+ case android.telephony.ims.feature.ImsFeature.STATE_NOT_AVAILABLE:
+ synchronized (mLock) {
+ mIsImsServiceUp = false;
+ }
+ break;
+ default: {
+ Rlog.w(TAG, "Unexpected State!");
+ }
+ }
+ } catch (ImsException e) {
+ // Could not get the ImsService, retry!
+ retryGetImsService();
+ }
+ }
+
+ @Override
+ public void notifyUnavailable() {
+ retryGetImsService();
+ }
+ };
+
+ private final IImsSmsListener mImsSmsListener = new IImsSmsListener.Stub() {
+ @Override
+ public void onSendSmsResult(int token, int messageRef, @SendStatusResult int status,
+ int reason) throws RemoteException {
+ SmsTracker tracker = mTrackers.get(token);
+ if (tracker == null) {
+ throw new IllegalArgumentException("Invalid token.");
+ }
+ switch(reason) {
+ case SmsImplBase.SEND_STATUS_OK:
+ tracker.onSent(mContext);
+ break;
+ case SmsImplBase.SEND_STATUS_ERROR:
+ tracker.onFailed(mContext, reason, 0 /* errorCode */);
+ mTrackers.remove(token);
+ break;
+ case SmsImplBase.SEND_STATUS_ERROR_RETRY:
+ tracker.mRetryCount += 1;
+ sendSms(tracker);
+ break;
+ case SmsImplBase.SEND_STATUS_ERROR_FALLBACK:
+ fallbackToPstn(token, tracker);
+ break;
+ default:
+ }
+ }
+
+ @Override
+ public void onSmsStatusReportReceived(int token, int messageRef, String format, byte[] pdu)
+ throws RemoteException {
+ Rlog.d(TAG, "Status report received.");
+ SmsTracker tracker = mTrackers.get(token);
+ if (tracker == null) {
+ throw new RemoteException("Invalid token.");
+ }
+ Pair<Boolean, Boolean> result = mSmsDispatchersController.handleSmsStatusReport(
+ tracker, format, pdu);
+ Rlog.d(TAG, "Status report handle result, success: " + result.first +
+ "complete: " + result.second);
+ try {
+ getImsManager().acknowledgeSmsReport(
+ token,
+ messageRef,
+ result.first ? SmsImplBase.STATUS_REPORT_STATUS_OK
+ : SmsImplBase.STATUS_REPORT_STATUS_ERROR);
+ } catch (ImsException e) {
+ Rlog.e(TAG, "Failed to acknowledgeSmsReport(). Error: "
+ + e.getMessage());
+ }
+ if (result.second) {
+ mTrackers.remove(token);
+ }
+ }
+
+ @Override
+ public void onSmsReceived(int token, String format, byte[] pdu)
+ throws RemoteException {
+ Rlog.d(TAG, "SMS received.");
+ mSmsDispatchersController.injectSmsPdu(pdu, format, result -> {
+ Rlog.d(TAG, "SMS handled result: " + result);
+ try {
+ getImsManager().acknowledgeSms(token,
+ 0,
+ result == Intents.RESULT_SMS_HANDLED
+ ? SmsImplBase.STATUS_REPORT_STATUS_OK
+ : SmsImplBase.DELIVER_STATUS_ERROR);
+ } catch (ImsException e) {
+ Rlog.e(TAG, "Failed to acknowledgeSms(). Error: " + e.getMessage());
+ }
+ });
+ }
+ };
+
+ public ImsSmsDispatcher(Phone phone, SmsDispatchersController smsDispatchersController) {
+ super(phone, smsDispatchersController);
+
+ mImsServiceRetryCount = 0;
+ // Send a message to connect to the Ims Service and open a connection through
+ // getImsService().
+ sendEmptyMessage(EVENT_GET_IMS_SERVICE);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case EVENT_GET_IMS_SERVICE:
+ try {
+ getImsService();
+ } catch (ImsException e) {
+ Rlog.e(TAG, "setListeners: " + e);
+ retryGetImsService();
+ }
+ break;
+ default:
+ super.handleMessage(msg);
+ }
+ }
+
+ private void getImsService() throws ImsException {
+ Rlog.d(TAG, "getImsService");
+ // Adding to set, will be safe adding multiple times. If the ImsService is not active yet,
+ // this method will throw an ImsException.
+ getImsManager().addNotifyStatusChangedCallbackIfAvailable(mNotifyStatusChangedCallback);
+ // Wait for ImsService.STATE_READY to start listening for SMS.
+ // Call the callback right away for compatibility with older devices that do not use states.
+ mNotifyStatusChangedCallback.notifyStateChanged();
+ }
+
+ private void setListeners() throws ImsException {
+ getImsManager().addRegistrationCallback(mRegistrationCallback);
+ getImsManager().addCapabilitiesCallback(mCapabilityCallback);
+ getImsManager().setSmsListener(mImsSmsListener);
+ getImsManager().onSmsReady();
+ mImsServiceRetryCount = 0;
+ }
+
+ private void retryGetImsService() {
+ // The binder connection is already up. Do not try to get it again.
+ if (getImsManager().isServiceAvailable()) {
+ return;
+ }
+ // remove callback so we do not receive updates from old ImsServiceProxy when switching
+ // between ImsServices.
+ getImsManager().removeNotifyStatusChangedCallback(mNotifyStatusChangedCallback);
+ // Exponential backoff during retry, limited to 32 seconds.
+ Rlog.e(TAG, "getImsService: Retrying getting ImsService...");
+ removeMessages(EVENT_GET_IMS_SERVICE);
+ sendEmptyMessageDelayed(EVENT_GET_IMS_SERVICE, mRetryTimeout.get());
+ }
+
+ public boolean isAvailable() {
+ synchronized (mLock) {
+ return mIsImsServiceUp && mIsRegistered && mIsSmsCapable;
+ }
+ }
+
+ @Override
+ protected String getFormat() {
+ try {
+ return getImsManager().getSmsFormat();
+ } catch (ImsException e) {
+ Rlog.e(TAG, "Failed to get sms format. Error: " + e.getMessage());
+ return SmsConstants.FORMAT_UNKNOWN;
+ }
+ }
+
+ @Override
+ protected boolean shouldBlockSms() {
+ return SMSDispatcherUtil.shouldBlockSms(isCdmaMo(), mPhone);
+ }
+
+ @Override
+ protected SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
+ String message, boolean statusReportRequested, SmsHeader smsHeader) {
+ return SMSDispatcherUtil.getSubmitPdu(isCdmaMo(), scAddr, destAddr, message,
+ statusReportRequested, smsHeader);
+ }
+
+ @Override
+ protected SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
+ int destPort, byte[] message, boolean statusReportRequested) {
+ return SMSDispatcherUtil.getSubmitPdu(isCdmaMo(), scAddr, destAddr, destPort, message,
+ statusReportRequested);
+ }
+
+ @Override
+ protected TextEncodingDetails calculateLength(CharSequence messageBody, boolean use7bitOnly) {
+ return SMSDispatcherUtil.calculateLength(isCdmaMo(), messageBody, use7bitOnly);
+ }
+
+ @Override
+ public void sendSms(SmsTracker tracker) {
+ Rlog.d(TAG, "sendSms: "
+ + " mRetryCount=" + tracker.mRetryCount
+ + " mMessageRef=" + tracker.mMessageRef
+ + " SS=" + mPhone.getServiceState().getState());
+
+ HashMap<String, Object> map = tracker.getData();
+
+ byte[] pdu = (byte[]) map.get(MAP_KEY_PDU);
+ byte smsc[] = (byte[]) map.get(MAP_KEY_SMSC);
+ boolean isRetry = tracker.mRetryCount > 0;
+
+ if (SmsConstants.FORMAT_3GPP.equals(getFormat()) && tracker.mRetryCount > 0) {
+ // 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
+ }
+ }
+
+ int token = mNextToken.incrementAndGet();
+ mTrackers.put(token, tracker);
+ try {
+ getImsManager().sendSms(
+ token,
+ tracker.mMessageRef,
+ getFormat(),
+ smsc != null ? new String(smsc) : null,
+ isRetry,
+ pdu);
+ } catch (ImsException e) {
+ Rlog.e(TAG, "sendSms failed. Falling back to PSTN. Error: " + e.getMessage());
+ fallbackToPstn(token, tracker);
+ }
+ }
+
+ private ImsManager getImsManager() {
+ return ImsManager.getInstance(mContext, mPhone.getPhoneId());
+ }
+
+ @VisibleForTesting
+ public void fallbackToPstn(int token, SmsTracker tracker) {
+ mSmsDispatchersController.sendRetrySms(tracker);
+ mTrackers.remove(token);
+ }
+
+ @Override
+ protected boolean isCdmaMo() {
+ return mSmsDispatchersController.isCdmaFormat(getFormat());
+ }
+
+ @VisibleForTesting
+ public interface IRetryTimeout {
+ int get();
+ }
+}
diff --git a/src/java/com/android/internal/telephony/InboundSmsHandler.java b/src/java/com/android/internal/telephony/InboundSmsHandler.java
index 2d663cd..cb87032 100644
--- a/src/java/com/android/internal/telephony/InboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/InboundSmsHandler.java
@@ -603,9 +603,9 @@
*/
private void handleInjectSms(AsyncResult ar) {
int result;
- PendingIntent receivedIntent = null;
+ SmsDispatchersController.SmsInjectionCallback callback = null;
try {
- receivedIntent = (PendingIntent) ar.userObj;
+ callback = (SmsDispatchersController.SmsInjectionCallback) ar.userObj;
SmsMessage sms = (SmsMessage) ar.result;
if (sms == null) {
result = Intents.RESULT_SMS_GENERIC_ERROR;
@@ -617,10 +617,8 @@
result = Intents.RESULT_SMS_GENERIC_ERROR;
}
- if (receivedIntent != null) {
- try {
- receivedIntent.send(result);
- } catch (CanceledException e) { }
+ if (callback != null) {
+ callback.onSmsInjectedResult(result);
}
}
diff --git a/src/java/com/android/internal/telephony/PhoneInternalInterface.java b/src/java/com/android/internal/telephony/PhoneInternalInterface.java
index 46a9e8c..c64c090 100644
--- a/src/java/com/android/internal/telephony/PhoneInternalInterface.java
+++ b/src/java/com/android/internal/telephony/PhoneInternalInterface.java
@@ -592,6 +592,35 @@
Message onComplete);
/**
+ * Gets a call barring option. The return value of ((AsyncResult) onComplete.obj) will be an
+ * Integer representing the sum of enabled serivice classes (sum of SERVICE_CLASS_*)
+ *
+ * @param facility is one of CB_FACILTY_*
+ * @param password is password or "" if not required
+ * @param serviceClass is a sum of SERVICE_CLASS_*
+ * @param onComplete is callback message when the action is completed.
+ */
+ public void getCallBarring(String facility,
+ String password,
+ Message onComplete,
+ int serviceClass);
+
+ /**
+ * Sets a call barring option.
+ *
+ * @param facility is one of CB_FACILTY_*
+ * @param lockState is true means lock, false means unlock
+ * @param password is password or "" if not required
+ * @param serviceClass is a sum of SERVICE_CLASS_*
+ * @param onComplete is callback message when the action is completed.
+ */
+ public void setCallBarring(String facility,
+ boolean lockState,
+ String password,
+ Message onComplete,
+ int serviceClass);
+
+ /**
* getOutgoingCallerIdDisplay
* gets outgoing caller id display. The return value of
* ((AsyncResult)onComplete.obj) is an array of int, with a length of 2.
diff --git a/src/java/com/android/internal/telephony/PhoneSwitcher.java b/src/java/com/android/internal/telephony/PhoneSwitcher.java
index 1c6e023..cd28b2b 100644
--- a/src/java/com/android/internal/telephony/PhoneSwitcher.java
+++ b/src/java/com/android/internal/telephony/PhoneSwitcher.java
@@ -124,7 +124,8 @@
mCommandsInterfaces = cis;
try {
- tr.addOnSubscriptionsChangedListener("PhoneSwitcher", mSubscriptionsChangedListener);
+ tr.addOnSubscriptionsChangedListener(context.getOpPackageName(),
+ mSubscriptionsChangedListener);
} catch (RemoteException e) {
}
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index eefcdc8..ce4743f 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -55,6 +55,7 @@
import android.net.ConnectivityManager;
import android.net.KeepalivePacketData;
import android.net.LinkAddress;
+import android.net.LinkProperties;
import android.net.NetworkUtils;
import android.os.AsyncResult;
import android.os.Build;
@@ -81,12 +82,14 @@
import android.telephony.RadioAccessFamily;
import android.telephony.RadioAccessSpecifier;
import android.telephony.Rlog;
+import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.SmsManager;
import android.telephony.TelephonyHistogram;
import android.telephony.TelephonyManager;
import android.telephony.data.DataCallResponse;
import android.telephony.data.DataProfile;
+import android.telephony.data.DataService;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
@@ -1225,8 +1228,9 @@
}
@Override
- public void setupDataCall(int radioTechnology, DataProfile dataProfile, boolean isRoaming,
- boolean allowRoaming, Message result) {
+ public void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
+ boolean allowRoaming, int reason, LinkProperties linkProperties,
+ Message result) {
IRadio radioProxy = getRadioProxy(result);
if (radioProxy != null) {
@@ -1237,17 +1241,49 @@
// Convert to HAL data profile
DataProfileInfo dpi = convertToHalDataProfile(dataProfile);
- if (RILJ_LOGD) {
- riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
- + ",radioTechnology=" + radioTechnology + ",isRoaming="
- + isRoaming + ",allowRoaming=" + allowRoaming + "," + dataProfile);
- }
-
+ android.hardware.radio.V1_2.IRadio radioProxy12 =
+ android.hardware.radio.V1_2.IRadio.castFrom(radioProxy);
try {
- radioProxy.setupDataCall(rr.mSerial, radioTechnology, dpi,
- dataProfile.isModemCognitive(), allowRoaming, isRoaming);
- mMetrics.writeRilSetupDataCall(mPhoneId, rr.mSerial, radioTechnology, dpi.profileId,
- dpi.apn, dpi.authType, dpi.protocol);
+ if (radioProxy12 == null) {
+ // IRadio V1.0
+ if (RILJ_LOGD) {
+ riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ + ",radioTechnology=unknown,isRoaming=" + isRoaming
+ + ",allowRoaming=" + allowRoaming + "," + dataProfile);
+ }
+ // The RAT field in setup data call request was never used before. Starting from
+ // P, the new API passes in access network type instead of RAT. Since it's
+ // not possible to convert access network type back to RAT, but we still need to
+ // support the 1.0 API, we passed in unknown RAT to the modem. And modem must
+ // setup the data call on its current camped network.
+ radioProxy.setupDataCall(rr.mSerial, ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN,
+ dpi, dataProfile.isModemCognitive(), allowRoaming, isRoaming);
+ } else {
+ // IRadio V1.2
+ ArrayList<String> addresses = null;
+ ArrayList<String> dnses = null;
+ if (linkProperties != null) {
+ addresses = new ArrayList<>();
+ for (InetAddress address : linkProperties.getAddresses()) {
+ addresses.add(address.getHostAddress());
+ }
+ dnses = new ArrayList<>();
+ for (InetAddress dns : linkProperties.getDnsServers()) {
+ dnses.add(dns.getHostAddress());
+ }
+ }
+
+ if (RILJ_LOGD) {
+ riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ + ",accessNetworkType=" + accessNetworkType + ",isRoaming="
+ + isRoaming + ",allowRoaming=" + allowRoaming + "," + dataProfile
+ + ",addresses=" + addresses + ",dnses=" + dnses);
+ }
+
+ radioProxy12.setupDataCall_1_2(rr.mSerial, accessNetworkType, dpi,
+ dataProfile.isModemCognitive(), allowRoaming, isRoaming, reason,
+ addresses, dnses);
+ }
} catch (RemoteException | RuntimeException e) {
handleRadioProxyExceptionForRR(rr, "setupDataCall", e);
}
@@ -1531,10 +1567,17 @@
+ requestToString(rr.mRequest) + " cid = " + cid + " reason = " + reason);
}
+ android.hardware.radio.V1_2.IRadio radioProxy12 =
+ android.hardware.radio.V1_2.IRadio.castFrom(radioProxy);
+
try {
- radioProxy.deactivateDataCall(rr.mSerial, cid, (reason == 0) ? false : true);
- mMetrics.writeRilDeactivateDataCall(mPhoneId, rr.mSerial,
- cid, reason);
+ if (radioProxy12 == null) {
+ radioProxy.deactivateDataCall(rr.mSerial, cid,
+ (reason == DataService.REQUEST_REASON_SHUTDOWN));
+ } else {
+ radioProxy12.deactivateDataCall_1_2(rr.mSerial, cid, reason);
+ }
+ mMetrics.writeRilDeactivateDataCall(mPhoneId, rr.mSerial, cid, reason);
} catch (RemoteException | RuntimeException e) {
handleRadioProxyExceptionForRR(rr, "deactivateDataCall", e);
}
diff --git a/src/java/com/android/internal/telephony/RadioResponse.java b/src/java/com/android/internal/telephony/RadioResponse.java
index d12e35b..b636917 100644
--- a/src/java/com/android/internal/telephony/RadioResponse.java
+++ b/src/java/com/android/internal/telephony/RadioResponse.java
@@ -180,6 +180,15 @@
/**
* @param responseInfo Response info struct containing response type, serial no. and error
+ * @param calls Current call list
+ */
+ public void getCurrentCallsResponse_1_2(RadioResponseInfo responseInfo,
+ ArrayList<android.hardware.radio.V1_2.Call> calls) {
+ responseCurrentCalls_1_2(responseInfo, calls);
+ }
+
+ /**
+ * @param responseInfo Response info struct containing response type, serial no. and error
*/
public void dialResponse(RadioResponseInfo responseInfo) {
responseVoid(responseInfo);
@@ -1489,6 +1498,88 @@
}
}
+ private void responseCurrentCalls_1_2(RadioResponseInfo responseInfo,
+ ArrayList<android.hardware.radio.V1_2.Call> calls) {
+ RILRequest rr = mRil.processResponse(responseInfo);
+
+ if (rr != null) {
+ int num = calls.size();
+ ArrayList<DriverCall> dcCalls = new ArrayList<DriverCall>(num);
+ DriverCall dc;
+
+ for (int i = 0; i < num; i++) {
+ dc = new DriverCall();
+ // TODO: change name of function stateFromCLCC() in DriverCall.java to name
+ // clarifying what is CLCC
+ dc.state = DriverCall.stateFromCLCC((int) (calls.get(i).base.state));
+ dc.index = calls.get(i).base.index;
+ dc.TOA = calls.get(i).base.toa;
+ dc.isMpty = calls.get(i).base.isMpty;
+ dc.isMT = calls.get(i).base.isMT;
+ dc.als = calls.get(i).base.als;
+ dc.isVoice = calls.get(i).base.isVoice;
+ dc.isVoicePrivacy = calls.get(i).base.isVoicePrivacy;
+ dc.number = calls.get(i).base.number;
+ dc.numberPresentation =
+ DriverCall.presentationFromCLIP(
+ (int) (calls.get(i).base.numberPresentation));
+ dc.name = calls.get(i).base.name;
+ dc.namePresentation =
+ DriverCall.presentationFromCLIP((int) (calls.get(i).base.namePresentation));
+ if (calls.get(i).base.uusInfo.size() == 1) {
+ dc.uusInfo = new UUSInfo();
+ dc.uusInfo.setType(calls.get(i).base.uusInfo.get(0).uusType);
+ dc.uusInfo.setDcs(calls.get(i).base.uusInfo.get(0).uusDcs);
+ if (!TextUtils.isEmpty(calls.get(i).base.uusInfo.get(0).uusData)) {
+ byte[] userData = calls.get(i).base.uusInfo.get(0).uusData.getBytes();
+ dc.uusInfo.setUserData(userData);
+ } else {
+ mRil.riljLog("responseCurrentCalls: uusInfo data is null or empty");
+ }
+
+ mRil.riljLogv(String.format("Incoming UUS : type=%d, dcs=%d, length=%d",
+ dc.uusInfo.getType(), dc.uusInfo.getDcs(),
+ dc.uusInfo.getUserData().length));
+ mRil.riljLogv("Incoming UUS : data (hex): "
+ + IccUtils.bytesToHexString(dc.uusInfo.getUserData()));
+ } else {
+ mRil.riljLogv("Incoming UUS : NOT present!");
+ }
+
+ // Make sure there's a leading + on addresses with a TOA of 145
+ dc.number = PhoneNumberUtils.stringFromStringAndTOA(dc.number, dc.TOA);
+
+ dc.audioQuality = (int) (calls.get(i).audioQuality);
+
+ dcCalls.add(dc);
+
+ if (dc.isVoicePrivacy) {
+ mRil.mVoicePrivacyOnRegistrants.notifyRegistrants();
+ mRil.riljLog("InCall VoicePrivacy is enabled");
+ } else {
+ mRil.mVoicePrivacyOffRegistrants.notifyRegistrants();
+ mRil.riljLog("InCall VoicePrivacy is disabled");
+ }
+ }
+
+ Collections.sort(dcCalls);
+
+ if ((num == 0) && mRil.mTestingEmergencyCall.getAndSet(false)) {
+ if (mRil.mEmergencyCallbackModeRegistrant != null) {
+ mRil.riljLog("responseCurrentCalls: call ended, testing emergency call,"
+ + " notify ECM Registrants");
+ mRil.mEmergencyCallbackModeRegistrant.notifyRegistrant();
+ }
+ }
+
+ if (responseInfo.error == RadioError.NONE) {
+ sendMessageResponse(rr.mResult, dcCalls);
+ }
+ mRil.processResponseDone(rr, responseInfo, dcCalls);
+ }
+ }
+
+
private void responseVoid(RadioResponseInfo responseInfo) {
RILRequest rr = mRil.processResponse(responseInfo);
diff --git a/src/java/com/android/internal/telephony/SMSDispatcher.java b/src/java/com/android/internal/telephony/SMSDispatcher.java
index 2ec5101..0c160e2 100644
--- a/src/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/SMSDispatcher.java
@@ -61,6 +61,7 @@
import android.telephony.PhoneNumberUtils;
import android.telephony.Rlog;
import android.telephony.ServiceState;
+import android.telephony.SmsManager;
import android.telephony.TelephonyManager;
import android.text.Html;
import android.text.Spanned;
@@ -77,6 +78,7 @@
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.cdma.sms.UserData;
import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
import com.android.internal.telephony.uicc.UiccCard;
import com.android.internal.telephony.uicc.UiccController;
@@ -92,6 +94,13 @@
static final String TAG = "SMSDispatcher"; // accessed from inner class
static final boolean DBG = false;
private static final String SEND_NEXT_MSG_EXTRA = "SendNextMsg";
+ protected static final String MAP_KEY_PDU = "pdu";
+ protected static final String MAP_KEY_SMSC = "smsc";
+ protected static final String MAP_KEY_DEST_ADDR = "destAddr";
+ protected static final String MAP_KEY_SC_ADDR = "scAddr";
+ protected static final String MAP_KEY_DEST_PORT = "destPort";
+ protected static final String MAP_KEY_DATA = "data";
+ protected static final String MAP_KEY_TEXT = "text";
private static final int PREMIUM_RULE_USE_SIM = 1;
private static final int PREMIUM_RULE_USE_NETWORK = 2;
@@ -123,18 +132,11 @@
/** Handle status report from {@code CdmaInboundSmsHandler}. */
protected static final int EVENT_HANDLE_STATUS_REPORT = 10;
- /** Radio is ON */
- protected static final int EVENT_RADIO_ON = 11;
-
- /** IMS registration/SMS format changed */
- protected static final int EVENT_IMS_STATE_CHANGED = 12;
-
- /** Callback from RIL_REQUEST_IMS_REGISTRATION_STATE */
- protected static final int EVENT_IMS_STATE_DONE = 13;
-
// other
protected static final int EVENT_NEW_ICC_SMS = 14;
protected static final int EVENT_ICC_CHANGED = 15;
+ protected static final int EVENT_GET_IMS_SERVICE = 16;
+
protected Phone mPhone;
protected final Context mContext;
@@ -159,10 +161,7 @@
*/
private static int sConcatenatedRef = new Random().nextInt(256);
- /** Outgoing message counter. Shared by all dispatchers. */
- private SmsUsageMonitor mUsageMonitor;
-
- private ImsSMSDispatcher mImsSMSDispatcher;
+ protected SmsDispatchersController mSmsDispatchersController;
/** Number of outgoing SmsTrackers waiting for user confirmation. */
private int mPendingTrackerCount;
@@ -179,16 +178,13 @@
/**
* Create a new SMS dispatcher.
* @param phone the Phone to use
- * @param usageMonitor the SmsUsageMonitor to use
*/
- protected SMSDispatcher(Phone phone, SmsUsageMonitor usageMonitor,
- ImsSMSDispatcher imsSMSDispatcher) {
+ protected SMSDispatcher(Phone phone, SmsDispatchersController smsDispatchersController) {
mPhone = phone;
- mImsSMSDispatcher = imsSMSDispatcher;
+ mSmsDispatchersController = smsDispatchersController;
mContext = phone.getContext();
mResolver = mContext.getContentResolver();
mCi = phone.mCi;
- mUsageMonitor = usageMonitor;
mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
mSettingsObserver = new SettingsObserver(this, mPremiumSmsRule, mContext);
mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
@@ -224,7 +220,6 @@
protected void updatePhoneObject(Phone phone) {
mPhone = phone;
- mUsageMonitor = phone.mSmsUsageMonitor;
Rlog.d(TAG, "Active phone changed to " + mPhone.getPhoneName() );
}
@@ -392,7 +387,7 @@
@Override
protected void onServiceReady(ICarrierMessagingService carrierMessagingService) {
HashMap<String, Object> map = mTracker.getData();
- String text = (String) map.get("text");
+ String text = (String) map.get(MAP_KEY_TEXT);
if (text != null) {
try {
@@ -424,8 +419,8 @@
@Override
protected void onServiceReady(ICarrierMessagingService carrierMessagingService) {
HashMap<String, Object> map = mTracker.getData();
- byte[] data = (byte[]) map.get("data");
- int destPort = (int) map.get("destPort");
+ byte[] data = (byte[]) map.get(MAP_KEY_DATA);
+ int destPort = (int) map.get(MAP_KEY_DEST_PORT);
if (data != null) {
try {
@@ -630,7 +625,19 @@
/**
* Send an SMS PDU. Usually just calls {@link sendRawPdu}.
*/
- protected abstract void sendSubmitPdu(SmsTracker tracker);
+ private void sendSubmitPdu(SmsTracker tracker) {
+ if (shouldBlockSms()) {
+ Rlog.d(TAG, "Block SMS in Emergency Callback mode");
+ tracker.onFailed(mContext, SmsManager.RESULT_ERROR_NO_SERVICE, 0/*errorCode*/);
+ } else {
+ sendRawPdu(tracker);
+ }
+ }
+
+ /**
+ * @return true if MO SMS should be blocked.
+ */
+ protected abstract boolean shouldBlockSms();
/**
* Called when SMS send completes. Broadcasts a sentIntent on success.
@@ -727,7 +734,9 @@
} else {
sentIntent.send(RESULT_ERROR_NO_SERVICE);
}
- } catch (CanceledException ex) {}
+ } catch (CanceledException ex) {
+ Rlog.e(TAG, "Failed to send result");
+ }
}
}
@@ -768,8 +777,25 @@
* broadcast when the message is delivered to the recipient. The
* raw pdu of the status report is in the extended data ("pdu").
*/
- protected abstract void sendData(String destAddr, String scAddr, int destPort,
- byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent);
+ protected void sendData(String destAddr, String scAddr, int destPort,
+ byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
+ SmsMessageBase.SubmitPduBase pdu = getSubmitPdu(
+ scAddr, destAddr, destPort, data, (deliveryIntent != null));
+ if (pdu != null) {
+ HashMap map = getSmsTrackerMap(destAddr, scAddr, destPort, data, pdu);
+ SmsTracker tracker = getSmsTracker(map, sentIntent, deliveryIntent, getFormat(),
+ null /*messageUri*/, false /*isExpectMore*/,
+ null /*fullMessageText*/, false /*isText*/,
+ true /*persistMessage*/);
+
+ if (!sendSmsByCarrierApp(true /* isDataSms */, tracker)) {
+ sendSubmitPdu(tracker);
+ }
+ } else {
+ Rlog.e(TAG, "SMSDispatcher.sendData(): getSubmitPdu() returned null");
+ triggerSentIntentForFailure(sentIntent);
+ }
+ }
/**
* Send a text based SMS.
@@ -798,21 +824,59 @@
* @param persistMessage whether to save the sent message into SMS DB for a
* non-default SMS app.
*/
- protected abstract void sendText(String destAddr, String scAddr, String text,
- PendingIntent sentIntent, PendingIntent deliveryIntent, Uri messageUri,
- String callingPkg, boolean persistMessage);
+ public void sendText(String destAddr, String scAddr, String text,
+ PendingIntent sentIntent, PendingIntent deliveryIntent, Uri messageUri,
+ String callingPkg, boolean persistMessage) {
+ Rlog.d(TAG, "sendText");
+ SmsMessageBase.SubmitPduBase pdu = getSubmitPdu(
+ scAddr, destAddr, text, (deliveryIntent != null), null);
+ if (pdu != null) {
+ HashMap map = getSmsTrackerMap(destAddr, scAddr, text, pdu);
+ SmsTracker tracker = getSmsTracker(map, sentIntent, deliveryIntent, getFormat(),
+ messageUri, false /*isExpectMore*/, text, true /*isText*/,
+ persistMessage);
- /**
- * Inject an SMS PDU into the android platform.
- *
- * @param pdu is the byte array of pdu to be injected into android telephony layer
- * @param format is the format of SMS pdu (3gpp or 3gpp2)
- * @param receivedIntent if not NULL this <code>PendingIntent</code> is
- * broadcast when the message is successfully received by the
- * android telephony layer. This intent is broadcasted at
- * the same time an SMS received from radio is responded back.
- */
- protected abstract void injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent);
+ if (!sendSmsByCarrierApp(false /* isDataSms */, tracker)) {
+ sendSubmitPdu(tracker);
+ }
+ } else {
+ Rlog.e(TAG, "SmsDispatcher.sendText(): getSubmitPdu() returned null");
+ triggerSentIntentForFailure(sentIntent);
+ }
+ }
+
+ private void triggerSentIntentForFailure(PendingIntent sentIntent) {
+ if (sentIntent != null) {
+ try {
+ sentIntent.send(SmsManager.RESULT_ERROR_GENERIC_FAILURE);
+ } catch (CanceledException ex) {
+ Rlog.e(TAG, "Intent has been canceled!");
+ }
+ }
+ }
+
+ private boolean sendSmsByCarrierApp(boolean isDataSms, SmsTracker tracker ) {
+ String carrierPackage = getCarrierAppPackageName();
+ if (carrierPackage != null) {
+ Rlog.d(TAG, "Found carrier package.");
+ SmsSender smsSender;
+ if (isDataSms) {
+ smsSender = new DataSmsSender(tracker);
+ } else {
+ smsSender = new TextSmsSender(tracker);
+ }
+ smsSender.sendSmsByCarrierApp(carrierPackage, new SmsSenderCallback(smsSender));
+ return true;
+ }
+
+ return false;
+ }
+
+ protected abstract SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
+ String message, boolean statusReportRequested, SmsHeader smsHeader);
+
+ protected abstract SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
+ int destPort, byte[] message, boolean statusReportRequested);
/**
* Calculate the number of septets needed to encode the message. This function should only be
@@ -927,7 +991,8 @@
if (carrierPackage != null) {
Rlog.d(TAG, "Found carrier package.");
MultipartSmsSender smsSender = new MultipartSmsSender(parts, trackers);
- smsSender.sendSmsByCarrierApp(carrierPackage, new MultipartSmsSenderCallback(smsSender));
+ smsSender.sendSmsByCarrierApp(carrierPackage,
+ new MultipartSmsSenderCallback(smsSender));
} else {
Rlog.v(TAG, "No carrier package.");
for (SmsTracker tracker : trackers) {
@@ -943,11 +1008,57 @@
/**
* Create a new SubmitPdu and return the SMS tracker.
*/
- protected abstract SmsTracker getNewSubmitPduTracker(String destinationAddress, String scAddress,
+ private SmsTracker getNewSubmitPduTracker(String destinationAddress, String scAddress,
String message, SmsHeader smsHeader, int encoding,
PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart,
AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri,
- String fullMessageText);
+ String fullMessageText) {
+ if (isCdmaMo()) {
+ UserData uData = new UserData();
+ uData.payloadStr = message;
+ uData.userDataHeader = smsHeader;
+ if (encoding == SmsConstants.ENCODING_7BIT) {
+ uData.msgEncoding = UserData.ENCODING_GSM_7BIT_ALPHABET;
+ } else { // assume UTF-16
+ uData.msgEncoding = UserData.ENCODING_UNICODE_16;
+ }
+ uData.msgEncodingSet = true;
+
+ /* By setting the statusReportRequested bit only for the
+ * last message fragment, this will result in only one
+ * callback to the sender when that last fragment delivery
+ * has been acknowledged. */
+ //TODO FIX
+ SmsMessageBase.SubmitPduBase submitPdu =
+ com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(destinationAddress,
+ uData, (deliveryIntent != null) && lastPart);
+
+ HashMap map = getSmsTrackerMap(destinationAddress, scAddress,
+ message, submitPdu);
+ return getSmsTracker(map, sentIntent, deliveryIntent,
+ getFormat(), unsentPartCount, anyPartFailed, messageUri, smsHeader,
+ false /*isExpectMore*/, fullMessageText, true /*isText*/,
+ true /*persistMessage*/);
+
+ } else {
+ SmsMessageBase.SubmitPduBase pdu =
+ com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress,
+ destinationAddress, message, deliveryIntent != null,
+ SmsHeader.toByteArray(smsHeader), encoding, smsHeader.languageTable,
+ smsHeader.languageShiftTable);
+ if (pdu != null) {
+ HashMap map = getSmsTrackerMap(destinationAddress, scAddress,
+ message, pdu);
+ return getSmsTracker(map, sentIntent,
+ deliveryIntent, getFormat(), unsentPartCount, anyPartFailed, messageUri,
+ smsHeader, !lastPart, fullMessageText, true /*isText*/,
+ false /*persistMessage*/);
+ } else {
+ Rlog.e(TAG, "GsmSMSDispatcher.sendNewSubmitPdu(): getSubmitPdu() returned null");
+ return null;
+ }
+ }
+ }
/**
* Send an SMS
@@ -974,7 +1085,7 @@
@VisibleForTesting
public void sendRawPdu(SmsTracker tracker) {
HashMap map = tracker.getData();
- byte pdu[] = (byte[]) map.get("pdu");
+ byte pdu[] = (byte[]) map.get(MAP_KEY_PDU);
if (mSmsSendDisabled) {
Rlog.e(TAG, "Device does not support sending sms.");
@@ -1016,7 +1127,8 @@
// handler with the SmsTracker to request user confirmation before sending.
if (checkDestination(tracker)) {
// check for excessive outgoing SMS usage by this app
- if (!mUsageMonitor.check(appInfo.packageName, SINGLE_PART_SMS)) {
+ if (!mSmsDispatchersController.getUsageMonitor().check(
+ appInfo.packageName, SINGLE_PART_SMS)) {
sendMessage(obtainMessage(EVENT_SEND_LIMIT_REACHED_CONFIRMATION, tracker));
return;
}
@@ -1050,7 +1162,8 @@
simCountryIso = mTelephonyManager.getNetworkCountryIso();
}
- smsCategory = mUsageMonitor.checkDestination(tracker.mDestAddress, simCountryIso);
+ smsCategory = mSmsDispatchersController.getUsageMonitor().checkDestination(
+ tracker.mDestAddress, simCountryIso);
}
if (rule == PREMIUM_RULE_USE_NETWORK || rule == PREMIUM_RULE_USE_BOTH) {
String networkCountryIso = mTelephonyManager.getNetworkCountryIso();
@@ -1060,7 +1173,8 @@
}
smsCategory = SmsUsageMonitor.mergeShortCodeCategories(smsCategory,
- mUsageMonitor.checkDestination(tracker.mDestAddress, networkCountryIso));
+ mSmsDispatchersController.getUsageMonitor().checkDestination(
+ tracker.mDestAddress, networkCountryIso));
}
if (smsCategory == SmsUsageMonitor.CATEGORY_NOT_SHORT_CODE
@@ -1076,7 +1190,8 @@
}
// Wait for user confirmation unless the user has set permission to always allow/deny
- int premiumSmsPermission = mUsageMonitor.getPremiumSmsPermission(
+ int premiumSmsPermission =
+ mSmsDispatchersController.getUsageMonitor().getPremiumSmsPermission(
tracker.getAppPackageName());
if (premiumSmsPermission == SmsUsageMonitor.PREMIUM_SMS_PERMISSION_UNKNOWN) {
// First time trying to send to premium SMS.
@@ -1233,32 +1348,6 @@
}
/**
- * Returns the premium SMS permission for the specified package. If the package has never
- * been seen before, the default {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ASK_USER}
- * will be returned.
- * @param packageName the name of the package to query permission
- * @return one of {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_UNKNOWN},
- * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ASK_USER},
- * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_NEVER_ALLOW}, or
- * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW}
- */
- public int getPremiumSmsPermission(String packageName) {
- return mUsageMonitor.getPremiumSmsPermission(packageName);
- }
-
- /**
- * Sets the premium SMS permission for the specified package and save the value asynchronously
- * to persistent storage.
- * @param packageName the name of the package to set permission
- * @param permission one of {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ASK_USER},
- * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_NEVER_ALLOW}, or
- * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW}
- */
- public void setPremiumSmsPermission(String packageName, int permission) {
- mUsageMonitor.setPremiumSmsPermission(packageName, permission);
- }
-
- /**
* Send the message along to the radio.
*
* @param tracker holds the SMS message to send
@@ -1266,23 +1355,16 @@
protected abstract void sendSms(SmsTracker tracker);
/**
- * Send the SMS via the PSTN network.
- *
- * @param tracker holds the Sms tracker ready to be sent
- */
- protected abstract void sendSmsByPstn(SmsTracker tracker);
-
- /**
* Retry the message along to the radio.
*
* @param tracker holds the SMS message to send
*/
public void sendRetrySms(SmsTracker tracker) {
- // re-routing to ImsSMSDispatcher
- if (mImsSMSDispatcher != null) {
- mImsSMSDispatcher.sendRetrySms(tracker);
+ // re-routing to SmsDispatchersController
+ if (mSmsDispatchersController != null) {
+ mSmsDispatchersController.sendRetrySms(tracker);
} else {
- Rlog.e(TAG, mImsSMSDispatcher + " is null. Retry failed");
+ Rlog.e(TAG, mSmsDispatchersController + " is null. Retry failed");
}
}
@@ -1320,7 +1402,8 @@
}
sendMultipartText(destinationAddress, scAddress, parts, sentIntents, deliveryIntents,
- null/*messageUri*/, null/*callingPkg*/, tracker.mPersistMessage);
+ null/*messageUri*/, null/*callingPkg*/,
+ tracker.mPersistMessage);
}
/**
@@ -1632,30 +1715,30 @@
PendingIntent deliveryIntent, String format, Uri messageUri, boolean isExpectMore,
String fullMessageText, boolean isText, boolean persistMessage) {
return getSmsTracker(data, sentIntent, deliveryIntent, format, null/*unsentPartCount*/,
- null/*anyPartFailed*/, messageUri, null/*smsHeader*/, isExpectMore,
- fullMessageText, isText, persistMessage);
+ null/*anyPartFailed*/, messageUri, null/*smsHeader*/,
+ isExpectMore, fullMessageText, isText, persistMessage);
}
protected HashMap<String, Object> getSmsTrackerMap(String destAddr, String scAddr,
String text, SmsMessageBase.SubmitPduBase pdu) {
HashMap<String, Object> map = new HashMap<String, Object>();
- map.put("destAddr", destAddr);
- map.put("scAddr", scAddr);
- map.put("text", text);
- map.put("smsc", pdu.encodedScAddress);
- map.put("pdu", pdu.encodedMessage);
+ map.put(MAP_KEY_DEST_ADDR, destAddr);
+ map.put(MAP_KEY_SC_ADDR, scAddr);
+ map.put(MAP_KEY_TEXT, text);
+ map.put(MAP_KEY_SMSC, pdu.encodedScAddress);
+ map.put(MAP_KEY_PDU, pdu.encodedMessage);
return map;
}
protected HashMap<String, Object> getSmsTrackerMap(String destAddr, String scAddr,
int destPort, byte[] data, SmsMessageBase.SubmitPduBase pdu) {
HashMap<String, Object> map = new HashMap<String, Object>();
- map.put("destAddr", destAddr);
- map.put("scAddr", scAddr);
- map.put("destPort", destPort);
- map.put("data", data);
- map.put("smsc", pdu.encodedScAddress);
- map.put("pdu", pdu.encodedMessage);
+ map.put(MAP_KEY_DEST_ADDR, destAddr);
+ map.put(MAP_KEY_SC_ADDR, scAddr);
+ map.put(MAP_KEY_DEST_PORT, destPort);
+ map.put(MAP_KEY_DATA, data);
+ map.put(MAP_KEY_SMSC, pdu.encodedScAddress);
+ map.put(MAP_KEY_PDU, pdu.encodedMessage);
return map;
}
@@ -1720,7 +1803,8 @@
}
sendMessage(msg);
}
- setPremiumSmsPermission(mTracker.getAppPackageName(), newSmsPermission);
+ mSmsDispatchersController.setPremiumSmsPermission(mTracker.getAppPackageName(),
+ newSmsPermission);
}
@Override
@@ -1755,23 +1839,14 @@
}
public boolean isIms() {
- if (mImsSMSDispatcher != null) {
- return mImsSMSDispatcher.isIms();
+ if (mSmsDispatchersController != null) {
+ return mSmsDispatchersController.isIms();
} else {
- Rlog.e(TAG, mImsSMSDispatcher + " is null");
+ Rlog.e(TAG, "mSmsDispatchersController is null");
return false;
}
}
- public String getImsSmsFormat() {
- if (mImsSMSDispatcher != null) {
- return mImsSMSDispatcher.getImsSmsFormat();
- } else {
- Rlog.e(TAG, mImsSMSDispatcher + " is null");
- return null;
- }
- }
-
private String getMultipartMessageText(ArrayList<String> parts) {
final StringBuilder sb = new StringBuilder();
for (String part : parts) {
@@ -1819,4 +1894,8 @@
throw new SecurityException("Caller is not phone or carrier app!");
}
}
+
+ protected boolean isCdmaMo() {
+ return mSmsDispatchersController.isCdmaMo();
+ }
}
diff --git a/src/java/com/android/internal/telephony/SmsDispatchersController.java b/src/java/com/android/internal/telephony/SmsDispatchersController.java
new file mode 100644
index 0000000..f62a90a
--- /dev/null
+++ b/src/java/com/android/internal/telephony/SmsDispatchersController.java
@@ -0,0 +1,562 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+package com.android.internal.telephony;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.app.PendingIntent.CanceledException;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.provider.Telephony.Sms;
+import android.provider.Telephony.Sms.Intents;
+import android.telephony.Rlog;
+import android.telephony.SmsManager;
+import android.util.Pair;
+
+import com.android.ims.ImsManager;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.cdma.CdmaInboundSmsHandler;
+import com.android.internal.telephony.cdma.CdmaSMSDispatcher;
+import com.android.internal.telephony.gsm.GsmInboundSmsHandler;
+import com.android.internal.telephony.gsm.GsmSMSDispatcher;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ *
+ */
+public class SmsDispatchersController extends Handler {
+ private static final String TAG = "SmsDispatchersController";
+
+ /** Radio is ON */
+ private static final int EVENT_RADIO_ON = 11;
+
+ /** IMS registration/SMS format changed */
+ private static final int EVENT_IMS_STATE_CHANGED = 12;
+
+ /** Callback from RIL_REQUEST_IMS_REGISTRATION_STATE */
+ private static final int EVENT_IMS_STATE_DONE = 13;
+
+ private SMSDispatcher mCdmaDispatcher;
+ private SMSDispatcher mGsmDispatcher;
+ private ImsSmsDispatcher mImsSmsDispatcher;
+
+ private GsmInboundSmsHandler mGsmInboundSmsHandler;
+ private CdmaInboundSmsHandler mCdmaInboundSmsHandler;
+
+ private Phone mPhone;
+ /** Outgoing message counter. Shared by all dispatchers. */
+ private final SmsUsageMonitor mUsageMonitor;
+ private final CommandsInterface mCi;
+ private final Context mContext;
+
+ /** true if IMS is registered and sms is supported, false otherwise.*/
+ private boolean mIms = false;
+ private String mImsSmsFormat = SmsConstants.FORMAT_UNKNOWN;
+
+ public SmsDispatchersController(Phone phone, SmsStorageMonitor storageMonitor,
+ SmsUsageMonitor usageMonitor) {
+ Rlog.d(TAG, "SmsDispatchersController created");
+
+ mContext = phone.getContext();
+ mUsageMonitor = usageMonitor;
+ mCi = phone.mCi;
+ mPhone = phone;
+
+ // Create dispatchers, inbound SMS handlers and
+ // broadcast undelivered messages in raw table.
+ mImsSmsDispatcher = new ImsSmsDispatcher(phone, this);
+ mCdmaDispatcher = new CdmaSMSDispatcher(phone, this);
+ mGsmInboundSmsHandler = GsmInboundSmsHandler.makeInboundSmsHandler(phone.getContext(),
+ storageMonitor, phone);
+ mCdmaInboundSmsHandler = CdmaInboundSmsHandler.makeInboundSmsHandler(phone.getContext(),
+ storageMonitor, phone, (CdmaSMSDispatcher) mCdmaDispatcher);
+ mGsmDispatcher = new GsmSMSDispatcher(phone, this, mGsmInboundSmsHandler);
+ SmsBroadcastUndelivered.initialize(phone.getContext(),
+ mGsmInboundSmsHandler, mCdmaInboundSmsHandler);
+ InboundSmsHandler.registerNewMessageNotificationActionHandler(phone.getContext());
+
+ mCi.registerForOn(this, EVENT_RADIO_ON, null);
+ mCi.registerForImsNetworkStateChanged(this, EVENT_IMS_STATE_CHANGED, null);
+ }
+
+ /* Updates the phone object when there is a change */
+ protected void updatePhoneObject(Phone phone) {
+ Rlog.d(TAG, "In IMS updatePhoneObject ");
+ mCdmaDispatcher.updatePhoneObject(phone);
+ mGsmDispatcher.updatePhoneObject(phone);
+ mGsmInboundSmsHandler.updatePhoneObject(phone);
+ mCdmaInboundSmsHandler.updatePhoneObject(phone);
+ }
+
+ public void dispose() {
+ mCi.unregisterForOn(this);
+ mCi.unregisterForImsNetworkStateChanged(this);
+ mGsmDispatcher.dispose();
+ mCdmaDispatcher.dispose();
+ mGsmInboundSmsHandler.dispose();
+ mCdmaInboundSmsHandler.dispose();
+ }
+
+ /**
+ * Handles events coming from the phone stack. Overridden from handler.
+ *
+ * @param msg the message to handle
+ */
+ @Override
+ public void handleMessage(Message msg) {
+ AsyncResult ar;
+
+ switch (msg.what) {
+ case EVENT_RADIO_ON:
+ case EVENT_IMS_STATE_CHANGED: // received unsol
+ mCi.getImsRegistrationState(this.obtainMessage(EVENT_IMS_STATE_DONE));
+ break;
+
+ case EVENT_IMS_STATE_DONE:
+ ar = (AsyncResult) msg.obj;
+
+ if (ar.exception == null) {
+ updateImsInfo(ar);
+ } else {
+ Rlog.e(TAG, "IMS State query failed with exp "
+ + ar.exception);
+ }
+ break;
+
+ default:
+ if (isCdmaMo()) {
+ mCdmaDispatcher.handleMessage(msg);
+ } else {
+ mGsmDispatcher.handleMessage(msg);
+ }
+ }
+ }
+
+ private void setImsSmsFormat(int format) {
+ switch (format) {
+ case PhoneConstants.PHONE_TYPE_GSM:
+ mImsSmsFormat = SmsConstants.FORMAT_3GPP;
+ break;
+ case PhoneConstants.PHONE_TYPE_CDMA:
+ mImsSmsFormat = SmsConstants.FORMAT_3GPP2;
+ break;
+ default:
+ mImsSmsFormat = SmsConstants.FORMAT_UNKNOWN;
+ break;
+ }
+ }
+
+ private void updateImsInfo(AsyncResult ar) {
+ int[] responseArray = (int[]) ar.result;
+ setImsSmsFormat(responseArray[1]);
+ mIms = responseArray[0] == 1 && !SmsConstants.FORMAT_UNKNOWN.equals(mImsSmsFormat);
+ Rlog.d(TAG, "IMS registration state: " + mIms + " format: " + mImsSmsFormat);
+ }
+
+ /**
+ * Inject an SMS PDU into the android platform.
+ *
+ * @param pdu is the byte array of pdu to be injected into android telephony layer
+ * @param format is the format of SMS pdu (3gpp or 3gpp2)
+ * @param callback if not NULL this callback is triggered when the message is successfully
+ * received by the android telephony layer. This callback is triggered at
+ * the same time an SMS received from radio is responded back.
+ */
+ @VisibleForTesting
+ public void injectSmsPdu(byte[] pdu, String format, SmsInjectionCallback callback) {
+ Rlog.d(TAG, "SmsDispatchersController:injectSmsPdu");
+ try {
+ // TODO We need to decide whether we should allow injecting GSM(3gpp)
+ // SMS pdus when the phone is camping on CDMA(3gpp2) network and vice versa.
+ android.telephony.SmsMessage msg =
+ android.telephony.SmsMessage.createFromPdu(pdu, format);
+
+ // Only class 1 SMS are allowed to be injected.
+ if (msg == null
+ || msg.getMessageClass() != android.telephony.SmsMessage.MessageClass.CLASS_1) {
+ if (msg == null) {
+ Rlog.e(TAG, "injectSmsPdu: createFromPdu returned null");
+ }
+ callback.onSmsInjectedResult(Intents.RESULT_SMS_GENERIC_ERROR);
+ return;
+ }
+
+ AsyncResult ar = new AsyncResult(callback, msg, null);
+
+ if (format.equals(SmsConstants.FORMAT_3GPP)) {
+ Rlog.i(TAG, "SmsDispatchersController:injectSmsText Sending msg=" + msg
+ + ", format=" + format + "to mGsmInboundSmsHandler");
+ mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_INJECT_SMS, ar);
+ } else if (format.equals(SmsConstants.FORMAT_3GPP2)) {
+ Rlog.i(TAG, "SmsDispatchersController:injectSmsText Sending msg=" + msg
+ + ", format=" + format + "to mCdmaInboundSmsHandler");
+ mCdmaInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_INJECT_SMS, ar);
+ } else {
+ // Invalid pdu format.
+ Rlog.e(TAG, "Invalid pdu format: " + format);
+ callback.onSmsInjectedResult(Intents.RESULT_SMS_GENERIC_ERROR);
+ }
+ } catch (Exception e) {
+ Rlog.e(TAG, "injectSmsPdu failed: ", e);
+ callback.onSmsInjectedResult(Intents.RESULT_SMS_GENERIC_ERROR);
+ }
+ }
+
+ /**
+ * Retry the message along to the radio.
+ *
+ * @param tracker holds the SMS message to send
+ */
+ public void sendRetrySms(SMSDispatcher.SmsTracker tracker) {
+ String oldFormat = tracker.mFormat;
+
+ // newFormat will be based on voice technology
+ String newFormat =
+ (PhoneConstants.PHONE_TYPE_CDMA == mPhone.getPhoneType())
+ ? mCdmaDispatcher.getFormat() : mGsmDispatcher.getFormat();
+
+ // was previously sent sms format match with voice tech?
+ if (oldFormat.equals(newFormat)) {
+ if (isCdmaFormat(newFormat)) {
+ Rlog.d(TAG, "old format matched new format (cdma)");
+ mCdmaDispatcher.sendSms(tracker);
+ return;
+ } else {
+ Rlog.d(TAG, "old format matched new format (gsm)");
+ mGsmDispatcher.sendSms(tracker);
+ return;
+ }
+ }
+
+ // format didn't match, need to re-encode.
+ HashMap map = tracker.getData();
+
+ // to re-encode, fields needed are: scAddr, destAddr, and
+ // text if originally sent as sendText or
+ // data and destPort if originally sent as sendData.
+ if (!(map.containsKey("scAddr") && map.containsKey("destAddr")
+ && (map.containsKey("text")
+ || (map.containsKey("data") && map.containsKey("destPort"))))) {
+ // should never come here...
+ Rlog.e(TAG, "sendRetrySms failed to re-encode per missing fields!");
+ tracker.onFailed(mContext, SmsManager.RESULT_ERROR_GENERIC_FAILURE, 0/*errorCode*/);
+ return;
+ }
+ String scAddr = (String) map.get("scAddr");
+ String destAddr = (String) map.get("destAddr");
+
+ SmsMessageBase.SubmitPduBase pdu = null;
+ // figure out from tracker if this was sendText/Data
+ if (map.containsKey("text")) {
+ Rlog.d(TAG, "sms failed was text");
+ String text = (String) map.get("text");
+
+ if (isCdmaFormat(newFormat)) {
+ Rlog.d(TAG, "old format (gsm) ==> new format (cdma)");
+ pdu = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(
+ scAddr, destAddr, text, (tracker.mDeliveryIntent != null), null);
+ } else {
+ Rlog.d(TAG, "old format (cdma) ==> new format (gsm)");
+ pdu = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(
+ scAddr, destAddr, text, (tracker.mDeliveryIntent != null), null);
+ }
+ } else if (map.containsKey("data")) {
+ Rlog.d(TAG, "sms failed was data");
+ byte[] data = (byte[]) map.get("data");
+ Integer destPort = (Integer) map.get("destPort");
+
+ if (isCdmaFormat(newFormat)) {
+ Rlog.d(TAG, "old format (gsm) ==> new format (cdma)");
+ pdu = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(
+ scAddr, destAddr, destPort.intValue(), data,
+ (tracker.mDeliveryIntent != null));
+ } else {
+ Rlog.d(TAG, "old format (cdma) ==> new format (gsm)");
+ pdu = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(
+ scAddr, destAddr, destPort.intValue(), data,
+ (tracker.mDeliveryIntent != null));
+ }
+ }
+
+ // replace old smsc and pdu with newly encoded ones
+ map.put("smsc", pdu.encodedScAddress);
+ map.put("pdu", pdu.encodedMessage);
+
+ SMSDispatcher dispatcher = (isCdmaFormat(newFormat)) ? mCdmaDispatcher : mGsmDispatcher;
+
+ tracker.mFormat = dispatcher.getFormat();
+ dispatcher.sendSms(tracker);
+ }
+
+ public boolean isIms() {
+ return mIms;
+ }
+
+ public String getImsSmsFormat() {
+ return mImsSmsFormat;
+ }
+
+ /**
+ * Determines whether or not to use CDMA format for MO SMS.
+ * If SMS over IMS is supported, then format is based on IMS SMS format,
+ * otherwise format is based on current phone type.
+ *
+ * @return true if Cdma format should be used for MO SMS, false otherwise.
+ */
+ protected boolean isCdmaMo() {
+ if (!isIms()) {
+ // IMS is not registered, use Voice technology to determine SMS format.
+ return (PhoneConstants.PHONE_TYPE_CDMA == mPhone.getPhoneType());
+ }
+ // IMS is registered with SMS support
+ return isCdmaFormat(mImsSmsFormat);
+ }
+
+ /**
+ * Determines whether or not format given is CDMA format.
+ *
+ * @param format
+ * @return true if format given is CDMA format, false otherwise.
+ */
+ public boolean isCdmaFormat(String format) {
+ return (mCdmaDispatcher.getFormat().equals(format));
+ }
+
+ /**
+ * Send a data based SMS to a specific application port.
+ *
+ * @param destAddr the address to send the message to
+ * @param scAddr is the service center address or null to use
+ * the current default SMSC
+ * @param destPort the port to deliver the message to
+ * @param data the body of the message to send
+ * @param sentIntent if not NULL this <code>PendingIntent</code> is
+ * broadcast when the message is successfully sent, or failed.
+ * The result code will be <code>Activity.RESULT_OK<code> for success,
+ * or one of these errors:<br>
+ * <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
+ * <code>RESULT_ERROR_RADIO_OFF</code><br>
+ * <code>RESULT_ERROR_NULL_PDU</code><br>
+ * <code>RESULT_ERROR_NO_SERVICE</code><br>.
+ * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
+ * the extra "errorCode" containing a radio technology specific value,
+ * generally only useful for troubleshooting.<br>
+ * The per-application based SMS control checks sentIntent. If sentIntent
+ * is NULL the caller will be checked against all unknown applications,
+ * which cause smaller number of SMS to be sent in checking period.
+ * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
+ * broadcast when the message is delivered to the recipient. The
+ * raw pdu of the status report is in the extended data ("pdu").
+ */
+ protected void sendData(String destAddr, String scAddr, int destPort,
+ byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
+ if (mImsSmsDispatcher.isAvailable()) {
+ mImsSmsDispatcher.sendData(destAddr, scAddr, destPort, data, sentIntent,
+ deliveryIntent);
+ } else if (isCdmaMo()) {
+ mCdmaDispatcher.sendData(destAddr, scAddr, destPort, data, sentIntent, deliveryIntent);
+ } else {
+ mGsmDispatcher.sendData(destAddr, scAddr, destPort, data, sentIntent, deliveryIntent);
+ }
+ }
+
+ /**
+ * Send a text based SMS.
+ * @param destAddr the address to send the message to
+ * @param scAddr is the service center address or null to use
+ * the current default SMSC
+ * @param text the body of the message to send
+ * @param sentIntent if not NULL this <code>PendingIntent</code> is
+ * broadcast when the message is successfully sent, or failed.
+ * The result code will be <code>Activity.RESULT_OK<code> for success,
+ * or one of these errors:<br>
+ * <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
+ * <code>RESULT_ERROR_RADIO_OFF</code><br>
+ * <code>RESULT_ERROR_NULL_PDU</code><br>
+ * <code>RESULT_ERROR_NO_SERVICE</code><br>.
+ * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
+ * the extra "errorCode" containing a radio technology specific value,
+ * generally only useful for troubleshooting.<br>
+ * The per-application based SMS control checks sentIntent. If sentIntent
+ * is NULL the caller will be checked against all unknown applications,
+ * which cause smaller number of SMS to be sent in checking period.
+ * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
+ * broadcast when the message is delivered to the recipient. The
+ * @param messageUri optional URI of the message if it is already stored in the system
+ * @param callingPkg the calling package name
+ * @param persistMessage whether to save the sent message into SMS DB for a
+ * non-default SMS app.
+ */
+ public void sendText(String destAddr, String scAddr, String text,
+ PendingIntent sentIntent, PendingIntent deliveryIntent, Uri messageUri,
+ String callingPkg, boolean persistMessage) {
+ if (mImsSmsDispatcher.isAvailable()) {
+ mImsSmsDispatcher.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent,
+ messageUri, callingPkg, persistMessage);
+ } else if (isCdmaMo()) {
+ mCdmaDispatcher.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent, messageUri,
+ callingPkg, persistMessage);
+ } else {
+ mGsmDispatcher.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent, messageUri,
+ callingPkg, persistMessage);
+ }
+ }
+
+ /**
+ * Send a multi-part text based SMS.
+ * @param destAddr the address to send the message to
+ * @param scAddr is the service center address or null to use
+ * the current default SMSC
+ * @param parts an <code>ArrayList</code> of strings that, in order,
+ * comprise the original message
+ * @param sentIntents if not null, an <code>ArrayList</code> of
+ * <code>PendingIntent</code>s (one for each message part) that is
+ * broadcast when the corresponding message part has been sent.
+ * The result code will be <code>Activity.RESULT_OK<code> for success,
+ * or one of these errors:
+ * <code>RESULT_ERROR_GENERIC_FAILURE</code>
+ * <code>RESULT_ERROR_RADIO_OFF</code>
+ * <code>RESULT_ERROR_NULL_PDU</code>
+ * <code>RESULT_ERROR_NO_SERVICE</code>.
+ * The per-application based SMS control checks sentIntent. If sentIntent
+ * is NULL the caller will be checked against all unknown applications,
+ * which cause smaller number of SMS to be sent in checking period.
+ * @param deliveryIntents if not null, an <code>ArrayList</code> of
+ * <code>PendingIntent</code>s (one for each message part) that is
+ * broadcast when the corresponding message part has been delivered
+ * to the recipient. The raw pdu of the status report is in the
+ * @param messageUri optional URI of the message if it is already stored in the system
+ * @param callingPkg the calling package name
+ * @param persistMessage whether to save the sent message into SMS DB for a
+ * non-default SMS app.
+ */
+ protected void sendMultipartText(String destAddr, String scAddr,
+ ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,
+ ArrayList<PendingIntent> deliveryIntents, Uri messageUri, String callingPkg,
+ boolean persistMessage) {
+ if (mImsSmsDispatcher.isAvailable()) {
+ mImsSmsDispatcher.sendMultipartText(destAddr, scAddr, parts, sentIntents,
+ deliveryIntents, messageUri, callingPkg, persistMessage);
+ } else if (isCdmaMo()) {
+ mCdmaDispatcher.sendMultipartText(destAddr, scAddr, parts, sentIntents, deliveryIntents,
+ messageUri, callingPkg, persistMessage);
+ } else {
+ mGsmDispatcher.sendMultipartText(destAddr, scAddr, parts, sentIntents, deliveryIntents,
+ messageUri, callingPkg, persistMessage);
+ }
+ }
+
+ /**
+ * Returns the premium SMS permission for the specified package. If the package has never
+ * been seen before, the default {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ASK_USER}
+ * will be returned.
+ * @param packageName the name of the package to query permission
+ * @return one of {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_UNKNOWN},
+ * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ASK_USER},
+ * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_NEVER_ALLOW}, or
+ * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW}
+ */
+ public int getPremiumSmsPermission(String packageName) {
+ return mUsageMonitor.getPremiumSmsPermission(packageName);
+ }
+
+ /**
+ * Sets the premium SMS permission for the specified package and save the value asynchronously
+ * to persistent storage.
+ * @param packageName the name of the package to set permission
+ * @param permission one of {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ASK_USER},
+ * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_NEVER_ALLOW}, or
+ * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW}
+ */
+ public void setPremiumSmsPermission(String packageName, int permission) {
+ mUsageMonitor.setPremiumSmsPermission(packageName, permission);
+ }
+
+ public SmsUsageMonitor getUsageMonitor() {
+ return mUsageMonitor;
+ }
+
+ /**
+ * Triggers the correct method for handling the sms status report based on the format.
+ *
+ * @param tracker the sms tracker.
+ * @param format the format.
+ * @param pdu the pdu of the report.
+ * @return a Pair in which the first boolean is whether the report was handled successfully
+ * or not and the second boolean is whether processing the sms is complete and the
+ * tracker no longer need to be kept track of, false if we should expect more callbacks
+ * and the tracker should be kept.
+ */
+ public Pair<Boolean, Boolean> handleSmsStatusReport(SMSDispatcher.SmsTracker tracker,
+ String format, byte[] pdu) {
+ if (isCdmaFormat(format)) {
+ return handleCdmaStatusReport(tracker, format, pdu);
+ } else {
+ return handleGsmStatusReport(tracker, format, pdu);
+ }
+ }
+
+ private Pair<Boolean, Boolean> handleCdmaStatusReport(SMSDispatcher.SmsTracker tracker,
+ String format, byte[] pdu) {
+ tracker.updateSentMessageStatus(mContext, Sms.STATUS_COMPLETE);
+ boolean success = triggerDeliveryIntent(tracker, format, pdu);
+ return new Pair(success, true /* complete */);
+ }
+
+ private Pair<Boolean, Boolean> handleGsmStatusReport(SMSDispatcher.SmsTracker tracker,
+ String format, byte[] pdu) {
+ com.android.internal.telephony.gsm.SmsMessage sms =
+ com.android.internal.telephony.gsm.SmsMessage.newFromCDS(pdu);
+ boolean complete = false;
+ boolean success = false;
+ if (sms != null) {
+ int tpStatus = sms.getStatus();
+ if(tpStatus >= Sms.STATUS_FAILED || tpStatus < Sms.STATUS_PENDING ) {
+ // Update the message status (COMPLETE or FAILED)
+ tracker.updateSentMessageStatus(mContext, tpStatus);
+ complete = true;
+ }
+ success = triggerDeliveryIntent(tracker, format, pdu);
+ }
+ return new Pair(success, complete);
+ }
+
+ private boolean triggerDeliveryIntent(SMSDispatcher.SmsTracker tracker, String format,
+ byte[] pdu) {
+ PendingIntent intent = tracker.mDeliveryIntent;
+ Intent fillIn = new Intent();
+ fillIn.putExtra("pdu", pdu);
+ fillIn.putExtra("format", format);
+ try {
+ intent.send(mContext, Activity.RESULT_OK, fillIn);
+ return true;
+ } catch (CanceledException ex) {
+ return false;
+ }
+ }
+
+
+ public interface SmsInjectionCallback {
+ void onSmsInjectedResult(int result);
+ }
+}
diff --git a/src/java/com/android/internal/telephony/SubscriptionMonitor.java b/src/java/com/android/internal/telephony/SubscriptionMonitor.java
index 4307875..8ccec6f 100644
--- a/src/java/com/android/internal/telephony/SubscriptionMonitor.java
+++ b/src/java/com/android/internal/telephony/SubscriptionMonitor.java
@@ -70,7 +70,7 @@
public SubscriptionMonitor(ITelephonyRegistry tr, Context context,
SubscriptionController subscriptionController, int numPhones) {
try {
- tr.addOnSubscriptionsChangedListener("SubscriptionMonitor",
+ tr.addOnSubscriptionsChangedListener(context.getOpPackageName(),
mSubscriptionsChangedListener);
} catch (RemoteException e) {
}
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/src/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
index 1cfdc33..97f4c83 100755
--- a/src/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -20,38 +20,31 @@
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
import android.content.Intent;
-import android.net.Uri;
import android.os.Message;
-import android.os.SystemProperties;
import android.provider.Telephony.Sms;
import android.telephony.Rlog;
import android.telephony.ServiceState;
-import android.telephony.SmsManager;
import android.telephony.TelephonyManager;
+import android.util.Pair;
-import com.android.internal.telephony.GsmAlphabet;
import com.android.internal.telephony.GsmCdmaPhone;
-import com.android.internal.telephony.ImsSMSDispatcher;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.telephony.SMSDispatcher;
import com.android.internal.telephony.SmsConstants;
+import com.android.internal.telephony.SMSDispatcher;
+import com.android.internal.telephony.SmsDispatchersController;
import com.android.internal.telephony.SmsHeader;
-import com.android.internal.telephony.SmsUsageMonitor;
-import com.android.internal.telephony.TelephonyProperties;
-import com.android.internal.telephony.cdma.sms.UserData;
+import com.android.internal.telephony.util.SMSDispatcherUtil;
+import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
+import com.android.internal.telephony.SmsMessageBase;
-import java.util.HashMap;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
public class CdmaSMSDispatcher extends SMSDispatcher {
private static final String TAG = "CdmaSMSDispatcher";
private static final boolean VDBG = false;
- public CdmaSMSDispatcher(Phone phone, SmsUsageMonitor usageMonitor,
- ImsSMSDispatcher imsSMSDispatcher) {
- super(phone, usageMonitor, imsSMSDispatcher);
+ public CdmaSMSDispatcher(Phone phone, SmsDispatchersController smsDispatchersController) {
+ super(phone, smsDispatchersController);
Rlog.d(TAG, "CdmaSMSDispatcher created");
}
@@ -79,6 +72,29 @@
}
}
+ @Override
+ protected boolean shouldBlockSms() {
+ return SMSDispatcherUtil.shouldBlockSms(isCdmaMo(), mPhone);
+ }
+
+ @Override
+ protected SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
+ String message, boolean statusReportRequested, SmsHeader smsHeader) {
+ return SMSDispatcherUtil.getSubmitPduCdma(scAddr, destAddr, message,
+ statusReportRequested, smsHeader);
+ }
+
+ @Override
+ protected SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
+ int destPort, byte[] message, boolean statusReportRequested) {
+ return SMSDispatcherUtil.getSubmitPduCdma(scAddr, destAddr, destPort, message,
+ statusReportRequested);
+ }
+
+ @Override
+ protected TextEncodingDetails calculateLength(CharSequence messageBody, boolean use7bitOnly) {
+ return SMSDispatcherUtil.calculateLengthCdma(messageBody, use7bitOnly);
+ }
/**
* Called from parent class to handle status report from {@code CdmaInboundSmsHandler}.
* @param sms the CDMA SMS message to process
@@ -87,18 +103,12 @@
for (int i = 0, count = deliveryPendingList.size(); i < count; i++) {
SmsTracker tracker = deliveryPendingList.get(i);
if (tracker.mMessageRef == sms.mMessageRef) {
- // Found it. Remove from list and broadcast.
- deliveryPendingList.remove(i);
- // Update the message status (COMPLETE)
- tracker.updateSentMessageStatus(mContext, Sms.STATUS_COMPLETE);
-
- PendingIntent intent = tracker.mDeliveryIntent;
- Intent fillIn = new Intent();
- fillIn.putExtra("pdu", sms.getPdu());
- fillIn.putExtra("format", getFormat());
- try {
- intent.send(mContext, Activity.RESULT_OK, fillIn);
- } catch (CanceledException ex) {}
+ Pair<Boolean, Boolean> result =
+ mSmsDispatchersController.handleSmsStatusReport(tracker, getFormat(),
+ sms.getPdu());
+ if (result.second) {
+ deliveryPendingList.remove(i);
+ }
break; // Only expect to see one tracker matching this message.
}
}
@@ -106,129 +116,6 @@
/** {@inheritDoc} */
@Override
- public void sendData(String destAddr, String scAddr, int destPort,
- byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
- SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
- scAddr, destAddr, destPort, data, (deliveryIntent != null));
- if (pdu != null) {
- HashMap map = getSmsTrackerMap(destAddr, scAddr, destPort, data, pdu);
- SmsTracker tracker = getSmsTracker(map, sentIntent, deliveryIntent, getFormat(),
- null /*messageUri*/, false /*isExpectMore*/, null /*fullMessageText*/,
- false /*isText*/, true /*persistMessage*/);
-
- 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.");
- sendSubmitPdu(tracker);
- }
- } else {
- Rlog.e(TAG, "CdmaSMSDispatcher.sendData(): getSubmitPdu() returned null");
- if (sentIntent != null) {
- try {
- sentIntent.send(SmsManager.RESULT_ERROR_GENERIC_FAILURE);
- } catch (CanceledException ex) {
- Rlog.e(TAG, "Intent has been canceled!");
- }
- }
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public void sendText(String destAddr, String scAddr, String text, PendingIntent sentIntent,
- PendingIntent deliveryIntent, Uri messageUri, String callingPkg,
- boolean persistMessage) {
- SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
- scAddr, destAddr, text, (deliveryIntent != null), null);
- if (pdu != null) {
- HashMap map = getSmsTrackerMap(destAddr, scAddr, text, pdu);
- SmsTracker tracker = getSmsTracker(map, sentIntent, deliveryIntent, getFormat(),
- messageUri, false /*isExpectMore*/, text, true /*isText*/, persistMessage);
-
- 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.");
- sendSubmitPdu(tracker);
- }
- } else {
- Rlog.e(TAG, "CdmaSMSDispatcher.sendText(): getSubmitPdu() returned null");
- if (sentIntent != null) {
- try {
- sentIntent.send(SmsManager.RESULT_ERROR_GENERIC_FAILURE);
- } catch (CanceledException ex) {
- Rlog.e(TAG, "Intent has been canceled!");
- }
- }
- }
- }
-
- /** {@inheritDoc} */
- @Override
- protected void injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent) {
- throw new IllegalStateException("This method must be called only on ImsSMSDispatcher");
- }
-
- /** {@inheritDoc} */
- @Override
- protected GsmAlphabet.TextEncodingDetails calculateLength(CharSequence messageBody,
- boolean use7bitOnly) {
- return SmsMessage.calculateLength(messageBody, use7bitOnly, false);
- }
-
- /** {@inheritDoc} */
- @Override
- protected SmsTracker getNewSubmitPduTracker(String destinationAddress, String scAddress,
- String message, SmsHeader smsHeader, int encoding,
- PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart,
- AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri,
- String fullMessageText) {
- UserData uData = new UserData();
- uData.payloadStr = message;
- uData.userDataHeader = smsHeader;
- if (encoding == SmsConstants.ENCODING_7BIT) {
- uData.msgEncoding = UserData.ENCODING_GSM_7BIT_ALPHABET;
- } else { // assume UTF-16
- uData.msgEncoding = UserData.ENCODING_UNICODE_16;
- }
- uData.msgEncodingSet = true;
-
- /* By setting the statusReportRequested bit only for the
- * last message fragment, this will result in only one
- * callback to the sender when that last fragment delivery
- * has been acknowledged. */
- SmsMessage.SubmitPdu submitPdu = SmsMessage.getSubmitPdu(destinationAddress,
- uData, (deliveryIntent != null) && lastPart);
-
- HashMap map = getSmsTrackerMap(destinationAddress, scAddress,
- message, submitPdu);
- return getSmsTracker(map, sentIntent, deliveryIntent,
- getFormat(), unsentPartCount, anyPartFailed, messageUri, smsHeader,
- false /*isExpextMore*/, fullMessageText, true /*isText*/,
- true /*persistMessage*/);
- }
-
- @Override
- protected void sendSubmitPdu(SmsTracker tracker) {
- if (mPhone.isInEcm()) {
- if (VDBG) {
- Rlog.d(TAG, "Block SMS in Emergency Callback mode");
- }
- tracker.onFailed(mContext, SmsManager.RESULT_ERROR_NO_SERVICE, 0/*errorCode*/);
- return;
- }
- sendRawPdu(tracker);
- }
-
- /** {@inheritDoc} */
- @Override
public void sendSms(SmsTracker tracker) {
Rlog.d(TAG, "sendSms: "
+ " isIms()=" + isIms()
@@ -237,12 +124,6 @@
+ " mMessageRef=" + tracker.mMessageRef
+ " SS=" + mPhone.getServiceState().getState());
- sendSmsByPstn(tracker);
- }
-
- /** {@inheritDoc} */
- @Override
- protected void sendSmsByPstn(SmsTracker tracker) {
int ss = mPhone.getServiceState().getState();
// if sms over IMS is not supported on data and voice is not available...
if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) {
diff --git a/src/java/com/android/internal/telephony/dataconnection/CellularDataService.java b/src/java/com/android/internal/telephony/dataconnection/CellularDataService.java
new file mode 100644
index 0000000..cbc3efe
--- /dev/null
+++ b/src/java/com/android/internal/telephony/dataconnection/CellularDataService.java
@@ -0,0 +1,334 @@
+/*
+ * Copyright 2018 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.
+ */
+
+package com.android.internal.telephony.dataconnection;
+
+import android.hardware.radio.V1_0.SetupDataCallResult;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.NetworkUtils;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.telephony.Rlog;
+import android.telephony.SubscriptionManager;
+import android.telephony.data.DataCallResponse;
+import android.telephony.data.DataProfile;
+import android.telephony.data.DataService;
+import android.telephony.data.DataServiceCallback;
+import android.text.TextUtils;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class represents cellular data service which handles telephony data requests and response
+ * from the cellular modem.
+ */
+public class CellularDataService extends DataService {
+ private static final String TAG = CellularDataService.class.getSimpleName();
+
+ private static final boolean DBG = false;
+
+ private static final int SETUP_DATA_CALL_COMPLETE = 1;
+ private static final int DEACTIVATE_DATA_ALL_COMPLETE = 2;
+ private static final int SET_INITIAL_ATTACH_APN_COMPLETE = 3;
+ private static final int SET_DATA_PROFILE_COMPLETE = 4;
+ private static final int GET_DATA_CALL_LIST_COMPLETE = 5;
+ private static final int DATA_CALL_LIST_CHANGED = 6;
+
+ private class CellularDataServiceProvider extends DataService.DataServiceProvider {
+
+ private final Map<Message, DataServiceCallback> mCallbackMap = new HashMap<>();
+
+ private final Looper mLooper;
+
+ private final Handler mHandler;
+
+ private final Phone mPhone;
+
+ private CellularDataServiceProvider(int slotId) {
+ super(slotId);
+
+ mPhone = PhoneFactory.getPhone(getSlotId());
+
+ HandlerThread thread = new HandlerThread(CellularDataService.class.getSimpleName());
+ thread.start();
+ mLooper = thread.getLooper();
+ mHandler = new Handler(mLooper) {
+ @Override
+ public void handleMessage(Message message) {
+ DataServiceCallback callback = mCallbackMap.remove(message);
+
+ AsyncResult ar = (AsyncResult) message.obj;
+ switch (message.what) {
+ case SETUP_DATA_CALL_COMPLETE:
+ SetupDataCallResult result = (SetupDataCallResult) ar.result;
+ callback.onSetupDataCallComplete(ar.exception != null
+ ? DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE
+ : DataServiceCallback.RESULT_SUCCESS,
+ convertDataCallResult(result));
+ break;
+ case DEACTIVATE_DATA_ALL_COMPLETE:
+ callback.onDeactivateDataCallComplete(ar.exception != null
+ ? DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE
+ : DataServiceCallback.RESULT_SUCCESS);
+ break;
+ case SET_INITIAL_ATTACH_APN_COMPLETE:
+ callback.onSetInitialAttachApnComplete(ar.exception != null
+ ? DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE
+ : DataServiceCallback.RESULT_SUCCESS);
+ break;
+ case SET_DATA_PROFILE_COMPLETE:
+ callback.onSetDataProfileComplete(ar.exception != null
+ ? DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE
+ : DataServiceCallback.RESULT_SUCCESS);
+ break;
+ case GET_DATA_CALL_LIST_COMPLETE:
+ callback.onGetDataCallListComplete(
+ ar.exception != null
+ ? DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE
+ : DataServiceCallback.RESULT_SUCCESS,
+ ar.exception != null
+ ? null
+ : getDataCallList((List<SetupDataCallResult>) ar.result)
+ );
+ break;
+ case DATA_CALL_LIST_CHANGED:
+ notifyDataCallListChanged(getDataCallList(
+ (List<SetupDataCallResult>) ar.result));
+ break;
+ default:
+ loge("Unexpected event: " + message.what);
+ return;
+ }
+ }
+ };
+
+ if (DBG) log("Register for data call list changed.");
+ mPhone.mCi.registerForDataCallListChanged(mHandler, DATA_CALL_LIST_CHANGED, null);
+ }
+
+ private List<DataCallResponse> getDataCallList(List<SetupDataCallResult> dcList) {
+ List<DataCallResponse> dcResponseList = new ArrayList<>();
+ for (SetupDataCallResult dcResult : dcList) {
+ dcResponseList.add(convertDataCallResult(dcResult));
+ }
+ return dcResponseList;
+ }
+
+ @Override
+ public void setupDataCall(int radioTechnology, DataProfile dataProfile, boolean isRoaming,
+ boolean allowRoaming, int reason, LinkProperties linkProperties,
+ DataServiceCallback callback) {
+ if (DBG) log("setupDataCall " + getSlotId());
+
+ Message message = null;
+ // Only obtain the message when the caller wants a callback. If the caller doesn't care
+ // the request completed or results, then no need to pass the message down.
+ if (callback != null) {
+ message = Message.obtain(mHandler, SETUP_DATA_CALL_COMPLETE);
+ mCallbackMap.put(message, callback);
+ }
+
+ mPhone.mCi.setupDataCall(radioTechnology, dataProfile, isRoaming, allowRoaming, reason,
+ linkProperties, message);
+ }
+
+ @Override
+ public void deactivateDataCall(int cid, int reason, DataServiceCallback callback) {
+ if (DBG) log("deactivateDataCall " + getSlotId());
+
+ Message message = null;
+ // Only obtain the message when the caller wants a callback. If the caller doesn't care
+ // the request completed or results, then no need to pass the message down.
+ if (callback != null) {
+ message = Message.obtain(mHandler, DEACTIVATE_DATA_ALL_COMPLETE);
+ mCallbackMap.put(message, callback);
+ }
+
+ mPhone.mCi.deactivateDataCall(cid, reason, message);
+ }
+
+ @Override
+ public void setInitialAttachApn(DataProfile dataProfile, boolean isRoaming,
+ DataServiceCallback callback) {
+ if (DBG) log("setInitialAttachApn " + getSlotId());
+
+ Message message = null;
+ // Only obtain the message when the caller wants a callback. If the caller doesn't care
+ // the request completed or results, then no need to pass the message down.
+ if (callback != null) {
+ message = Message.obtain(mHandler, SET_INITIAL_ATTACH_APN_COMPLETE);
+ mCallbackMap.put(message, callback);
+ }
+
+ mPhone.mCi.setInitialAttachApn(dataProfile, isRoaming, message);
+ }
+
+ @Override
+ public void setDataProfile(List<DataProfile> dps, boolean isRoaming,
+ DataServiceCallback callback) {
+ if (DBG) log("setDataProfile " + getSlotId());
+
+ Message message = null;
+ // Only obtain the message when the caller wants a callback. If the caller doesn't care
+ // the request completed or results, then no need to pass the message down.
+ if (callback != null) {
+ message = Message.obtain(mHandler, SET_DATA_PROFILE_COMPLETE);
+ mCallbackMap.put(message, callback);
+ }
+
+ mPhone.mCi.setDataProfile(dps.toArray(new DataProfile[dps.size()]), isRoaming, message);
+ }
+
+ @Override
+ public void getDataCallList(DataServiceCallback callback) {
+ if (DBG) log("getDataCallList " + getSlotId());
+
+ Message message = null;
+ // Only obtain the message when the caller wants a callback. If the caller doesn't care
+ // the request completed or results, then no need to pass the message down.
+ if (callback != null) {
+ message = Message.obtain(mHandler, GET_DATA_CALL_LIST_COMPLETE);
+ mCallbackMap.put(message, callback);
+ }
+ mPhone.mCi.getDataCallList(message);
+ }
+ }
+
+ @Override
+ public DataServiceProvider createDataServiceProvider(int slotId) {
+ log("Cellular data service created for slot " + slotId);
+ if (!SubscriptionManager.isValidSlotIndex(slotId)) {
+ loge("Tried to cellular data service with invalid slotId " + slotId);
+ return null;
+ }
+ return new CellularDataServiceProvider(slotId);
+ }
+
+ /**
+ * Convert SetupDataCallResult defined in types.hal into DataCallResponse
+ * @param dcResult setup data call result
+ * @return converted DataCallResponse object
+ */
+ @VisibleForTesting
+ public DataCallResponse convertDataCallResult(SetupDataCallResult dcResult) {
+ if (dcResult == null) return null;
+
+ // Process address
+ String[] addresses = null;
+ if (!TextUtils.isEmpty(dcResult.addresses)) {
+ addresses = dcResult.addresses.split("\\s+");
+ }
+
+ List<LinkAddress> laList = new ArrayList<>();
+ if (addresses != null) {
+ for (String address : addresses) {
+ address = address.trim();
+ if (address.isEmpty()) continue;
+
+ try {
+ LinkAddress la;
+ // Check if the address contains prefix length. If yes, LinkAddress
+ // can parse that.
+ if (address.split("/").length == 2) {
+ la = new LinkAddress(address);
+ } else {
+ InetAddress ia = NetworkUtils.numericToInetAddress(address);
+ la = new LinkAddress(ia, (ia instanceof Inet4Address) ? 32 : 128);
+ }
+
+ laList.add(la);
+ } catch (IllegalArgumentException e) {
+ loge("Unknown address: " + address + ", exception = " + e);
+ }
+ }
+ }
+
+ // Process dns
+ String[] dnses = null;
+ if (!TextUtils.isEmpty(dcResult.dnses)) {
+ dnses = dcResult.dnses.split("\\s+");
+ }
+
+ List<InetAddress> dnsList = new ArrayList<>();
+ if (dnses != null) {
+ for (String dns : dnses) {
+ dns = dns.trim();
+ InetAddress ia;
+ try {
+ ia = NetworkUtils.numericToInetAddress(dns);
+ dnsList.add(ia);
+ } catch (IllegalArgumentException e) {
+ loge("Unknown dns: " + dns + ", exception = " + e);
+ }
+ }
+ }
+
+ // Process gateway
+ String[] gateways = null;
+ if (!TextUtils.isEmpty(dcResult.gateways)) {
+ gateways = dcResult.gateways.split("\\s+");
+ }
+
+ List<InetAddress> gatewayList = new ArrayList<>();
+ if (gateways != null) {
+ for (String gateway : gateways) {
+ gateway = gateway.trim();
+ InetAddress ia;
+ try {
+ ia = NetworkUtils.numericToInetAddress(gateway);
+ gatewayList.add(ia);
+ } catch (IllegalArgumentException e) {
+ loge("Unknown gateway: " + gateway + ", exception = " + e);
+ }
+ }
+ }
+
+ return new DataCallResponse(dcResult.status,
+ dcResult.suggestedRetryTime,
+ dcResult.cid,
+ dcResult.active,
+ dcResult.type,
+ dcResult.ifname,
+ laList,
+ dnsList,
+ gatewayList,
+ new ArrayList<>(Arrays.asList(dcResult.pcscf.trim().split("\\s+"))),
+ dcResult.mtu
+ );
+ }
+
+ private void log(String s) {
+ Rlog.d(TAG, s);
+ }
+
+ private void loge(String s) {
+ Rlog.e(TAG, s);
+ }
+}
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
index 0cc846f..b94c8a1 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
@@ -44,6 +44,7 @@
import android.telephony.TelephonyManager;
import android.telephony.data.DataCallResponse;
import android.telephony.data.DataProfile;
+import android.telephony.data.DataService;
import android.text.TextUtils;
import android.util.LocalLog;
import android.util.Pair;
@@ -61,6 +62,7 @@
import com.android.internal.telephony.RetryManager;
import com.android.internal.telephony.ServiceStateTracker;
import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.metrics.TelephonyMetrics;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Protocol;
@@ -527,7 +529,10 @@
boolean allowRoaming = mPhone.getDataRoamingEnabled()
|| (isModemRoaming && !mPhone.getServiceState().getDataRoaming());
- mPhone.mCi.setupDataCall(cp.mRilRat, dp, isModemRoaming, allowRoaming, msg);
+ mPhone.mCi.setupDataCall(ServiceState.rilRadioTechnologyToAccessNetworkType(cp.mRilRat), dp,
+ isModemRoaming, allowRoaming, DataService.REQUEST_REASON_NORMAL, null, msg);
+ TelephonyMetrics.getInstance().writeSetupDataCall(mPhone.getPhoneId(), cp.mRilRat,
+ dp.getProfileId(), dp.getApn(), dp.getProtocol());
}
public void onSubscriptionOverride(int overrideMask, int overrideValue) {
@@ -544,15 +549,14 @@
* @param o is the object returned in the AsyncResult.obj.
*/
private void tearDownData(Object o) {
- int discReason = RILConstants.DEACTIVATE_REASON_NONE;
+ int discReason = DataService.REQUEST_REASON_NORMAL;
ApnContext apnContext = null;
if ((o != null) && (o instanceof DisconnectParams)) {
DisconnectParams dp = (DisconnectParams)o;
apnContext = dp.mApnContext;
- if (TextUtils.equals(dp.mReason, Phone.REASON_RADIO_TURNED_OFF)) {
- discReason = RILConstants.DEACTIVATE_REASON_RADIO_OFF;
- } else if (TextUtils.equals(dp.mReason, Phone.REASON_PDP_RESET)) {
- discReason = RILConstants.DEACTIVATE_REASON_PDP_RESET;
+ if (TextUtils.equals(dp.mReason, Phone.REASON_RADIO_TURNED_OFF)
+ || TextUtils.equals(dp.mReason, Phone.REASON_PDP_RESET)) {
+ discReason = DataService.REQUEST_REASON_SHUTDOWN;
}
}
@@ -1332,12 +1336,10 @@
}
deferMessage(msg);
break;
-
case EVENT_TEAR_DOWN_NOW:
if (DBG) log("DcDefaultState EVENT_TEAR_DOWN_NOW");
- mPhone.mCi.deactivateDataCall(mCid, 0, null);
+ mPhone.mCi.deactivateDataCall(mCid, DataService.REQUEST_REASON_NORMAL, null);
break;
-
case EVENT_LOST_CONNECTION:
if (DBG) {
String s = "DcDefaultState ignore EVENT_LOST_CONNECTION"
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
index c27d706..dd20592 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
@@ -34,13 +34,11 @@
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
import android.net.NetworkConfig;
-import android.net.NetworkInfo;
import android.net.NetworkRequest;
import android.net.NetworkUtils;
import android.net.ProxyInfo;
import android.net.TrafficStats;
import android.net.Uri;
-import android.net.wifi.WifiManager;
import android.os.AsyncResult;
import android.os.Build;
import android.os.Bundle;
@@ -245,24 +243,6 @@
} else if (action.equals(INTENT_PROVISIONING_APN_ALARM)) {
if (DBG) log("Provisioning apn alarm");
onActionIntentProvisioningApnAlarm(intent);
- } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
- final android.net.NetworkInfo networkInfo = (NetworkInfo)
- intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
- mIsWifiConnected = (networkInfo != null && networkInfo.isConnected());
- if (DBG) log("NETWORK_STATE_CHANGED_ACTION: mIsWifiConnected=" + mIsWifiConnected);
- } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
- if (DBG) log("Wifi state changed");
- final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
- WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
- if (!enabled) {
- // when WiFi got disabled, the NETWORK_STATE_CHANGED_ACTION
- // quit and won't report disconnected until next enabling.
- mIsWifiConnected = false;
- }
- if (DBG) {
- log("WIFI_STATE_CHANGED_ACTION: enabled=" + enabled
- + " mIsWifiConnected=" + mIsWifiConnected);
- }
} else if (action.equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
if (mIccRecords.get() != null && mIccRecords.get().getRecordsLoaded()) {
setDefaultDataRoamingEnabled();
@@ -488,9 +468,6 @@
// True when in voice call
private boolean mInVoiceCall = false;
- // wifi connection status will be updated by sticky intent
- private boolean mIsWifiConnected = false;
-
/** Intent sent when the reconnect alarm fires. */
private PendingIntent mReconnectIntent = null;
@@ -607,8 +584,6 @@
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
- filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
- filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
filter.addAction(INTENT_DATA_STALL_ALARM);
filter.addAction(INTENT_PROVISIONING_APN_ALARM);
filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
@@ -4171,7 +4146,6 @@
pw.println(" mSentSinceLastRecv=" + mSentSinceLastRecv);
pw.println(" mNoRecvPollCount=" + mNoRecvPollCount);
pw.println(" mResolver=" + mResolver);
- pw.println(" mIsWifiConnected=" + mIsWifiConnected);
pw.println(" mReconnectIntent=" + mReconnectIntent);
pw.println(" mAutoAttachOnCreation=" + mAutoAttachOnCreation.get());
pw.println(" mIsScreenOn=" + mIsScreenOn);
diff --git a/src/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java b/src/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
index 8f18c61..6663a73 100644
--- a/src/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
@@ -20,36 +20,33 @@
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
import android.content.Intent;
-import android.net.Uri;
import android.os.AsyncResult;
import android.os.Message;
import android.provider.Telephony.Sms;
import android.provider.Telephony.Sms.Intents;
import android.telephony.Rlog;
import android.telephony.ServiceState;
+import android.util.Pair;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.GsmAlphabet;
-import com.android.internal.telephony.ImsSMSDispatcher;
+import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
import com.android.internal.telephony.InboundSmsHandler;
import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.SMSDispatcher;
import com.android.internal.telephony.SmsConstants;
+import com.android.internal.telephony.SmsDispatchersController;
+import com.android.internal.telephony.SMSDispatcher;
import com.android.internal.telephony.SmsHeader;
-import com.android.internal.telephony.SmsUsageMonitor;
+import com.android.internal.telephony.SmsMessageBase;
import com.android.internal.telephony.uicc.IccRecords;
import com.android.internal.telephony.uicc.IccUtils;
import com.android.internal.telephony.uicc.UiccCardApplication;
import com.android.internal.telephony.uicc.UiccController;
+import com.android.internal.telephony.util.SMSDispatcherUtil;
import java.util.HashMap;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
public final class GsmSMSDispatcher extends SMSDispatcher {
private static final String TAG = "GsmSMSDispatcher";
- private static final boolean VDBG = false;
protected UiccController mUiccController = null;
private AtomicReference<IccRecords> mIccRecords = new AtomicReference<IccRecords>();
private AtomicReference<UiccCardApplication> mUiccApplication =
@@ -59,10 +56,9 @@
/** Status report received */
private static final int EVENT_NEW_SMS_STATUS_REPORT = 100;
- public GsmSMSDispatcher(Phone phone, SmsUsageMonitor usageMonitor,
- ImsSMSDispatcher imsSMSDispatcher,
+ public GsmSMSDispatcher(Phone phone, SmsDispatchersController smsDispatchersController,
GsmInboundSmsHandler gsmInboundSmsHandler) {
- super(phone, usageMonitor, imsSMSDispatcher);
+ super(phone, smsDispatchersController);
mCi.setOnSmsStatus(this, EVENT_NEW_SMS_STATUS_REPORT, null);
mGsmInboundSmsHandler = gsmInboundSmsHandler;
mUiccController = UiccController.getInstance();
@@ -109,6 +105,29 @@
}
}
+ @Override
+ protected boolean shouldBlockSms() {
+ return SMSDispatcherUtil.shouldBlockSms(isCdmaMo(), mPhone);
+ }
+
+ @Override
+ protected SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
+ String message, boolean statusReportRequested, SmsHeader smsHeader) {
+ return SMSDispatcherUtil.getSubmitPduGsm(scAddr, destAddr, message, statusReportRequested);
+ }
+
+ @Override
+ protected SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
+ int destPort, byte[] message, boolean statusReportRequested) {
+ return SMSDispatcherUtil.getSubmitPduGsm(scAddr, destAddr, destPort, message,
+ statusReportRequested);
+ }
+
+ @Override
+ protected TextEncodingDetails calculateLength(CharSequence messageBody, boolean use7bitOnly) {
+ return SMSDispatcherUtil.calculateLengthGsm(messageBody, use7bitOnly);
+ }
+
/**
* Called when a status report is received. This should correspond to
* a previously successful SEND.
@@ -121,25 +140,17 @@
SmsMessage sms = SmsMessage.newFromCDS(pdu);
if (sms != null) {
- int tpStatus = sms.getStatus();
int messageRef = sms.mMessageRef;
for (int i = 0, count = deliveryPendingList.size(); i < count; i++) {
SmsTracker tracker = deliveryPendingList.get(i);
if (tracker.mMessageRef == messageRef) {
- // Found it. Remove from list and broadcast.
- if(tpStatus >= Sms.STATUS_FAILED || tpStatus < Sms.STATUS_PENDING ) {
- deliveryPendingList.remove(i);
- // Update the message status (COMPLETE or FAILED)
- tracker.updateSentMessageStatus(mContext, tpStatus);
+ Pair<Boolean, Boolean> result = mSmsDispatchersController.handleSmsStatusReport(
+ tracker,
+ getFormat(),
+ pdu);
+ if (result.second) {
+ deliveryPendingList.remove(i);
}
- PendingIntent intent = tracker.mDeliveryIntent;
- Intent fillIn = new Intent();
- fillIn.putExtra("pdu", pdu);
- fillIn.putExtra("format", getFormat());
- try {
- intent.send(mContext, Activity.RESULT_OK, fillIn);
- } catch (CanceledException ex) {}
-
// Only expect to see one tracker matching this messageref
break;
}
@@ -150,101 +161,6 @@
/** {@inheritDoc} */
@Override
- protected void sendData(String destAddr, String scAddr, int destPort,
- byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
- SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
- scAddr, destAddr, destPort, data, (deliveryIntent != null));
- if (pdu != null) {
- HashMap map = getSmsTrackerMap(destAddr, scAddr, destPort, data, pdu);
- SmsTracker tracker = getSmsTracker(map, sentIntent, deliveryIntent, getFormat(),
- null /*messageUri*/, false /*isExpectMore*/, null /*fullMessageText*/,
- false /*isText*/, true /*persistMessage*/);
-
- 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");
- }
- }
-
- /** {@inheritDoc} */
- @VisibleForTesting
- @Override
- public void sendText(String destAddr, String scAddr, String text, PendingIntent sentIntent,
- PendingIntent deliveryIntent, Uri messageUri, String callingPkg,
- boolean persistMessage) {
- SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
- scAddr, destAddr, text, (deliveryIntent != null));
- if (pdu != null) {
- HashMap map = getSmsTrackerMap(destAddr, scAddr, text, pdu);
- SmsTracker tracker = getSmsTracker(map, sentIntent, deliveryIntent, getFormat(),
- messageUri, false /*isExpectMore*/, text /*fullMessageText*/, true /*isText*/,
- persistMessage);
-
- 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");
- }
- }
-
- /** {@inheritDoc} */
- @Override
- protected void injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent) {
- throw new IllegalStateException("This method must be called only on ImsSMSDispatcher");
- }
-
- /** {@inheritDoc} */
- @Override
- protected GsmAlphabet.TextEncodingDetails calculateLength(CharSequence messageBody,
- boolean use7bitOnly) {
- return SmsMessage.calculateLength(messageBody, use7bitOnly);
- }
-
- /** {@inheritDoc} */
- @Override
- protected SmsTracker getNewSubmitPduTracker(String destinationAddress, String scAddress,
- String message, SmsHeader smsHeader, int encoding,
- PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart,
- AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri,
- String fullMessageText) {
- SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(scAddress, destinationAddress,
- message, deliveryIntent != null, SmsHeader.toByteArray(smsHeader),
- encoding, smsHeader.languageTable, smsHeader.languageShiftTable);
- if (pdu != null) {
- HashMap map = getSmsTrackerMap(destinationAddress, scAddress,
- message, pdu);
- return getSmsTracker(map, sentIntent,
- deliveryIntent, getFormat(), unsentPartCount, anyPartFailed, messageUri,
- smsHeader, !lastPart, fullMessageText, true /*isText*/,
- false /*persistMessage*/);
- } else {
- Rlog.e(TAG, "GsmSMSDispatcher.sendNewSubmitPdu(): getSubmitPdu() returned null");
- return null;
- }
- }
-
- @Override
- protected void sendSubmitPdu(SmsTracker tracker) {
- sendRawPdu(tracker);
- }
-
- /** {@inheritDoc} */
- @Override
protected void sendSms(SmsTracker tracker) {
HashMap<String, Object> map = tracker.getData();
@@ -271,12 +187,6 @@
+ " mMessageRef=" + tracker.mMessageRef
+ " SS=" + mPhone.getServiceState().getState());
- sendSmsByPstn(tracker);
- }
-
- /** {@inheritDoc} */
- @Override
- protected void sendSmsByPstn(SmsTracker tracker) {
int ss = mPhone.getServiceState().getState();
// if sms over IMS is not supported on data and voice is not available...
if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) {
@@ -284,10 +194,7 @@
return;
}
- HashMap<String, Object> map = tracker.getData();
-
byte smsc[] = (byte[]) map.get("smsc");
- byte[] pdu = (byte[]) map.get("pdu");
Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
// sms over gsm is used:
@@ -295,15 +202,6 @@
// this is not a retry case after sms over IMS failed
// indicated by mImsRetry > 0
if (0 == tracker.mImsRetry && !isIms()) {
- if (tracker.mRetryCount > 0) {
- // 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
- }
- }
if (tracker.mRetryCount == 0 && tracker.mExpectMore) {
mCi.sendSMSExpectMore(IccUtils.bytesToHexString(smsc),
IccUtils.bytesToHexString(pdu), reply);
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
index 53e92f2..03b280e 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
@@ -956,6 +956,12 @@
}
public void getCallBarring(String facility, Message onComplete, int serviceClass) {
+ getCallBarring(facility, "", onComplete, serviceClass);
+ }
+
+ @Override
+ public void getCallBarring(String facility, String password, Message onComplete,
+ int serviceClass) {
if (DBG) {
Rlog.d(LOG_TAG, "getCallBarring facility=" + facility
+ ", serviceClass = " + serviceClass);
@@ -965,6 +971,7 @@
try {
ImsUtInterface ut = mCT.getUtInterface();
+ // password is not required with Ut interface
ut.queryCallBarring(getCBTypeFromFacility(facility), resp, serviceClass);
} catch (ImsException e) {
sendErrorResponse(onComplete, e);
@@ -977,6 +984,7 @@
CommandsInterface.SERVICE_CLASS_NONE);
}
+ @Override
public void setCallBarring(String facility, boolean lockState, String password,
Message onComplete, int serviceClass) {
if (DBG) {
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneBase.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneBase.java
index a54190e..d5519dd 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneBase.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneBase.java
@@ -546,6 +546,16 @@
}
@Override
+ public void getCallBarring(String facility, String password, Message onComplete,
+ int serviceClass) {
+ }
+
+ @Override
+ public void setCallBarring(String facility, boolean lockState, String password,
+ Message onComplete, int serviceClass) {
+ }
+
+ @Override
protected void onUpdateIccAvailability() {
}
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCommandInterface.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCommandInterface.java
index 770fbb1..76cc26d 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCommandInterface.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCommandInterface.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.net.KeepalivePacketData;
+import android.net.LinkProperties;
import android.os.Handler;
import android.os.Message;
import android.service.carrier.CarrierIdentifier;
@@ -269,8 +270,9 @@
}
@Override
- public void setupDataCall(int radioTechnology, DataProfile dataProfile, boolean isRoaming,
- boolean allowRoaming, Message result) {
+ public void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
+ boolean allowRoaming, int reason, LinkProperties linkProperties,
+ Message result) {
}
@Override
diff --git a/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java b/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java
index 9eb1666..a0c5630 100644
--- a/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java
+++ b/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java
@@ -17,7 +17,6 @@
package com.android.internal.telephony.metrics;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
-
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_ANSWER;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_CDMA_SEND_SMS;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_DEACTIVATE_DATA_CALL;
@@ -42,6 +41,7 @@
import android.telephony.TelephonyHistogram;
import android.telephony.TelephonyManager;
import android.telephony.data.DataCallResponse;
+import android.telephony.data.DataService;
import android.text.TextUtils;
import android.util.Base64;
import android.util.SparseArray;
@@ -70,10 +70,10 @@
import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.CarrierIdMatchingResult;
import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.ModemRestart;
import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.RilDeactivateDataCall;
+import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.RilDeactivateDataCall.DeactivateReason;
import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.RilSetupDataCall;
import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.RilSetupDataCallResponse;
-import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.RilSetupDataCallResponse
- .RilDataCallFailCause;
+import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.RilSetupDataCallResponse.RilDataCallFailCause;
import com.android.internal.telephony.nano.TelephonyProto.TelephonyLog;
import com.android.internal.telephony.nano.TelephonyProto.TelephonyServiceState;
import com.android.internal.telephony.nano.TelephonyProto.TelephonySettings;
@@ -1009,19 +1009,17 @@
* Write setup data call event
*
* @param phoneId Phone id
- * @param rilSerial RIL request serial number
* @param radioTechnology The data call RAT
- * @param profile Data profile
+ * @param profileId Data profile id
* @param apn APN in string
- * @param authType Authentication type
* @param protocol Data connection protocol
*/
- public void writeRilSetupDataCall(int phoneId, int rilSerial, int radioTechnology, int profile,
- String apn, int authType, String protocol) {
+ public void writeSetupDataCall(int phoneId, int radioTechnology, int profileId, String apn,
+ String protocol) {
RilSetupDataCall setupDataCall = new RilSetupDataCall();
setupDataCall.rat = radioTechnology;
- setupDataCall.dataProfile = profile + 1; // off by 1 between proto and RIL constants.
+ setupDataCall.dataProfile = profileId + 1; // off by 1 between proto and RIL constants.
if (apn != null) {
setupDataCall.apn = apn;
}
@@ -1045,7 +1043,19 @@
RilDeactivateDataCall deactivateDataCall = new RilDeactivateDataCall();
deactivateDataCall.cid = cid;
- deactivateDataCall.reason = reason + 1;
+ switch (reason) {
+ case DataService.REQUEST_REASON_NORMAL:
+ deactivateDataCall.reason = DeactivateReason.DEACTIVATE_REASON_NONE;
+ break;
+ case DataService.REQUEST_REASON_SHUTDOWN:
+ deactivateDataCall.reason = DeactivateReason.DEACTIVATE_REASON_RADIO_OFF;
+ break;
+ case DataService.REQUEST_REASON_HANDOVER:
+ deactivateDataCall.reason = DeactivateReason.DEACTIVATE_REASON_HANDOVER;
+ break;
+ default:
+ deactivateDataCall.reason = DeactivateReason.DEACTIVATE_REASON_UNKNOWN;
+ }
addTelephonyEvent(new TelephonyEventBuilder(phoneId).setDeactivateDataCall(
deactivateDataCall).build());
diff --git a/src/java/com/android/internal/telephony/sip/SipCommandInterface.java b/src/java/com/android/internal/telephony/sip/SipCommandInterface.java
index 9fd22ed..0cd8fab 100644
--- a/src/java/com/android/internal/telephony/sip/SipCommandInterface.java
+++ b/src/java/com/android/internal/telephony/sip/SipCommandInterface.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.net.KeepalivePacketData;
+import android.net.LinkProperties;
import android.os.Handler;
import android.os.Message;
import android.service.carrier.CarrierIdentifier;
@@ -270,8 +271,9 @@
}
@Override
- public void setupDataCall(int radioTechnology, DataProfile dataProfile, boolean isRoaming,
- boolean allowRoaming, Message result) {
+ public void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
+ boolean allowRoaming, int reason, LinkProperties linkProperties,
+ Message result) {
}
@Override
diff --git a/src/java/com/android/internal/telephony/sip/SipPhoneBase.java b/src/java/com/android/internal/telephony/sip/SipPhoneBase.java
index c2160dd..ade427b 100755
--- a/src/java/com/android/internal/telephony/sip/SipPhoneBase.java
+++ b/src/java/com/android/internal/telephony/sip/SipPhoneBase.java
@@ -552,4 +552,14 @@
@Override
public void setBroadcastEmergencyCallStateChanges(boolean broadcast) {
}
+
+ @Override
+ public void getCallBarring(String facility, String password, Message onComplete,
+ int serviceClass) {
+ }
+
+ @Override
+ public void setCallBarring(String facility, boolean lockState, String password,
+ Message onComplete, int serviceClass) {
+ }
}
diff --git a/src/java/com/android/internal/telephony/test/SimulatedCommands.java b/src/java/com/android/internal/telephony/test/SimulatedCommands.java
index 277fbd6..ff8c0a8 100644
--- a/src/java/com/android/internal/telephony/test/SimulatedCommands.java
+++ b/src/java/com/android/internal/telephony/test/SimulatedCommands.java
@@ -20,6 +20,7 @@
import android.hardware.radio.V1_0.VoiceRegStateResult;
import android.net.KeepalivePacketData;
import android.net.LinkAddress;
+import android.net.LinkProperties;
import android.net.NetworkUtils;
import android.os.AsyncResult;
import android.os.Handler;
@@ -1123,11 +1124,12 @@
}
@Override
- public void setupDataCall(int radioTechnology, DataProfile dataProfile, boolean isRoaming,
- boolean allowRoaming, Message result) {
+ public void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
+ boolean allowRoaming, int reason, LinkProperties linkProperties,
+ Message result) {
- SimulatedCommandsVerifier.getInstance().setupDataCall(radioTechnology, dataProfile,
- isRoaming, allowRoaming, result);
+ SimulatedCommandsVerifier.getInstance().setupDataCall(accessNetworkType, dataProfile,
+ isRoaming, allowRoaming, reason, linkProperties, result);
if (mDcResponse == null) {
try {
diff --git a/src/java/com/android/internal/telephony/test/SimulatedCommandsVerifier.java b/src/java/com/android/internal/telephony/test/SimulatedCommandsVerifier.java
index 4a3939b..f060ef4 100644
--- a/src/java/com/android/internal/telephony/test/SimulatedCommandsVerifier.java
+++ b/src/java/com/android/internal/telephony/test/SimulatedCommandsVerifier.java
@@ -17,6 +17,7 @@
package com.android.internal.telephony.test;
import android.net.KeepalivePacketData;
+import android.net.LinkProperties;
import android.os.Handler;
import android.os.Message;
import android.service.carrier.CarrierIdentifier;
@@ -1142,8 +1143,9 @@
}
@Override
- public void setupDataCall(int radioTechnology, DataProfile dataProfile, boolean isRoaming,
- boolean allowRoaming, Message result) {
+ public void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
+ boolean allowRoaming, int reason, LinkProperties linkProperties,
+ Message result) {
}
@Override
diff --git a/src/java/com/android/internal/telephony/uicc/IccCardProxy.java b/src/java/com/android/internal/telephony/uicc/IccCardProxy.java
index 7c18d35..f9629e7 100644
--- a/src/java/com/android/internal/telephony/uicc/IccCardProxy.java
+++ b/src/java/com/android/internal/telephony/uicc/IccCardProxy.java
@@ -382,10 +382,6 @@
}
private void registerUiccCardEvents() {
- if (mUiccSlot != null) {
- // todo: reregistration is not needed unless slot mapping changes
- mUiccSlot.registerForAbsent(this, EVENT_ICC_ABSENT, null);
- }
if (mUiccApplication != null) {
mUiccApplication.registerForReady(this, EVENT_APP_READY, null);
}
@@ -399,7 +395,6 @@
}
private void unregisterUiccCardEvents() {
- if (mUiccSlot != null) mUiccSlot.unregisterForAbsent(this);
if (mUiccCard != null) mUiccCard.unregisterForCarrierPrivilegeRulesLoaded(this);
if (mUiccApplication != null) {
mUiccApplication.unregisterForReady(this);
diff --git a/src/java/com/android/internal/telephony/uicc/UiccProfile.java b/src/java/com/android/internal/telephony/uicc/UiccProfile.java
index a425d9e..cf32dd5 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccProfile.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccProfile.java
@@ -879,10 +879,9 @@
}
}
if (VDBG) {
- log("areAllApplicationsReady: outside loop, return " + (mUiccApplications[0] != null));
+ log("areAllApplicationsReady: outside loop, return " + (mUiccApplication != null));
}
- // Returns false if there is no application in the UiccProfile.
- return mUiccApplications[0] != null;
+ return mUiccApplication != null;
}
private boolean areAllRecordsLoaded() {
@@ -896,10 +895,9 @@
}
}
if (VDBG) {
- log("areAllRecordsLoaded: outside loop, return " + (mUiccApplications[0] != null));
+ log("areAllRecordsLoaded: outside loop, return " + (mUiccApplication != null));
}
- // Returns false if there is no application in the UiccProfile.
- return mUiccApplications[0] != null;
+ return mUiccApplication != null;
}
private int checkIndexLocked(int index, AppType expectedAppType, AppType altExpectedAppType) {
diff --git a/src/java/com/android/internal/telephony/uicc/UiccSlot.java b/src/java/com/android/internal/telephony/uicc/UiccSlot.java
index 4fabf0b..dd17b75 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccSlot.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccSlot.java
@@ -26,8 +26,6 @@
import android.os.Handler;
import android.os.Message;
import android.os.PowerManager;
-import android.os.Registrant;
-import android.os.RegistrantList;
import android.telephony.Rlog;
import android.util.LocalLog;
import android.view.WindowManager;
@@ -62,9 +60,6 @@
private String mIccId;
private Integer mPhoneId = null;
- // todo: remove if this is not needed
- private RegistrantList mAbsentRegistrants = new RegistrantList();
-
private static final int EVENT_CARD_REMOVED = 13;
private static final int EVENT_CARD_ADDED = 14;
@@ -98,7 +93,6 @@
// No notifications while radio is off or we just powering up
if (radioState == RadioState.RADIO_ON && mLastRadioState == RadioState.RADIO_ON) {
if (DBG) log("update: notify card removed");
- mAbsentRegistrants.notifyRegistrants();
sendMessage(obtainMessage(EVENT_CARD_REMOVED, null));
}
@@ -147,11 +141,10 @@
if (iss.slotState == IccSlotStatus.SlotState.SLOTSTATE_INACTIVE) {
if (mActive) {
mActive = false;
- // treat as radio state unavailable
- onRadioStateUnavailable();
- // set mPhoneId to null only after sim state changed broadcast is sent as it
- // needs the phoneId. The broadcast is sent from onRadioStateUnavailable()
+ mLastRadioState = RadioState.RADIO_UNAVAILABLE;
mPhoneId = null;
+ if (mUiccCard != null) mUiccCard.dispose();
+ mUiccCard = null;
}
parseAtr(iss.atr);
mCardState = iss.cardState;
@@ -321,30 +314,6 @@
mLastRadioState = RadioState.RADIO_UNAVAILABLE;
}
- /**
- * Notifies handler of any transition into State.ABSENT
- */
- public void registerForAbsent(Handler h, int what, Object obj) {
- synchronized (mLock) {
- Registrant r = new Registrant(h, what, obj);
-
- mAbsentRegistrants.add(r);
-
- if (mCardState == CardState.CARDSTATE_ABSENT) {
- r.notifyRegistrant();
- }
- }
- }
-
- /**
- * Unregister a handler for card absent notification
- */
- public void unregisterForAbsent(Handler h) {
- synchronized (mLock) {
- mAbsentRegistrants.remove(h);
- }
- }
-
private void log(String msg) {
Rlog.d(TAG, msg);
}
@@ -365,11 +334,6 @@
pw.println(" mCi=" + mCi);
pw.println(" mActive=" + mActive);
pw.println(" mLastRadioState=" + mLastRadioState);
- pw.println(" mAbsentRegistrants: size=" + mAbsentRegistrants.size());
- for (int i = 0; i < mAbsentRegistrants.size(); i++) {
- pw.println(" mAbsentRegistrants[" + i + "]="
- + ((Registrant) mAbsentRegistrants.get(i)).getHandler());
- }
pw.println(" mCardState=" + mCardState);
if (mUiccCard != null) {
pw.println(" mUiccCard=" + mUiccCard);
diff --git a/src/java/com/android/internal/telephony/util/SMSDispatcherUtil.java b/src/java/com/android/internal/telephony/util/SMSDispatcherUtil.java
new file mode 100644
index 0000000..d2ee223
--- /dev/null
+++ b/src/java/com/android/internal/telephony/util/SMSDispatcherUtil.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2018 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
+ */
+
+package com.android.internal.telephony.util;
+
+import com.android.internal.telephony.ImsSmsDispatcher;
+import com.android.internal.telephony.cdma.CdmaSMSDispatcher;
+import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.SmsMessageBase;
+import com.android.internal.telephony.SmsHeader;
+import com.android.internal.telephony.gsm.GsmSMSDispatcher;
+
+/**
+ * Utilities used by {@link com.android.internal.telephony.SMSDispatcher}'s subclasses.
+ *
+ * These methods can not be moved to {@link CdmaSMSDispatcher} and {@link GsmSMSDispatcher} because
+ * they also need to be called from {@link ImsSmsDispatcher} and the utilities will invoke the cdma
+ * or gsm version of the method based on the format.
+ */
+public final class SMSDispatcherUtil {
+ // Prevent instantiation.
+ private SMSDispatcherUtil() {}
+
+ /**
+ * Whether to block SMS or not.
+ *
+ * @param isCdma true if cdma format should be used.
+ * @param phone the Phone to use
+ * @return true to block sms; false otherwise.
+ */
+ public static boolean shouldBlockSms(boolean isCdma, Phone phone) {
+ return isCdma && phone.isInEcm();
+ }
+
+ /**
+ * Trigger the proper implementation for getting submit pdu for text sms based on format.
+ *
+ * @param isCdma true if cdma format should be used.
+ * @param scAddr is the service center address or null to use the current default SMSC
+ * @param destAddr the address to send the message to
+ * @param message the body of the message.
+ * @param statusReportRequested whether or not a status report is requested.
+ * @param smsHeader message header.
+ * @return the submit pdu.
+ */
+ public static SmsMessageBase.SubmitPduBase getSubmitPdu(boolean isCdma, String scAddr,
+ String destAddr, String message, boolean statusReportRequested, SmsHeader smsHeader) {
+ if (isCdma) {
+ return getSubmitPduCdma(scAddr, destAddr, message, statusReportRequested, smsHeader);
+ } else {
+ return getSubmitPduGsm(scAddr, destAddr, message, statusReportRequested);
+ }
+ }
+
+ /**
+ * Gsm implementation for
+ * {@link #getSubmitPdu(boolean, String, String, String, boolean, SmsHeader)}
+ *
+ * @param scAddr is the service center address or null to use the current default SMSC
+ * @param destAddr the address to send the message to
+ * @param message the body of the message.
+ * @param statusReportRequested whether or not a status report is requested.
+ * @return the submit pdu.
+ */
+ public static SmsMessageBase.SubmitPduBase getSubmitPduGsm(String scAddr, String destAddr,
+ String message, boolean statusReportRequested) {
+ return com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddr, destAddr, message,
+ statusReportRequested);
+ }
+
+ /**
+ * Cdma implementation for
+ * {@link #getSubmitPdu(boolean, String, String, String, boolean, SmsHeader)}
+ *
+ * @param scAddr is the service center address or null to use the current default SMSC
+ * @param destAddr the address to send the message to
+ * @param message the body of the message.
+ * @param statusReportRequested whether or not a status report is requested.
+ * @param smsHeader message header.
+ * @return the submit pdu.
+ */
+ public static SmsMessageBase.SubmitPduBase getSubmitPduCdma(String scAddr, String destAddr,
+ String message, boolean statusReportRequested, SmsHeader smsHeader) {
+ return com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddr, destAddr,
+ message, statusReportRequested, smsHeader);
+ }
+
+ /**
+ * Trigger the proper implementation for getting submit pdu for data sms based on format.
+ *
+ * @param isCdma true if cdma format should be used.
+ * @param destAddr the address to send the message to
+ * @param scAddr is the service center address or null to use the current default SMSC
+ * @param destPort the port to deliver the message to
+ * @param message the body of the message to send
+ * @param statusReportRequested whether or not a status report is requested.
+ * @return the submit pdu.
+ */
+ public static SmsMessageBase.SubmitPduBase getSubmitPdu(boolean isCdma, String scAddr,
+ String destAddr, int destPort, byte[] message, boolean statusReportRequested) {
+ if (isCdma) {
+ return getSubmitPduCdma(scAddr, destAddr, destPort, message, statusReportRequested);
+ } else {
+ return getSubmitPduGsm(scAddr, destAddr, destPort, message, statusReportRequested);
+ }
+ }
+
+ /**
+ * Cdma implementation of {@link #getSubmitPdu(boolean, String, String, int, byte[], boolean)}
+
+ * @param destAddr the address to send the message to
+ * @param scAddr is the service center address or null to use the current default SMSC
+ * @param destPort the port to deliver the message to
+ * @param message the body of the message to send
+ * @param statusReportRequested whether or not a status report is requested.
+ * @return the submit pdu.
+ */
+ public static SmsMessageBase.SubmitPduBase getSubmitPduCdma(String scAddr, String destAddr,
+ int destPort, byte[] message, boolean statusReportRequested) {
+ return com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddr, destAddr,
+ destPort, message, statusReportRequested);
+ }
+
+ /**
+ * Gsm implementation of {@link #getSubmitPdu(boolean, String, String, int, byte[], boolean)}
+ *
+ * @param destAddr the address to send the message to
+ * @param scAddr is the service center address or null to use the current default SMSC
+ * @param destPort the port to deliver the message to
+ * @param message the body of the message to send
+ * @param statusReportRequested whether or not a status report is requested.
+ * @return the submit pdu.
+ */
+ public static SmsMessageBase.SubmitPduBase getSubmitPduGsm(String scAddr, String destAddr,
+ int destPort, byte[] message, boolean statusReportRequested) {
+ return com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddr, destAddr,
+ destPort, message, statusReportRequested);
+
+ }
+
+ /**
+ * Calculate the number of septets needed to encode the message. This function should only be
+ * called for individual segments of multipart message.
+ *
+ * @param isCdma true if cdma format should be used.
+ * @param messageBody the message to encode
+ * @param use7bitOnly ignore (but still count) illegal characters if true
+ * @return TextEncodingDetails
+ */
+ public static TextEncodingDetails calculateLength(boolean isCdma, CharSequence messageBody,
+ boolean use7bitOnly) {
+ if (isCdma) {
+ return calculateLengthCdma(messageBody, use7bitOnly);
+ } else {
+ return calculateLengthGsm(messageBody, use7bitOnly);
+ }
+ }
+
+ /**
+ * Gsm implementation for {@link #calculateLength(boolean, CharSequence, boolean)}
+ *
+ * @param messageBody the message to encode
+ * @param use7bitOnly ignore (but still count) illegal characters if true
+ * @return TextEncodingDetails
+ */
+ public static TextEncodingDetails calculateLengthGsm(CharSequence messageBody,
+ boolean use7bitOnly) {
+ return com.android.internal.telephony.cdma.SmsMessage.calculateLength(messageBody,
+ use7bitOnly, false);
+
+ }
+
+ /**
+ * Cdma implementation for {@link #calculateLength(boolean, CharSequence, boolean)}
+ *
+ * @param messageBody the message to encode
+ * @param use7bitOnly ignore (but still count) illegal characters if true
+ * @return TextEncodingDetails
+ */
+ public static TextEncodingDetails calculateLengthCdma(CharSequence messageBody,
+ boolean use7bitOnly) {
+ return com.android.internal.telephony.gsm.SmsMessage.calculateLength(messageBody,
+ use7bitOnly);
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ImsSmsDispatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/ImsSmsDispatcherTest.java
new file mode 100644
index 0000000..f052a9a
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/ImsSmsDispatcherTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2018 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
+ */
+
+package com.android.internal.telephony;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.os.HandlerThread;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+
+public class ImsSmsDispatcherTest extends TelephonyTest {
+ @Mock private SmsDispatchersController mSmsDispatchersController;
+ @Mock private SMSDispatcher.SmsTracker mSmsTracker;
+ private ImsSmsDispatcher mImsSmsDispatcher;
+ private ImsSmsDispatcherTestHandler mImsSmsDispatcherTestHandler;
+
+
+ private class ImsSmsDispatcherTestHandler extends HandlerThread {
+
+ private ImsSmsDispatcherTestHandler(String name) {
+ super(name);
+ }
+
+ @Override
+ public void onLooperPrepared() {
+ mImsSmsDispatcher = spy(new ImsSmsDispatcher(mPhone, mSmsDispatchersController));
+ setReady(true);
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp(getClass().getSimpleName());
+
+ mImsSmsDispatcherTestHandler = new ImsSmsDispatcherTestHandler(TAG);
+ mImsSmsDispatcherTestHandler.start();
+ waitUntilReady();
+ }
+
+ @Test @SmallTest
+ public void testSendSms() {
+ int token = mImsSmsDispatcher.mNextToken.get();
+ int trackersSize = mImsSmsDispatcher.mTrackers.size();
+
+ mImsSmsDispatcher.sendSms(mSmsTracker);
+
+ assertEquals(token + 1, mImsSmsDispatcher.mNextToken.get());
+ assertEquals(trackersSize + 1, mImsSmsDispatcher.mTrackers.size());
+ }
+
+ @Test @SmallTest
+ public void testFallbackToPstn() {
+ int token = 0;
+ mImsSmsDispatcher.mTrackers.put(token, mSmsTracker);
+ doNothing().when(mSmsDispatchersController).sendRetrySms(mSmsTracker);
+
+ mImsSmsDispatcher.fallbackToPstn(token, mSmsTracker);
+
+ verify(mSmsDispatchersController).sendRetrySms(mSmsTracker);
+ assertNull(mImsSmsDispatcher.mTrackers.get(token));
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mImsSmsDispatcher = null;
+ mImsSmsDispatcherTestHandler.quit();
+ super.tearDown();
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NetworkScanResultTest.java b/tests/telephonytests/src/com/android/internal/telephony/NetworkScanResultTest.java
index f149211..47a9979 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/NetworkScanResultTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/NetworkScanResultTest.java
@@ -42,8 +42,7 @@
ArrayList<CellInfo> infos = new ArrayList<CellInfo>();
CellIdentityGsm cig = new CellIdentityGsm(310, 310, 1, 2, 3, 4);
- CellSignalStrengthGsm cssg = new CellSignalStrengthGsm();
- cssg.initialize(5, 6, 7);
+ CellSignalStrengthGsm cssg = new CellSignalStrengthGsm(5, 6, 7);
CellInfoGsm gsm = new CellInfoGsm();
gsm.setRegistered(true);
gsm.setTimeStampType(8);
@@ -53,8 +52,7 @@
infos.add(gsm);
CellIdentityLte cil = new CellIdentityLte(320, 320, 11, 12, 13, 14);
- CellSignalStrengthLte cssl = new CellSignalStrengthLte();
- cssl.initialize(15, 16, 17, 18, 19, 20);
+ CellSignalStrengthLte cssl = new CellSignalStrengthLte(15, 16, 17, 18, 19, 20);
CellInfoLte lte = new CellInfoLte();
lte.setRegistered(false);
lte.setTimeStampType(21);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
index 753e03c..d877ac4 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
@@ -1119,8 +1119,8 @@
expected.setTimeStampType(RIL_TIMESTAMP_TYPE_OEM_RIL);
CellIdentityGsm ci = new CellIdentityGsm(
LAC, CID, ARFCN, BSIC, MCC_STR, MNC_STR, EMPTY_ALPHA_LONG, EMPTY_ALPHA_SHORT);
- CellSignalStrengthGsm cs = new CellSignalStrengthGsm();
- cs.initialize(SIGNAL_STRENGTH, BIT_ERROR_RATE, TIME_ADVANCE);
+ CellSignalStrengthGsm cs = new CellSignalStrengthGsm(
+ SIGNAL_STRENGTH, BIT_ERROR_RATE, TIME_ADVANCE);
expected.setCellIdentity(ci);
expected.setCellSignalStrength(cs);
expected.setCellConnectionStatus(CellInfo.CONNECTION_UNKNOWN);
@@ -1285,8 +1285,8 @@
expected.setTimeStampType(RIL_TIMESTAMP_TYPE_OEM_RIL);
CellIdentityGsm ci = new CellIdentityGsm(
LAC, CID, ARFCN, BSIC, MCC_STR, MNC_STR, ALPHA_LONG, ALPHA_SHORT);
- CellSignalStrengthGsm cs = new CellSignalStrengthGsm();
- cs.initialize(SIGNAL_STRENGTH, BIT_ERROR_RATE, TIME_ADVANCE);
+ CellSignalStrengthGsm cs = new CellSignalStrengthGsm(
+ SIGNAL_STRENGTH, BIT_ERROR_RATE, TIME_ADVANCE);
expected.setCellIdentity(ci);
expected.setCellSignalStrength(cs);
expected.setCellConnectionStatus(CellInfo.CONNECTION_NONE);
@@ -1306,8 +1306,8 @@
expected.setTimeStampType(RIL_TIMESTAMP_TYPE_OEM_RIL);
CellIdentityGsm ci = new CellIdentityGsm(
LAC, CID, ARFCN, BSIC, MCC_STR, MNC_STR, EMPTY_ALPHA_LONG, EMPTY_ALPHA_SHORT);
- CellSignalStrengthGsm cs = new CellSignalStrengthGsm();
- cs.initialize(SIGNAL_STRENGTH, BIT_ERROR_RATE, TIME_ADVANCE);
+ CellSignalStrengthGsm cs = new CellSignalStrengthGsm(
+ SIGNAL_STRENGTH, BIT_ERROR_RATE, TIME_ADVANCE);
expected.setCellIdentity(ci);
expected.setCellSignalStrength(cs);
expected.setCellConnectionStatus(CellInfo.CONNECTION_NONE);
@@ -1329,8 +1329,8 @@
expected.setTimeStampType(RIL_TIMESTAMP_TYPE_OEM_RIL);
CellIdentityGsm ci = new CellIdentityGsm(
LAC, CID, ARFCN, BSIC, null, null, ALPHA_LONG, ALPHA_SHORT);
- CellSignalStrengthGsm cs = new CellSignalStrengthGsm();
- cs.initialize(SIGNAL_STRENGTH, BIT_ERROR_RATE, TIME_ADVANCE);
+ CellSignalStrengthGsm cs = new CellSignalStrengthGsm(
+ SIGNAL_STRENGTH, BIT_ERROR_RATE, TIME_ADVANCE);
expected.setCellIdentity(ci);
expected.setCellConnectionStatus(CellInfo.CONNECTION_NONE);
expected.setCellSignalStrength(cs);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ImsSMSDispatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
similarity index 78%
rename from tests/telephonytests/src/com/android/internal/telephony/ImsSMSDispatcherTest.java
rename to tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
index 105e0f8..ea40ea8 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ImsSMSDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
@@ -21,6 +21,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.isNull;
@@ -38,6 +39,7 @@
import android.content.IntentFilter;
import android.os.HandlerThread;
import android.os.Message;
+import android.provider.Telephony.Sms.Intents;
import android.test.FlakyTest;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Singleton;
@@ -49,24 +51,14 @@
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
-public class ImsSMSDispatcherTest extends TelephonyTest {
+public class SmsDispatchersControllerTest extends TelephonyTest {
@Mock
private SMSDispatcher.SmsTracker mTracker;
- private ImsSMSDispatcher mImsSmsDispatcher;
+ private SmsDispatchersController mSmsDispatchersController;
private ImsSmsDispatcherTestHandler mImsSmsDispatcherTestHandler;
- private boolean mReceivedTestIntent = false;
- private Object mLock = new Object();
+ private boolean mInjectionCallbackTriggered = false;
private static final String TEST_INTENT = "com.android.internal.telephony.TEST_INTENT";
- private BroadcastReceiver mTestReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- logd("onReceive");
- synchronized (mLock) {
- mReceivedTestIntent = true;
- }
- }
- };
private class ImsSmsDispatcherTestHandler extends HandlerThread {
@@ -76,7 +68,7 @@
@Override
public void onLooperPrepared() {
- mImsSmsDispatcher = new ImsSMSDispatcher(mPhone, mSmsStorageMonitor,
+ mSmsDispatchersController = new SmsDispatchersController(mPhone, mSmsStorageMonitor,
mSmsUsageMonitor);
//Initial state of RIL is power on, need to wait util RADIO_ON msg get handled
waitForMs(200);
@@ -96,29 +88,29 @@
@After
public void tearDown() throws Exception {
- mImsSmsDispatcher = null;
+ mSmsDispatchersController = null;
mImsSmsDispatcherTestHandler.quit();
super.tearDown();
}
@Test @SmallTest @FlakyTest @Ignore
public void testSmsHandleStateUpdate() throws Exception {
- assertEquals(SmsConstants.FORMAT_UNKNOWN, mImsSmsDispatcher.getImsSmsFormat());
+ assertEquals(SmsConstants.FORMAT_UNKNOWN, mSmsDispatchersController.getImsSmsFormat());
//Mock ImsNetWorkStateChange with GSM phone type
switchImsSmsFormat(PhoneConstants.PHONE_TYPE_GSM);
- assertEquals(SmsConstants.FORMAT_3GPP, mImsSmsDispatcher.getImsSmsFormat());
- assertTrue(mImsSmsDispatcher.isIms());
+ assertEquals(SmsConstants.FORMAT_3GPP, mSmsDispatchersController.getImsSmsFormat());
+ assertTrue(mSmsDispatchersController.isIms());
//Mock ImsNetWorkStateChange with Cdma Phone type
switchImsSmsFormat(PhoneConstants.PHONE_TYPE_CDMA);
- assertEquals(SmsConstants.FORMAT_3GPP2, mImsSmsDispatcher.getImsSmsFormat());
- assertTrue(mImsSmsDispatcher.isIms());
+ assertEquals(SmsConstants.FORMAT_3GPP2, mSmsDispatchersController.getImsSmsFormat());
+ assertTrue(mSmsDispatchersController.isIms());
}
@Test @SmallTest @FlakyTest @Ignore
public void testSendImsGmsTest() throws Exception {
switchImsSmsFormat(PhoneConstants.PHONE_TYPE_GSM);
- mImsSmsDispatcher.sendText("111"/* desAddr*/, "222" /*scAddr*/, TAG,
+ mSmsDispatchersController.sendText("111"/* desAddr*/, "222" /*scAddr*/, TAG,
null, null, null, null, false);
verify(mSimulatedCommandsVerifier).sendImsGsmSms(eq("038122f2"),
eq("0100038111f1000014c9f67cda9c12d37378983e4697e5d4f29c0e"), eq(0), eq(0),
@@ -128,7 +120,7 @@
@Test @SmallTest
public void testSendImsGmsTestWithOutDesAddr() throws Exception {
switchImsSmsFormat(PhoneConstants.PHONE_TYPE_GSM);
- mImsSmsDispatcher.sendText(null, "222" /*scAddr*/, TAG,
+ mSmsDispatchersController.sendText(null, "222" /*scAddr*/, TAG,
null, null, null, null, false);
verify(mSimulatedCommandsVerifier, times(0)).sendImsGsmSms(anyString(), anyString(),
anyInt(), anyInt(), any(Message.class));
@@ -137,7 +129,7 @@
@Test @SmallTest
public void testSendImsCdmaTest() throws Exception {
switchImsSmsFormat(PhoneConstants.PHONE_TYPE_CDMA);
- mImsSmsDispatcher.sendText("111"/* desAddr*/, "222" /*scAddr*/, TAG,
+ mSmsDispatchersController.sendText("111"/* desAddr*/, "222" /*scAddr*/, TAG,
null, null, null, null, false);
verify(mSimulatedCommandsVerifier).sendImsCdmaSms((byte[])any(), eq(0), eq(0),
any(Message.class));
@@ -151,7 +143,7 @@
replaceInstance(SMSDispatcher.SmsTracker.class, "mFormat", mTracker,
SmsConstants.FORMAT_3GPP2);
doReturn(PhoneConstants.PHONE_TYPE_CDMA).when(mPhone).getPhoneType();
- mImsSmsDispatcher.sendRetrySms(mTracker);
+ mSmsDispatchersController.sendRetrySms(mTracker);
verify(mSimulatedCommandsVerifier).sendImsCdmaSms(captor.capture(), eq(0), eq(0),
any(Message.class));
assertEquals(1, captor.getAllValues().size());
@@ -164,7 +156,7 @@
switchImsSmsFormat(PhoneConstants.PHONE_TYPE_GSM);
replaceInstance(SMSDispatcher.SmsTracker.class, "mFormat", mTracker,
SmsConstants.FORMAT_3GPP);
- mImsSmsDispatcher.sendRetrySms(mTracker);
+ mSmsDispatchersController.sendRetrySms(mTracker);
verify(mSimulatedCommandsVerifier).sendImsGsmSms((String)isNull(), (String)isNull(), eq(0),
eq(0), any(Message.class));
}
@@ -176,18 +168,15 @@
restoreInstance(Singleton.class, "mInstance", mIActivityManagerSingleton);
restoreInstance(ActivityManager.class, "IActivityManagerSingleton", null);
- Context realContext = TestApplication.getAppContext();
- realContext.registerReceiver(mTestReceiver, new IntentFilter(TEST_INTENT));
-
- PendingIntent pendingIntent = PendingIntent.getBroadcast(realContext, 0,
- new Intent(TEST_INTENT), 0);
-
// inject null sms pdu. This should cause intent to be received since pdu is null.
- mImsSmsDispatcher.injectSmsPdu(null, SmsConstants.FORMAT_3GPP, pendingIntent);
+ mSmsDispatchersController.injectSmsPdu(null, SmsConstants.FORMAT_3GPP,
+ (SmsDispatchersController.SmsInjectionCallback) result -> {
+ mInjectionCallbackTriggered = true;
+ assertEquals(Intents.RESULT_SMS_GENERIC_ERROR, result);
+ }
+ );
waitForMs(100);
- synchronized (mLock) {
- assertEquals(true, mReceivedTestIntent);
- }
+ assertEquals(true, mInjectionCallbackTriggered);
}
private void switchImsSmsFormat(int phoneType) {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsDispatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsDispatcherTest.java
index a308762..82a7317 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsDispatcherTest.java
@@ -20,8 +20,8 @@
import android.os.Message;
import android.test.suitebuilder.annotation.SmallTest;
-import com.android.internal.telephony.ImsSMSDispatcher;
import com.android.internal.telephony.SMSDispatcher;
+import com.android.internal.telephony.SmsDispatchersController;
import com.android.internal.telephony.TelephonyTest;
import static org.mockito.Mockito.*;
@@ -37,7 +37,7 @@
@Mock
private SmsMessage mCdmaSmsMessage;
@Mock
- private ImsSMSDispatcher mImsSmsDispatcher;
+ private SmsDispatchersController mSmsDispatchersController;
@Mock
private SMSDispatcher.SmsTracker mSmsTracker;
@@ -52,8 +52,7 @@
@Override
public void onLooperPrepared() {
- mCdmaSmsDispatcher = new CdmaSMSDispatcher(mPhone, mSmsUsageMonitor,
- mImsSmsDispatcher);
+ mCdmaSmsDispatcher = new CdmaSMSDispatcher(mPhone, mSmsDispatchersController);
setReady(true);
}
}
@@ -63,7 +62,7 @@
super.setUp(this.getClass().getSimpleName());
setupMockPackagePermissionChecks();
-
+ doReturn(mSmsUsageMonitor).when(mSmsDispatchersController).getUsageMonitor();
mCdmaSmsDispatcherTestHandler = new CdmaSmsDispatcherTestHandler(TAG);
mCdmaSmsDispatcherTestHandler.start();
waitUntilReady();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/CellularDataServiceTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/CellularDataServiceTest.java
new file mode 100644
index 0000000..a34febc
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/CellularDataServiceTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package com.android.internal.telephony;
+
+
+import static junit.framework.Assert.assertEquals;
+
+import android.hardware.radio.V1_0.SetupDataCallResult;
+import android.net.LinkAddress;
+import android.net.NetworkUtils;
+import android.telephony.data.DataCallResponse;
+
+import com.android.internal.telephony.dataconnection.CellularDataService;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Arrays;
+
+public class CellularDataServiceTest extends TelephonyTest {
+
+ private CellularDataService mCellularDataService;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp(getClass().getSimpleName());
+ mCellularDataService = new CellularDataService();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ @Test
+ public void testConvertDataCallResult() throws Exception {
+
+ SetupDataCallResult result = new SetupDataCallResult();
+ result.status = 0;
+ result.suggestedRetryTime = -1;
+ result.cid = 1;
+ result.active = 1;
+ result.type = "IP";
+ result.ifname = "eth0";
+ result.addresses = "10.0.2.15";
+ result.dnses = "10.0.2.3";
+ result.gateways = "10.0.2.15 fe80::2";
+ result.pcscf = "";
+ result.mtu = 1500;
+
+ DataCallResponse response = new DataCallResponse(0, -1, 1, 1, "IP",
+ "eth0",
+ Arrays.asList(new LinkAddress(NetworkUtils.numericToInetAddress("10.0.2.15"), 32)),
+ Arrays.asList(NetworkUtils.numericToInetAddress("10.0.2.3")),
+ Arrays.asList(NetworkUtils.numericToInetAddress("10.0.2.15"),
+ NetworkUtils.numericToInetAddress("fe80::2")),
+ Arrays.asList(""),
+ 1500);
+
+ assertEquals(response, mCellularDataService.convertDataCallResult(result));
+
+ result.status = 0;
+ result.suggestedRetryTime = -1;
+ result.cid = 0;
+ result.active = 2;
+ result.type = "IPV4V6";
+ result.ifname = "ifname";
+ result.addresses = "2607:fb90:a620:651d:eabe:f8da:c107:44be/64";
+ result.dnses = "fd00:976a::9 fd00:976a::10";
+ result.gateways = "fe80::4c61:1832:7b28:d36c 1.2.3.4";
+ result.pcscf = "fd00:976a:c206:20::6 fd00:976a:c206:20::9 fd00:976a:c202:1d::9";
+ result.mtu = 1500;
+
+ response = new DataCallResponse(0, -1, 0, 2, "IPV4V6",
+ "ifname",
+ Arrays.asList(new LinkAddress("2607:fb90:a620:651d:eabe:f8da:c107:44be/64")),
+ Arrays.asList(NetworkUtils.numericToInetAddress("fd00:976a::9"),
+ NetworkUtils.numericToInetAddress("fd00:976a::10")),
+ Arrays.asList(NetworkUtils.numericToInetAddress("fe80::4c61:1832:7b28:d36c"),
+ NetworkUtils.numericToInetAddress("1.2.3.4")),
+ Arrays.asList("fd00:976a:c206:20::6", "fd00:976a:c206:20::9",
+ "fd00:976a:c202:1d::9"),
+ 1500);
+
+ assertEquals(response, mCellularDataService.convertDataCallResult(result));
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java
index 98b3deb..975c9a1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java
@@ -20,14 +20,12 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkPolicyManager.OVERRIDE_CONGESTED;
import static android.net.NetworkPolicyManager.OVERRIDE_UNMETERED;
-
import static com.android.internal.telephony.TelephonyTestUtils.waitForMs;
import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_ADDRESS;
import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_DNS;
import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_GATEWAY;
import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_IFNAME;
import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_PCSCF_ADDRESS;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -46,14 +44,15 @@
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
+import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.CarrierConfigManager;
import android.telephony.ServiceState;
import android.telephony.data.DataCallResponse;
import android.telephony.data.DataProfile;
+import android.telephony.data.DataService;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.RetryManager;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.dataconnection.DataConnection.ConnectionParams;
@@ -226,8 +225,8 @@
ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
- eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), dpCaptor.capture(),
- eq(false), eq(false), any(Message.class));
+ eq(AccessNetworkType.UTRAN), dpCaptor.capture(), eq(false),
+ eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(), any(Message.class));
assertEquals("spmode.ne.jp", dpCaptor.getValue().getApn());
@@ -243,7 +242,7 @@
waitForMs(100);
verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(eq(1),
- eq(RILConstants.DEACTIVATE_REASON_NONE), any(Message.class));
+ eq(DataService.REQUEST_REASON_NORMAL), any(Message.class));
assertEquals("DcInactiveState", getCurrentState().getName());
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
index 7434abf..c6a17dd 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
@@ -18,7 +18,6 @@
import static com.android.internal.telephony.TelephonyTestUtils.waitForMs;
import static com.android.internal.telephony.dataconnection.ApnSettingTest.createApnSetting;
-
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -63,6 +62,7 @@
import android.telephony.TelephonyManager;
import android.telephony.data.DataCallResponse;
import android.telephony.data.DataProfile;
+import android.telephony.data.DataService;
import android.test.mock.MockContentProvider;
import android.test.mock.MockContentResolver;
import android.test.suitebuilder.annotation.MediumTest;
@@ -559,8 +559,10 @@
ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
// Verify if RIL command was sent properly.
verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
- eq(mServiceState.getRilDataRadioTechnology()), dpCaptor.capture(),
- eq(false), eq(false), any(Message.class));
+ eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
+ mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+ eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
+ any(Message.class));
verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5, 1, LTE_BEARER_BITMASK);
verifyDataConnected(FAKE_APN1);
@@ -630,8 +632,10 @@
ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
// Verify if RIL command was sent properly.
verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
- eq(mServiceState.getRilDataRadioTechnology()), dpCaptor.capture(),
- eq(false), eq(false), any(Message.class));
+ eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
+ mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+ eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
+ any(Message.class));
verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5, 1, LTE_BEARER_BITMASK);
// Make sure we never notify connected because the data call setup is supposed to fail.
@@ -656,8 +660,10 @@
dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
// Verify if RIL command was sent properly.
verify(mSimulatedCommandsVerifier, times(2)).setupDataCall(
- eq(mServiceState.getRilDataRadioTechnology()), dpCaptor.capture(),
- eq(false), eq(false), any(Message.class));
+ eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
+ mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+ eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
+ any(Message.class));
verifyDataProfile(dpCaptor.getValue(), FAKE_APN2, 0, 5, 1, LTE_BEARER_BITMASK);
// Verify connected with APN2 setting.
@@ -691,8 +697,10 @@
waitForMs(200);
ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
verify(mSimulatedCommandsVerifier, times(2)).setupDataCall(
- eq(mServiceState.getRilDataRadioTechnology()), dpCaptor.capture(),
- eq(false), eq(false), any(Message.class));
+ eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
+ mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+ eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
+ any(Message.class));
verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5, 1, LTE_BEARER_BITMASK);
logd("Sending DATA_DISABLED_CMD");
@@ -700,7 +708,8 @@
waitForMs(200);
// expected tear down all metered DataConnections
- verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(anyInt(), anyInt(),
+ verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(
+ eq(DataService.REQUEST_REASON_NORMAL), anyInt(),
any(Message.class));
assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
assertEquals(DctConstants.State.IDLE, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
@@ -742,8 +751,10 @@
waitForMs(300);
ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
verify(mSimulatedCommandsVerifier, times(2)).setupDataCall(
- eq(mServiceState.getRilDataRadioTechnology()), dpCaptor.capture(),
- eq(false), eq(false), any(Message.class));
+ eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
+ mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+ eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
+ any(Message.class));
verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5, 1, LTE_BEARER_BITMASK);
//user is in roaming
@@ -754,7 +765,8 @@
waitForMs(200);
// expected tear down all metered DataConnections
- verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(anyInt(), anyInt(),
+ verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(
+ eq(DataService.REQUEST_REASON_NORMAL), anyInt(),
any(Message.class));
assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
assertEquals(DctConstants.State.IDLE, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
@@ -800,8 +812,10 @@
waitForMs(200);
ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
- eq(mServiceState.getRilDataRadioTechnology()), dpCaptor.capture(),
- eq(false), eq(false), any(Message.class));
+ eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
+ mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+ eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
+ any(Message.class));
verifyDataProfile(dpCaptor.getValue(), FAKE_APN3, 2, 64, 0, 0);
assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
@@ -906,8 +920,10 @@
ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
verify(mSimulatedCommandsVerifier, times(2)).setupDataCall(
- eq(mServiceState.getRilDataRadioTechnology()), dpCaptor.capture(),
- eq(false), eq(false), any(Message.class));
+ eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
+ mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+ eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
+ any(Message.class));
verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5, 1, LTE_BEARER_BITMASK);
assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
@@ -918,7 +934,8 @@
waitForMs(100);
// Validate all metered data connections have been torn down
- verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(anyInt(), anyInt(),
+ verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(
+ eq(DataService.REQUEST_REASON_NORMAL), anyInt(),
any(Message.class));
assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
assertEquals(DctConstants.State.IDLE, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
@@ -950,8 +967,10 @@
waitForMs(200);
verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
- eq(mServiceState.getRilDataRadioTechnology()), any(DataProfile.class),
- eq(false), eq(false), any(Message.class));
+ eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
+ mServiceState.getRilDataRadioTechnology())), any(DataProfile.class),
+ eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
+ any(Message.class));
}
// Test the unmetered APN setup when data is disabled.
@@ -976,8 +995,10 @@
waitForMs(200);
verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
- eq(mServiceState.getRilDataRadioTechnology()), any(DataProfile.class),
- eq(false), eq(false), any(Message.class));
+ eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
+ mServiceState.getRilDataRadioTechnology())), any(DataProfile.class),
+ eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
+ any(Message.class));
}
// Test the metered APN setup when data is disabled.
@@ -1001,8 +1022,9 @@
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, mApnContext));
waitForMs(200);
- verify(mSimulatedCommandsVerifier, times(0)).setupDataCall(
- anyInt(), any(DataProfile.class), eq(false), eq(false), any(Message.class));
+ verify(mSimulatedCommandsVerifier, times(0)).setupDataCall(anyInt(), any(DataProfile.class),
+ eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
+ any(Message.class));
}
// Test the restricted data request when data is disabled.
@@ -1028,8 +1050,9 @@
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, mApnContext));
waitForMs(200);
- verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
- anyInt(), any(DataProfile.class), eq(false), eq(false), any(Message.class));
+ verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(anyInt(), any(DataProfile.class),
+ eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
+ any(Message.class));
}
// Test the default data when data is not connectable.
@@ -1054,8 +1077,9 @@
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, mApnContext));
waitForMs(200);
- verify(mSimulatedCommandsVerifier, times(0)).setupDataCall(
- anyInt(), any(DataProfile.class), eq(false), eq(false), any(Message.class));
+ verify(mSimulatedCommandsVerifier, times(0)).setupDataCall(anyInt(), any(DataProfile.class),
+ eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
+ any(Message.class));
}
// Test the default data on IWLAN.
@@ -1081,8 +1105,9 @@
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, mApnContext));
waitForMs(200);
- verify(mSimulatedCommandsVerifier, times(0)).setupDataCall(
- anyInt(), any(DataProfile.class), eq(false), eq(false), any(Message.class));
+ verify(mSimulatedCommandsVerifier, times(0)).setupDataCall(anyInt(), any(DataProfile.class),
+ eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
+ any(Message.class));
}
// Test the default data when the phone is in ECBM.
@@ -1107,8 +1132,9 @@
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, mApnContext));
waitForMs(200);
- verify(mSimulatedCommandsVerifier, times(0)).setupDataCall(
- anyInt(), any(DataProfile.class), eq(false), eq(false), any(Message.class));
+ verify(mSimulatedCommandsVerifier, times(0)).setupDataCall(anyInt(), any(DataProfile.class),
+ eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
+ any(Message.class));
}
// Test update waiting apn list when on data rat change
@@ -1134,8 +1160,10 @@
ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
// Verify if RIL command was sent properly.
verify(mSimulatedCommandsVerifier).setupDataCall(
- eq(mServiceState.getRilDataRadioTechnology()), dpCaptor.capture(),
- eq(false), eq(false), any(Message.class));
+ eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
+ mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+ eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
+ any(Message.class));
verifyDataProfile(dpCaptor.getValue(), FAKE_APN4, 0, 5, 2, EHRPD_BEARER_BITMASK);
assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
@@ -1148,7 +1176,8 @@
// Verify the disconnected data call due to rat change and retry manger schedule another
// data call setup
- verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(anyInt(), anyInt(),
+ verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(
+ eq(DataService.REQUEST_REASON_NORMAL), anyInt(),
any(Message.class));
verify(mAlarmManager, times(1)).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
anyLong(), any(PendingIntent.class));
@@ -1163,8 +1192,10 @@
// Verify if RIL command was sent properly.
verify(mSimulatedCommandsVerifier).setupDataCall(
- eq(mServiceState.getRilDataRadioTechnology()), dpCaptor.capture(),
- eq(false), eq(false), any(Message.class));
+ eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
+ mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+ eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
+ any(Message.class));
verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5, 1, LTE_BEARER_BITMASK);
assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
}
@@ -1216,8 +1247,10 @@
ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
// Verify if RIL command was sent properly.
verify(mSimulatedCommandsVerifier).setupDataCall(
- eq(mServiceState.getRilDataRadioTechnology()), dpCaptor.capture(),
- eq(false), eq(false), any(Message.class));
+ eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
+ mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+ eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
+ any(Message.class));
verifyDataProfile(dpCaptor.getValue(), FAKE_APN4, 0, 5, 2, EHRPD_BEARER_BITMASK);
assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
@@ -1229,7 +1262,8 @@
waitForMs(200);
// Verify data connection is on
- verify(mSimulatedCommandsVerifier, times(0)).deactivateDataCall(anyInt(), anyInt(),
+ verify(mSimulatedCommandsVerifier, times(0)).deactivateDataCall(
+ eq(DataService.REQUEST_REASON_NORMAL), anyInt(),
any(Message.class));
// Data rat resume from unknown to ehrpd
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java
index 501131e..ae66726 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java
@@ -26,6 +26,7 @@
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -51,8 +52,8 @@
import com.android.internal.telephony.ContextFixture;
import com.android.internal.telephony.ISub;
-import com.android.internal.telephony.ImsSMSDispatcher;
import com.android.internal.telephony.SMSDispatcher;
+import com.android.internal.telephony.SmsDispatchersController;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.TelephonyTestUtils;
import com.android.internal.telephony.TestApplication;
@@ -75,7 +76,7 @@
@Mock
private SmsMessage mGsmSmsMessage;
@Mock
- private ImsSMSDispatcher mImsSmsDispatcher;
+ private SmsDispatchersController mSmsDispatchersController;
@Mock
private GsmInboundSmsHandler mGsmInboundSmsHandler;
@Mock
@@ -108,8 +109,8 @@
@Override
public void onLooperPrepared() {
- mGsmSmsDispatcher = new GsmSMSDispatcher(mPhone, mSmsUsageMonitor,
- mImsSmsDispatcher, mGsmInboundSmsHandler);
+ mGsmSmsDispatcher = new GsmSMSDispatcher(mPhone, mSmsDispatchersController,
+ mGsmInboundSmsHandler);
setReady(true);
}
}
@@ -123,6 +124,7 @@
// in the cache, a real instance is used.
mServiceManagerMockedServices.put("isub", mISubStub);
+ doReturn(mSmsUsageMonitor).when(mSmsDispatchersController).getUsageMonitor();
mGsmSmsDispatcherTestHandler = new GsmSmsDispatcherTestHandler(getClass().getSimpleName());
mGsmSmsDispatcherTestHandler.start();
waitUntilReady();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/TelephonyMetricsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/TelephonyMetricsTest.java
index 591cf42..6d45db0 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/TelephonyMetricsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/TelephonyMetricsTest.java
@@ -18,7 +18,6 @@
import static android.telephony.ServiceState.RIL_RADIO_TECHNOLOGY_LTE;
import static android.telephony.ServiceState.ROAMING_TYPE_DOMESTIC;
-
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_DEACTIVATE_DATA_CALL;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SEND_SMS;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SETUP_DATA_CALL;
@@ -28,7 +27,6 @@
import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_IFNAME;
import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_PCSCF_ADDRESS;
import static com.android.internal.telephony.nano.TelephonyProto.PdpType.PDP_TYPE_IPV4V6;
-
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -534,8 +532,8 @@
@Test
@SmallTest
public void testWriteRilSetupDataCall() throws Exception {
- mMetrics.writeRilSetupDataCall(
- mPhone.getPhoneId(), 1, 14, 3, "apn", 0, "IPV4V6");
+ mMetrics.writeSetupDataCall(
+ mPhone.getPhoneId(), 14, 3, "apn", "IPV4V6");
TelephonyLog log = buildProto();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/mocks/PhoneMock.java b/tests/telephonytests/src/com/android/internal/telephony/mocks/PhoneMock.java
index b41846e..7bd1b08 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/mocks/PhoneMock.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/mocks/PhoneMock.java
@@ -1208,6 +1208,14 @@
throw new RuntimeException("not implemented");
}
+ public void getCallBarring(String facility, String password, Message onComplete,
+ int serviceClass) {
+ }
+
+ public void setCallBarring(String facility, boolean lockState, String password,
+ Message onComplete, int serviceClass) {
+ }
+
public void getOutgoingCallerIdDisplay(Message onComplete) {
throw new RuntimeException("not implemented");
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccProfileTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccProfileTest.java
index bbe2ce9..9dd1af0 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccProfileTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccProfileTest.java
@@ -126,8 +126,11 @@
@Before
public void setUp() throws Exception {
super.setUp(getClass().getSimpleName());
- /* initially there are no application available */
- mIccCardStatus.mApplications = new IccCardApplicationStatus[]{};
+ /* initially there are no application available, but the array should not be empty. */
+ IccCardApplicationStatus umtsApp = composeUiccApplicationStatus(
+ IccCardApplicationStatus.AppType.APPTYPE_USIM,
+ IccCardApplicationStatus.AppState.APPSTATE_UNKNOWN, "0xA2");
+ mIccCardStatus.mApplications = new IccCardApplicationStatus[]{umtsApp};
mIccCardStatus.mCdmaSubscriptionAppIndex =
mIccCardStatus.mImsSubscriptionAppIndex =
mIccCardStatus.mGsmUmtsSubscriptionAppIndex = -1;
@@ -154,12 +157,17 @@
@Test
@SmallTest
public void tesUiccProfileInfoSanity() {
- assertEquals(0, mUiccProfile.getNumApplications());
+ assertEquals(1, mUiccProfile.getNumApplications());
assertNull(mUiccProfile.getUniversalPinState());
assertNull(mUiccProfile.getOperatorBrandOverride());
for (IccCardApplicationStatus.AppType mAppType :
IccCardApplicationStatus.AppType.values()) {
- assertFalse(mUiccProfile.isApplicationOnIcc(mAppType));
+ if (mAppType == IccCardApplicationStatus.AppType.APPTYPE_USIM) {
+ assertTrue(mUiccProfile.isApplicationOnIcc(mAppType));
+ } else {
+ assertFalse(mUiccProfile.isApplicationOnIcc(mAppType));
+ }
+
}
}
@@ -347,4 +355,53 @@
// response for them right away. Ideally applications and records should be mocked.
assertEquals(State.LOADED, mUiccProfile.getState());
}
+
+ @Test
+ @SmallTest
+ public void testUpdateUiccProfileApplicationNoApplication() {
+ mIccCardStatus.mApplications = new IccCardApplicationStatus[]{};
+ mIccCardStatus.mCdmaSubscriptionAppIndex = -1;
+ mIccCardStatus.mImsSubscriptionAppIndex = -1;
+ mIccCardStatus.mGsmUmtsSubscriptionAppIndex = -1;
+ Message mProfileUpdate = mHandler.obtainMessage(UICCPROFILE_UPDATE_APPLICATION_EVENT);
+ setReady(false);
+ mProfileUpdate.sendToTarget();
+
+ waitUntilReady();
+
+ /* wait for the carrier privilege rules to be loaded */
+ waitForMs(50);
+ assertEquals(0, mUiccProfile.getNumApplications());
+
+ mUiccProfile.sendMessage(mUiccProfile.obtainMessage(EVENT_APP_READY));
+ waitForMs(SCARY_SLEEP_MS);
+ // state is loaded since there is no applications.
+ assertEquals(State.NOT_READY, mUiccProfile.getState());
+ }
+
+ @Test
+ @SmallTest
+ public void testUpdateUiccProfileApplicationNoSupportApplication() {
+ IccCardApplicationStatus unknownApp = composeUiccApplicationStatus(
+ IccCardApplicationStatus.AppType.APPTYPE_UNKNOWN,
+ IccCardApplicationStatus.AppState.APPSTATE_UNKNOWN, "");
+ mIccCardStatus.mApplications = new IccCardApplicationStatus[]{unknownApp};
+ mIccCardStatus.mCdmaSubscriptionAppIndex = -1;
+ mIccCardStatus.mImsSubscriptionAppIndex = -1;
+ mIccCardStatus.mGsmUmtsSubscriptionAppIndex = -1;
+ Message mProfileUpdate = mHandler.obtainMessage(UICCPROFILE_UPDATE_APPLICATION_EVENT);
+ setReady(false);
+ mProfileUpdate.sendToTarget();
+
+ waitUntilReady();
+
+ /* wait for the carrier privilege rules to be loaded */
+ waitForMs(50);
+ assertEquals(1, mUiccProfile.getNumApplications());
+
+ mUiccProfile.sendMessage(mUiccProfile.obtainMessage(EVENT_APP_READY));
+ waitForMs(SCARY_SLEEP_MS);
+ // state is loaded since there is no applications.
+ assertEquals(State.NOT_READY, mUiccProfile.getState());
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java
index 88a32e5..9a18d8c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java
@@ -15,14 +15,10 @@
*/
package com.android.internal.telephony.uicc;
-import static com.android.internal.telephony.TelephonyTestUtils.waitForMs;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.verify;
import android.os.Handler;
import android.os.HandlerThread;
@@ -34,7 +30,6 @@
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
-import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
public class UiccSlotTest extends TelephonyTest {
@@ -98,35 +93,6 @@
super.tearDown();
}
-
- @Test @SmallTest
- public void testCardAbsentListener() {
- mUiccSlot.registerForAbsent(mMockedHandler, UICCCARD_ABSENT, null);
- /* assume hotswap capable, avoid bootup on card removal */
- mContextFixture.putBooleanResource(com.android.internal.R.bool.config_hotswapCapable, true);
- mSimulatedCommands.setRadioPower(true, null);
-
- /* Mock Card State transition from card_present to card_absent */
- logd("UICC Card Present update");
- mIccCardStatus.mCardState = IccCardStatus.CardState.CARDSTATE_PRESENT;
- // mUiccSlot.update() needs to be called from the handler thread because it creates UiccCard
- Message mCardUpdate = mTestHandler.obtainMessage(UICCCARD_UPDATE_CARD_STATE_EVENT);
- setReady(false);
- mCardUpdate.sendToTarget();
- waitUntilReady();
-
- logd("UICC Card absent update");
- mIccCardStatus.mCardState = IccCardStatus.CardState.CARDSTATE_ABSENT;
- mUiccSlot.update(mSimulatedCommands, mIccCardStatus, 0 /* phoneId */);
- waitForMs(50);
-
- ArgumentCaptor<Message> mCaptorMessage = ArgumentCaptor.forClass(Message.class);
- ArgumentCaptor<Long> mCaptorLong = ArgumentCaptor.forClass(Long.class);
- verify(mMockedHandler, atLeast(1)).sendMessageDelayed(mCaptorMessage.capture(),
- mCaptorLong.capture());
- assertEquals(UICCCARD_ABSENT, mCaptorMessage.getValue().what);
- }
-
@Test
@SmallTest
public void testUpdateSlotStatus() {